From: Ilia Alshanetsky Date: Mon, 14 Aug 2006 16:35:23 +0000 (+0000) Subject: MFB: Upgraded libsqlite in pdo_sqlite to 3.3.7 X-Git-Tag: RELEASE_1_0_0RC1~1963 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5c01690d9b6b84ad576787f38805a85f75b3b82f;p=php MFB: Upgraded libsqlite in pdo_sqlite to 3.3.7 --- diff --git a/ext/pdo_sqlite/config.m4 b/ext/pdo_sqlite/config.m4 index 418e4b7d48..9d5d8b8cc9 100644 --- a/ext/pdo_sqlite/config.m4 +++ b/ext/pdo_sqlite/config.m4 @@ -72,14 +72,14 @@ if test "$PHP_PDO_SQLITE" != "no"; then pdo_sqlite_sources="sqlite/src/attach.c sqlite/src/auth.c sqlite/src/btree.c \ sqlite/src/build.c sqlite/src/callback.c sqlite/src/date.c sqlite/src/delete.c sqlite/src/expr.c \ sqlite/src/func.c sqlite/src/hash.c sqlite/src/insert.c sqlite/src/legacy.c \ - sqlite/src/main.c sqlite/src/os_mac.c sqlite/src/os_unix.c sqlite/src/os_win.c \ + sqlite/src/main.c sqlite/src/os_unix.c sqlite/src/os_win.c sqlite/src/os.c \ sqlite/src/pager.c sqlite/src/pragma.c sqlite/src/prepare.c \ sqlite/src/printf.c sqlite/src/random.c sqlite/src/select.c \ - sqlite/src/table.c sqlite/src/tokenize.c sqlite/src/analyze.c \ + sqlite/src/table.c sqlite/src/tokenize.c sqlite/src/analyze.c sqlite/src/complete.c \ sqlite/src/trigger.c sqlite/src/update.c sqlite/src/utf.c sqlite/src/util.c \ sqlite/src/vacuum.c sqlite/src/vdbeapi.c sqlite/src/vdbeaux.c sqlite/src/vdbe.c \ sqlite/src/vdbemem.c sqlite/src/where.c sqlite/src/parse.c sqlite/src/opcodes.c \ - sqlite/src/alter.c sqlite/src/vdbefifo.c sqlite/src/experimental.c" + sqlite/src/alter.c sqlite/src/vdbefifo.c sqlite/src/vtab.c sqlite/src/loadext.c" PHP_NEW_EXTENSION(pdo_sqlite, $php_pdo_sqlite_sources_core $pdo_sqlite_sources, diff --git a/ext/pdo_sqlite/config.w32 b/ext/pdo_sqlite/config.w32 index 11f09e3507..f9d663f17f 100644 --- a/ext/pdo_sqlite/config.w32 +++ b/ext/pdo_sqlite/config.w32 @@ -22,9 +22,9 @@ if (PHP_PDO_SQLITE != "no") { EXTENSION("pdo_sqlite", "pdo_sqlite.c sqlite_driver.c sqlite_statement.c", null, "/DSQLITE_OMIT_CURSOR /I" + configure_module_dirname + "/sqlite/src /I" + configure_module_dirname); ADD_SOURCES(configure_module_dirname + "/sqlite/src", "attach.c auth.c btree.c build.c callback.c date.c delete.c expr.c func.c hash.c insert.c \ - legacy.c main.c os_mac.c os_unix.c os_win.c pager.c pragma.c prepare.c printf.c random.c \ - select.c table.c tokenize.c trigger.c update.c utf.c util.c vacuum.c vdbeapi.c analyze.c \ - vdbeaux.c vdbe.c vdbemem.c vdbefifo.c where.c parse.c opcodes.c alter.c experimental.c", "pdo_sqlite"); + legacy.c main.c os.c os_unix.c os_win.c pager.c pragma.c prepare.c printf.c random.c \ + select.c table.c tokenize.c trigger.c update.c utf.c util.c vacuum.c vdbeapi.c analyze.c complete.c \ + vdbeaux.c vdbe.c vdbemem.c vdbefifo.c where.c parse.c opcodes.c alter.c vtab.c loadext.c", "pdo_sqlite"); ADD_EXTENSION_DEP('pdo_sqlite', 'pdo'); } diff --git a/ext/pdo_sqlite/package.xml b/ext/pdo_sqlite/package.xml index a47666a7a4..2461d8d351 100755 --- a/ext/pdo_sqlite/package.xml +++ b/ext/pdo_sqlite/package.xml @@ -139,6 +139,7 @@ + diff --git a/ext/pdo_sqlite/sqlite/Makefile.in b/ext/pdo_sqlite/sqlite/Makefile.in index db47144225..712823e5f6 100644 --- a/ext/pdo_sqlite/sqlite/Makefile.in +++ b/ext/pdo_sqlite/sqlite/Makefile.in @@ -32,7 +32,7 @@ TCC = @TARGET_CC@ @TARGET_CFLAGS@ -I. -I${TOP}/src # Omitting the define will cause extra debugging code to be inserted and # includes extra comments when "EXPLAIN stmt" is used. # -TCC += @TARGET_DEBUG@ +TCC += @TARGET_DEBUG@ @XTHREADCONNECT@ # Compiler options needed for programs that use the TCL library. # @@ -58,6 +58,13 @@ TCC += -DTHREADSAFE=@THREADSAFE@ # LIBPTHREAD=@TARGET_THREAD_LIB@ +# Do threads override each others locks by default (1), or do we test (-1) +# +TCC += -DSQLITE_THREAD_OVERRIDE_LOCK=@THREADSOVERRIDELOCKS@ + +# The fdatasync library +TLIBS = @TARGET_LIBS@ + # Flags controlling use of the in memory btree implementation # # TEMP_STORE is 0 to force temporary tables to be in a file, 1 to @@ -104,9 +111,12 @@ LTCOMPILE = $(LIBTOOL) --mode=compile $(TCC) LTLINK = $(LIBTOOL) --mode=link $(TCC) LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL) +# nawk compatible awk. +NAWK = @AWK@ + # You should not have to change anything below this line ############################################################################### - +OPTS = OPTS += -DSQLITE_OMIT_CURSOR # Cursors do not work at this time TCC += -DSQLITE_OMIT_CURSOR @@ -114,13 +124,13 @@ TCC += -DSQLITE_OMIT_CURSOR # LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btree.lo build.lo \ callback.lo complete.lo date.lo \ - delete.lo expr.lo func.lo hash.lo insert.lo \ - main.lo opcodes.lo os_unix.lo os_win.lo \ + delete.lo expr.lo func.lo hash.lo insert.lo loadext.lo \ + main.lo opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \ pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \ select.lo table.lo tokenize.lo trigger.lo update.lo \ util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbefifo.lo vdbemem.lo \ - where.lo utf.lo legacy.lo + where.lo utf.lo legacy.lo vtab.lo # All of the source code files. # @@ -142,9 +152,12 @@ SRC = \ $(TOP)/src/hash.h \ $(TOP)/src/insert.c \ $(TOP)/src/legacy.c \ + $(TOP)/src/loadext.c \ $(TOP)/src/main.c \ + $(TOP)/src/os.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ + $(TOP)/src/os_os2.c \ $(TOP)/src/pager.c \ $(TOP)/src/pager.h \ $(TOP)/src/parse.y \ @@ -171,6 +184,7 @@ SRC = \ $(TOP)/src/vdbefifo.c \ $(TOP)/src/vdbemem.c \ $(TOP)/src/vdbeInt.h \ + $(TOP)/src/vtab.c \ $(TOP)/src/where.c # Source code to the test files. @@ -179,8 +193,10 @@ TESTSRC = \ $(TOP)/src/btree.c \ $(TOP)/src/date.c \ $(TOP)/src/func.c \ + $(TOP)/src/os.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ + $(TOP)/src/os_os2.c \ $(TOP)/src/pager.c \ $(TOP)/src/pragma.c \ $(TOP)/src/printf.c \ @@ -189,10 +205,17 @@ TESTSRC = \ $(TOP)/src/test3.c \ $(TOP)/src/test4.c \ $(TOP)/src/test5.c \ + $(TOP)/src/test6.c \ + $(TOP)/src/test7.c \ + $(TOP)/src/test8.c \ + $(TOP)/src/test_async.c \ + $(TOP)/src/test_md5.c \ + $(TOP)/src/test_schema.c \ + $(TOP)/src/test_server.c \ + $(TOP)/src/test_tclvar.c \ $(TOP)/src/utf.c \ $(TOP)/src/util.c \ $(TOP)/src/vdbe.c \ - $(TOP)/src/md5.c \ $(TOP)/src/where.c # Header files used by all library source files. @@ -204,8 +227,7 @@ HDR = \ opcodes.h \ $(TOP)/src/os.h \ $(TOP)/src/os_common.h \ - $(TOP)/src/os_unix.h \ - $(TOP)/src/os_win.h \ + $(TOP)/src/sqlite3ext.h \ $(TOP)/src/sqliteInt.h \ $(TOP)/src/vdbe.h \ parse.h @@ -228,8 +250,8 @@ Makefile: $(TOP)/Makefile.in # of the most recently modified source code file # last_change: $(SRC) - cat $(SRC) | grep '$$Id: ' | sort +4 | tail -1 \ - | awk '{print $$5,$$6}' >last_change + cat $(SRC) | grep '$$Id: ' | sort -k 5 | tail -1 \ + | $(NAWK) '{print $$5,$$6}' >last_change libsqlite3.la: $(LIBOBJ) $(LTLINK) -o libsqlite3.la $(LIBOBJ) $(LIBPTHREAD) \ @@ -243,7 +265,8 @@ libtclsqlite3.la: tclsqlite.lo libsqlite3.la sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h $(LTLINK) $(READLINE_FLAGS) $(LIBPTHREAD) \ - -o sqlite3 $(TOP)/src/shell.c libsqlite3.la $(LIBREADLINE) + -o $@ $(TOP)/src/shell.c libsqlite3.la \ + $(LIBREADLINE) $(TLIBS) # This target creates a directory named "tsrc" and fills it with # copies of all of the C source code and header files needed to @@ -313,6 +336,9 @@ insert.lo: $(TOP)/src/insert.c $(HDR) legacy.lo: $(TOP)/src/legacy.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/legacy.c +loadext.lo: $(TOP)/src/loadext.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/loadext.c + main.lo: $(TOP)/src/main.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.c @@ -323,10 +349,13 @@ opcodes.lo: opcodes.c $(LTCOMPILE) -c opcodes.c opcodes.c: opcodes.h $(TOP)/mkopcodec.awk - sort -n -b +2 opcodes.h | awk -f $(TOP)/mkopcodec.awk >opcodes.c + sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >opcodes.c opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk - cat parse.h $(TOP)/src/vdbe.c | awk -f $(TOP)/mkopcodeh.awk >opcodes.h + cat parse.h $(TOP)/src/vdbe.c | $(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h + +os.lo: $(TOP)/src/os.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os.c os_unix.lo: $(TOP)/src/os_unix.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/os_unix.c @@ -334,14 +363,19 @@ os_unix.lo: $(TOP)/src/os_unix.c $(HDR) os_win.lo: $(TOP)/src/os_win.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/os_win.c +os_os2.lo: $(TOP)/src/os_os2.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os_os2.c + parse.lo: parse.c $(HDR) $(LTCOMPILE) -c parse.c parse.h: parse.c -parse.c: $(TOP)/src/parse.y lemon$(BEXE) +parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk cp $(TOP)/src/parse.y . ./lemon $(OPTS) parse.y + mv parse.h parse.h.temp + awk -f $(TOP)/addopcodes.awk parse.h.temp >parse.h pragma.lo: $(TOP)/src/pragma.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/pragma.c @@ -405,6 +439,9 @@ vdbefifo.lo: $(TOP)/src/vdbefifo.c $(VDBEHDR) vdbemem.lo: $(TOP)/src/vdbemem.c $(VDBEHDR) $(LTCOMPILE) -c $(TOP)/src/vdbemem.c +vtab.lo: $(TOP)/src/vtab.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vtab.c + where.lo: $(TOP)/src/where.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/where.c @@ -419,19 +456,12 @@ tclsqlite3: tclsqlite-shell.lo libsqlite3.la libsqlite3.la $(LIBTCL) testfixture$(TEXE): $(TOP)/src/tclsqlite.c libsqlite3.la $(TESTSRC) - $(LTLINK) -DTCLSH=1 -DSQLITE_TEST=1 $(TEMP_STORE) \ - -o testfixture $(TESTSRC) $(TOP)/src/tclsqlite.c \ + $(LTLINK) -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 \ + $(TEMP_STORE) -o testfixture $(TESTSRC) $(TOP)/src/tclsqlite.c \ libsqlite3.la $(LIBTCL) -crashtest$(TEXE): $(TOP)/src/tclsqlite.c libsqlite3.la $(TESTSRC) $(TOP)/src/os_test.c - $(LTLINK) -DOS_TEST=1 -DTCLSH=1 -DSQLITE_TEST=1 \ - -o crashtest \ - $(TESTSRC) $(TOP)/src/os_test.c $(TOP)/src/tclsqlite.c \ - libsqlite3.la $(LIBTCL) - - -fulltest: testfixture$(TEXE) sqlite3$(TEXE) crashtest$(TEXE) +fulltest: testfixture$(TEXE) sqlite3$(TEXE) ./testfixture $(TOP)/test/all.test test: testfixture$(TEXE) sqlite3$(TEXE) diff --git a/ext/pdo_sqlite/sqlite/Makefile.linux-gcc b/ext/pdo_sqlite/sqlite/Makefile.linux-gcc index 202f4a1ee2..c865024b44 100644 --- a/ext/pdo_sqlite/sqlite/Makefile.linux-gcc +++ b/ext/pdo_sqlite/sqlite/Makefile.linux-gcc @@ -41,6 +41,11 @@ THREADSAFE = -DTHREADSAFE=0 #THREADLIB = -lpthread THREADLIB = +#### Specify any extra libraries needed to access required functions. +# +#TLIBS = -lrt # fdatasync on Solaris 8 +TLIBS = + #### Leave SQLITE_DEBUG undefined for maximum speed. Use SQLITE_DEBUG=1 # to check for memory leaks. Use SQLITE_DEBUG=2 to print a log of all # malloc()s and free()s in order to track down memory leaks. @@ -53,6 +58,7 @@ THREADLIB = #OPTS = -DSQLITE_DEBUG=1 #OPTS = OPTS = -DNDEBUG=1 +OPTS += -DHAVE_FDATASYNC=1 #### The suffix to add to executable files. ".exe" for windows. # Nothing for unix. @@ -77,6 +83,12 @@ AR = ar cr RANLIB = ranlib #RANLIB = /opt/mingw/bin/i386-mingw32-ranlib +MKSHLIB = gcc -shared +SO = so +SHPREFIX = lib +# SO = dll +# SHPREFIX = + #### Extra compiler options needed for programs that use the TCL library. # #TCL_FLAGS = @@ -107,6 +119,12 @@ LIBREADLINE = # ENCODING = UTF8 ENCODING = ISO8859 + +#### Which "awk" program provides nawk compatibilty +# +# NAWK = nawk +NAWK = awk + # You should not have to change anything below this line ############################################################################### include $(TOP)/main.mk diff --git a/ext/pdo_sqlite/sqlite/VERSION b/ext/pdo_sqlite/sqlite/VERSION index f092941a75..86fb650440 100644 --- a/ext/pdo_sqlite/sqlite/VERSION +++ b/ext/pdo_sqlite/sqlite/VERSION @@ -1 +1 @@ -3.2.8 +3.3.7 diff --git a/ext/pdo_sqlite/sqlite/aclocal.m4 b/ext/pdo_sqlite/sqlite/aclocal.m4 index 852eb3134b..b50b61e56a 100644 --- a/ext/pdo_sqlite/sqlite/aclocal.m4 +++ b/ext/pdo_sqlite/sqlite/aclocal.m4 @@ -151,7 +151,7 @@ ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" -AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(AR, ar, AC_CHECK_TOOL(AR, emxomfar, false)) AC_CHECK_TOOL(RANLIB, ranlib, :) AC_CHECK_TOOL(STRIP, strip, :) diff --git a/ext/pdo_sqlite/sqlite/configure b/ext/pdo_sqlite/sqlite/configure index 11e3c9c51b..666f18668e 100755 --- a/ext/pdo_sqlite/sqlite/configure +++ b/ext/pdo_sqlite/sqlite/configure @@ -463,7 +463,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP CPP CXX CXXFLAGS ac_ct_CXX CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA program_prefix VERSION RELEASE VERSION_NUMBER BUILD_CC BUILD_CFLAGS BUILD_LIBS TARGET_CC TARGET_CFLAGS TARGET_LINK TARGET_LFLAGS TARGET_RANLIB TARGET_AR THREADSAFE TARGET_THREAD_LIB ALLOWRELEASE TEMP_STORE BUILD_EXEEXT OS_UNIX OS_WIN TARGET_EXEEXT TARGET_LIBS TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR TCL_LIBS TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC HAVE_TCL TARGET_READLINE_LIBS TARGET_READLINE_INC TARGET_HAVE_READLINE TARGET_DEBUG LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP CPP CXX CXXFLAGS ac_ct_CXX CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AWK program_prefix VERSION RELEASE VERSION_NUMBER BUILD_CC BUILD_CFLAGS BUILD_LIBS TARGET_CC TARGET_CFLAGS TARGET_LINK TARGET_LFLAGS TARGET_RANLIB TARGET_AR THREADSAFE TARGET_THREAD_LIB XTHREADCONNECT THREADSOVERRIDELOCKS ALLOWRELEASE TEMP_STORE BUILD_EXEEXT OS_UNIX OS_WIN OS_OS2 TARGET_EXEEXT TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR TCL_LIBS TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC HAVE_TCL TARGET_READLINE_LIBS TARGET_READLINE_INC TARGET_HAVE_READLINE TARGET_DEBUG TARGET_LIBS LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -1025,11 +1025,16 @@ Optional Features: --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) - --enable-threadsafe Support threadsafe operation - --enable-releasemode Support libtool link to release mode - --enable-tempstore Use an in-ram database for temporary tables (never,no,yes,always) - --disable-tcl do not build TCL extension - --enable-debug enable debugging & verbose explain + --enable-threadsafe Support threadsafe operation + --enable-cross-thread-connections + Allow connection sharing across threads + --enable-threads-override-locks + Threads can override each others locks + --enable-releasemode Support libtool link to release mode + --enable-tempstore Use an in-ram database for temporary tables + (never,no,yes,always) + --disable-tcl do not build TCL extension + --enable-debug enable debugging & verbose explain Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1040,7 +1045,8 @@ Optional Packages: --with-tags[=TAGS] include additional configurations [automatic] --with-hints=FILE Read configuration options from FILE - --with-tcl=DIR directory containing tcl configuration (tclConfig.sh) + --with-tcl=DIR directory containing tcl configuration + (tclConfig.sh) Some influential environment variables: CC C compiler command @@ -3055,7 +3061,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 3058 "configure"' > conftest.$ac_ext + echo '#line 3064 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -4518,7 +4524,7 @@ fi # Provide some information about the compiler. -echo "$as_me:4521:" \ +echo "$as_me:4527:" \ "checking for Fortran 77 compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 @@ -5552,11 +5558,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:5555: $lt_compile\"" >&5) + (eval echo "\"\$as_me:5561: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:5559: \$? = $ac_status" >&5 + echo "$as_me:5565: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -5785,11 +5791,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:5788: $lt_compile\"" >&5) + (eval echo "\"\$as_me:5794: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:5792: \$? = $ac_status" >&5 + echo "$as_me:5798: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -5845,11 +5851,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:5848: $lt_compile\"" >&5) + (eval echo "\"\$as_me:5854: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:5852: \$? = $ac_status" >&5 + echo "$as_me:5858: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -8029,7 +8035,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:10315: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:10313: \$? = $ac_status" >&5 + echo "$as_me:10319: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -10366,11 +10372,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:10369: $lt_compile\"" >&5) + (eval echo "\"\$as_me:10375: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:10373: \$? = $ac_status" >&5 + echo "$as_me:10379: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -11727,7 +11733,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:12661: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:12659: \$? = $ac_status" >&5 + echo "$as_me:12665: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -12712,11 +12718,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12715: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12721: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12719: \$? = $ac_status" >&5 + echo "$as_me:12725: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -14746,11 +14752,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14749: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14755: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14753: \$? = $ac_status" >&5 + echo "$as_me:14759: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -14979,11 +14985,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14982: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14988: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14986: \$? = $ac_status" >&5 + echo "$as_me:14992: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -15039,11 +15045,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15042: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15048: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:15046: \$? = $ac_status" >&5 + echo "$as_me:15052: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -17223,7 +17229,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$AWK" && break +done + ######### # Set up an appropriate program prefix @@ -19499,6 +19545,57 @@ else fi +########## +# Do we want to allow a connection created in one thread to be used +# in another thread. This does not work on many Linux systems (ex: RedHat 9) +# due to bugs in the threading implementations. This is thus off by default. +# +# Check whether --enable-cross-thread-connections or --disable-cross-thread-connections was given. +if test "${enable_cross_thread_connections+set}" = set; then + enableval="$enable_cross_thread_connections" + +else + enable_xthreadconnect=no +fi; +echo "$as_me:$LINENO: checking whether to allow connections to be shared across threads" >&5 +echo $ECHO_N "checking whether to allow connections to be shared across threads... $ECHO_C" >&6 +if test "$enable_xthreadconnect" = "no"; then + XTHREADCONNECT='' + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +else + XTHREADCONNECT='-DSQLITE_ALLOW_XTHREAD_CONNECT=1' + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +fi + + +########## +# Do we want to set threadsOverrideEachOthersLocks variable to be 1 (true) by +# default. Normally, a test at runtime is performed to determine the +# appropriate value of this variable. Use this option only if you're sure that +# threads can safely override each others locks in all runtime situations. +# +# Check whether --enable-threads-override-locks or --disable-threads-override-locks was given. +if test "${enable_threads_override_locks+set}" = set; then + enableval="$enable_threads_override_locks" + +else + enable_threads_override_locks=no +fi; +echo "$as_me:$LINENO: checking whether threads can override each others locks" >&5 +echo $ECHO_N "checking whether threads can override each others locks... $ECHO_C" >&6 +if test "$enable_threads_override_locks" = "no"; then + THREADSOVERRIDELOCKS='-1' + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +else + THREADSOVERRIDELOCKS='1' + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +fi + + ########## # Do we want to support release # @@ -19530,7 +19627,7 @@ if test "${enable_tempstore+set}" = set; then enableval="$enable_tempstore" else - enable_tempstore=yes + enable_tempstore=no fi; echo "$as_me:$LINENO: checking whether to use an in-ram database for temporary tables" >&5 echo $ECHO_N "checking whether to use an in-ram database for temporary tables... $ECHO_C" >&6 @@ -19548,10 +19645,15 @@ echo "${ECHO_T}no" >&6 always ) TEMP_STORE=3 echo "$as_me:$LINENO: result: always" >&5 +echo "${ECHO_T}always" >&6 + ;; + yes ) + TEMP_STORE=3 + echo "$as_me:$LINENO: result: always" >&5 echo "${ECHO_T}always" >&6 ;; * ) - TEMP_STORE=2 + TEMP_STORE=1 echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 ;; @@ -19593,13 +19695,26 @@ else TARGET_EXEEXT=$config_TARGET_EXEEXT fi if test "$TARGET_EXEEXT" = ".exe"; then - OS_UNIX=0 - OS_WIN=1 - tclsubdir=win - TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1" + if test $OS2_SHELL ; then + OS_UNIX=0 + OS_WIN=0 + OS_OS2=1 + TARGET_CFLAGS="$TARGET_CFLAGS -DOS_OS2=1" + if test "$ac_compiler_gnu" == "yes" ; then + TARGET_CFLAGS="$TARGET_CFLAGS -Zomf -Zexe -Zmap" + BUILD_CFLAGS="$BUILD_CFLAGS -Zomf -Zexe" + fi + else + OS_UNIX=0 + OS_WIN=1 + OS_OS2=0 + tclsubdir=win + TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1" + fi else OS_UNIX=1 OS_WIN=0 + OS_OS2=0 tclsubdir=unix TARGET_CFLAGS="$TARGET_CFLAGS -DOS_UNIX=1" fi @@ -19618,7 +19733,6 @@ else TARGET_LIBS="" fi - ########## # Figure out all the parameters needed to compile against Tcl. # @@ -19999,6 +20113,140 @@ fi fi +########## +# Figure out what C libraries are required to compile programs +# that use "fdatasync()" function. +# +CC=$TARGET_CC +LIBS=$TARGET_LIBS +echo "$as_me:$LINENO: checking for library containing fdatasync" >&5 +echo $ECHO_N "checking for library containing fdatasync... $ECHO_C" >&6 +if test "${ac_cv_search_fdatasync+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_fdatasync=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fdatasync (); +int +main () +{ +fdatasync (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_fdatasync="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_fdatasync" = no; then + for ac_lib in rt; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fdatasync (); +int +main () +{ +fdatasync (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_fdatasync="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_fdatasync" >&5 +echo "${ECHO_T}$ac_cv_search_fdatasync" >&6 +if test "$ac_cv_search_fdatasync" != no; then + test "$ac_cv_search_fdatasync" = "none required" || LIBS="$ac_cv_search_fdatasync $LIBS" + +fi + +TARGET_LIBS="$LIBS" + ########## # Figure out where to get the READLINE header files. # @@ -20236,7 +20484,7 @@ else use_debug=no fi; if test "${use_debug}" = "yes" ; then - TARGET_DEBUG="" + TARGET_DEBUG="-DSQLITE_DEBUG=1" else TARGET_DEBUG="-DNDEBUG" fi @@ -20340,6 +20588,110 @@ if test $ac_cv_func_usleep = yes; then fi +#-------------------------------------------------------------------- +# Redefine fdatasync as fsync on systems that lack fdatasync +#-------------------------------------------------------------------- + +echo "$as_me:$LINENO: checking for fdatasync" >&5 +echo $ECHO_N "checking for fdatasync... $ECHO_C" >&6 +if test "${ac_cv_func_fdatasync+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define fdatasync to an innocuous variant, in case declares fdatasync. + For example, HP-UX 11i declares gettimeofday. */ +#define fdatasync innocuous_fdatasync + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char fdatasync (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef fdatasync + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fdatasync (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_fdatasync) || defined (__stub___fdatasync) +choke me +#else +char (*f) () = fdatasync; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != fdatasync; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_fdatasync=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_fdatasync=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_fdatasync" >&5 +echo "${ECHO_T}$ac_cv_func_fdatasync" >&6 +if test $ac_cv_func_fdatasync = yes; then + TARGET_CFLAGS="$TARGET_CFLAGS -DHAVE_FDATASYNC=1" +fi + + +######### +# Put out accumulated miscellaneous LIBRARIES +# + + ######### # Generate the output files. # @@ -21016,6 +21368,7 @@ s,@LIBTOOL@,$LIBTOOL,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@AWK@,$AWK,;t t s,@program_prefix@,$program_prefix,;t t s,@VERSION@,$VERSION,;t t s,@RELEASE@,$RELEASE,;t t @@ -21031,13 +21384,15 @@ s,@TARGET_RANLIB@,$TARGET_RANLIB,;t t s,@TARGET_AR@,$TARGET_AR,;t t s,@THREADSAFE@,$THREADSAFE,;t t s,@TARGET_THREAD_LIB@,$TARGET_THREAD_LIB,;t t +s,@XTHREADCONNECT@,$XTHREADCONNECT,;t t +s,@THREADSOVERRIDELOCKS@,$THREADSOVERRIDELOCKS,;t t s,@ALLOWRELEASE@,$ALLOWRELEASE,;t t s,@TEMP_STORE@,$TEMP_STORE,;t t s,@BUILD_EXEEXT@,$BUILD_EXEEXT,;t t s,@OS_UNIX@,$OS_UNIX,;t t s,@OS_WIN@,$OS_WIN,;t t +s,@OS_OS2@,$OS_OS2,;t t s,@TARGET_EXEEXT@,$TARGET_EXEEXT,;t t -s,@TARGET_LIBS@,$TARGET_LIBS,;t t s,@TCL_VERSION@,$TCL_VERSION,;t t s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t @@ -21054,6 +21409,7 @@ s,@TARGET_READLINE_LIBS@,$TARGET_READLINE_LIBS,;t t s,@TARGET_READLINE_INC@,$TARGET_READLINE_INC,;t t s,@TARGET_HAVE_READLINE@,$TARGET_HAVE_READLINE,;t t s,@TARGET_DEBUG@,$TARGET_DEBUG,;t t +s,@TARGET_LIBS@,$TARGET_LIBS,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF diff --git a/ext/pdo_sqlite/sqlite/configure.ac b/ext/pdo_sqlite/sqlite/configure.ac index 3682bf8210..cfec34ab36 100644 --- a/ext/pdo_sqlite/sqlite/configure.ac +++ b/ext/pdo_sqlite/sqlite/configure.ac @@ -123,6 +123,7 @@ dnl show in in configure. # AC_PROG_LIBTOOL AC_PROG_INSTALL +AC_PROG_AWK ######### # Set up an appropriate program prefix @@ -152,7 +153,7 @@ AC_SUBST(VERSION_NUMBER) # $system is the result of uname -s. # AC_ARG_WITH(hints, - [ --with-hints=FILE Read configuration options from FILE], + AC_HELP_STRING([--with-hints=FILE],[Read configuration options from FILE]), hints=$withval) if test "$hints" = ""; then host=`hostname | sed 's/\..*//'` @@ -278,7 +279,7 @@ fi # Do we want to support multithreaded use of sqlite # AC_ARG_ENABLE(threadsafe, -[ --enable-threadsafe Support threadsafe operation],,enable_threadsafe=no) +AC_HELP_STRING([--enable-threadsafe],[Support threadsafe operation]),,enable_threadsafe=no) AC_MSG_CHECKING([whether to support threadsafe operation]) if test "$enable_threadsafe" = "no"; then THREADSAFE=0 @@ -299,11 +300,46 @@ else fi AC_SUBST(TARGET_THREAD_LIB) +########## +# Do we want to allow a connection created in one thread to be used +# in another thread. This does not work on many Linux systems (ex: RedHat 9) +# due to bugs in the threading implementations. This is thus off by default. +# +AC_ARG_ENABLE(cross-thread-connections, +AC_HELP_STRING([--enable-cross-thread-connections],[Allow connection sharing across threads]),,enable_xthreadconnect=no) +AC_MSG_CHECKING([whether to allow connections to be shared across threads]) +if test "$enable_xthreadconnect" = "no"; then + XTHREADCONNECT='' + AC_MSG_RESULT([no]) +else + XTHREADCONNECT='-DSQLITE_ALLOW_XTHREAD_CONNECT=1' + AC_MSG_RESULT([yes]) +fi +AC_SUBST(XTHREADCONNECT) + +########## +# Do we want to set threadsOverrideEachOthersLocks variable to be 1 (true) by +# default. Normally, a test at runtime is performed to determine the +# appropriate value of this variable. Use this option only if you're sure that +# threads can safely override each others locks in all runtime situations. +# +AC_ARG_ENABLE(threads-override-locks, +AC_HELP_STRING([--enable-threads-override-locks],[Threads can override each others locks]),,enable_threads_override_locks=no) +AC_MSG_CHECKING([whether threads can override each others locks]) +if test "$enable_threads_override_locks" = "no"; then + THREADSOVERRIDELOCKS='-1' + AC_MSG_RESULT([no]) +else + THREADSOVERRIDELOCKS='1' + AC_MSG_RESULT([yes]) +fi +AC_SUBST(THREADSOVERRIDELOCKS) + ########## # Do we want to support release # AC_ARG_ENABLE(releasemode, -[ --enable-releasemode Support libtool link to release mode],,enable_releasemode=no) +AC_HELP_STRING([--enable-releasemode],[Support libtool link to release mode]),,enable_releasemode=no) AC_MSG_CHECKING([whether to support shared library linked as release mode or not]) if test "$enable_releasemode" = "no"; then ALLOWRELEASE="" @@ -318,7 +354,7 @@ AC_SUBST(ALLOWRELEASE) # Do we want temporary databases in memory # AC_ARG_ENABLE(tempstore, -[ --enable-tempstore Use an in-ram database for temporary tables (never,no,yes,always)],,enable_tempstore=yes) +AC_HELP_STRING([--enable-tempstore],[Use an in-ram database for temporary tables (never,no,yes,always)]),,enable_tempstore=no) AC_MSG_CHECKING([whether to use an in-ram database for temporary tables]) case "$enable_tempstore" in never ) @@ -333,8 +369,12 @@ case "$enable_tempstore" in TEMP_STORE=3 AC_MSG_RESULT([always]) ;; + yes ) + TEMP_STORE=3 + AC_MSG_RESULT([always]) + ;; * ) - TEMP_STORE=2 + TEMP_STORE=1 AC_MSG_RESULT([yes]) ;; esac @@ -367,13 +407,26 @@ else TARGET_EXEEXT=$config_TARGET_EXEEXT fi if test "$TARGET_EXEEXT" = ".exe"; then - OS_UNIX=0 - OS_WIN=1 - tclsubdir=win - TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1" + if test $OS2_SHELL ; then + OS_UNIX=0 + OS_WIN=0 + OS_OS2=1 + TARGET_CFLAGS="$TARGET_CFLAGS -DOS_OS2=1" + if test "$ac_compiler_gnu" == "yes" ; then + TARGET_CFLAGS="$TARGET_CFLAGS -Zomf -Zexe -Zmap" + BUILD_CFLAGS="$BUILD_CFLAGS -Zomf -Zexe" + fi + else + OS_UNIX=0 + OS_WIN=1 + OS_OS2=0 + tclsubdir=win + TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1" + fi else OS_UNIX=1 OS_WIN=0 + OS_OS2=0 tclsubdir=unix TARGET_CFLAGS="$TARGET_CFLAGS -DOS_UNIX=1" fi @@ -381,6 +434,7 @@ fi AC_SUBST(BUILD_EXEEXT) AC_SUBST(OS_UNIX) AC_SUBST(OS_WIN) +AC_SUBST(OS_OS2) AC_SUBST(TARGET_EXEEXT) ########## @@ -391,7 +445,6 @@ if test "$config_TARGET_LIBS" != ""; then else TARGET_LIBS="" fi -AC_SUBST(TARGET_LIBS) ########## # Figure out all the parameters needed to compile against Tcl. @@ -401,10 +454,10 @@ AC_SUBST(TARGET_LIBS) # Those macros could not be used directly since we have to make some # minor changes to accomodate systems that do not have TCL installed. # -AC_ARG_ENABLE(tcl, [ --disable-tcl do not build TCL extension], +AC_ARG_ENABLE(tcl, AC_HELP_STRING([--disable-tcl],[do not build TCL extension]), [use_tcl=$enableval],[use_tcl=yes]) if test "${use_tcl}" = "yes" ; then - AC_ARG_WITH(tcl, [ --with-tcl=DIR directory containing tcl configuration (tclConfig.sh)], with_tclconfig=${withval}) + AC_ARG_WITH(tcl, AC_HELP_STRING([--with-tcl=DIR],[directory containing tcl configuration (tclConfig.sh)]), with_tclconfig=${withval}) AC_MSG_CHECKING([for Tcl configuration]) AC_CACHE_VAL(ac_cv_c_tclconfig,[ # First check to see if --with-tcl was specified. @@ -550,6 +603,15 @@ else fi AC_SUBST(TARGET_READLINE_LIBS) +########## +# Figure out what C libraries are required to compile programs +# that use "fdatasync()" function. +# +CC=$TARGET_CC +LIBS=$TARGET_LIBS +AC_SEARCH_LIBS(fdatasync, [rt]) +TARGET_LIBS="$LIBS" + ########## # Figure out where to get the READLINE header files. # @@ -593,10 +655,10 @@ AC_SUBST(TARGET_HAVE_READLINE) ######### # check for debug enabled -AC_ARG_ENABLE(debug, [ --enable-debug enable debugging & verbose explain], +AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]), [use_debug=$enableval],[use_debug=no]) if test "${use_debug}" = "yes" ; then - TARGET_DEBUG="" + TARGET_DEBUG="-DSQLITE_DEBUG=1" else TARGET_DEBUG="-DNDEBUG" fi @@ -607,6 +669,17 @@ AC_SUBST(TARGET_DEBUG) # AC_CHECK_FUNC(usleep, [TARGET_CFLAGS="$TARGET_CFLAGS -DHAVE_USLEEP=1"]) +#-------------------------------------------------------------------- +# Redefine fdatasync as fsync on systems that lack fdatasync +#-------------------------------------------------------------------- + +AC_CHECK_FUNC(fdatasync, [TARGET_CFLAGS="$TARGET_CFLAGS -DHAVE_FDATASYNC=1"]) + +######### +# Put out accumulated miscellaneous LIBRARIES +# +AC_SUBST(TARGET_LIBS) + ######### # Generate the output files. # diff --git a/ext/pdo_sqlite/sqlite/main.mk b/ext/pdo_sqlite/sqlite/main.mk index d931e281ae..2653815457 100644 --- a/ext/pdo_sqlite/sqlite/main.mk +++ b/ext/pdo_sqlite/sqlite/main.mk @@ -42,7 +42,8 @@ # LIBREADLINE Linker options needed by programs using readline() must # link against. # -# ENCODING "UTF8" or "ISO8859" +# NAWK Nawk compatible awk program. Older (obsolete?) solaris +# systems need this to avoid using the original AT&T AWK. # # Once the macros above are defined, the rest of this make script will # build the SQLite library and testing tools. @@ -56,13 +57,13 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src # LIBOBJ+= alter.o analyze.o attach.o auth.o btree.o build.o \ callback.o complete.o date.o delete.o \ - expr.o func.o hash.o insert.o \ - main.o opcodes.o os_unix.o os_win.o \ + expr.o func.o hash.o insert.o loadext.o \ + main.o opcodes.o os.o os_os2.o os_unix.o os_win.o \ pager.o parse.o pragma.o prepare.o printf.o random.o \ select.o table.o tclsqlite.o tokenize.o trigger.o \ update.o util.o vacuum.o \ vdbe.o vdbeapi.o vdbeaux.o vdbefifo.o vdbemem.o \ - where.o utf.o legacy.o + where.o utf.o legacy.o vtab.o # All of the source code files. # @@ -84,7 +85,10 @@ SRC = \ $(TOP)/src/hash.h \ $(TOP)/src/insert.c \ $(TOP)/src/legacy.c \ + $(TOP)/src/loadext.c \ $(TOP)/src/main.c \ + $(TOP)/src/os.c \ + $(TOP)/src/os_os2.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ @@ -113,6 +117,7 @@ SRC = \ $(TOP)/src/vdbefifo.c \ $(TOP)/src/vdbemem.c \ $(TOP)/src/vdbeInt.h \ + $(TOP)/src/vtab.c \ $(TOP)/src/where.c # Source code to the test files. @@ -121,6 +126,8 @@ TESTSRC = \ $(TOP)/src/btree.c \ $(TOP)/src/date.c \ $(TOP)/src/func.c \ + $(TOP)/src/os.c \ + $(TOP)/src/os_os2.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ @@ -131,10 +138,17 @@ TESTSRC = \ $(TOP)/src/test3.c \ $(TOP)/src/test4.c \ $(TOP)/src/test5.c \ + $(TOP)/src/test6.c \ + $(TOP)/src/test7.c \ + $(TOP)/src/test8.c \ + $(TOP)/src/test_async.c \ + $(TOP)/src/test_md5.c \ + $(TOP)/src/test_schema.c \ + $(TOP)/src/test_server.c \ + $(TOP)/src/test_tclvar.c \ $(TOP)/src/utf.c \ $(TOP)/src/util.c \ $(TOP)/src/vdbe.c \ - $(TOP)/src/md5.c \ $(TOP)/src/where.c # Header files used by all library source files. @@ -146,8 +160,7 @@ HDR = \ opcodes.h \ $(TOP)/src/os.h \ $(TOP)/src/os_common.h \ - $(TOP)/src/os_unix.h \ - $(TOP)/src/os_win.h \ + $(TOP)/src/sqlite3ext.h \ $(TOP)/src/sqliteInt.h \ $(TOP)/src/vdbe.h \ parse.h @@ -167,8 +180,8 @@ all: sqlite3.h libsqlite3.a sqlite3$(EXE) # of the most recently modified source code file # last_change: $(SRC) - cat $(SRC) | grep '$$Id: ' | sort +4 | tail -1 \ - | awk '{print $$5,$$6}' >last_change + cat $(SRC) | grep '$$Id: ' | sort -k 5 | tail -1 \ + | $(NAWK) '{print $$5,$$6}' >last_change libsqlite3.a: $(LIBOBJ) $(AR) libsqlite3.a $(LIBOBJ) @@ -176,7 +189,7 @@ libsqlite3.a: $(LIBOBJ) sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h $(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(TOP)/src/shell.c \ - libsqlite3.a $(LIBREADLINE) $(THREADLIB) + libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB) objects: $(LIBOBJ_ORIG) @@ -247,6 +260,9 @@ insert.o: $(TOP)/src/insert.c $(HDR) legacy.o: $(TOP)/src/legacy.c $(HDR) $(TCCX) -c $(TOP)/src/legacy.c +loadext.o: $(TOP)/src/loadext.c $(HDR) + $(TCCX) -c $(TOP)/src/loadext.c + main.o: $(TOP)/src/main.c $(HDR) $(TCCX) -c $(TOP)/src/main.c @@ -257,10 +273,16 @@ opcodes.o: opcodes.c $(TCCX) -c opcodes.c opcodes.c: opcodes.h $(TOP)/mkopcodec.awk - sort -n -b +2 opcodes.h | awk -f $(TOP)/mkopcodec.awk >opcodes.c + sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >opcodes.c opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk - cat parse.h $(TOP)/src/vdbe.c | awk -f $(TOP)/mkopcodeh.awk >opcodes.h + cat parse.h $(TOP)/src/vdbe.c | $(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h + +os.o: $(TOP)/src/os.c $(HDR) + $(TCCX) -c $(TOP)/src/os.c + +os_os2.o: $(TOP)/src/os_os2.c $(HDR) + $(TCCX) -c $(TOP)/src/os_os2.c os_unix.o: $(TOP)/src/os_unix.c $(HDR) $(TCCX) -c $(TOP)/src/os_unix.c @@ -273,9 +295,11 @@ parse.o: parse.c $(HDR) parse.h: parse.c -parse.c: $(TOP)/src/parse.y lemon +parse.c: $(TOP)/src/parse.y lemon $(TOP)/addopcodes.awk cp $(TOP)/src/parse.y . ./lemon $(OPTS) parse.y + mv parse.h parse.h.temp + awk -f $(TOP)/addopcodes.awk parse.h.temp >parse.h pragma.o: $(TOP)/src/pragma.c $(HDR) $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/pragma.c @@ -294,7 +318,7 @@ select.o: $(TOP)/src/select.c $(HDR) sqlite3.h: $(TOP)/src/sqlite.h.in sed -e s/--VERS--/`cat ${TOP}/VERSION`/ \ - -e s/--VERSION-NUMBER--/`cat ${TOP}/VERSION | sed 's/[^0-9]/ /g' | awk '{printf "%d%03d%03d",$$1,$$2,$$3}'`/ \ + -e s/--VERSION-NUMBER--/`cat ${TOP}/VERSION | sed 's/[^0-9]/ /g' | $(NAWK) '{printf "%d%03d%03d",$$1,$$2,$$3}'`/ \ $(TOP)/src/sqlite.h.in >sqlite3.h table.o: $(TOP)/src/table.c $(HDR) @@ -340,6 +364,9 @@ vdbefifo.o: $(TOP)/src/vdbefifo.c $(VDBEHDR) vdbemem.o: $(TOP)/src/vdbemem.c $(VDBEHDR) $(TCCX) -c $(TOP)/src/vdbemem.c +vtab.o: $(TOP)/src/vtab.c $(VDBEHDR) + $(TCCX) -c $(TOP)/src/vtab.c + where.o: $(TOP)/src/where.c $(HDR) $(TCCX) -c $(TOP)/src/where.c @@ -350,17 +377,12 @@ tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a $(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB) testfixture$(EXE): $(TOP)/src/tclsqlite.c libsqlite3.a $(TESTSRC) - $(TCCX) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1 -o testfixture$(EXE) \ + $(TCCX) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 \ + -DSQLITE_SERVER=1 -o testfixture$(EXE) \ $(TESTSRC) $(TOP)/src/tclsqlite.c \ libsqlite3.a $(LIBTCL) $(THREADLIB) -crashtest: $(TOP)/src/tclsqlite.c libsqlite3.a $(TESTSRC) $(TOP)/src/os_test.c - $(TCCX) $(TCL_FLAGS) -DOS_TEST=1 -DTCLSH=1 -DSQLITE_TEST=1 \ - -o crashtest \ - $(TESTSRC) $(TOP)/src/os_test.c $(TOP)/src/tclsqlite.c \ - libsqlite3.a $(LIBTCL) $(THREADLIB) - -fulltest: testfixture$(EXE) sqlite3$(EXE) crashtest +fulltest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/all.test test: testfixture$(EXE) sqlite3$(EXE) @@ -375,10 +397,17 @@ sqlite3_analyzer$(EXE): $(TOP)/src/tclsqlite.c libsqlite3.a $(TESTSRC) \ -e 's,^,",' \ -e 's,$$,\\n",' \ $(TOP)/tool/spaceanal.tcl >spaceanal_tcl.h - $(TCCX) $(TCL_FLAGS) -DTCLSH=2 -DSQLITE_TEST=1 -o \ + $(TCCX) $(TCL_FLAGS) -DTCLSH=2 -DSQLITE_TEST=1 -DSQLITE_DEBUG=1 -o \ sqlite3_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \ libsqlite3.a $(LIBTCL) $(THREADLIB) +TEST_EXTENSION = $(SHPREFIX)testloadext.$(SO) +$(TEST_EXTENSION): $(TOP)/src/test_loadext.c + $(MKSHLIB) $(TOP)/src/test_loadext.c -o $(TEST_EXTENSION) + +extensiontest: testfixture$(EXE) $(TEST_EXTENSION) + ./testfixture$(EXE) $(TOP)/test/loadext.test + # Rules used to build documentation # arch.html: $(TOP)/www/arch.tcl @@ -469,6 +498,9 @@ omitted.html: $(TOP)/www/omitted.tcl opcode.html: $(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c tclsh $(TOP)/www/opcode.tcl $(TOP)/src/vdbe.c >opcode.html +sharedcache.html: $(TOP)/www/sharedcache.tcl + tclsh $(TOP)/www/sharedcache.tcl >sharedcache.html + mingw.html: $(TOP)/www/mingw.tcl tclsh $(TOP)/www/mingw.tcl >mingw.html @@ -537,6 +569,7 @@ DOC = \ opcode.html \ pragma.html \ quickstart.html \ + sharedcache.html \ speed.html \ sqlite.gif \ sqlite.html \ @@ -558,7 +591,7 @@ install: sqlite3 libsqlite3.a sqlite3.h mv sqlite3.h /usr/include clean: - rm -f *.o sqlite3 libsqlite3.a sqlite3.h opcodes.* crashtest + rm -f *.o sqlite3 libsqlite3.a sqlite3.h opcodes.* rm -f lemon lempar.c parse.* sqlite*.tar.gz mkkeywordhash keywordhash.h rm -f $(PUBLISH) rm -f *.da *.bb *.bbg gmon.out diff --git a/ext/pdo_sqlite/sqlite/mkdll.sh b/ext/pdo_sqlite/sqlite/mkdll.sh index 1ad5f83326..50dd60b711 100644 --- a/ext/pdo_sqlite/sqlite/mkdll.sh +++ b/ext/pdo_sqlite/sqlite/mkdll.sh @@ -11,7 +11,7 @@ cd tsrc PATH=$PATH:/opt/mingw/bin TCLDIR=/home/drh/tcltk/846/win/846win TCLSTUBLIB=$TCLDIR/libtcl84stub.a -OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1 -DTHREADSAFE=1' +OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1 -DTHREADSAFE=1 -DBUILD_sqlite=1' CC="i386-mingw32msvc-gcc -O2 $OPTS -I. -I$TCLDIR" rm shell.c for i in *.c; do @@ -31,7 +31,7 @@ i386-mingw32msvc-dllwrap \ --as i386-mingw32msvc-as \ --target i386-mingw32 \ -dllname tclsqlite3.dll -lmsvcrt *.o $TCLSTUBLIB -i386-mingw32msvc-strip tclsqlite3.dll +#i386-mingw32msvc-strip tclsqlite3.dll rm tclsqlite.o i386-mingw32msvc-dllwrap \ --def sqlite3.def -v --export-all \ @@ -40,5 +40,5 @@ i386-mingw32msvc-dllwrap \ --as i386-mingw32msvc-as \ --target i386-mingw32 \ -dllname sqlite3.dll -lmsvcrt *.o -i386-mingw32msvc-strip sqlite3.dll +#i386-mingw32msvc-strip sqlite3.dll cd .. diff --git a/ext/pdo_sqlite/sqlite/mkopcodeh.awk b/ext/pdo_sqlite/sqlite/mkopcodeh.awk index a258194ca8..0fa50ead09 100644 --- a/ext/pdo_sqlite/sqlite/mkopcodeh.awk +++ b/ext/pdo_sqlite/sqlite/mkopcodeh.awk @@ -14,14 +14,28 @@ # the OP_ is the same as the TK_ value. If missing, the OP_ value is assigned # a small integer that is different from every other OP_ value. # -# We go to the trouble of making some OP_ value the same as TK_ values +# We go to the trouble of making some OP_ values the same as TK_ values # as an optimization. During parsing, things like expression operators # are coded with TK_ values such as TK_ADD, TK_DIVIDE, and so forth. Later # during code generation, we need to generate corresponding opcodes like # OP_Add and OP_Divide. By making TK_ADD==OP_Add and TK_DIVIDE==OP_Divide, -# code to translation from one to the other is avoided. This makes the +# code to translate from one to the other is avoided. This makes the # code generator run (infinitesimally) faster and more importantly it makes -# the total library smaller. +# the library footprint smaller. +# +# This script also scans for lines of the form: +# +# case OP_aaaa: /* no-push */ +# +# When the no-push comment is found on an opcode, it means that that +# opcode does not leave a result on the stack. By identifying which +# opcodes leave results on the stack it is possible to determine a +# much smaller upper bound on the size of the stack. This allows +# a smaller stack to be allocated, which is important to embedded +# systems with limited memory space. This script generates a series +# of "NOPUSH_MASK" defines that contain bitmaps of opcodes that leave +# results on the stack. The NOPUSH_MASK defines are used in vdbeaux.c +# to help determine the maximum stack size. # @@ -104,7 +118,10 @@ END { } } printf "\n" + print "/* Opcodes that are guaranteed to never push a value onto the stack" + print "** contain a 1 their corresponding position of the following mask" + print "** set. See the opcodeNoPush() function in vdbeaux.c */" for(i=0; i<10; i++){ - printf "#define NOPUSH_MASK_%d %d\n", i, nopush[i] + printf "#define NOPUSH_MASK_%d 0x%04x\n", i, nopush[i] } } diff --git a/ext/pdo_sqlite/sqlite/publish.sh b/ext/pdo_sqlite/sqlite/publish.sh index 0a61d90ed2..043c89a039 100644 --- a/ext/pdo_sqlite/sqlite/publish.sh +++ b/ext/pdo_sqlite/sqlite/publish.sh @@ -113,3 +113,5 @@ mv $HOME/rpm/SRPMS/sqlite-$vers*.rpm doc # #cp $srcdir/../historical/* doc make doc +cd doc +chmod 644 *.gz diff --git a/ext/pdo_sqlite/sqlite/sqlite3.def b/ext/pdo_sqlite/sqlite/sqlite3.def index c57ca68973..e42a0cd3d6 100644 --- a/ext/pdo_sqlite/sqlite/sqlite3.def +++ b/ext/pdo_sqlite/sqlite/sqlite3.def @@ -40,6 +40,7 @@ sqlite3_create_function sqlite3_create_function16 sqlite3_data_count sqlite3_db_handle +sqlite3_enable_shared_cache sqlite3_errcode sqlite3_errmsg sqlite3_errmsg16 @@ -75,13 +76,16 @@ sqlite3_result_text16 sqlite3_result_text16be sqlite3_result_text16le sqlite3_result_value +sqlite3_rollback_hook sqlite3_set_authorizer sqlite3_set_auxdata sqlite3_snprintf sqlite3_step +sqlite3_thread_cleanup sqlite3_total_changes sqlite3_trace sqlite3_transfer_bindings +sqlite3_update_hook sqlite3_user_data sqlite3_value_blob sqlite3_value_bytes diff --git a/ext/pdo_sqlite/sqlite/src/alter.c b/ext/pdo_sqlite/sqlite/src/alter.c index ada0769b5d..0d6bfbf9dc 100644 --- a/ext/pdo_sqlite/sqlite/src/alter.c +++ b/ext/pdo_sqlite/sqlite/src/alter.c @@ -47,7 +47,7 @@ static void renameTableFunc( int token; Token tname; - char const *zCsr = zSql; + unsigned char const *zCsr = zSql; int len = 0; char *zRet; @@ -96,7 +96,7 @@ static void renameTriggerFunc( int token; Token tname; int dist = 3; - char const *zCsr = zSql; + unsigned char const *zCsr = zSql; int len = 0; char *zRet; @@ -162,7 +162,7 @@ void sqlite3AlterFunctions(sqlite3 *db){ int i; for(i=0; iiDb!=1 ){ + 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 ){ for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){ - if( pTrig->iDb==1 ){ + if( pTrig->pSchema==pTempSchema ){ if( !zWhere ){ zWhere = sqlite3MPrintf("name=%Q", pTrig->name); }else{ @@ -204,20 +211,22 @@ static char *whereTempTriggers(Parse *pParse, Table *pTab){ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ Vdbe *v; char *zWhere; - int iDb; + int iDb; /* Index of database containing pTab */ #ifndef SQLITE_OMIT_TRIGGER Trigger *pTrig; #endif v = sqlite3GetVdbe(pParse); if( !v ) return; - iDb = pTab->iDb; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 ); #ifndef SQLITE_OMIT_TRIGGER /* Drop any table triggers from the internal schema. */ for(pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext){ - assert( pTrig->iDb==iDb || pTrig->iDb==1 ); - sqlite3VdbeOp3(v, OP_DropTrigger, pTrig->iDb, 0, pTrig->name, 0); + int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); + assert( iTrigDb==iDb || iTrigDb==1 ); + sqlite3VdbeOp3(v, OP_DropTrigger, iTrigDb, 0, pTrig->name, 0); } #endif @@ -233,7 +242,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ /* 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)) ){ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zWhere, P3_DYNAMIC); } #endif @@ -258,12 +267,18 @@ void sqlite3AlterRenameTable( char *zWhere = 0; /* Where clause to locate temp triggers */ #endif - if( sqlite3_malloc_failed ) goto exit_rename_table; + if( sqlite3MallocFailed() ) goto exit_rename_table; assert( pSrc->nSrc==1 ); pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); if( !pTab ) goto exit_rename_table; - iDb = pTab->iDb; +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); + goto exit_rename_table; + } +#endif + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); zDb = db->aDb[iDb].zName; /* Get a NULL terminated version of the new table name. */ @@ -349,7 +364,7 @@ void sqlite3AlterRenameTable( ** table. Don't do this if the table being ALTERed is itself located in ** the temp database. */ - if( (zWhere=whereTempTriggers(pParse, pTab)) ){ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ sqlite3NestedParse(pParse, "UPDATE sqlite_temp_master SET " "sql = sqlite_rename_trigger(sql, %Q), " @@ -385,13 +400,12 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ char *zCol; /* Null-terminated column definition */ Column *pCol; /* The new column */ Expr *pDflt; /* Default value for the new column */ - Vdbe *v; if( pParse->nErr ) return; pNew = pParse->pNewTable; assert( pNew ); - iDb = pNew->iDb; + iDb = sqlite3SchemaToIndex(pParse->db, pNew->pSchema); zDb = pParse->db->aDb[iDb].zName; zTab = pNew->zName; pCol = &pNew->aCol[pNew->nCol-1]; @@ -399,6 +413,13 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ pTab = sqlite3FindTable(pParse->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. @@ -442,7 +463,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ } /* Modify the CREATE TABLE statement. */ - zCol = sqliteStrNDup(pColDef->z, pColDef->n); + zCol = sqliteStrNDup((char*)pColDef->z, pColDef->n); if( zCol ){ char *zEnd = &zCol[pColDef->n-1]; while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){ @@ -462,22 +483,12 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ ** format to 2. If the default value of the new column is not NULL, ** the file format becomes 3. */ - if( (v=sqlite3GetVdbe(pParse)) ){ - int f = (pDflt?3:2); - - /* Only set the file format to $f if it is currently less than $f. */ - sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); - sqlite3VdbeAddOp(v, OP_Integer, f, 0); - sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp(v, OP_Integer, f, 0); - sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); - } + 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 @@ -501,13 +512,19 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ int i; int nAlloc; - /* Look up the table being altered. */ assert( pParse->pNewTable==0 ); - if( sqlite3_malloc_failed ) goto exit_begin_add_column; + if( sqlite3MallocFailed() ) goto exit_begin_add_column; pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); 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"); @@ -515,7 +532,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ } assert( pTab->addColOffset>0 ); - iDb = pTab->iDb; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); /* Put a copy of the Table struct in Parse.pNewTable for the ** sqlite3AddColumn() function and friends to modify. @@ -537,10 +554,11 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ for(i=0; inCol; i++){ Column *pCol = &pNew->aCol[i]; pCol->zName = sqliteStrDup(pCol->zName); + pCol->zColl = 0; pCol->zType = 0; pCol->pDflt = 0; } - pNew->iDb = iDb; + pNew->pSchema = pParse->db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; pNew->nRef = 1; diff --git a/ext/pdo_sqlite/sqlite/src/analyze.c b/ext/pdo_sqlite/sqlite/src/analyze.c index a6c92e9f6f..dc1f33286d 100644 --- a/ext/pdo_sqlite/sqlite/src/analyze.c +++ b/ext/pdo_sqlite/sqlite/src/analyze.c @@ -61,8 +61,14 @@ static void openStatTable( sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb); } - /* Open the sqlite_stat1 table for writing. + /* Open the sqlite_stat1 table for writing. Unless it was created + ** by this vdbe program, lock it for writing at the shared-cache level. + ** If this vdbe did create the sqlite_stat1 table, then it must have + ** already obtained a schema-lock, making the write-lock redundant. */ + if( iRootPage>0 ){ + sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1"); + } sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage); sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3); @@ -86,6 +92,7 @@ static void analyzeOneTable( int topOfLoop; /* The top of the loop */ int endOfLoop; /* The end of the loop */ int addr; /* The address of an instruction */ + int iDb; /* Index of database containing pTab */ v = sqlite3GetVdbe(pParse); if( pTab==0 || pTab->pIndex==0 ){ @@ -93,21 +100,29 @@ static void analyzeOneTable( return; } + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, - pParse->db->aDb[pTab->iDb].zName ) ){ + pParse->db->aDb[iDb].zName ) ){ return; } #endif + /* Establish a read-lock on the table at the shared-cache level. */ + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); + iIdxCur = pParse->nTab; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + /* Open a cursor to the index to be analyzed */ - sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); + assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); VdbeComment((v, "# %s", pIdx->zName)); sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, - (char*)&pIdx->keyInfo, P3_KEYINFO); + (char *)pKey, P3_KEYINFO_HANDOFF); nCol = pIdx->nColumn; if( iMem+nCol*2>=pParse->nMem ){ pParse->nMem = iMem+nCol*2+1; @@ -139,7 +154,7 @@ static void analyzeOneTable( endOfLoop = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, endOfLoop); topOfLoop = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp(v, OP_MemIncr, iMem, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, 1, iMem); for(i=0; idb; + Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ HashElem *k; int iStatCur; int iMem; @@ -222,7 +239,7 @@ static void analyzeDatabase(Parse *pParse, int iDb){ iStatCur = pParse->nTab++; openStatTable(pParse, iDb, iStatCur, 0); iMem = pParse->nMem; - for(k=sqliteHashFirst(&db->aDb[iDb].tblHash); k; k=sqliteHashNext(k)){ + for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); analyzeOneTable(pParse, pTab, iStatCur, iMem); } @@ -238,7 +255,7 @@ static void analyzeTable(Parse *pParse, Table *pTab){ int iStatCur; assert( pTab!=0 ); - iDb = pTab->iDb; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); sqlite3BeginWriteOperation(pParse, 0, iDb); iStatCur = pParse->nTab++; openStatTable(pParse, iDb, iStatCur, pTab->zName); @@ -360,7 +377,7 @@ void sqlite3AnalysisLoad(sqlite3 *db, int iDb){ char *zSql; /* Clear any prior statistics */ - for(i=sqliteHashFirst(&db->aDb[iDb].idxHash); i; i=sqliteHashNext(i)){ + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); sqlite3DefaultRowEst(pIdx); } diff --git a/ext/pdo_sqlite/sqlite/src/attach.c b/ext/pdo_sqlite/sqlite/src/attach.c index 46b653e975..10abc49014 100644 --- a/ext/pdo_sqlite/sqlite/src/attach.c +++ b/ext/pdo_sqlite/sqlite/src/attach.c @@ -16,196 +16,348 @@ #include "sqliteInt.h" /* -** This routine is called by the parser to process an ATTACH statement: +** 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. ** -** ATTACH DATABASE filename AS dbname +** i.e. if the parser sees: ** -** The pFilename and pDbname arguments are the tokens that define the -** filename and dbname in the ATTACH statement. +** 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. */ -void sqlite3Attach( - Parse *pParse, /* The parser context */ - Token *pFilename, /* Name of database file */ - Token *pDbname, /* Name of the database to use internally */ - int keyType, /* 0: no key. 1: TEXT, 2: BLOB */ - Token *pKey /* Text of the key for keytype 1 and 2 */ +static int resolveAttachExpr(NameContext *pName, Expr *pExpr) +{ + int rc = SQLITE_OK; + if( pExpr ){ + if( pExpr->op!=TK_ID ){ + rc = sqlite3ExprResolveNames(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 argc, + sqlite3_value **argv ){ + int i; + int rc = 0; + sqlite3 *db = sqlite3_user_data(context); + const char *zName; + const char *zFile; Db *aNew; - int rc, i; - char *zFile = 0; - char *zName = 0; - sqlite3 *db; - Vdbe *v; + char zErr[128]; + char *zErrDyn = 0; - v = sqlite3GetVdbe(pParse); - if( !v ) return; - sqlite3VdbeAddOp(v, OP_Expire, 1, 0); - sqlite3VdbeAddOp(v, OP_Halt, 0, 0); - if( pParse->explain ) return; - db = pParse->db; + 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>=MAX_ATTACHED+2 ){ - sqlite3ErrorMsg(pParse, "too many attached databases - max %d", - MAX_ATTACHED); - pParse->rc = SQLITE_ERROR; - return; + sqlite3_snprintf( + sizeof(zErr), zErr, "too many attached databases - max %d", MAX_ATTACHED + ); + goto attach_error; } - if( !db->autoCommit ){ - sqlite3ErrorMsg(pParse, "cannot ATTACH database within transaction"); - pParse->rc = SQLITE_ERROR; - return; - } - - zFile = sqlite3NameFromToken(pFilename); - if( zFile==0 ){ - goto attach_end; - } -#ifndef SQLITE_OMIT_AUTHORIZATION - if( sqlite3AuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){ - goto attach_end; - } -#endif /* SQLITE_OMIT_AUTHORIZATION */ - - zName = sqlite3NameFromToken(pDbname); - if( zName==0 ){ - goto attach_end; + strcpy(zErr, "cannot ATTACH database within transaction"); + goto attach_error; } for(i=0; inDb; i++){ char *z = db->aDb[i].zName; - if( z && sqlite3StrICmp(z, zName)==0 ){ - sqlite3ErrorMsg(pParse, "database %s is already in use", zName); - pParse->rc = SQLITE_ERROR; - goto attach_end; + if( z && zName && sqlite3StrICmp(z, zName)==0 ){ + sqlite3_snprintf(sizeof(zErr), zErr, "database %s is already in use", zName); + goto attach_error; } } + /* Allocate the new entry in the db->aDb[] array and initialise the schema + ** hash tables. + */ if( db->aDb==db->aDbStatic ){ aNew = sqliteMalloc( sizeof(db->aDb[0])*3 ); if( aNew==0 ){ - goto attach_end; + return; } memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); }else{ aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); if( aNew==0 ){ - goto attach_end; + return; } } db->aDb = aNew; aNew = &db->aDb[db->nDb++]; memset(aNew, 0, sizeof(*aNew)); - sqlite3HashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); - aNew->zName = zName; - zName = 0; - aNew->safety_level = 3; + + /* 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 initialised. + */ rc = sqlite3BtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt); - if( rc ){ - sqlite3ErrorMsg(pParse, "unable to open database: %s", zFile); + if( rc==SQLITE_OK ){ + aNew->pSchema = sqlite3SchemaGet(aNew->pBt); + if( !aNew->pSchema ){ + rc = SQLITE_NOMEM; + }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ + strcpy(zErr, + "attached databases must use the same text encoding as main database"); + goto attach_error; + } } + aNew->zName = sqliteStrDup(zName); + aNew->safety_level = 3; + #if SQLITE_HAS_CODEC { extern int sqlite3CodecAttach(sqlite3*, int, void*, int); - char *zKey; + extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); int nKey; - if( keyType==0 ){ - /* No key specified. Use the key from the main database */ - extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); - sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); - }else if( keyType==1 ){ - /* Key specified as text */ - zKey = sqlite3NameFromToken(pKey); - nKey = strlen(zKey); - }else{ - /* Key specified as a BLOB */ - char *zTemp; - assert( keyType==2 ); - pKey->z++; - pKey->n--; - zTemp = sqlite3NameFromToken(pKey); - zKey = sqlite3HexToBlob(zTemp); - sqliteFree(zTemp); - } - sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); - if( keyType ){ - sqliteFree(zKey); + char *zKey; + int t = sqlite3_value_type(argv[2]); + switch( t ){ + case SQLITE_INTEGER: + case SQLITE_FLOAT: + zErrDyn = sqliteStrDup("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]); + 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); + sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); + break; } } #endif - db->flags &= ~SQLITE_Initialized; - if( pParse->nErr==0 && rc==SQLITE_OK ){ - rc = sqlite3ReadSchema(pParse); + + /* 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 ){ + sqlite3SafetyOn(db); + rc = sqlite3Init(db, &zErrDyn); + sqlite3SafetyOff(db); } if( rc ){ - int i = db->nDb - 1; - assert( i>=2 ); - if( db->aDb[i].pBt ){ - sqlite3BtreeClose(db->aDb[i].pBt); - db->aDb[i].pBt = 0; + 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; } sqlite3ResetInternalSchema(db, 0); - assert( pParse->nErr>0 ); /* Always set by sqlite3ReadSchema() */ - if( pParse->rc==SQLITE_OK ){ - pParse->rc = SQLITE_ERROR; + db->nDb = iDb; + if( rc==SQLITE_NOMEM ){ + if( !sqlite3MallocFailed() ) sqlite3FailedMalloc(); + sqlite3_snprintf(sizeof(zErr),zErr, "out of memory"); + }else{ + sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile); } + goto attach_error; } + + return; -attach_end: - sqliteFree(zFile); - sqliteFree(zName); +attach_error: + /* Return an error if we get here */ + if( zErrDyn ){ + sqlite3_result_error(context, zErrDyn, -1); + sqliteFree(zErrDyn); + }else{ + zErr[sizeof(zErr)-1] = 0; + sqlite3_result_error(context, zErr, -1); + } } /* -** This routine is called by the parser to process a DETACH statement: +** 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 dbname +** DETACH DATABASE x ** -** The pDbname argument is the name of the database in the DETACH statement. +** SELECT sqlite_detach(x) */ -void sqlite3Detach(Parse *pParse, Token *pDbname){ +static void detachFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zName = (const char *)sqlite3_value_text(argv[0]); + sqlite3 *db = sqlite3_user_data(context); int i; - sqlite3 *db; - Vdbe *v; Db *pDb = 0; - char *zName; + char zErr[128]; - v = sqlite3GetVdbe(pParse); - if( !v ) return; - sqlite3VdbeAddOp(v, OP_Expire, 0, 0); - sqlite3VdbeAddOp(v, OP_Halt, 0, 0); - if( pParse->explain ) return; - db = pParse->db; - zName = sqlite3NameFromToken(pDbname); - if( zName==0 ) return; + 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 ){ - sqlite3ErrorMsg(pParse, "no such database: %z", zName); - return; + sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName); + goto detach_error; } if( i<2 ){ - sqlite3ErrorMsg(pParse, "cannot detach database %z", zName); - return; + sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName); + goto detach_error; } - sqliteFree(zName); if( !db->autoCommit ){ - sqlite3ErrorMsg(pParse, "cannot DETACH database within transaction"); - pParse->rc = SQLITE_ERROR; - return; + strcpy(zErr, "cannot DETACH database within transaction"); + goto detach_error; } -#ifndef SQLITE_OMIT_AUTHORIZATION - if( sqlite3AuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){ - return; + if( sqlite3BtreeIsInReadTrans(pDb->pBt) ){ + sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName); + goto detach_error; } -#endif /* SQLITE_OMIT_AUTHORIZATION */ + sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; + pDb->pSchema = 0; sqlite3ResetInternalSchema(db, 0); + 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 */ + const char *zFunc, /* Either "sqlite_attach" or "sqlite_detach */ + int nFunc, /* Number of args to pass to zFunc */ + 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; + FuncDef *pFunc; + sqlite3* db = pParse->db; + +#ifndef SQLITE_OMIT_AUTHORIZATION + assert( sqlite3MallocFailed() || pAuthArg ); + if( pAuthArg ){ + char *zAuthArg = sqlite3NameFromToken(&pAuthArg->span); + if( !zAuthArg ){ + goto attach_end; + } + rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); + sqliteFree(zAuthArg); + if(rc!=SQLITE_OK ){ + goto attach_end; + } + } +#endif /* SQLITE_OMIT_AUTHORIZATION */ + + 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)) + ){ + pParse->nErr++; + goto attach_end; + } + + v = sqlite3GetVdbe(pParse); + sqlite3ExprCode(pParse, pFilename); + sqlite3ExprCode(pParse, pDbname); + sqlite3ExprCode(pParse, pKey); + + assert( v || sqlite3MallocFailed() ); + if( v ){ + sqlite3VdbeAddOp(v, OP_Function, 0, nFunc); + pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0); + sqlite3VdbeChangeP3(v, -1, (char *)pFunc, P3_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). + */ + sqlite3VdbeAddOp(v, OP_Expire, (type==SQLITE_ATTACH), 0); + } + +attach_end: + sqlite3ExprDelete(pFilename); + sqlite3ExprDelete(pDbname); + sqlite3ExprDelete(pKey); +} + +/* +** Called by the parser to compile a DETACH statement. +** +** DETACH pDbname +*/ +void sqlite3Detach(Parse *pParse, Expr *pDbname){ + codeAttach(pParse, SQLITE_DETACH, "sqlite_detach", 1, pDbname, 0, 0, pDbname); +} + +/* +** Called by the parser to compile an ATTACH statement. +** +** ATTACH p AS pDbname KEY pKey +*/ +void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ + codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, pKey); +} + +/* +** Register the functions sqlite_attach and sqlite_detach. +*/ +void sqlite3AttachFunctions(sqlite3 *db){ + static const int enc = SQLITE_UTF8; + sqlite3CreateFunc(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0); + sqlite3CreateFunc(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 0); } /* diff --git a/ext/pdo_sqlite/sqlite/src/auth.c b/ext/pdo_sqlite/sqlite/src/auth.c index 693baa2c89..3983c1bc69 100644 --- a/ext/pdo_sqlite/sqlite/src/auth.c +++ b/ext/pdo_sqlite/sqlite/src/auth.c @@ -112,10 +112,17 @@ void sqlite3AuthRead( int iSrc; /* Index in pTabList->a[] of table being read */ const char *zDBase; /* Name of database being accessed */ TriggerStack *pStack; /* The stack of current triggers */ + int iDb; /* The index of the database the expression refers to */ if( db->xAuth==0 ) return; if( pExpr->op==TK_AS ) return; assert( pExpr->op==TK_COLUMN ); + iDb = sqlite3SchemaToIndex(pParse->db, pExpr->pSchema); + if( iDb<0 ){ + /* An attempt to read a column out of a subquery or other + ** temporary table. */ + return; + } for(iSrc=0; pTabList && iSrcnSrc; iSrc++){ if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; } @@ -140,14 +147,14 @@ void sqlite3AuthRead( }else{ zCol = "ROWID"; } - assert( pExpr->iDbnDb ); - zDBase = db->aDb[pExpr->iDb].zName; + assert( iDb>=0 && iDbnDb ); + zDBase = db->aDb[iDb].zName; rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, pParse->zAuthContext); if( rc==SQLITE_IGNORE ){ pExpr->op = TK_NULL; }else if( rc==SQLITE_DENY ){ - if( db->nDb>2 || pExpr->iDb!=0 ){ + if( db->nDb>2 || iDb!=0 ){ sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited", zDBase, pTab->zName, zCol); }else{ @@ -175,8 +182,10 @@ int sqlite3AuthCheck( sqlite3 *db = pParse->db; int rc; - /* Don't do any authorization checks if the database is initialising. */ - if( db->init.busy ){ + /* 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; } diff --git a/ext/pdo_sqlite/sqlite/src/btree.c b/ext/pdo_sqlite/sqlite/src/btree.c index f1ef6a2a4c..52bc749a32 100644 --- a/ext/pdo_sqlite/sqlite/src/btree.c +++ b/ext/pdo_sqlite/sqlite/src/btree.c @@ -230,6 +230,7 @@ /* Forward declarations */ typedef struct MemPage MemPage; +typedef struct BtLock BtLock; /* ** This is a magic string that appears at the beginning of every @@ -285,10 +286,10 @@ struct MemPage { u16 nFree; /* Number of free bytes on the page */ u16 nCell; /* Number of cells on this page, local and ovfl */ struct _OvflCell { /* Cells that will not fit on aData[] */ - u8 *pCell; /* Pointers to the body of the overflow cell */ - u16 idx; /* Insert this cell before idx-th non-overflow cell */ + u8 *pCell; /* Pointers to the body of the overflow cell */ + u16 idx; /* Insert this cell before idx-th non-overflow cell */ } aOvfl[5]; - struct Btree *pBt; /* Pointer back to BTree structure */ + BtShared *pBt; /* Pointer back to BTree structure */ u8 *aData; /* Pointer back to the start of the page */ Pgno pgno; /* Page number for this page */ MemPage *pParent; /* The parent of this page. NULL for root */ @@ -301,14 +302,32 @@ struct MemPage { */ #define EXTRA_SIZE sizeof(MemPage) +/* Btree handle */ +struct Btree { + sqlite3 *pSqlite; + BtShared *pBt; + u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ +}; + +/* +** 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. Variable Btree.pDb +** points to the handle that owns any current write-transaction. +*/ +#define TRANS_NONE 0 +#define TRANS_READ 1 +#define TRANS_WRITE 2 + /* ** Everything we need to know about an open database */ -struct Btree { +struct BtShared { Pager *pPager; /* The page cache */ BtCursor *pCursor; /* A list of all open cursors */ MemPage *pPage1; /* First page of the database */ - u8 inTrans; /* True if a transaction is in progress */ u8 inStmt; /* True if we are in a statement subtransaction */ u8 readOnly; /* True if the underlying file is readonly */ u8 maxEmbedFrac; /* Maximum payload as % of total page size */ @@ -325,15 +344,16 @@ struct Btree { int maxLeaf; /* Maximum local payload in a LEAFDATA table */ int minLeaf; /* Minimum local payload in a LEAFDATA table */ BusyHandler *pBusyHandler; /* Callback for when there is lock contention */ + u8 inTransaction; /* Transaction state */ + int nRef; /* Number of references to this structure */ + int nTransaction; /* Number of open transactions (read + write) */ + void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ + void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ +#ifndef SQLITE_OMIT_SHARED_CACHE + BtLock *pLock; /* List of locks held on this shared-btree struct */ + BtShared *pNext; /* Next in ThreadData.pBtree linked list */ +#endif }; -typedef Btree Bt; - -/* -** Btree.inTrans may take one of the following values. -*/ -#define TRANS_NONE 0 -#define TRANS_READ 1 -#define TRANS_WRITE 2 /* ** An instance of the following structure is used to hold information @@ -357,7 +377,7 @@ struct CellInfo { ** MemPage.aCell[] of the entry. */ struct BtCursor { - Btree *pBt; /* The Btree to which this cursor belongs */ + Btree *pBtree; /* The Btree to which this cursor belongs */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */ void *pArg; /* First arg to xCompare() */ @@ -366,9 +386,38 @@ struct BtCursor { int idx; /* Index of the entry in pPage->aCell[] */ CellInfo info; /* A parse of the cell we are pointing at */ u8 wrFlag; /* True if writable */ - u8 isValid; /* TRUE if points to a valid entry */ + u8 eState; /* One of the CURSOR_XXX constants (see below) */ +#ifndef SQLITE_OMIT_SHARED_CACHE + void *pKey; /* Saved key that was cursor's last known position */ + i64 nKey; /* Size of pKey, or last integer key */ + int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */ +#endif }; +/* +** Potential values for BtCursor.eState. The first two values (VALID and +** INVALID) may occur in any build. The third (REQUIRESEEK) may only occur +** if sqlite was compiled without the OMIT_SHARED_CACHE symbol defined. +** +** CURSOR_VALID: +** Cursor points to a valid entry. getPayload() etc. may be called. +** +** 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_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, restoreOrClearCursorPosition() can be called to attempt to +** seek the cursor to the saved position. +*/ +#define CURSOR_INVALID 0 +#define CURSOR_VALID 1 +#define CURSOR_REQUIRESEEK 2 + /* ** The TRACE macro will print high-level status information about the ** btree operation when the global variable sqlite3_btree_trace is @@ -377,15 +426,15 @@ struct BtCursor { #if SQLITE_TEST # define TRACE(X) if( sqlite3_btree_trace )\ { sqlite3DebugPrintf X; fflush(stdout); } +int sqlite3_btree_trace=0; /* True to enable tracing */ #else # define TRACE(X) #endif -int sqlite3_btree_trace=0; /* True to enable tracing */ /* ** Forward declaration */ -static int checkReadLocks(Btree*,Pgno,BtCursor*); +static int checkReadLocks(BtShared*,Pgno,BtCursor*); /* ** Read or write a two- and four-byte big-endian integer values. @@ -413,14 +462,290 @@ static void put4byte(unsigned char *p, u32 v){ ** file. */ #define getVarint sqlite3GetVarint -#define getVarint32 sqlite3GetVarint32 +/* #define getVarint32 sqlite3GetVarint32 */ +#define getVarint32(A,B) ((*B=*(A))<=0x7f?1:sqlite3GetVarint32(A,B)) #define putVarint sqlite3PutVarint /* The database page the PENDING_BYTE occupies. This page is never used. ** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They ** should possibly be consolidated (presumably in pager.h). +** +** If disk I/O is omitted (meaning that the database is stored purely +** in memory) then there is no pending byte. +*/ +#ifdef SQLITE_OMIT_DISKIO +# define PENDING_BYTE_PAGE(pBt) 0x7fffffff +#else +# define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1) +#endif + +/* +** 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 + +#ifdef SQLITE_OMIT_SHARED_CACHE + /* + ** The functions queryTableLock(), lockTable() and unlockAllTables() + ** 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 queryTableLock(a,b,c) SQLITE_OK + #define lockTable(a,b,c) SQLITE_OK + #define unlockAllTables(a) + #define restoreOrClearCursorPosition(a,b) SQLITE_OK + #define saveAllCursors(a,b,c) SQLITE_OK + +#else + +static void releasePage(MemPage *pPage); + +/* +** Save the current cursor position in the variables BtCursor.nKey +** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. +*/ +static int saveCursorPosition(BtCursor *pCur){ + int rc; + + assert( CURSOR_VALID==pCur->eState ); + assert( 0==pCur->pKey ); + + rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); + + /* 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( rc==SQLITE_OK && 0==pCur->pPage->intKey){ + void *pKey = sqliteMalloc(pCur->nKey); + if( pKey ){ + rc = sqlite3BtreeKey(pCur, 0, pCur->nKey, pKey); + if( rc==SQLITE_OK ){ + pCur->pKey = pKey; + }else{ + sqliteFree(pKey); + } + }else{ + rc = SQLITE_NOMEM; + } + } + assert( !pCur->pPage->intKey || !pCur->pKey ); + + if( rc==SQLITE_OK ){ + releasePage(pCur->pPage); + pCur->pPage = 0; + pCur->eState = CURSOR_REQUIRESEEK; + } + + return rc; +} + +/* +** Save the positions of all cursors except pExcept open on the table +** with root-page iRoot. Usually, this is called just before cursor +** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). +*/ +static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ + BtCursor *p; + if( sqlite3ThreadDataReadOnly()->useSharedData ){ + for(p=pBt->pCursor; p; p=p->pNext){ + if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && + p->eState==CURSOR_VALID ){ + int rc = saveCursorPosition(p); + if( SQLITE_OK!=rc ){ + return rc; + } + } + } + } + return SQLITE_OK; +} + +/* +** 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 restoreOrClearCursorPosition() call after each +** saveCursorPosition(). +** +** If the second argument argument - doSeek - is false, then instead of +** returning the cursor to it's saved position, any saved position is deleted +** and the cursor state set to CURSOR_INVALID. +*/ +static int restoreOrClearCursorPositionX(BtCursor *pCur, int doSeek){ + int rc = SQLITE_OK; + assert( sqlite3ThreadDataReadOnly()->useSharedData ); + assert( pCur->eState==CURSOR_REQUIRESEEK ); + pCur->eState = CURSOR_INVALID; + if( doSeek ){ + rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip); + } + if( rc==SQLITE_OK ){ + sqliteFree(pCur->pKey); + pCur->pKey = 0; + assert( CURSOR_VALID==pCur->eState || CURSOR_INVALID==pCur->eState ); + } + return rc; +} + +#define restoreOrClearCursorPosition(p,x) \ + (p->eState==CURSOR_REQUIRESEEK?restoreOrClearCursorPositionX(p,x):SQLITE_OK) + +/* +** 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 lockTable()), or +** SQLITE_LOCKED if not. +*/ +static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ + BtShared *pBt = p->pBt; + BtLock *pIter; + + /* This is a no-op if the shared-cache is not enabled */ + if( 0==sqlite3ThreadDataReadOnly()->useSharedData ){ + return SQLITE_OK; + } + + /* This (along with lockTable()) is where the ReadUncommitted flag is + ** dealt with. If the caller is querying for a read-lock and the flag is + ** set, it is unconditionally granted - even if there are write-locks + ** on the table. If a write-lock is requested, the ReadUncommitted flag + ** is not considered. + ** + ** In function lockTable(), if a read-lock is demanded and the + ** ReadUncommitted flag is set, no entry is added to the locks list + ** (BtShared.pLock). + ** + ** To summarize: If the ReadUncommitted flag is set, then read cursors do + ** not create or respect table locks. The locking procedure for a + ** write-cursor does not change. + */ + if( + !p->pSqlite || + 0==(p->pSqlite->flags&SQLITE_ReadUncommitted) || + eLock==WRITE_LOCK || + iTab==MASTER_ROOT + ){ + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->pBtree!=p && pIter->iTable==iTab && + (pIter->eLock!=eLock || eLock!=READ_LOCK) ){ + return SQLITE_LOCKED; + } + } + } + return SQLITE_OK; +} + +/* +** 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. +** +** SQLITE_OK is returned if the lock is added successfully. SQLITE_BUSY and +** SQLITE_NOMEM may also be returned. */ -#define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1) +static int lockTable(Btree *p, Pgno iTable, u8 eLock){ + BtShared *pBt = p->pBt; + BtLock *pLock = 0; + BtLock *pIter; + + /* This is a no-op if the shared-cache is not enabled */ + if( 0==sqlite3ThreadDataReadOnly()->useSharedData ){ + return SQLITE_OK; + } + + assert( SQLITE_OK==queryTableLock(p, iTable, eLock) ); + + /* If the read-uncommitted flag is set and a read-lock is requested, + ** return early without adding an entry to the BtShared.pLock list. See + ** comment in function queryTableLock() for more info on handling + ** the ReadUncommitted flag. + */ + if( + (p->pSqlite) && + (p->pSqlite->flags&SQLITE_ReadUncommitted) && + (eLock==READ_LOCK) && + iTable!=MASTER_ROOT + ){ + return SQLITE_OK; + } + + /* 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 *)sqliteMalloc(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; +} + +/* +** Release all the table locks (locks obtained via calls to the lockTable() +** procedure) held by Btree handle p. +*/ +static void unlockAllTables(Btree *p){ + BtLock **ppIter = &p->pBt->pLock; + + /* If the shared-cache extension is not enabled, there should be no + ** locks in the BtShared.pLock list, making this procedure a no-op. Assert + ** that this is the case. + */ + assert( sqlite3ThreadDataReadOnly()->useSharedData || 0==*ppIter ); + + while( *ppIter ){ + BtLock *pLock = *ppIter; + if( pLock->pBtree==p ){ + *ppIter = pLock->pNext; + sqliteFree(pLock); + }else{ + ppIter = &pLock->pNext; + } + } +} +#endif /* SQLITE_OMIT_SHARED_CACHE */ #ifndef SQLITE_OMIT_AUTOVACUUM /* @@ -438,9 +763,19 @@ static void put4byte(unsigned char *p, u32 v){ ** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements ** this test. */ -#define PTRMAP_PAGENO(pgsz, pgno) (((pgno-2)/(pgsz/5+1))*(pgsz/5+1)+2) -#define PTRMAP_PTROFFSET(pgsz, pgno) (((pgno-2)%(pgsz/5+1)-1)*5) -#define PTRMAP_ISPAGE(pgsz, pgno) (PTRMAP_PAGENO(pgsz,pgno)==pgno) +#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno) +#define PTRMAP_PTROFFSET(pBt, pgno) (5*(pgno-ptrmapPageno(pBt, pgno)-1)) +#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno)) + +static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ + int nPagesPerMapPage = (pBt->usableSize/5)+1; + int iPtrMap = (pgno-2)/nPagesPerMapPage; + int ret = (iPtrMap*nPagesPerMapPage) + 2; + if( ret==PENDING_BYTE_PAGE(pBt) ){ + ret++; + } + return ret; +} /* ** The pointer map is a lookup table that identifies the parent page for @@ -486,22 +821,25 @@ static void put4byte(unsigned char *p, u32 v){ ** so that it maps to type 'eType' and parent page number 'pgno'. ** An error code is returned if something goes wrong, otherwise SQLITE_OK. */ -static int ptrmapPut(Btree *pBt, Pgno key, u8 eType, Pgno parent){ +static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ u8 *pPtrmap; /* The pointer map page */ Pgno iPtrmap; /* The pointer map page number */ int offset; /* Offset in pointer map page */ int rc; + /* 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 ){ return SQLITE_CORRUPT_BKPT; } - iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key); + iPtrmap = PTRMAP_PAGENO(pBt, key); rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap); if( rc!=SQLITE_OK ){ return rc; } - offset = PTRMAP_PTROFFSET(pBt->usableSize, key); + offset = PTRMAP_PTROFFSET(pBt, key); if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); @@ -523,20 +861,21 @@ static int ptrmapPut(Btree *pBt, Pgno key, u8 eType, Pgno parent){ ** 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(Btree *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ +static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ int iPtrmap; /* Pointer map page index */ u8 *pPtrmap; /* Pointer map page data */ int offset; /* Offset of entry in pointer map */ int rc; - iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key); + iPtrmap = PTRMAP_PAGENO(pBt, key); rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap); if( rc!=0 ){ return rc; } - offset = PTRMAP_PTROFFSET(pBt->usableSize, key); - if( pEType ) *pEType = pPtrmap[offset]; + offset = PTRMAP_PTROFFSET(pBt, key); + assert( pEType!=0 ); + *pEType = pPtrmap[offset]; if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); sqlite3pager_unref(pPtrmap); @@ -604,12 +943,16 @@ static void parseCellPtr( }else{ nPayload = 0; } - n += getVarint(&pCell[n], (u64 *)&pInfo->nKey); - pInfo->nHeader = n; pInfo->nData = nPayload; - if( !pPage->intKey ){ - nPayload += pInfo->nKey; + if( pPage->intKey ){ + n += getVarint(&pCell[n], (u64 *)&pInfo->nKey); + }else{ + u32 x; + n += getVarint32(&pCell[n], &x); + pInfo->nKey = x; + nPayload += x; } + pInfo->nHeader = n; if( nPayload<=pPage->maxLocal ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. @@ -790,10 +1133,20 @@ static void _pageIntegrity(MemPage *pPage){ # define pageIntegrity(X) #endif +/* A bunch of assert() statements to check the transaction state variables +** of handle p (type Btree*) are internally consistent. +*/ +#define btreeIntegrity(p) \ + assert( p->inTrans!=TRANS_NONE || p->pBt->nTransactionpBt->nRef ); \ + assert( p->pBt->nTransaction<=p->pBt->nRef ); \ + assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \ + assert( p->pBt->inTransaction>=p->inTrans ); + /* ** Defragment the page given. All Cells are moved to the -** beginning of the page and all free space is collected -** into one big FreeBlk at the end of the page. +** 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. */ static int defragmentPage(MemPage *pPage){ int i; /* Loop counter */ @@ -928,6 +1281,12 @@ static void freeSpace(MemPage *pPage, int start, int size){ assert( (start + size)<=pPage->pBt->usableSize ); if( size<4 ) size = 4; +#ifdef SQLITE_SECURE_DELETE + /* Overwrite deleted information with zeros when the SECURE_DELETE + ** option is enabled at compile-time */ + memset(&data[start], 0, size); +#endif + /* Add the space back into the linked list of freeblocks */ hdr = pPage->hdrOffset; addr = hdr + 1; @@ -977,7 +1336,7 @@ static void freeSpace(MemPage *pPage, int start, int size){ ** and initialize fields of the MemPage structure accordingly. */ static void decodeFlags(MemPage *pPage, int flagByte){ - Btree *pBt; /* A copy of pPage->pBt */ + BtShared *pBt; /* A copy of pPage->pBt */ assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0; @@ -1017,7 +1376,7 @@ static int initPage( int pc; /* Address of a freeblock within pPage->aData[] */ int hdr; /* Offset to beginning of page header */ u8 *data; /* Equal to pPage->aData */ - Btree *pBt; /* The main btree structure */ + BtShared *pBt; /* The main btree structure */ int usableSize; /* Amount of usable space on each page */ int cellOffset; /* Offset from start of page to first cell pointer */ int nFree; /* Number of unused bytes on the page */ @@ -1090,7 +1449,7 @@ static int initPage( */ static void zeroPage(MemPage *pPage, int flags){ unsigned char *data = pPage->aData; - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; int hdr = pPage->hdrOffset; int first; @@ -1118,7 +1477,7 @@ static void zeroPage(MemPage *pPage, int flags){ ** Get a page from the pager. Initialize the MemPage.pBt and ** MemPage.aData elements if needed. */ -static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){ +static int getPage(BtShared *pBt, Pgno pgno, MemPage **ppPage){ int rc; unsigned char *aData; MemPage *pPage; @@ -1139,7 +1498,7 @@ static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){ ** getPage() and initPage(). */ static int getAndInitPage( - Btree *pBt, /* The database file */ + BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage, /* Write the page pointer here */ MemPage *pParent /* Parent of the page */ @@ -1212,21 +1571,69 @@ static void pageReinit(void *pData, int pageSize){ */ int sqlite3BtreeOpen( const char *zFilename, /* Name of the file containing the BTree database */ + sqlite3 *pSqlite, /* Associated database handle */ Btree **ppBtree, /* Pointer to new Btree object written here */ int flags /* Options */ ){ - Btree *pBt; + BtShared *pBt; /* Shared part of btree structure */ + Btree *p; /* Handle to return */ int rc; int nReserve; unsigned char zDbHeader[100]; +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + const ThreadData *pTsdro; +#endif + + /* Set the variable isMemdb to true for an in-memory database, or + ** false for a file-based database. This symbol is only required if + ** either of the shared-data or autovacuum features are compiled + ** into the library. + */ +#if !defined(SQLITE_OMIT_SHARED_CACHE) || !defined(SQLITE_OMIT_AUTOVACUUM) + #ifdef SQLITE_OMIT_MEMORYDB + const int isMemdb = !zFilename; + #else + const int isMemdb = !zFilename || (strcmp(zFilename, ":memory:")?0:1); + #endif +#endif + + p = sqliteMalloc(sizeof(Btree)); + if( !p ){ + return SQLITE_NOMEM; + } + p->inTrans = TRANS_NONE; + p->pSqlite = pSqlite; + + /* Try to find an existing Btree structure opened on zFilename. */ +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + pTsdro = sqlite3ThreadDataReadOnly(); + if( pTsdro->useSharedData && zFilename && !isMemdb ){ + char *zFullPathname = sqlite3OsFullPathname(zFilename); + if( !zFullPathname ){ + sqliteFree(p); + return SQLITE_NOMEM; + } + for(pBt=pTsdro->pBtree; pBt; pBt=pBt->pNext){ + assert( pBt->nRef>0 ); + if( 0==strcmp(zFullPathname, sqlite3pager_filename(pBt->pPager)) ){ + p->pBt = pBt; + *ppBtree = p; + pBt->nRef++; + sqliteFree(zFullPathname); + return SQLITE_OK; + } + } + sqliteFree(zFullPathname); + } +#endif /* ** 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(i64)==8 || sizeof(i64)==4 ); + assert( sizeof(u64)==8 || sizeof(u64)==4 ); assert( sizeof(u32)==4 ); assert( sizeof(u16)==2 ); assert( sizeof(Pgno)==4 ); @@ -1234,15 +1641,19 @@ int sqlite3BtreeOpen( pBt = sqliteMalloc( sizeof(*pBt) ); if( pBt==0 ){ *ppBtree = 0; + sqliteFree(p); return SQLITE_NOMEM; } rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, flags); if( rc!=SQLITE_OK ){ if( pBt->pPager ) sqlite3pager_close(pBt->pPager); sqliteFree(pBt); + sqliteFree(p); *ppBtree = 0; return rc; } + p->pBt = pBt; + sqlite3pager_set_destructor(pBt->pPager, pageDestructor); sqlite3pager_set_reiniter(pBt->pPager, pageReinit); pBt->pCursor = 0; @@ -1263,11 +1674,7 @@ int sqlite3BtreeOpen( ** then ":memory:" is just a regular file-name. Respect the auto-vacuum ** default in this case. */ -#ifndef SQLITE_OMIT_MEMORYDB - if( zFilename && strcmp(zFilename,":memory:") ){ -#else - if( zFilename ){ -#endif + if( zFilename && !isMemdb ){ pBt->autoVacuum = SQLITE_DEFAULT_AUTOVACUUM; } #endif @@ -1285,18 +1692,87 @@ int sqlite3BtreeOpen( pBt->usableSize = pBt->pageSize - nReserve; assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize); - *ppBtree = pBt; + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* Add the new btree to the linked list starting at ThreadData.pBtree. + ** There is no chance that a malloc() may fail inside of the + ** sqlite3ThreadData() call, as the ThreadData structure must have already + ** been allocated for pTsdro->useSharedData to be non-zero. + */ + if( pTsdro->useSharedData && zFilename && !isMemdb ){ + pBt->pNext = pTsdro->pBtree; + sqlite3ThreadData()->pBtree = pBt; + } +#endif + pBt->nRef = 1; + *ppBtree = p; return SQLITE_OK; } /* ** Close an open database and invalidate all cursors. */ -int sqlite3BtreeClose(Btree *pBt){ - while( pBt->pCursor ){ - sqlite3BtreeCloseCursor(pBt->pCursor); +int sqlite3BtreeClose(Btree *p){ + BtShared *pBt = p->pBt; + BtCursor *pCur; + +#ifndef SQLITE_OMIT_SHARED_CACHE + ThreadData *pTsd; +#endif + + /* Close all cursors opened via this handle. */ + 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); + sqliteFree(p); + +#ifndef SQLITE_OMIT_SHARED_CACHE + /* 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( pBt->nRef>0 ); + pBt->nRef--; + if( pBt->nRef ){ + return SQLITE_OK; } + + /* Remove the shared-btree from the thread wide list. Call + ** ThreadDataReadOnly() and then cast away the const property of the + ** pointer to avoid allocating thread data if it is not really required. + */ + pTsd = (ThreadData *)sqlite3ThreadDataReadOnly(); + if( pTsd->pBtree==pBt ){ + assert( pTsd==sqlite3ThreadData() ); + pTsd->pBtree = pBt->pNext; + }else{ + BtShared *pPrev; + for(pPrev=pTsd->pBtree; pPrev && pPrev->pNext!=pBt; pPrev=pPrev->pNext){} + if( pPrev ){ + assert( pTsd==sqlite3ThreadData() ); + pPrev->pNext = pBt->pNext; + } + } +#endif + + /* Close the pager and free the shared-btree structure */ + assert( !pBt->pCursor ); sqlite3pager_close(pBt->pPager); + if( pBt->xFreeSchema && pBt->pSchema ){ + pBt->xFreeSchema(pBt->pSchema); + } + sqliteFree(pBt->pSchema); sqliteFree(pBt); return SQLITE_OK; } @@ -1304,7 +1780,8 @@ int sqlite3BtreeClose(Btree *pBt){ /* ** Change the busy handler callback function. */ -int sqlite3BtreeSetBusyHandler(Btree *pBt, BusyHandler *pHandler){ +int sqlite3BtreeSetBusyHandler(Btree *p, BusyHandler *pHandler){ + BtShared *pBt = p->pBt; pBt->pBusyHandler = pHandler; sqlite3pager_set_busyhandler(pBt->pPager, pHandler); return SQLITE_OK; @@ -1325,7 +1802,8 @@ int sqlite3BtreeSetBusyHandler(Btree *pBt, BusyHandler *pHandler){ ** Synchronous is on by default so database corruption is not ** normally a worry. */ -int sqlite3BtreeSetCacheSize(Btree *pBt, int mxPage){ +int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ + BtShared *pBt = p->pBt; sqlite3pager_set_cachesize(pBt->pPager, mxPage); return SQLITE_OK; } @@ -1339,8 +1817,9 @@ int sqlite3BtreeSetCacheSize(Btree *pBt, int mxPage){ ** probability of damage to near zero but with a write performance reduction. */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS -int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){ - sqlite3pager_set_safety_level(pBt->pPager, level); +int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ + BtShared *pBt = p->pBt; + sqlite3pager_set_safety_level(pBt->pPager, level, fullSync); return SQLITE_OK; } #endif @@ -1349,7 +1828,8 @@ int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){ ** Return TRUE if the given btree is set to safety level 1. In other ** words, return TRUE if no sync() occurs on the disk files. */ -int sqlite3BtreeSyncDisabled(Btree *pBt){ +int sqlite3BtreeSyncDisabled(Btree *p){ + BtShared *pBt = p->pBt; assert( pBt && pBt->pPager ); return sqlite3pager_nosync(pBt->pPager); } @@ -1370,7 +1850,8 @@ int sqlite3BtreeSyncDisabled(Btree *pBt){ ** If parameter nReserve is less than zero, then the number of reserved ** bytes per page is left unchanged. */ -int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){ +int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve){ + BtShared *pBt = p->pBt; if( pBt->pageSizeFixed ){ return SQLITE_READONLY; } @@ -1380,6 +1861,7 @@ int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){ if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && ((pageSize-1)&pageSize)==0 ){ assert( (pageSize & 7)==0 ); + assert( !pBt->pPage1 && !pBt->pCursor ); pBt->pageSize = sqlite3pager_set_pagesize(pBt->pPager, pageSize); } pBt->usableSize = pBt->pageSize - nReserve; @@ -1389,11 +1871,11 @@ int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){ /* ** Return the currently defined page size */ -int sqlite3BtreeGetPageSize(Btree *pBt){ - return pBt->pageSize; +int sqlite3BtreeGetPageSize(Btree *p){ + return p->pBt->pageSize; } -int sqlite3BtreeGetReserve(Btree *pBt){ - return pBt->pageSize - pBt->usableSize; +int sqlite3BtreeGetReserve(Btree *p){ + return p->pBt->pageSize - p->pBt->usableSize; } #endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ @@ -1403,7 +1885,8 @@ int sqlite3BtreeGetReserve(Btree *pBt){ ** is disabled. The default value for the auto-vacuum property is ** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. */ -int sqlite3BtreeSetAutoVacuum(Btree *pBt, int autoVacuum){ +int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){ + BtShared *pBt = p->pBt;; #ifdef SQLITE_OMIT_AUTOVACUUM return SQLITE_READONLY; #else @@ -1419,11 +1902,11 @@ int sqlite3BtreeSetAutoVacuum(Btree *pBt, int autoVacuum){ ** Return the value of the 'auto-vacuum' property. If auto-vacuum is ** enabled 1 is returned. Otherwise 0. */ -int sqlite3BtreeGetAutoVacuum(Btree *pBt){ +int sqlite3BtreeGetAutoVacuum(Btree *p){ #ifdef SQLITE_OMIT_AUTOVACUUM return 0; #else - return pBt->autoVacuum; + return p->pBt->autoVacuum; #endif } @@ -1438,7 +1921,7 @@ int sqlite3BtreeGetAutoVacuum(Btree *pBt){ ** is returned if we run out of memory. SQLITE_PROTOCOL is returned ** if there is a locking protocol violation. */ -static int lockBtree(Btree *pBt){ +static int lockBtree(BtShared *pBt){ int rc, pageSize; MemPage *pPage1; if( pBt->pPage1 ) return SQLITE_OK; @@ -1510,11 +1993,18 @@ page1_init_failed: ** This routine works like lockBtree() except that it also invokes the ** busy callback if there is lock contention. */ -static int lockBtreeWithRetry(Btree *pBt){ +static int lockBtreeWithRetry(Btree *pRef){ int rc = SQLITE_OK; - if( pBt->inTrans==TRANS_NONE ){ - rc = sqlite3BtreeBeginTrans(pBt, 0); - pBt->inTrans = TRANS_NONE; + if( pRef->inTrans==TRANS_NONE ){ + u8 inTransaction = pRef->pBt->inTransaction; + btreeIntegrity(pRef); + rc = sqlite3BtreeBeginTrans(pRef, 0); + pRef->pBt->inTransaction = inTransaction; + pRef->inTrans = TRANS_NONE; + if( rc==SQLITE_OK ){ + pRef->pBt->nTransaction--; + } + btreeIntegrity(pRef); } return rc; } @@ -1530,11 +2020,11 @@ static int lockBtreeWithRetry(Btree *pBt){ ** ** If there is a transaction in progress, this routine is a no-op. */ -static void unlockBtreeIfUnused(Btree *pBt){ - if( pBt->inTrans==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ +static void unlockBtreeIfUnused(BtShared *pBt){ + if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ if( pBt->pPage1->aData==0 ){ MemPage *pPage = pBt->pPage1; - pPage->aData = &((char*)pPage)[-pBt->pageSize]; + pPage->aData = &((u8*)pPage)[-pBt->pageSize]; pPage->pBt = pBt; pPage->pgno = 1; } @@ -1548,7 +2038,7 @@ static void unlockBtreeIfUnused(Btree *pBt){ ** Create a new database by initializing the first page of the ** file. */ -static int newDatabase(Btree *pBt){ +static int newDatabase(BtShared *pBt){ MemPage *pP1; unsigned char *data; int rc; @@ -1613,14 +2103,17 @@ static int newDatabase(Btree *pBt){ ** when A already has a read lock, we encourage A to give up and let B ** proceed. */ -int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){ +int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ + BtShared *pBt = p->pBt; int rc = SQLITE_OK; + 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( pBt->inTrans==TRANS_WRITE || (pBt->inTrans==TRANS_READ && !wrflag) ){ + if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ return SQLITE_OK; } @@ -1629,6 +2122,14 @@ int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){ return SQLITE_READONLY; } + /* If another database handle has already opened a write transaction + ** on this shared-btree structure and a second write transaction is + ** requested, return SQLITE_BUSY. + */ + if( pBt->inTransaction==TRANS_WRITE && wrflag ){ + return SQLITE_BUSY; + } + do { if( pBt->pPage1==0 ){ rc = lockBtree(pBt); @@ -1642,13 +2143,24 @@ int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){ } if( rc==SQLITE_OK ){ - pBt->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); if( wrflag ) pBt->inStmt = 0; }else{ unlockBtreeIfUnused(pBt); } - }while( rc==SQLITE_BUSY && pBt->inTrans==TRANS_NONE && + }while( rc==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && sqlite3InvokeBusyHandler(pBt->pBusyHandler) ); + + if( rc==SQLITE_OK ){ + if( p->inTrans==TRANS_NONE ){ + pBt->nTransaction++; + } + p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); + if( p->inTrans>pBt->inTransaction ){ + pBt->inTransaction = p->inTrans; + } + } + + btreeIntegrity(p); return rc; } @@ -1663,7 +2175,7 @@ static int setChildPtrmaps(MemPage *pPage){ int i; /* Counter variable */ int nCell; /* Number of cells in page pPage */ int rc = SQLITE_OK; /* Return code */ - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; int isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; @@ -1763,7 +2275,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ ** database. The pDbPage reference remains valid. */ static int relocatePage( - Btree *pBt, /* Btree */ + 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 */ @@ -1833,19 +2345,19 @@ static int relocatePage( } /* Forward declaration required by autoVacuumCommit(). */ -static int allocatePage(Btree *, MemPage **, Pgno *, Pgno, u8); +static int allocatePage(BtShared *, MemPage **, Pgno *, Pgno, u8); /* ** This routine is called prior to sqlite3pager_commit when a transaction ** is commited for an auto-vacuum database. */ -static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){ +static int autoVacuumCommit(BtShared *pBt, Pgno *nTrunc){ Pager *pPager = pBt->pPager; - Pgno nFreeList; /* Number of pages remaining on the free-list. */ - int nPtrMap; /* Number of pointer-map pages deallocated */ - Pgno origSize; /* Pages in the database file */ - Pgno finSize; /* Pages in the database file after truncation */ - int rc; /* Return code */ + Pgno nFreeList; /* Number of pages remaining on the free-list. */ + int nPtrMap; /* Number of pointer-map pages deallocated */ + Pgno origSize; /* Pages in the database file */ + Pgno finSize; /* Pages in the database file after truncation */ + int rc; /* Return code */ u8 eType; int pgsz = pBt->pageSize; /* Page size for this database */ Pgno iDbPage; /* The database page to move */ @@ -1855,11 +2367,11 @@ static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){ MemPage *pFreeMemPage = 0; /* "" */ #ifndef NDEBUG - int nRef = *sqlite3pager_stats(pPager); + int nRef = sqlite3pager_refcount(pPager); #endif assert( pBt->autoVacuum ); - if( PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) ){ + if( PTRMAP_ISPAGE(pBt, sqlite3pager_pagecount(pPager)) ){ return SQLITE_CORRUPT_BKPT; } @@ -1872,14 +2384,26 @@ static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){ return SQLITE_OK; } + /* This block figures out how many pages there are in the database + ** now (variable origSize), and how many there will be after the + ** truncation (variable finSize). + ** + ** The final size is the original size, less the number of free pages + ** in the database, less any pointer-map pages that will no longer + ** be required, less 1 if the pending-byte page was part of the database + ** but is not after the truncation. + **/ origSize = sqlite3pager_pagecount(pPager); - nPtrMap = (nFreeList-origSize+PTRMAP_PAGENO(pgsz, origSize)+pgsz/5)/(pgsz/5); + if( origSize==PENDING_BYTE_PAGE(pBt) ){ + origSize--; + } + nPtrMap = (nFreeList-origSize+PTRMAP_PAGENO(pBt, origSize)+pgsz/5)/(pgsz/5); finSize = origSize - nFreeList - nPtrMap; - if( origSize>=PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){ + if( origSize>PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){ + finSize--; + } + while( PTRMAP_ISPAGE(pBt, finSize) || finSize==PENDING_BYTE_PAGE(pBt) ){ finSize--; - if( PTRMAP_ISPAGE(pBt->usableSize, finSize) ){ - finSize--; - } } TRACE(("AUTOVACUUM: Begin (db size %d->%d)\n", origSize, finSize)); @@ -1891,7 +2415,7 @@ static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){ */ for( iDbPage=finSize+1; iDbPage<=origSize; iDbPage++ ){ /* If iDbPage is a pointer map page, or the pending-byte page, skip it. */ - if( PTRMAP_ISPAGE(pgsz, iDbPage) || iDbPage==PENDING_BYTE_PAGE(pBt) ){ + if( PTRMAP_ISPAGE(pBt, iDbPage) || iDbPage==PENDING_BYTE_PAGE(pBt) ){ continue; } @@ -1928,6 +2452,12 @@ static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){ releasePage(pFreeMemPage); pFreeMemPage = 0; + /* Relocate the page into the body of the file. Note that although the + ** page has moved within the database file, the pDbMemPage pointer + ** remains valid. This means that this function can run without + ** invalidating cursors open on the btree. This is important in + ** shared-cache mode. + */ rc = relocatePage(pBt, pDbMemPage, eType, iPtrPage, iFreePage); releasePage(pDbMemPage); if( rc!=SQLITE_OK ) goto autovacuum_out; @@ -1941,11 +2471,11 @@ static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){ if( rc!=SQLITE_OK ) goto autovacuum_out; put4byte(&pBt->pPage1->aData[32], 0); put4byte(&pBt->pPage1->aData[36], 0); - if( rc!=SQLITE_OK ) goto autovacuum_out; *nTrunc = finSize; + assert( finSize!=PENDING_BYTE_PAGE(pBt) ); autovacuum_out: - assert( nRef==*sqlite3pager_stats(pPager) ); + assert( nRef==sqlite3pager_refcount(pPager) ); if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); } @@ -1959,15 +2489,47 @@ autovacuum_out: ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ -int sqlite3BtreeCommit(Btree *pBt){ - int rc = SQLITE_OK; - if( pBt->inTrans==TRANS_WRITE ){ +int sqlite3BtreeCommit(Btree *p){ + BtShared *pBt = p->pBt; + + 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; + assert( pBt->inTransaction==TRANS_WRITE ); + assert( pBt->nTransaction>0 ); rc = sqlite3pager_commit(pBt->pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + pBt->inTransaction = TRANS_READ; + pBt->inStmt = 0; } - pBt->inTrans = TRANS_NONE; - pBt->inStmt = 0; + unlockAllTables(p); + + /* If the handle has 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 ){ + pBt->nTransaction--; + if( 0==pBt->nTransaction ){ + pBt->inTransaction = TRANS_NONE; + } + } + + /* Set the handles 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); - return rc; + + btreeIntegrity(p); + return SQLITE_OK; } #ifndef NDEBUG @@ -1976,29 +2538,30 @@ int sqlite3BtreeCommit(Btree *pBt){ ** in assert() expressions, so it is only compiled if NDEBUG is not ** defined. */ -static int countWriteCursors(Btree *pBt){ +static int countWriteCursors(BtShared *pBt){ BtCursor *pCur; int r = 0; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( pCur->wrFlag ) r++; + if( pCur->wrFlag ) r++; } return r; } #endif -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) /* ** Print debugging information about all cursors to standard output. */ -void sqlite3BtreeCursorList(Btree *pBt){ +void sqlite3BtreeCursorList(Btree *p){ BtCursor *pCur; + BtShared *pBt = p->pBt; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ MemPage *pPage = pCur->pPage; char *zMode = pCur->wrFlag ? "rw" : "ro"; sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n", pCur, pCur->pgnoRoot, zMode, pPage ? pPage->pgno : 0, pCur->idx, - pCur->isValid ? "" : " eof" + (pCur->eState==CURSOR_VALID) ? "" : " eof" ); } } @@ -2013,11 +2576,41 @@ void sqlite3BtreeCursorList(Btree *pBt){ ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ -int sqlite3BtreeRollback(Btree *pBt){ - int rc = SQLITE_OK; +int sqlite3BtreeRollback(Btree *p){ + int rc; + BtShared *pBt = p->pBt; MemPage *pPage1; - if( pBt->inTrans==TRANS_WRITE ){ - rc = sqlite3pager_rollback(pBt->pPager); + + rc = saveAllCursors(pBt, 0, 0); +#ifndef SQLITE_OMIT_SHARED_CACHE + if( rc!=SQLITE_OK ){ + /* This is a horrible situation. An IO or malloc() error occured whilst + ** trying to save cursor positions. If this is an automatic rollback (as + ** the result of a constraint, malloc() failure or IO error) then + ** the cache may be internally inconsistent (not contain valid trees) so + ** we cannot simply return the error to the caller. Instead, abort + ** all queries that may be using any of the cursors that failed to save. + */ + while( pBt->pCursor ){ + sqlite3 *db = pBt->pCursor->pBtree->pSqlite; + if( db ){ + sqlite3AbortOtherActiveVdbes(db, 0); + } + } + } +#endif + btreeIntegrity(p); + unlockAllTables(p); + + if( p->inTrans==TRANS_WRITE ){ + int rc2; + + assert( TRANS_WRITE==pBt->inTransaction ); + rc2 = sqlite3pager_rollback(pBt->pPager); + if( rc2!=SQLITE_OK ){ + rc = rc2; + } + /* The rollback may have destroyed the pPage1->aData value. So ** call getPage() on page 1 again to make sure pPage1->aData is ** set correctly. */ @@ -2025,10 +2618,22 @@ int sqlite3BtreeRollback(Btree *pBt){ releasePage(pPage1); } assert( countWriteCursors(pBt)==0 ); + pBt->inTransaction = TRANS_READ; } - pBt->inTrans = TRANS_NONE; + + if( p->inTrans!=TRANS_NONE ){ + assert( pBt->nTransaction>0 ); + pBt->nTransaction--; + if( 0==pBt->nTransaction ){ + pBt->inTransaction = TRANS_NONE; + } + } + + p->inTrans = TRANS_NONE; pBt->inStmt = 0; unlockBtreeIfUnused(pBt); + + btreeIntegrity(p); return rc; } @@ -2047,11 +2652,13 @@ int sqlite3BtreeRollback(Btree *pBt){ ** error occurs within the statement, the effect of that one statement ** can be rolled back without having to rollback the entire transaction. */ -int sqlite3BtreeBeginStmt(Btree *pBt){ +int sqlite3BtreeBeginStmt(Btree *p){ int rc; - if( (pBt->inTrans!=TRANS_WRITE) || pBt->inStmt ){ + BtShared *pBt = p->pBt; + if( (p->inTrans!=TRANS_WRITE) || pBt->inStmt ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } + assert( pBt->inTransaction==TRANS_WRITE ); rc = pBt->readOnly ? SQLITE_OK : sqlite3pager_stmt_begin(pBt->pPager); pBt->inStmt = 1; return rc; @@ -2062,8 +2669,9 @@ int sqlite3BtreeBeginStmt(Btree *pBt){ ** Commit the statment subtransaction currently in progress. If no ** subtransaction is active, this is a no-op. */ -int sqlite3BtreeCommitStmt(Btree *pBt){ +int sqlite3BtreeCommitStmt(Btree *p){ int rc; + BtShared *pBt = p->pBt; if( pBt->inStmt && !pBt->readOnly ){ rc = sqlite3pager_stmt_commit(pBt->pPager); }else{ @@ -2081,12 +2689,16 @@ int sqlite3BtreeCommitStmt(Btree *pBt){ ** to use a cursor that was open at the beginning of this operation ** will result in an error. */ -int sqlite3BtreeRollbackStmt(Btree *pBt){ - int rc; - if( pBt->inStmt==0 || pBt->readOnly ) return SQLITE_OK; - rc = sqlite3pager_stmt_rollback(pBt->pPager); - assert( countWriteCursors(pBt)==0 ); - pBt->inStmt = 0; +int sqlite3BtreeRollbackStmt(Btree *p){ + int rc = SQLITE_OK; + BtShared *pBt = p->pBt; + sqlite3MallocDisallow(); + if( pBt->inStmt && !pBt->readOnly ){ + rc = sqlite3pager_stmt_rollback(pBt->pPager); + assert( countWriteCursors(pBt)==0 ); + pBt->inStmt = 0; + } + sqlite3MallocAllow(); return rc; } @@ -2150,7 +2762,7 @@ static int dfltCompare( ** always ignored for INTKEY tables. */ int sqlite3BtreeCursor( - Btree *pBt, /* The btree */ + Btree *p, /* The btree */ int iTable, /* Root page of table to open */ int wrFlag, /* 1 to write. 0 read-only */ int (*xCmp)(void*,int,const void*,int,const void*), /* Key Comparison func */ @@ -2159,6 +2771,7 @@ int sqlite3BtreeCursor( ){ int rc; BtCursor *pCur; + BtShared *pBt = p->pBt; *ppCur = 0; if( wrFlag ){ @@ -2169,19 +2782,19 @@ int sqlite3BtreeCursor( return SQLITE_LOCKED; } } + if( pBt->pPage1==0 ){ - rc = lockBtreeWithRetry(pBt); + rc = lockBtreeWithRetry(p); if( rc!=SQLITE_OK ){ return rc; } } - pCur = sqliteMallocRaw( sizeof(*pCur) ); + pCur = sqliteMalloc( sizeof(*pCur) ); if( pCur==0 ){ rc = SQLITE_NOMEM; goto create_cursor_exception; } pCur->pgnoRoot = (Pgno)iTable; - pCur->pPage = 0; /* For exit-handler, in case getAndInitPage() fails. */ if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){ rc = SQLITE_EMPTY; goto create_cursor_exception; @@ -2190,22 +2803,24 @@ int sqlite3BtreeCursor( if( rc!=SQLITE_OK ){ goto create_cursor_exception; } + + /* Now that no other errors can occur, finish filling in the BtCursor + ** variables, link the cursor into the BtShared list and set *ppCur (the + ** output argument to this function). + */ pCur->xCompare = xCmp ? xCmp : dfltCompare; pCur->pArg = pArg; - pCur->pBt = pBt; + pCur->pBtree = p; pCur->wrFlag = wrFlag; - pCur->idx = 0; - memset(&pCur->info, 0, sizeof(pCur->info)); pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } - pCur->pPrev = 0; pBt->pCursor = pCur; - pCur->isValid = 0; + pCur->eState = CURSOR_INVALID; *ppCur = pCur; - return SQLITE_OK; + return SQLITE_OK; create_cursor_exception: if( pCur ){ releasePage(pCur->pPage); @@ -2234,7 +2849,8 @@ void sqlite3BtreeSetCompare( ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ - Btree *pBt = pCur->pBt; + BtShared *pBt = pCur->pBtree->pBt; + restoreOrClearCursorPosition(pCur, 0); if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; }else{ @@ -2301,13 +2917,17 @@ static void getCellInfo(BtCursor *pCur){ ** itself, not the number of bytes in the key. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ - if( !pCur->isValid ){ - *pSize = 0; - }else{ - getCellInfo(pCur); - *pSize = pCur->info.nKey; + int rc = restoreOrClearCursorPosition(pCur, 1); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); + if( pCur->eState==CURSOR_INVALID ){ + *pSize = 0; + }else{ + getCellInfo(pCur); + *pSize = pCur->info.nKey; + } } - return SQLITE_OK; + return rc; } /* @@ -2318,14 +2938,18 @@ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ ** the database is empty) then *pSize is set to 0. */ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ - if( !pCur->isValid ){ - /* Not pointing at a valid entry - set *pSize to 0. */ - *pSize = 0; - }else{ - getCellInfo(pCur); - *pSize = pCur->info.nData; + int rc = restoreOrClearCursorPosition(pCur, 1); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); + if( pCur->eState==CURSOR_INVALID ){ + /* Not pointing at a valid entry - set *pSize to 0. */ + *pSize = 0; + }else{ + getCellInfo(pCur); + *pSize = pCur->info.nData; + } } - return SQLITE_OK; + return rc; } /* @@ -2348,19 +2972,18 @@ static int getPayload( Pgno nextPage; int rc; MemPage *pPage; - Btree *pBt; + BtShared *pBt; int ovflSize; u32 nKey; assert( pCur!=0 && pCur->pPage!=0 ); - assert( pCur->isValid ); - pBt = pCur->pBt; + assert( pCur->eState==CURSOR_VALID ); + pBt = pCur->pBtree->pBt; pPage = pCur->pPage; pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idxnCell ); getCellInfo(pCur); - aPayload = pCur->info.pCell; - aPayload += pCur->info.nHeader; + aPayload = pCur->info.pCell + pCur->info.nHeader; if( pPage->intKey ){ nKey = 0; }else{ @@ -2429,14 +3052,18 @@ static int getPayload( ** the available payload. */ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - assert( pCur->isValid ); - assert( pCur->pPage!=0 ); - if( pCur->pPage->intKey ){ - return SQLITE_CORRUPT_BKPT; + int rc = restoreOrClearCursorPosition(pCur, 1); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->pPage!=0 ); + if( pCur->pPage->intKey ){ + return SQLITE_CORRUPT_BKPT; + } + assert( pCur->pPage->intKey==0 ); + assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + rc = getPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); } - assert( pCur->pPage->intKey==0 ); - assert( pCur->idx>=0 && pCur->idxpPage->nCell ); - return getPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); + return rc; } /* @@ -2449,10 +3076,14 @@ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ ** the available payload. */ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - assert( pCur->isValid ); - assert( pCur->pPage!=0 ); - assert( pCur->idx>=0 && pCur->idxpPage->nCell ); - return getPayload(pCur, offset, amt, pBuf, 1); + int rc = restoreOrClearCursorPosition(pCur, 1); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->pPage!=0 ); + assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + rc = getPayload(pCur, offset, amt, pBuf, 1); + } + return rc; } /* @@ -2485,7 +3116,7 @@ static const unsigned char *fetchPayload( int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); pPage = pCur->pPage; pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idxnCell ); @@ -2523,10 +3154,16 @@ static const unsigned char *fetchPayload( ** in the common case where no overflow pages are used. */ const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ - return (const void*)fetchPayload(pCur, pAmt, 0); + if( pCur->eState==CURSOR_VALID ){ + return (const void*)fetchPayload(pCur, pAmt, 0); + } + return 0; } const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ - return (const void*)fetchPayload(pCur, pAmt, 1); + if( pCur->eState==CURSOR_VALID ){ + return (const void*)fetchPayload(pCur, pAmt, 1); + } + return 0; } @@ -2538,9 +3175,9 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ int rc; MemPage *pNewPage; MemPage *pOldPage; - Btree *pBt = pCur->pBt; + BtShared *pBt = pCur->pBtree->pBt; - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); if( rc ) return rc; pageIntegrity(pNewPage); @@ -2587,7 +3224,7 @@ static void moveToParent(BtCursor *pCur){ MemPage *pPage; int idxParent; - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); pPage = pCur->pPage; assert( pPage!=0 ); assert( !isRootPage(pPage) ); @@ -2609,17 +3246,24 @@ static void moveToParent(BtCursor *pCur){ */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; - int rc; - Btree *pBt = pCur->pBt; + int rc = SQLITE_OK; + BtShared *pBt = pCur->pBtree->pBt; - rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0); - if( rc ){ - pCur->isValid = 0; - return rc; + restoreOrClearCursorPosition(pCur, 0); + pRoot = pCur->pPage; + if( pRoot && pRoot->pgno==pCur->pgnoRoot ){ + assert( pRoot->isInit ); + }else{ + if( + SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0)) + ){ + pCur->eState = CURSOR_INVALID; + return rc; + } + releasePage(pCur->pPage); + pageIntegrity(pRoot); + pCur->pPage = pRoot; } - releasePage(pCur->pPage); - pageIntegrity(pRoot); - pCur->pPage = pRoot; pCur->idx = 0; pCur->info.nSize = 0; if( pRoot->nCell==0 && !pRoot->leaf ){ @@ -2627,23 +3271,26 @@ static int moveToRoot(BtCursor *pCur){ assert( pRoot->pgno==1 ); subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); assert( subpage>0 ); - pCur->isValid = 1; + pCur->eState = CURSOR_VALID; rc = moveToChild(pCur, subpage); } - pCur->isValid = pCur->pPage->nCell>0; + pCur->eState = ((pCur->pPage->nCell>0)?CURSOR_VALID: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; MemPage *pPage; - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); while( !(pPage = pCur->pPage)->leaf ){ assert( pCur->idx>=0 && pCur->idxnCell ); pgno = get4byte(findCell(pPage, pCur->idx)); @@ -2659,13 +3306,16 @@ static int moveToLeftmost(BtCursor *pCur){ ** 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; MemPage *pPage; - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); while( !(pPage = pCur->pPage)->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pCur->idx = pPage->nCell; @@ -2685,7 +3335,7 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ int rc; rc = moveToRoot(pCur); if( rc ) return rc; - if( pCur->isValid==0 ){ + if( pCur->eState==CURSOR_INVALID ){ assert( pCur->pPage->nCell==0 ); *pRes = 1; return SQLITE_OK; @@ -2704,12 +3354,12 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; rc = moveToRoot(pCur); if( rc ) return rc; - if( pCur->isValid==0 ){ + if( CURSOR_INVALID==pCur->eState ){ assert( pCur->pPage->nCell==0 ); *pRes = 1; return SQLITE_OK; } - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); *pRes = 0; rc = moveToRightmost(pCur); return rc; @@ -2720,7 +3370,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ ** ** For INTKEY tables, only the nKey parameter is used. pKey is ** ignored. For other tables, nKey is the number of bytes of data -** in nKey. The comparison function specified when the cursor was +** in pKey. The comparison function specified when the cursor was ** created is used to compare keys. ** ** If an exact match is not found, then the cursor is always @@ -2744,11 +3394,13 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ */ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ int rc; + int tryRightmost; rc = moveToRoot(pCur); if( rc ) return rc; assert( pCur->pPage ); assert( pCur->pPage->isInit ); - if( pCur->isValid==0 ){ + tryRightmost = pCur->pPage->intKey; + if( pCur->eState==CURSOR_INVALID ){ *pRes = -1; assert( pCur->pPage->nCell==0 ); return SQLITE_OK; @@ -2769,18 +3421,29 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ i64 nCellKey; pCur->idx = (lwr+upr)/2; pCur->info.nSize = 0; - sqlite3BtreeKeySize(pCur, &nCellKey); if( pPage->intKey ){ + u8 *pCell; + if( tryRightmost ){ + pCur->idx = upr; + } + pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; + if( pPage->hasData ){ + u32 dummy; + pCell += getVarint32(pCell, &dummy); + } + getVarint(pCell, (u64 *)&nCellKey); if( nCellKeynKey ){ c = +1; + tryRightmost = 0; }else{ c = 0; } }else{ int available; pCellKey = (void *)fetchPayload(pCur, &available, 0); + nCellKey = pCur->info.nKey; if( available>=nCellKey ){ c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); }else{ @@ -2840,7 +3503,11 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ ** the first entry. TRUE is also returned if the table is empty. */ int sqlite3BtreeEof(BtCursor *pCur){ - return pCur->isValid==0; + /* 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); } /* @@ -2851,10 +3518,24 @@ int sqlite3BtreeEof(BtCursor *pCur){ */ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; - MemPage *pPage = pCur->pPage; + MemPage *pPage; + +#ifndef SQLITE_OMIT_SHARED_CACHE + rc = restoreOrClearCursorPosition(pCur, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + if( pCur->skip>0 ){ + pCur->skip = 0; + *pRes = 0; + return SQLITE_OK; + } + pCur->skip = 0; +#endif assert( pRes!=0 ); - if( pCur->isValid==0 ){ + pPage = pCur->pPage; + if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; } @@ -2874,7 +3555,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ do{ if( isRootPage(pPage) ){ *pRes = 1; - pCur->isValid = 0; + pCur->eState = CURSOR_INVALID; return SQLITE_OK; } moveToParent(pCur); @@ -2906,7 +3587,21 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int rc; Pgno pgno; MemPage *pPage; - if( pCur->isValid==0 ){ + +#ifndef SQLITE_OMIT_SHARED_CACHE + rc = restoreOrClearCursorPosition(pCur, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + if( pCur->skip<0 ){ + pCur->skip = 0; + *pRes = 0; + return SQLITE_OK; + } + pCur->skip = 0; +#endif + + if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; } @@ -2922,7 +3617,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ }else{ while( pCur->idx==0 ){ if( isRootPage(pPage) ){ - pCur->isValid = 0; + pCur->eState = CURSOR_INVALID; *pRes = 1; return SQLITE_OK; } @@ -2963,7 +3658,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ ** is only used by auto-vacuum databases when allocating a new table. */ static int allocatePage( - Btree *pBt, + BtShared *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby, @@ -3150,7 +3845,7 @@ static int allocatePage( *pPgno = sqlite3pager_pagecount(pBt->pPager) + 1; #ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt->usableSize, *pPgno) ){ + if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){ /* 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. @@ -3181,7 +3876,7 @@ static int allocatePage( ** sqlite3pager_unref() is NOT called for pPage. */ static int freePage(MemPage *pPage){ - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; MemPage *pPage1 = pBt->pPage1; int rc, n, k; @@ -3197,6 +3892,15 @@ static int freePage(MemPage *pPage){ n = get4byte(&pPage1->aData[36]); put4byte(&pPage1->aData[36], n+1); +#ifdef SQLITE_SECURE_DELETE + /* If the SQLITE_SECURE_DELETE compile-time option is enabled, then + ** always fully overwrite deleted information with zeros. + */ + rc = sqlite3pager_write(pPage->aData); + if( rc ) return rc; + memset(pPage->aData, 0, pPage->pBt->pageSize); +#endif + #ifndef SQLITE_OMIT_AUTOVACUUM /* If the database supports auto-vacuum, write an entry in the pointer-map ** to indicate that the page is free. @@ -3237,7 +3941,9 @@ static int freePage(MemPage *pPage){ if( rc ) return rc; put4byte(&pTrunk->aData[4], k+1); put4byte(&pTrunk->aData[8+k*4], pPage->pgno); +#ifndef SQLITE_SECURE_DELETE sqlite3pager_dont_write(pBt->pPager, pPage->pgno); +#endif TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); } releasePage(pTrunk); @@ -3249,7 +3955,7 @@ static int freePage(MemPage *pPage){ ** Free any overflow pages associated with the given Cell. */ static int clearCell(MemPage *pPage, unsigned char *pCell){ - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; CellInfo info; Pgno ovflPgno; int rc; @@ -3301,7 +4007,7 @@ static int fillInCell( MemPage *pToRelease = 0; unsigned char *pPrior; unsigned char *pPayload; - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; Pgno pgnoOvfl = 0; int nHeader; CellInfo info; @@ -3370,6 +4076,7 @@ static int fillInCell( n = nPayload; if( n>spaceLeft ) n = spaceLeft; if( n>nSrc ) n = nSrc; + assert( pSrc ); memcpy(pPayload, pSrc, n); nPayload -= n; pPayload += n; @@ -3390,10 +4097,11 @@ static int fillInCell( ** given in the second argument so that MemPage.pParent holds the ** pointer in the third argument. */ -static int reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){ +static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){ MemPage *pThis; unsigned char *aData; + assert( pNewParent!=0 ); if( pgno==0 ) return SQLITE_OK; assert( pBt->pPager!=0 ); aData = sqlite3pager_lookup(pBt->pPager, pgno); @@ -3404,7 +4112,7 @@ static int reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){ if( pThis->pParent!=pNewParent ){ if( pThis->pParent ) sqlite3pager_unref(pThis->pParent->aData); pThis->pParent = pNewParent; - if( pNewParent ) sqlite3pager_ref(pNewParent->aData); + sqlite3pager_ref(pNewParent->aData); } pThis->idxParent = idx; } @@ -3433,7 +4141,7 @@ static int reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){ */ static int reparentChildPages(MemPage *pPage){ int i; - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; int rc = SQLITE_OK; if( pPage->leaf ) return SQLITE_OK; @@ -3666,7 +4374,7 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){ u8 *pCell; int szCell; CellInfo info; - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; int parentIdx = pParent->nCell; /* pParent new divider cell index */ int parentSize; /* Size of new divider cell */ u8 parentCell[64]; /* Space for the new divider cell */ @@ -3775,7 +4483,7 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){ */ static int balance_nonroot(MemPage *pPage){ MemPage *pParent; /* The parent of pPage */ - Btree *pBt; /* The whole database */ + BtShared *pBt; /* The whole database */ int nCell = 0; /* Number of cells in apCell[] */ int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */ int nOld; /* Number of pages in apOld[] */ @@ -3796,7 +4504,6 @@ static int balance_nonroot(MemPage *pPage){ MemPage *apCopy[NB]; /* Private copies of apOld[] pages */ MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ Pgno pgnoNew[NB+2]; /* Page numbers for each page in apNew[] */ - int idxDiv[NB]; /* Indices of divider cells in pParent */ u8 *apDiv[NB]; /* Divider cells in pParent */ int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */ int szNew[NB+2]; /* Combined size of cells place on i-th page */ @@ -3815,8 +4522,10 @@ static int balance_nonroot(MemPage *pPage){ assert( sqlite3pager_iswriteable(pPage->aData) ); pBt = pPage->pBt; pParent = pPage->pParent; - sqlite3pager_write(pParent->aData); assert( pParent ); + if( SQLITE_OK!=(rc = sqlite3pager_write(pParent->aData)) ){ + return rc; + } TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); #ifndef SQLITE_OMIT_QUICKBALANCE @@ -3888,7 +4597,6 @@ static int balance_nonroot(MemPage *pPage){ nDiv = 0; for(i=0, k=nxDiv; inCell ){ - idxDiv[i] = k; apDiv[i] = findCell(pParent, k); nDiv++; assert( !pParent->leaf ); @@ -4117,6 +4825,7 @@ static int balance_nonroot(MemPage *pPage){ rc = sqlite3pager_write(pNew->aData); if( rc ) goto balance_cleanup; }else{ + assert( i>0 ); rc = allocatePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0); if( rc ) goto balance_cleanup; apNew[i] = pNew; @@ -4268,6 +4977,8 @@ static int balance_nonroot(MemPage *pPage){ } } assert( j==nCell ); + assert( nOld>0 ); + assert( nNew>0 ); if( (pageFlags & PTF_LEAF)==0 ){ memcpy(&apNew[nNew-1]->aData[8], &apCopy[nOld-1]->aData[8], 4); } @@ -4326,7 +5037,7 @@ static int balance_shallower(MemPage *pPage){ MemPage *pChild; /* The only child page of pPage */ Pgno pgnoChild; /* Page number for pChild */ int rc = SQLITE_OK; /* Return code from subprocedures */ - Btree *pBt; /* The main BTree structure */ + BtShared *pBt; /* The main BTree structure */ int mxCellPerPage; /* Maximum number of cells per page */ u8 **apCell; /* All cells from pages being balanced */ int *szCell; /* Local size of all cells */ @@ -4428,7 +5139,7 @@ static int balance_deeper(MemPage *pPage){ int rc; /* Return value from subprocedures */ MemPage *pChild; /* Pointer to a new child page */ Pgno pgnoChild; /* Page number of the new child page */ - Btree *pBt; /* The BTree */ + BtShared *pBt; /* The BTree */ int usableSize; /* Total usable size of a page */ u8 *data; /* Content of the parent page */ u8 *cdata; /* Content of the child page */ @@ -4517,10 +5228,12 @@ static int balance(MemPage *pPage, int insert){ ** a page entirely and we do not want to leave any cursors ** pointing to non-existant pages or cells. */ -static int checkReadLocks(Btree *pBt, Pgno pgnoRoot, BtCursor *pExclude){ +static int checkReadLocks(BtShared *pBt, Pgno pgnoRoot, BtCursor *pExclude){ BtCursor *p; for(p=pBt->pCursor; p; p=p->pNext){ + u32 flags = (p->pBtree->pSqlite ? p->pBtree->pSqlite->flags : 0); if( p->pgnoRoot!=pgnoRoot || p==pExclude ) continue; + if( p->wrFlag==0 && flags&SQLITE_ReadUncommitted ) continue; if( p->wrFlag==0 ) return SQLITE_LOCKED; if( p->pPage->pgno!=p->pgnoRoot ){ moveToRoot(p); @@ -4547,11 +5260,11 @@ int sqlite3BtreeInsert( int loc; int szNew; MemPage *pPage; - Btree *pBt = pCur->pBt; + BtShared *pBt = pCur->pBtree->pBt; unsigned char *oldCell; unsigned char *newCell = 0; - if( pBt->inTrans!=TRANS_WRITE ){ + if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing an insert */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } @@ -4562,8 +5275,16 @@ int sqlite3BtreeInsert( if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } - rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc); - if( rc ) return rc; + + /* Save the positions of any other cursors open on this table */ + restoreOrClearCursorPosition(pCur, 0); + if( + SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || + SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc)) + ){ + return rc; + } + pPage = pCur->pPage; assert( pPage->intKey || nKey>=0 ); assert( pPage->leaf || !pPage->leafData ); @@ -4579,7 +5300,7 @@ int sqlite3BtreeInsert( if( rc ) goto end_insert; assert( szNew==cellSizePtr(pPage, newCell) ); assert( szNew<=MX_CELL_SIZE(pBt) ); - if( loc==0 && pCur->isValid ){ + if( loc==0 && CURSOR_VALID==pCur->eState ){ int szOld; assert( pCur->idx>=0 && pCur->idxnCell ); oldCell = findCell(pPage, pCur->idx); @@ -4619,10 +5340,10 @@ int sqlite3BtreeDelete(BtCursor *pCur){ unsigned char *pCell; int rc; Pgno pgnoChild = 0; - Btree *pBt = pCur->pBt; + BtShared *pBt = pCur->pBtree->pBt; assert( pPage->isInit ); - if( pBt->inTrans!=TRANS_WRITE ){ + if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing a delete */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } @@ -4636,8 +5357,19 @@ int sqlite3BtreeDelete(BtCursor *pCur){ if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } - rc = sqlite3pager_write(pPage->aData); - if( rc ) return rc; + + /* Restore the current cursor position (a no-op if the cursor is not in + ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors + ** open on the same table. Then call sqlite3pager_write() on the page + ** that the entry will be deleted from. + */ + if( + (rc = restoreOrClearCursorPosition(pCur, 1))!=0 || + (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 || + (rc = sqlite3pager_write(pPage->aData))!=0 + ){ + return rc; + } /* Locate the cell within it's page and leave pCell pointing to the ** data. The clearCell() call frees any overflow pages associated with the @@ -4660,7 +5392,9 @@ int sqlite3BtreeDelete(BtCursor *pCur){ */ BtCursor leafCur; unsigned char *pNext; - int szNext; + int szNext; /* The compiler warning is wrong: szNext is always + ** initialized before use. Adding an extra initialization + ** to silence the compiler slows down the code. */ int notUsed; unsigned char *tempCell = 0; assert( !pPage->leafData ); @@ -4722,11 +5456,12 @@ int sqlite3BtreeDelete(BtCursor *pCur){ ** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys ** BTREE_ZERODATA Used for SQL indices */ -int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){ +int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){ + BtShared *pBt = p->pBt; MemPage *pRoot; Pgno pgnoRoot; int rc; - if( pBt->inTrans!=TRANS_WRITE ){ + if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction first */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } @@ -4753,14 +5488,14 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){ ** 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). */ - rc = sqlite3BtreeGetMeta(pBt, 4, &pgnoRoot); + rc = sqlite3BtreeGetMeta(p, 4, &pgnoRoot); if( rc!=SQLITE_OK ) return rc; pgnoRoot++; /* The new root-page may not be allocated on a pointer-map page, or the ** PENDING_BYTE page. */ - if( pgnoRoot==PTRMAP_PAGENO(pBt->usableSize, pgnoRoot) || + if( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ pgnoRoot++; } @@ -4820,7 +5555,7 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){ releasePage(pRoot); return rc; } - rc = sqlite3BtreeUpdateMeta(pBt, 4, pgnoRoot); + rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot); if( rc ){ releasePage(pRoot); return rc; @@ -4843,7 +5578,7 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){ ** the page to the freelist. */ static int clearDatabasePage( - Btree *pBt, /* The BTree that contains the table */ + BtShared *pBt, /* The BTree that contains the table */ Pgno pgno, /* Page number to clear */ MemPage *pParent, /* Parent page. NULL for the root */ int freePageFlag /* Deallocate page if true */ @@ -4894,23 +5629,35 @@ cleardatabasepage_out: ** read cursors on the table. Open write cursors are moved to the ** root of the table. */ -int sqlite3BtreeClearTable(Btree *pBt, int iTable){ +int sqlite3BtreeClearTable(Btree *p, int iTable){ int rc; BtCursor *pCur; - if( pBt->inTrans!=TRANS_WRITE ){ + BtShared *pBt = p->pBt; + sqlite3 *db = p->pSqlite; + if( p->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } - for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( pCur->pgnoRoot==(Pgno)iTable ){ - if( pCur->wrFlag==0 ) return SQLITE_LOCKED; - moveToRoot(pCur); + + /* If this connection is not in read-uncommitted mode and currently has + ** a read-cursor open on the table being cleared, return SQLITE_LOCKED. + */ + if( 0==db || 0==(db->flags&SQLITE_ReadUncommitted) ){ + for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ + if( pCur->pBtree==p && pCur->pgnoRoot==(Pgno)iTable ){ + if( 0==pCur->wrFlag ){ + return SQLITE_LOCKED; + } + moveToRoot(pCur); + } } } - rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0); - if( rc ){ - sqlite3BtreeRollback(pBt); + + /* Save the position of all cursors open on this table */ + if( SQLITE_OK!=(rc = saveAllCursors(pBt, iTable, 0)) ){ + return rc; } - return rc; + + return clearDatabasePage(pBt, (Pgno)iTable, 0, 0); } /* @@ -4933,11 +5680,12 @@ int sqlite3BtreeClearTable(Btree *pBt, int iTable){ ** The last root page is recorded in meta[3] and the value of ** meta[3] is updated by this procedure. */ -int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){ +int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ int rc; MemPage *pPage = 0; + BtShared *pBt = p->pBt; - if( pBt->inTrans!=TRANS_WRITE ){ + if( p->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } @@ -4953,7 +5701,7 @@ int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){ rc = getPage(pBt, (Pgno)iTable, &pPage); if( rc ) return rc; - rc = sqlite3BtreeClearTable(pBt, iTable); + rc = sqlite3BtreeClearTable(p, iTable); if( rc ){ releasePage(pPage); return rc; @@ -4968,7 +5716,7 @@ int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){ #else if( pBt->autoVacuum ){ Pgno maxRootPgno; - rc = sqlite3BtreeGetMeta(pBt, 4, &maxRootPgno); + rc = sqlite3BtreeGetMeta(p, 4, &maxRootPgno); if( rc!=SQLITE_OK ){ releasePage(pPage); return rc; @@ -5020,12 +5768,12 @@ int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){ if( maxRootPgno==PENDING_BYTE_PAGE(pBt) ){ maxRootPgno--; } - if( maxRootPgno==PTRMAP_PAGENO(pBt->usableSize, maxRootPgno) ){ + if( maxRootPgno==PTRMAP_PAGENO(pBt, maxRootPgno) ){ maxRootPgno--; } assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); - rc = sqlite3BtreeUpdateMeta(pBt, 4, maxRootPgno); + rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno); }else{ rc = freePage(pPage); releasePage(pPage); @@ -5050,9 +5798,20 @@ int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){ ** layer (and the SetCookie and ReadCookie opcodes) the number of ** free pages is not visible. So Cookie[0] is the same as Meta[1]. */ -int sqlite3BtreeGetMeta(Btree *pBt, int idx, u32 *pMeta){ +int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ int rc; unsigned char *pP1; + BtShared *pBt = p->pBt; + + /* Reading a meta-data value requires a read-lock on page 1 (and hence + ** the sqlite_master table. We grab this lock regardless of whether or + ** not the SQLITE_ReadUncommitted flag is set (the table rooted at page + ** 1 is treated as a special case by queryTableLock() and lockTable()). + */ + rc = queryTableLock(p, 1, READ_LOCK); + if( rc!=SQLITE_OK ){ + return rc; + } assert( idx>=0 && idx<=15 ); rc = sqlite3pager_get(pBt->pPager, 1, (void**)&pP1); @@ -5067,18 +5826,21 @@ int sqlite3BtreeGetMeta(Btree *pBt, int idx, u32 *pMeta){ if( idx==4 && *pMeta>0 ) pBt->readOnly = 1; #endif - return SQLITE_OK; + /* Grab the read-lock on page 1. */ + rc = lockTable(p, 1, READ_LOCK); + return rc; } /* ** Write meta-information back into the database. Meta[0] is ** read-only and may not be written. */ -int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){ +int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){ + BtShared *pBt = p->pBt; unsigned char *pP1; int rc; assert( idx>=1 && idx<=15 ); - if( pBt->inTrans!=TRANS_WRITE ){ + if( p->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } assert( pBt->pPage1!=0 ); @@ -5094,6 +5856,9 @@ int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){ ** is currently pointing to. */ int sqlite3BtreeFlags(BtCursor *pCur){ + /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call + ** restoreOrClearCursorPosition() here. + */ MemPage *pPage = pCur->pPage; return pPage ? pPage->aData[pPage->hdrOffset] : 0; } @@ -5103,7 +5868,7 @@ int sqlite3BtreeFlags(BtCursor *pCur){ ** Print a disassembly of the given page on standard output. This routine ** is used for debugging and testing only. */ -static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){ +static int btreePageDump(BtShared *pBt, int pgno, int recursive, MemPage *pParent){ int rc; MemPage *pPage; int i, j, c; @@ -5199,12 +5964,12 @@ static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){ fflush(stdout); return SQLITE_OK; } -int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){ - return btreePageDump(pBt, pgno, recursive, 0); +int sqlite3BtreePageDump(Btree *p, int pgno, int recursive){ + return btreePageDump(p->pBt, pgno, recursive, 0); } #endif -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) /* ** Fill aResult[] with information about the entry and page that the ** cursor is pointing to. @@ -5227,6 +5992,11 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ MemPage *pPage = pCur->pPage; BtCursor tmpCur; + int rc = restoreOrClearCursorPosition(pCur, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + pageIntegrity(pPage); assert( pPage->isInit ); getTempCursor(pCur, &tmpCur); @@ -5273,8 +6043,8 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ ** Return the pager associated with a BTree. This routine is used for ** testing and debugging only. */ -Pager *sqlite3BtreePager(Btree *pBt){ - return pBt->pPager; +Pager *sqlite3BtreePager(Btree *p){ + return p->pBt->pPager; } /* @@ -5283,7 +6053,7 @@ Pager *sqlite3BtreePager(Btree *pBt){ */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { - Btree *pBt; /* The tree being checked out */ + BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ int nPage; /* Number of pages in the database */ int *anRef; /* Number of times each page is referenced */ @@ -5463,19 +6233,14 @@ static int checkTreePage( IntegrityCk *pCheck, /* Context for the sanity check */ int iPage, /* Page number of the page to check */ MemPage *pParent, /* Parent page */ - char *zParentContext, /* Parent context */ - char *zLowerBound, /* All keys should be greater than this, if not NULL */ - int nLower, /* Number of characters in zLowerBound */ - char *zUpperBound, /* All keys should be less than this, if not NULL */ - int nUpper /* Number of characters in zUpperBound */ + char *zParentContext /* Parent context */ ){ MemPage *pPage; int i, rc, depth, d2, pgno, cnt; int hdr, cellStart; int nCell; u8 *data; - BtCursor cur; - Btree *pBt; + BtShared *pBt; int usableSize; char zContext[100]; char *hit; @@ -5484,7 +6249,7 @@ static int checkTreePage( /* Check that the page exists */ - cur.pBt = pBt = pCheck->pBt; + pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage, zParentContext) ) return 0; @@ -5502,7 +6267,6 @@ static int checkTreePage( /* Check out all the cells. */ depth = 0; - cur.pPage = pPage; for(i=0; inCell; i++){ u8 *pCell; int sz; @@ -5535,7 +6299,7 @@ static int checkTreePage( checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); } #endif - d2 = checkTreePage(pCheck,pgno,pPage,zContext,0,0,0,0); + d2 = checkTreePage(pCheck,pgno,pPage,zContext); if( i>0 && d2!=depth ){ checkAppendMsg(pCheck, zContext, "Child page depth differs"); } @@ -5550,7 +6314,7 @@ static int checkTreePage( checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0); } #endif - checkTreePage(pCheck, pgno, pPage, zContext,0,0,0,0); + checkTreePage(pCheck, pgno, pPage, zContext); } /* Check for complete coverage of the page @@ -5618,13 +6382,14 @@ static int checkTreePage( ** and a pointer to that error message is returned. The calling function ** is responsible for freeing the error message when it is done. */ -char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ +char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){ int i; int nRef; IntegrityCk sCheck; + BtShared *pBt = p->pBt; - nRef = *sqlite3pager_stats(pBt->pPager); - if( lockBtreeWithRetry(pBt)!=SQLITE_OK ){ + nRef = sqlite3pager_refcount(pBt->pPager); + if( lockBtreeWithRetry(p)!=SQLITE_OK ){ return sqliteStrDup("Unable to acquire a read lock on the database"); } sCheck.pBt = pBt; @@ -5661,7 +6426,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); } #endif - checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ", 0,0,0,0); + checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: "); } /* Make sure every page in the file is referenced @@ -5676,11 +6441,11 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ ** references to pointer-map pages. */ if( sCheck.anRef[i]==0 && - (PTRMAP_PAGENO(pBt->usableSize, i)!=i || !pBt->autoVacuum) ){ + (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } if( sCheck.anRef[i]!=0 && - (PTRMAP_PAGENO(pBt->usableSize, i)==i && pBt->autoVacuum) ){ + (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); } #endif @@ -5689,10 +6454,10 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ /* Make sure this analysis did not leave any unref() pages */ unlockBtreeIfUnused(pBt); - if( nRef != *sqlite3pager_stats(pBt->pPager) ){ + if( nRef != sqlite3pager_refcount(pBt->pPager) ){ checkAppendMsg(&sCheck, 0, "Outstanding page count goes from %d to %d during this analysis", - nRef, *sqlite3pager_stats(pBt->pPager) + nRef, sqlite3pager_refcount(pBt->pPager) ); } @@ -5706,17 +6471,17 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ /* ** Return the full pathname of the underlying database file. */ -const char *sqlite3BtreeGetFilename(Btree *pBt){ - assert( pBt->pPager!=0 ); - return sqlite3pager_filename(pBt->pPager); +const char *sqlite3BtreeGetFilename(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3pager_filename(p->pBt->pPager); } /* ** Return the pathname of the directory that contains the database file. */ -const char *sqlite3BtreeGetDirname(Btree *pBt){ - assert( pBt->pPager!=0 ); - return sqlite3pager_dirname(pBt->pPager); +const char *sqlite3BtreeGetDirname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3pager_dirname(p->pBt->pPager); } /* @@ -5724,9 +6489,9 @@ const char *sqlite3BtreeGetDirname(Btree *pBt){ ** value of this routine is the same regardless of whether the journal file ** has been created or not. */ -const char *sqlite3BtreeGetJournalname(Btree *pBt){ - assert( pBt->pPager!=0 ); - return sqlite3pager_journalname(pBt->pPager); +const char *sqlite3BtreeGetJournalname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3pager_journalname(p->pBt->pPager); } #ifndef SQLITE_OMIT_VACUUM @@ -5737,11 +6502,14 @@ const char *sqlite3BtreeGetJournalname(Btree *pBt){ ** The size of file pBtFrom may be reduced by this operation. ** If anything goes wrong, the transaction on pBtFrom is rolled back. */ -int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ +int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ int rc = SQLITE_OK; Pgno i, nPage, nToPage, iSkip; - if( pBtTo->inTrans!=TRANS_WRITE || pBtFrom->inTrans!=TRANS_WRITE ){ + BtShared *pBtTo = pTo->pBt; + BtShared *pBtFrom = pFrom->pBt; + + if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){ return SQLITE_ERROR; } if( pBtTo->pCursor ) return SQLITE_BUSY; @@ -5770,7 +6538,7 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ rc = sqlite3pager_truncate(pBtTo->pPager, nPage); } if( rc ){ - sqlite3BtreeRollback(pBtTo); + sqlite3BtreeRollback(pTo); } return rc; } @@ -5779,15 +6547,22 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ /* ** Return non-zero if a transaction is active. */ -int sqlite3BtreeIsInTrans(Btree *pBt){ - return (pBt && (pBt->inTrans==TRANS_WRITE)); +int sqlite3BtreeIsInTrans(Btree *p){ + return (p && (p->inTrans==TRANS_WRITE)); } /* ** Return non-zero if a statement transaction is active. */ -int sqlite3BtreeIsInStmt(Btree *pBt){ - return (pBt && pBt->inStmt); +int sqlite3BtreeIsInStmt(Btree *p){ + return (p->pBt && p->pBt->inStmt); +} + +/* +** Return non-zero if a read (or write) transaction is active. +*/ +int sqlite3BtreeIsInReadTrans(Btree *p){ + return (p && (p->inTrans!=TRANS_NONE)); } /* @@ -5804,30 +6579,101 @@ int sqlite3BtreeIsInStmt(Btree *pBt){ ** Once this is routine has returned, the only thing required to commit ** the write-transaction for this database file is to delete the journal. */ -int sqlite3BtreeSync(Btree *pBt, const char *zMaster){ - if( pBt->inTrans==TRANS_WRITE ){ -#ifndef SQLITE_OMIT_AUTOVACUUM +int sqlite3BtreeSync(Btree *p, const char *zMaster){ + int rc = SQLITE_OK; + if( p->inTrans==TRANS_WRITE ){ + BtShared *pBt = p->pBt; Pgno nTrunc = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ - int rc = autoVacuumCommit(pBt, &nTrunc); - if( rc!=SQLITE_OK ) return rc; + rc = autoVacuumCommit(pBt, &nTrunc); + if( rc!=SQLITE_OK ){ + return rc; + } } - return sqlite3pager_sync(pBt->pPager, zMaster, nTrunc); #endif - return sqlite3pager_sync(pBt->pPager, zMaster, 0); + rc = sqlite3pager_sync(pBt->pPager, zMaster, nTrunc); } - return SQLITE_OK; + return rc; +} + +/* +** This function returns a pointer to a blob of memory associated with +** a single shared-btree. The memory is used by client code for it's 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. +** +** 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. This function should not call sqliteFree() +** on the memory, the btree layer does that. +*/ +void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ + BtShared *pBt = p->pBt; + if( !pBt->pSchema ){ + pBt->pSchema = sqliteMalloc(nBytes); + pBt->xFreeSchema = xFree; + } + return pBt->pSchema; } -#ifndef SQLITE_OMIT_GLOBALRECOVER /* -** Reset the btree and underlying pager after a malloc() failure. Any -** transaction that was active when malloc() failed is rolled back. +** Return true if another user of the same shared btree as the argument +** handle holds an exclusive lock on the sqlite_master table. */ -int sqlite3BtreeReset(Btree *pBt){ - if( pBt->pCursor ) return SQLITE_BUSY; - pBt->inTrans = TRANS_NONE; - unlockBtreeIfUnused(pBt); - return sqlite3pager_reset(pBt->pPager); +int sqlite3BtreeSchemaLocked(Btree *p){ + return (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK); +} + + +#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. +*/ +int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ + int rc = SQLITE_OK; + u8 lockType = (isWriteLock?WRITE_LOCK:READ_LOCK); + rc = queryTableLock(p, iTab, lockType); + if( rc==SQLITE_OK ){ + rc = lockTable(p, iTab, lockType); + } + return rc; +} +#endif + +/* +** The following debugging interface has to be in this file (rather +** than in, for example, test1.c) so that it can get access to +** the definition of BtShared. +*/ +#if defined(SQLITE_DEBUG) && defined(TCLSH) +#include +int sqlite3_shared_cache_report( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_SHARED_CACHE + const ThreadData *pTd = sqlite3ThreadDataReadOnly(); + if( pTd->useSharedData ){ + BtShared *pBt; + Tcl_Obj *pRet = Tcl_NewObj(); + for(pBt=pTd->pBtree; pBt; pBt=pBt->pNext){ + const char *zFile = sqlite3pager_filename(pBt->pPager); + Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1)); + Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef)); + } + Tcl_SetObjResult(interp, pRet); + } +#endif + return TCL_OK; } #endif diff --git a/ext/pdo_sqlite/sqlite/src/btree.h b/ext/pdo_sqlite/sqlite/src/btree.h index 9d4401ac81..896ebf11b1 100644 --- a/ext/pdo_sqlite/sqlite/src/btree.h +++ b/ext/pdo_sqlite/sqlite/src/btree.h @@ -36,10 +36,12 @@ */ typedef struct Btree Btree; typedef struct BtCursor BtCursor; +typedef struct BtShared BtShared; int sqlite3BtreeOpen( const char *zFilename, /* Name of database file to open */ + sqlite3 *db, /* Associated database connection */ Btree **, /* Return open Btree* here */ int flags /* Flags */ ); @@ -57,7 +59,7 @@ int sqlite3BtreeOpen( int sqlite3BtreeClose(Btree*); int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*); int sqlite3BtreeSetCacheSize(Btree*,int); -int sqlite3BtreeSetSafetyLevel(Btree*,int); +int sqlite3BtreeSetSafetyLevel(Btree*,int,int); int sqlite3BtreeSyncDisabled(Btree*); int sqlite3BtreeSetPageSize(Btree*,int,int); int sqlite3BtreeGetPageSize(Btree*); @@ -73,8 +75,11 @@ int sqlite3BtreeRollbackStmt(Btree*); int sqlite3BtreeCreateTable(Btree*, int*, int flags); int sqlite3BtreeIsInTrans(Btree*); int sqlite3BtreeIsInStmt(Btree*); +int sqlite3BtreeIsInReadTrans(Btree*); int sqlite3BtreeSync(Btree*, const char *zMaster); -int sqlite3BtreeReset(Btree *); +void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); +int sqlite3BtreeSchemaLocked(Btree *); +int sqlite3BtreeLockTable(Btree *, int, u8); const char *sqlite3BtreeGetFilename(Btree *); const char *sqlite3BtreeGetDirname(Btree *); diff --git a/ext/pdo_sqlite/sqlite/src/build.c b/ext/pdo_sqlite/sqlite/src/build.c index 537eede8c0..5294c1a316 100644 --- a/ext/pdo_sqlite/sqlite/src/build.c +++ b/ext/pdo_sqlite/sqlite/src/build.c @@ -36,6 +36,88 @@ void sqlite3BeginParse(Parse *pParse, int 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(). +*/ +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 */ +){ + int i; + int nBytes; + TableLock *p; + + if( 0==sqlite3ThreadDataReadOnly()->useSharedData || iDb<0 ){ + return; + } + + for(i=0; inTableLock; i++){ + p = &pParse->aTableLock[i]; + if( p->iDb==iDb && p->iTab==iTab ){ + p->isWriteLock = (p->isWriteLock || isWriteLock); + return; + } + } + + nBytes = sizeof(TableLock) * (pParse->nTableLock+1); + sqliteReallocOrFree((void **)&pParse->aTableLock, nBytes); + if( pParse->aTableLock ){ + p = &pParse->aTableLock[pParse->nTableLock++]; + p->iDb = iDb; + p->iTab = iTab; + p->isWriteLock = isWriteLock; + p->zName = zName; + } +} + +/* +** 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; + assert( sqlite3ThreadDataReadOnly()->useSharedData || pParse->nTableLock==0 ); + + if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){ + return; + } + + for(i=0; inTableLock; i++){ + TableLock *p = &pParse->aTableLock[i]; + int p1 = p->iDb; + if( p->isWriteLock ){ + p1 = -1*(p1+1); + } + sqlite3VdbeOp3(pVdbe, OP_TableLock, p1, p->iTab, p->zName, P3_STATIC); + } +} +#else + #define codeTableLocks(x) +#endif + /* ** This routine is called after a single SQL statement has been ** parsed and a VDBE program to execute that statement has been @@ -50,13 +132,13 @@ void sqlite3FinishCoding(Parse *pParse){ sqlite3 *db; Vdbe *v; - if( sqlite3_malloc_failed ) return; + if( sqlite3MallocFailed() ) return; if( pParse->nested ) return; if( !pParse->pVdbe ){ if( pParse->rc==SQLITE_OK && pParse->nErr ){ pParse->rc = SQLITE_ERROR; + return; } - return; } /* Begin by generating some termination code at the end of the @@ -82,6 +164,18 @@ void sqlite3FinishCoding(Parse *pParse){ sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pParse->pVirtualLock ){ + char *vtab = (char *)pParse->pVirtualLock->pVtab; + sqlite3VdbeOp3(v, OP_VBegin, 0, 0, vtab, P3_VTAB); + } +#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); sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->cookieGoto); } @@ -99,7 +193,7 @@ void sqlite3FinishCoding(Parse *pParse){ /* Get the VDBE program ready for execution */ - if( v && pParse->nErr==0 ){ + if( v && pParse->nErr==0 && !sqlite3MallocFailed() ){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, @@ -168,11 +262,10 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ Table *p = 0; int i; assert( zName!=0 ); - assert( (db->flags & SQLITE_Initialized) || db->init.busy ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; - p = sqlite3HashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1); + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, strlen(zName)+1); if( p ) break; } return p; @@ -224,11 +317,14 @@ Table *sqlite3LocateTable(Parse *pParse, const char *zName, const char *zDbase){ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ Index *p = 0; int i; - assert( (db->flags & SQLITE_Initialized) || db->init.busy ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + Schema *pSchema = db->aDb[j].pSchema; if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; - p = sqlite3HashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1); + assert( pSchema || (j==1 && !db->aDb[1].pBt) ); + if( pSchema ){ + p = sqlite3HashFind(&pSchema->idxHash, zName, strlen(zName)+1); + } if( p ) break; } return p; @@ -250,12 +346,11 @@ static void freeIndex(Index *p){ ** it is not unlinked from the Table that it indexes. ** Unlinking from the Table must be done by the calling function. */ -static void sqliteDeleteIndex(sqlite3 *db, Index *p){ +static void sqliteDeleteIndex(Index *p){ Index *pOld; + const char *zName = p->zName; - assert( db!=0 && p->zName!=0 ); - pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName, - strlen(p->zName)+1, 0); + pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, strlen( zName)+1, 0); assert( pOld==0 || pOld==p ); freeIndex(p); } @@ -269,9 +364,10 @@ static void sqliteDeleteIndex(sqlite3 *db, Index *p){ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ Index *pIndex; int len; + Hash *pHash = &db->aDb[iDb].pSchema->idxHash; len = strlen(zIdxName); - pIndex = sqlite3HashInsert(&db->aDb[iDb].idxHash, zIdxName, len+1, 0); + pIndex = sqlite3HashInsert(pHash, zIdxName, len+1, 0); if( pIndex ){ if( pIndex->pTable->pIndex==pIndex ){ pIndex->pTable->pIndex = pIndex->pNext; @@ -299,39 +395,21 @@ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ ** single file indicated. */ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ - HashElem *pElem; - Hash temp1; - Hash temp2; int i, j; assert( iDb>=0 && iDbnDb ); - db->flags &= ~SQLITE_Initialized; for(i=iDb; inDb; i++){ Db *pDb = &db->aDb[i]; - temp1 = pDb->tblHash; - temp2 = pDb->trigHash; - sqlite3HashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0); - sqlite3HashClear(&pDb->aFKey); - sqlite3HashClear(&pDb->idxHash); - for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ - sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem)); - } - sqlite3HashClear(&temp2); - sqlite3HashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0); - for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ - Table *pTab = sqliteHashData(pElem); - sqlite3DeleteTable(db, pTab); - } - sqlite3HashClear(&temp1); - pDb->pSeqTab = 0; - DbClearProperty(db, i, DB_SchemaLoaded); + if( pDb->pSchema ){ + sqlite3SchemaFree(pDb->pSchema); + } if( iDb>0 ) return; } assert( iDb==0 ); db->flags &= ~SQLITE_InternChanges; /* If one or more of the auxiliary database files has been closed, - ** then remove then from the auxiliary database list. We take the + ** then remove them from the auxiliary database list. We take the ** opportunity to do this here since we have just deleted all of the ** schema hash tables and therefore do not have to make any changes ** to any of those tables. @@ -394,6 +472,7 @@ static void sqliteResetColumnNames(Table *pTable){ sqliteFree(pCol->zName); sqlite3ExprDelete(pCol->pDflt); sqliteFree(pCol->zType); + sqliteFree(pCol->zColl); } sqliteFree(pTable->aCol); } @@ -420,6 +499,8 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ Index *pIndex, *pNext; FKey *pFKey, *pNextFKey; + db = 0; + if( pTable==0 ) return; /* Do not delete the table until the reference count reaches zero. */ @@ -433,8 +514,8 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; - assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) ); - sqliteDeleteIndex(db, pIndex); + assert( pIndex->pSchema==pTable->pSchema ); + sqliteDeleteIndex(pIndex); } #ifndef SQLITE_OMIT_FOREIGN_KEY @@ -443,8 +524,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ */ for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ pNextFKey = pFKey->pNextFrom; - assert( pTable->iDbnDb ); - assert( sqlite3HashFind(&db->aDb[pTable->iDb].aFKey, + assert( sqlite3HashFind(&pTable->pSchema->aFKey, pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); sqliteFree(pFKey); } @@ -456,6 +536,10 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ sqliteFree(pTable->zName); sqliteFree(pTable->zColAff); sqlite3SelectDelete(pTable->pSelect); +#ifndef SQLITE_OMIT_CHECK + sqlite3ExprDelete(pTable->pCheck); +#endif + sqlite3VtabClear(pTable); sqliteFree(pTable); } @@ -472,14 +556,14 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ assert( iDb>=0 && iDbnDb ); assert( zTabName && zTabName[0] ); pDb = &db->aDb[iDb]; - p = sqlite3HashInsert(&pDb->tblHash, zTabName, strlen(zTabName)+1, 0); + p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, strlen(zTabName)+1,0); if( p ){ #ifndef SQLITE_OMIT_FOREIGN_KEY for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){ int nTo = strlen(pF1->zTo) + 1; - pF2 = sqlite3HashFind(&pDb->aFKey, pF1->zTo, nTo); + pF2 = sqlite3HashFind(&pDb->pSchema->aFKey, pF1->zTo, nTo); if( pF2==pF1 ){ - sqlite3HashInsert(&pDb->aFKey, pF1->zTo, nTo, pF1->pNextTo); + sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo); }else{ while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } if( pF2 ){ @@ -506,7 +590,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ char *sqlite3NameFromToken(Token *pName){ char *zName; if( pName ){ - zName = sqliteStrNDup(pName->z, pName->n); + zName = sqliteStrNDup((char*)pName->z, pName->n); sqlite3Dequote(zName); }else{ zName = 0; @@ -518,7 +602,9 @@ char *sqlite3NameFromToken(Token *pName){ ** Open the sqlite_master table stored in database number iDb for ** writing. The table is opened using cursor 0. */ -void sqlite3OpenMasterTable(Vdbe *v, int iDb){ +void sqlite3OpenMasterTable(Parse *p, int iDb){ + Vdbe *v = sqlite3GetVdbe(p); + sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 0, MASTER_ROOT); sqlite3VdbeAddOp(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */ @@ -613,8 +699,7 @@ int sqlite3CheckObjectName(Parse *pParse, const char *zName){ ** 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 -** pStart token is the CREATE and pName is the table name. The isTemp +** 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 @@ -628,11 +713,12 @@ int sqlite3CheckObjectName(Parse *pParse, const char *zName){ */ void sqlite3StartTable( Parse *pParse, /* Parser context */ - Token *pStart, /* The "CREATE" token */ 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 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 */ @@ -695,7 +781,7 @@ void sqlite3StartTable( code = SQLITE_CREATE_TABLE; } } - if( sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ + if( !isVirtual && sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ goto begin_table_error; } } @@ -703,20 +789,28 @@ void sqlite3StartTable( /* 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. + ** 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( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - goto begin_table_error; - } - pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName); - if( pTable ){ - sqlite3ErrorMsg(pParse, "table %T already exists", pName); - goto begin_table_error; - } - if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){ - sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); - goto begin_table_error; + if( !IN_DECLARE_VTAB ){ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto begin_table_error; + } + pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName); + if( pTable ){ + if( !noErr ){ + sqlite3ErrorMsg(pParse, "table %T already exists", pName); + } + goto begin_table_error; + } + if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){ + sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); + goto begin_table_error; + } } + pTable = sqliteMalloc( sizeof(Table) ); if( pTable==0 ){ pParse->rc = SQLITE_NOMEM; @@ -724,11 +818,8 @@ void sqlite3StartTable( goto begin_table_error; } pTable->zName = zName; - pTable->nCol = 0; - pTable->aCol = 0; pTable->iPKey = -1; - pTable->pIndex = 0; - pTable->iDb = iDb; + pTable->pSchema = db->aDb[iDb].pSchema; pTable->nRef = 1; if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable); pParse->pNewTable = pTable; @@ -739,7 +830,7 @@ void sqlite3StartTable( */ #ifndef SQLITE_OMIT_AUTOINCREMENT if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){ - db->aDb[iDb].pSeqTab = pTable; + pTable->pSchema->pSeqTab = pTable; } #endif @@ -753,17 +844,26 @@ void sqlite3StartTable( */ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ int lbl; + int fileFormat; sqlite3BeginWriteOperation(pParse, 0, iDb); +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( isVirtual ){ + sqlite3VdbeAddOp(v, OP_VBegin, 0, 0); + } +#endif + /* If the file format and encoding in the database have not been set, ** set them now. */ sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */ lbl = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_If, 0, lbl); - sqlite3VdbeAddOp(v, OP_Integer, db->file_format, 0); + fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? + 1 : SQLITE_MAX_FILE_FORMAT; + sqlite3VdbeAddOp(v, OP_Integer, fileFormat, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); - sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0); + sqlite3VdbeAddOp(v, OP_Integer, ENC(db), 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4); sqlite3VdbeResolveLabel(v, lbl); @@ -775,15 +875,15 @@ void sqlite3StartTable( ** The rowid value is needed by the code that sqlite3EndTable will ** generate. */ -#ifndef SQLITE_OMIT_VIEW - if( isView ){ +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) + if( isView || isVirtual ){ sqlite3VdbeAddOp(v, OP_Integer, 0, 0); }else #endif { sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0); } - sqlite3OpenMasterTable(v, iDb); + sqlite3OpenMasterTable(pParse, iDb); sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Null, 0, 0); @@ -855,7 +955,6 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){ ** be called next to set pCol->affinity correctly. */ pCol->affinity = SQLITE_AFF_NONE; - pCol->pColl = pParse->db->pDfltColl; p->nCol++; } @@ -891,6 +990,9 @@ void sqlite3AddNotNull(Parse *pParse, int onError){ ** 'CLOB' | SQLITE_AFF_TEXT ** 'TEXT' | SQLITE_AFF_TEXT ** 'BLOB' | SQLITE_AFF_NONE +** 'REAL' | SQLITE_AFF_REAL +** 'FLOA' | SQLITE_AFF_REAL +** 'DOUB' | SQLITE_AFF_REAL ** ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. @@ -911,10 +1013,21 @@ char sqlite3AffinityType(const Token *pType){ }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */ aff = SQLITE_AFF_TEXT; }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */ - && aff==SQLITE_AFF_NUMERIC ){ + && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){ aff = SQLITE_AFF_NONE; +#ifndef SQLITE_OMIT_FLOATING_POINT + }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; + }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; + }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; +#endif }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ - aff = SQLITE_AFF_INTEGER; + aff = SQLITE_AFF_INTEGER; break; } } @@ -993,12 +1106,13 @@ void sqlite3AddPrimaryKey( Parse *pParse, /* Parsing context */ ExprList *pList, /* List of field names to be indexed */ int onError, /* What to do with a uniqueness conflict */ - int autoInc /* True if the AUTOINCREMENT keyword is present */ + int autoInc, /* True if the AUTOINCREMENT keyword is present */ + int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ ){ Table *pTab = pParse->pNewTable; char *zType = 0; int iCol = -1, i; - if( pTab==0 ) goto primary_key_exit; + if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit; if( pTab->hasPrimKey ){ sqlite3ErrorMsg(pParse, "table \"%s\" has more than one primary key", pTab->zName); @@ -1024,7 +1138,8 @@ void sqlite3AddPrimaryKey( if( iCol>=0 && iColnCol ){ zType = pTab->aCol[iCol].zType; } - if( zType && sqlite3StrICmp(zType, "INTEGER")==0 ){ + if( zType && sqlite3StrICmp(zType, "INTEGER")==0 + && sortOrder==SQLITE_SO_ASC ){ pTab->iPKey = iCol; pTab->keyConf = onError; pTab->autoInc = autoInc; @@ -1034,7 +1149,7 @@ void sqlite3AddPrimaryKey( "INTEGER PRIMARY KEY"); #endif }else{ - sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0); + sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0); pList = 0; } @@ -1043,47 +1158,51 @@ primary_key_exit: return; } +/* +** Add a new CHECK constraint to the table currently under construction. +*/ +void sqlite3AddCheckConstraint( + Parse *pParse, /* Parsing context */ + Expr *pCheckExpr /* The check expression */ +){ +#ifndef SQLITE_OMIT_CHECK + Table *pTab = pParse->pNewTable; + if( pTab && !IN_DECLARE_VTAB ){ + /* The CHECK expression must be duplicated so that tokens refer + ** to malloced space and not the (ephemeral) text of the CREATE TABLE + ** statement */ + pTab->pCheck = sqlite3ExprAnd(pTab->pCheck, sqlite3ExprDup(pCheckExpr)); + } +#endif + sqlite3ExprDelete(pCheckExpr); +} + /* ** Set the collation function of the most recently parsed table column ** to the CollSeq given. */ void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){ Table *p; - Index *pIdx; - CollSeq *pColl; int i; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; - pColl = sqlite3LocateCollSeq(pParse, zType, nType); - p->aCol[i].pColl = pColl; - - /* If the column is declared as " PRIMARY KEY COLLATE ", - ** then an index may have been created on this column before the - ** collation type was added. Correct this if it is the case. - */ - for(pIdx = p->pIndex; pIdx; pIdx=pIdx->pNext){ - assert( pIdx->nColumn==1 ); - if( pIdx->aiColumn[0]==i ) pIdx->keyInfo.aColl[0] = pColl; - } -} - -/* -** Call sqlite3CheckCollSeq() for all collating sequences in an index, -** in order to verify that all the necessary collating sequences are -** loaded. -*/ -int sqlite3CheckIndexCollSeq(Parse *pParse, Index *pIdx){ - if( pIdx ){ - int i; - for(i=0; inColumn; i++){ - if( sqlite3CheckCollSeq(pParse, pIdx->keyInfo.aColl[i]) ){ - return SQLITE_ERROR; + if( sqlite3LocateCollSeq(pParse, zType, nType) ){ + Index *pIdx; + p->aCol[i].zColl = sqliteStrNDup(zType, nType); + + /* If the column is declared as " PRIMARY KEY COLLATE ", + ** then an index may have been created on this column before the + ** collation type was added. Correct this if it is the case. + */ + for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ + assert( pIdx->nColumn==1 ); + if( pIdx->aiColumn[0]==i ){ + pIdx->azColl[0] = p->aCol[i].zColl; } } } - return SQLITE_OK; } /* @@ -1102,10 +1221,11 @@ int sqlite3CheckIndexCollSeq(Parse *pParse, Index *pIdx){ */ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){ sqlite3 *db = pParse->db; - u8 enc = db->enc; + u8 enc = ENC(db); u8 initbusy = db->init.busy; + CollSeq *pColl; - CollSeq *pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy); + pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy); if( !initbusy && (!pColl || !pColl->xCmp) ){ pColl = sqlite3GetCollSeq(db, pColl, zName, nName); if( !pColl ){ @@ -1138,7 +1258,7 @@ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){ ** 1 chance in 2^32. So we're safe enough. */ void sqlite3ChangeCookie(sqlite3 *db, Vdbe *v, int iDb){ - sqlite3VdbeAddOp(v, OP_Integer, db->aDb[iDb].schema_cookie+1, 0); + sqlite3VdbeAddOp(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 0); } @@ -1186,7 +1306,7 @@ static void identPut(char *z, int *pIdx, char *zSignedIdent){ ** table. Memory to hold the text of the statement is obtained ** from sqliteMalloc() and must be freed by the calling function. */ -static char *createTableStmt(Table *p){ +static char *createTableStmt(Table *p, int isTemp){ int i, k, n; char *zStmt; char *zSep, *zSep2, *zEnd, *z; @@ -1212,7 +1332,7 @@ static char *createTableStmt(Table *p){ n += 35 + 6*p->nCol; zStmt = sqliteMallocRaw( n ); if( zStmt==0 ) return 0; - strcpy(zStmt, !OMIT_TEMPDB&&p->iDb==1 ? "CREATE TEMP TABLE ":"CREATE TABLE "); + strcpy(zStmt, !OMIT_TEMPDB&&isTemp ? "CREATE TEMP TABLE ":"CREATE TABLE "); k = strlen(zStmt); identPut(zStmt, &k, p->zName); zStmt[k++] = '('; @@ -1259,13 +1379,40 @@ void sqlite3EndTable( ){ Table *p; sqlite3 *db = pParse->db; + int iDb; - if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3_malloc_failed ) return; + if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3MallocFailed() ) { + return; + } p = pParse->pNewTable; if( p==0 ) return; assert( !db->init.busy || !pSelect ); + iDb = sqlite3SchemaToIndex(db, p->pSchema); + +#ifndef SQLITE_OMIT_CHECK + /* Resolve names in all CHECK constraint expressions. + */ + if( p->pCheck ){ + SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ + NameContext sNC; /* Name context for pParse->pNewTable */ + + memset(&sNC, 0, sizeof(sNC)); + memset(&sSrc, 0, sizeof(sSrc)); + sSrc.nSrc = 1; + sSrc.a[0].zName = p->zName; + sSrc.a[0].pTab = p; + sSrc.a[0].iCursor = -1; + sNC.pParse = pParse; + sNC.pSrcList = &sSrc; + sNC.isCheck = 1; + if( sqlite3ExprResolveNames(&sNC, p->pCheck) ){ + return; + } + } +#endif /* !defined(SQLITE_OMIT_CHECK) */ + /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number @@ -1318,11 +1465,16 @@ void sqlite3EndTable( ** Once the SELECT has been coded by sqlite3Select(), it is in a ** suitable state to query for the column names and types to be used ** by the new table. + ** + ** A shared-cache write-lock is not required to write to the new table, + ** as a schema-lock must have already been obtained to create it. Since + ** a schema-lock excludes all other database users, the write-lock would + ** be redundant. */ if( pSelect ){ Table *pSelTab; sqlite3VdbeAddOp(v, OP_Dup, 0, 0); - sqlite3VdbeAddOp(v, OP_Integer, p->iDb, 0); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0); @@ -1341,7 +1493,7 @@ void sqlite3EndTable( /* Compute the complete text of the CREATE statement */ if( pSelect ){ - zStmt = createTableStmt(p); + zStmt = createTableStmt(p, p->pSchema==pParse->db->aDb[1].pSchema); }else{ n = pEnd->z - pParse->sNameToken.z + 1; zStmt = sqlite3MPrintf("CREATE %s %.*s", zType2, n, pParse->sNameToken.z); @@ -1357,22 +1509,22 @@ void sqlite3EndTable( "UPDATE %Q.%s " "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#0, sql=%Q " "WHERE rowid=#1", - db->aDb[p->iDb].zName, SCHEMA_TABLE(p->iDb), + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zType, p->zName, p->zName, zStmt ); sqliteFree(zStmt); - sqlite3ChangeCookie(db, v, p->iDb); + sqlite3ChangeCookie(db, v, iDb); #ifndef SQLITE_OMIT_AUTOINCREMENT /* Check to see if we need to create an sqlite_sequence table for ** keeping track of autoincrement keys. */ if( p->autoInc ){ - Db *pDb = &db->aDb[p->iDb]; - if( pDb->pSeqTab==0 ){ + Db *pDb = &db->aDb[iDb]; + if( pDb->pSchema->pSeqTab==0 ){ sqlite3NestedParse(pParse, "CREATE TABLE %Q.sqlite_sequence(name,seq)", pDb->zName @@ -1382,7 +1534,7 @@ void sqlite3EndTable( #endif /* Reparse everything to update our internal data structures */ - sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0, + sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC); } @@ -1392,8 +1544,8 @@ void sqlite3EndTable( if( db->init.busy && pParse->nErr==0 ){ Table *pOld; FKey *pFKey; - Db *pDb = &db->aDb[p->iDb]; - pOld = sqlite3HashInsert(&pDb->tblHash, p->zName, strlen(p->zName)+1, p); + Schema *pSchema = p->pSchema; + pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, strlen(p->zName)+1,p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ return; @@ -1401,8 +1553,8 @@ void sqlite3EndTable( #ifndef SQLITE_OMIT_FOREIGN_KEY for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){ int nTo = strlen(pFKey->zTo) + 1; - pFKey->pNextTo = sqlite3HashFind(&pDb->aFKey, pFKey->zTo, nTo); - sqlite3HashInsert(&pDb->aFKey, pFKey->zTo, nTo, pFKey); + pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo); + sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey); } #endif pParse->pNewTable = 0; @@ -1411,9 +1563,14 @@ void sqlite3EndTable( #ifndef SQLITE_OMIT_ALTERTABLE if( !p->pSelect ){ + const char *zName = (const char *)pParse->sNameToken.z; + int nName; assert( !pSelect && pCons && pEnd ); - if( pCons->z==0 ) pCons = pEnd; - p->addColOffset = 13 + (pCons->z - pParse->sNameToken.z); + if( pCons->z==0 ){ + pCons = pEnd; + } + nName = (const char *)pCons->z - zName; + p->addColOffset = 13 + sqlite3utf8CharLen(zName, nName); } #endif } @@ -1437,20 +1594,22 @@ void sqlite3CreateView( Token sEnd; DbFixer sFix; Token *pName; + int iDb; if( pParse->nVar>0 ){ sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); sqlite3SelectDelete(pSelect); return; } - sqlite3StartTable(pParse, pBegin, pName1, pName2, isTemp, 1); + sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, 0); p = pParse->pNewTable; if( p==0 || pParse->nErr ){ sqlite3SelectDelete(pSelect); return; } sqlite3TwoPartName(pParse, pName1, pName2, &pName); - if( sqlite3FixInit(&sFix, pParse, p->iDb, "view", pName) + iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema); + if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName) && sqlite3FixSelect(&sFix, pSelect) ){ sqlite3SelectDelete(pSelect); @@ -1464,6 +1623,9 @@ void sqlite3CreateView( */ p->pSelect = sqlite3SelectDup(pSelect); sqlite3SelectDelete(pSelect); + if( sqlite3MallocFailed() ){ + return; + } if( !pParse->db->init.busy ){ sqlite3ViewGetColumnNames(pParse, p); } @@ -1488,7 +1650,7 @@ void sqlite3CreateView( } #endif /* SQLITE_OMIT_VIEW */ -#ifndef SQLITE_OMIT_VIEW +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** The Table structure pTable is really a VIEW. Fill in the names of ** the columns of the view in the pTable structure. Return the number @@ -1502,6 +1664,14 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ assert( pTable ); +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( sqlite3VtabCallConnect(pParse, pTable) ){ + return SQLITE_ERROR; + } + if( IsVirtual(pTable) ) return 0; +#endif + +#ifndef SQLITE_OMIT_VIEW /* A positive nCol means the columns names for this view are ** already known. */ @@ -1517,12 +1687,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ ** Actually, this error is caught previously and so the following test ** should always fail. But we will leave it in place just to be safe. */ -#if 0 if( pTable->nCol<0 ){ sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); return 1; } -#endif assert( pTable->nCol>=0 ); /* If we get this far, it means we need to compute the table names. @@ -1534,27 +1702,32 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ */ assert( pTable->pSelect ); pSel = sqlite3SelectDup(pTable->pSelect); - n = pParse->nTab; - sqlite3SrcListAssignCursors(pParse, pSel->pSrc); - pTable->nCol = -1; - pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); - pParse->nTab = n; - if( pSelTab ){ - assert( pTable->aCol==0 ); - pTable->nCol = pSelTab->nCol; - pTable->aCol = pSelTab->aCol; - pSelTab->nCol = 0; - pSelTab->aCol = 0; - sqlite3DeleteTable(0, pSelTab); - DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews); - }else{ - pTable->nCol = 0; + if( pSel ){ + n = pParse->nTab; + sqlite3SrcListAssignCursors(pParse, pSel->pSrc); + pTable->nCol = -1; + pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); + pParse->nTab = n; + if( pSelTab ){ + assert( pTable->aCol==0 ); + pTable->nCol = pSelTab->nCol; + pTable->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(0, pSelTab); + pTable->pSchema->flags |= DB_UnresetViews; + }else{ + pTable->nCol = 0; + nErr++; + } + sqlite3SelectDelete(pSel); + } else { nErr++; } - sqlite3SelectDelete(pSel); +#endif /* SQLITE_OMIT_VIEW */ return nErr; } -#endif /* SQLITE_OMIT_VIEW */ +#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ #ifndef SQLITE_OMIT_VIEW /* @@ -1563,7 +1736,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ static void sqliteViewResetAll(sqlite3 *db, int idx){ HashElem *i; if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; - for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){ + for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); if( pTab->pSelect ){ sqliteResetColumnNames(pTab); @@ -1580,26 +1753,37 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){ ** used by SQLite when the btree layer moves a table root page. The ** root-page of a table or index in database iDb has changed from iFrom ** to iTo. +** +** Ticket #1728: The symbol table might still contain information +** on tables and/or indices that are the process of being deleted. +** If you are unlucky, one of those deleted indices or tables might +** have the same rootpage number as the real table or index that is +** being moved. So we cannot stop searching after the first match +** because the first match might be for one of the deleted indices +** or tables and not the table/index that is actually being moved. +** We must continue looping until all tables and indices with +** rootpage==iFrom have been converted to have a rootpage of iTo +** in order to be certain that we got the right one. */ #ifndef SQLITE_OMIT_AUTOVACUUM void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){ HashElem *pElem; - - for(pElem=sqliteHashFirst(&pDb->tblHash); pElem; pElem=sqliteHashNext(pElem)){ + Hash *pHash; + + pHash = &pDb->pSchema->tblHash; + for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); if( pTab->tnum==iFrom ){ pTab->tnum = iTo; - return; } } - for(pElem=sqliteHashFirst(&pDb->idxHash); pElem; pElem=sqliteHashNext(pElem)){ + pHash = &pDb->pSchema->idxHash; + for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ Index *pIdx = sqliteHashData(pElem); if( pIdx->tnum==iFrom ){ pIdx->tnum = iTo; - return; } } - assert(0); } #endif @@ -1636,9 +1820,10 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){ static void destroyTable(Parse *pParse, Table *pTab){ #ifdef SQLITE_OMIT_AUTOVACUUM Index *pIdx; - destroyRootPage(pParse, pTab->tnum, pTab->iDb); + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + destroyRootPage(pParse, pTab->tnum, iDb); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - destroyRootPage(pParse, pIdx->tnum, pIdx->iDb); + destroyRootPage(pParse, pIdx->tnum, iDb); } #else /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM @@ -1669,14 +1854,18 @@ static void destroyTable(Parse *pParse, Table *pTab){ } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int iIdx = pIdx->tnum; - assert( pIdx->iDb==pTab->iDb ); + assert( pIdx->pSchema==pTab->pSchema ); if( (iDestroyed==0 || (iIdxiLargest ){ iLargest = iIdx; } } - if( iLargest==0 ) return; - destroyRootPage(pParse, iLargest, pTab->iDb); - iDestroyed = iLargest; + if( iLargest==0 ){ + return; + }else{ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + destroyRootPage(pParse, iLargest, iDb); + iDestroyed = iLargest; + } } #endif } @@ -1685,24 +1874,32 @@ static void destroyTable(Parse *pParse, Table *pTab){ ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ -void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ +void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ Table *pTab; Vdbe *v; sqlite3 *db = pParse->db; int iDb; - if( pParse->nErr || sqlite3_malloc_failed ) goto exit_drop_table; + if( pParse->nErr || sqlite3MallocFailed() ){ + goto exit_drop_table; + } assert( pName->nSrc==1 ); pTab = sqlite3LocateTable(pParse, pName->a[0].zName, pName->a[0].zDatabase); - if( pTab==0 ) goto exit_drop_table; - iDb = pTab->iDb; + if( pTab==0 ){ + if( noErr ){ + sqlite3ErrorClear(pParse); + } + goto exit_drop_table; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 && iDbnDb ); #ifndef SQLITE_OMIT_AUTHORIZATION { int code; - const char *zTab = SCHEMA_TABLE(pTab->iDb); - const char *zDb = db->aDb[pTab->iDb].zName; + const char *zTab = SCHEMA_TABLE(iDb); + const char *zDb = db->aDb[iDb].zName; + const char *zArg2 = 0; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ goto exit_drop_table; } @@ -1712,6 +1909,14 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ }else{ code = SQLITE_DROP_VIEW; } +#ifndef SQLITE_OMIT_VIRTUALTABLE + }else if( IsVirtual(pTab) ){ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto exit_drop_table; + } + code = SQLITE_DROP_VTABLE; + zArg2 = pTab->pMod->zName; +#endif }else{ if( !OMIT_TEMPDB && iDb==1 ){ code = SQLITE_DROP_TEMP_TABLE; @@ -1719,7 +1924,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ code = SQLITE_DROP_TABLE; } } - if( sqlite3AuthCheck(pParse, code, pTab->zName, 0, zDb) ){ + if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){ goto exit_drop_table; } if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ @@ -1727,7 +1932,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ } } #endif - if( pTab->readOnly || pTab==db->aDb[iDb].pSeqTab ){ + if( pTab->readOnly || pTab==db->aDb[iDb].pSchema->pSeqTab ){ sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); goto exit_drop_table; } @@ -1752,18 +1957,27 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ v = sqlite3GetVdbe(pParse); if( v ){ Trigger *pTrigger; - int iDb = pTab->iDb; Db *pDb = &db->aDb[iDb]; sqlite3BeginWriteOperation(pParse, 0, iDb); +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp(v, OP_VBegin, 0, 0); + } + } +#endif + /* Drop all triggers associated with the table being dropped. Code ** is generated to remove entries from sqlite_master and/or ** sqlite_temp_master if required. */ pTrigger = pTab->pTrigger; while( pTrigger ){ - assert( pTrigger->iDb==iDb || pTrigger->iDb==1 ); - sqlite3DropTriggerPtr(pParse, pTrigger, 1); + assert( pTrigger->pSchema==pTab->pSchema || + pTrigger->pSchema==db->aDb[1].pSchema ); + sqlite3DropTriggerPtr(pParse, pTrigger); pTrigger = pTrigger->pNext; } @@ -1791,13 +2005,16 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", pDb->zName, SCHEMA_TABLE(iDb), pTab->zName); - if( !isView ){ + if( !isView && !IsVirtual(pTab) ){ destroyTable(pParse, pTab); } /* Remove the table entry from SQLite's internal schema and modify ** the schema cookie. */ + if( IsVirtual(pTab) ){ + sqlite3VdbeOp3(v, OP_VDestroy, iDb, 0, pTab->zName, 0); + } sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0); sqlite3ChangeCookie(db, v, iDb); } @@ -1841,7 +2058,7 @@ void sqlite3CreateForeignKey( char *z; assert( pTo!=0 ); - if( p==0 || pParse->nErr ) goto fk_end; + if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end; if( pFromCol==0 ){ int iCol = p->nCol-1; if( iCol<0 ) goto fk_end; @@ -1958,21 +2175,18 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ int addr1; /* Address of top of loop */ int tnum; /* Root page of index */ Vdbe *v; /* Generate code into this virtual machine */ + KeyInfo *pKey; /* KeyInfo for index */ + int iDb = sqlite3SchemaToIndex(pParse->db, pIndex->pSchema); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, - pParse->db->aDb[pIndex->iDb].zName ) ){ + pParse->db->aDb[iDb].zName ) ){ return; } #endif - /* Ensure all the required collation sequences are available. This - ** routine will invoke the collation-needed callback if necessary (and - ** if one has been registered). - */ - if( sqlite3CheckIndexCollSeq(pParse, pIndex) ){ - return; - } + /* Require a write-lock on the table to perform this operation */ + sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); v = sqlite3GetVdbe(pParse); if( v==0 ) return; @@ -1981,12 +2195,12 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ tnum = 0; }else{ tnum = pIndex->tnum; - sqlite3VdbeAddOp(v, OP_Clear, tnum, pIndex->iDb); + sqlite3VdbeAddOp(v, OP_Clear, tnum, iDb); } - sqlite3VdbeAddOp(v, OP_Integer, pIndex->iDb, 0); - sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum, - (char*)&pIndex->keyInfo, P3_KEYINFO); - sqlite3OpenTableForReading(v, iTab, pTab); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); + pKey = sqlite3IndexKeyinfo(pParse, pIndex); + sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum, (char *)pKey, P3_KEYINFO_HANDOFF); + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0); sqlite3GenerateIndexKey(v, pIndex, iTab); if( pIndex->onError!=OE_None ){ @@ -2027,20 +2241,30 @@ void sqlite3CreateIndex( ExprList *pList, /* A list of columns to be indexed */ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ - Token *pEnd /* The ")" that closes the CREATE INDEX statement */ + Token *pEnd, /* The ")" that closes the CREATE INDEX statement */ + int sortOrder, /* Sort order of primary key when pList==NULL */ + int ifNotExist /* Omit error if index already exists */ ){ - Table *pTab = 0; /* Table to be indexed */ - Index *pIndex = 0; /* The index to be created */ - char *zName = 0; + Table *pTab = 0; /* Table to be indexed */ + Index *pIndex = 0; /* The index to be created */ + char *zName = 0; /* Name of the index */ + int nName; /* Number of characters in zName */ int i, j; - Token nullId; /* Fake token for an empty ID list */ - DbFixer sFix; /* For assigning database names to pTable */ + Token nullId; /* Fake token for an empty ID list */ + DbFixer sFix; /* For assigning database names to pTable */ + int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */ sqlite3 *db = pParse->db; + Db *pDb; /* The specific table containing the indexed database */ + int iDb; /* Index of the database that is being written */ + Token *pName = 0; /* Unqualified name of the index to create */ + struct ExprList_item *pListItem; /* For looping over pList */ + int nCol; + int nExtra = 0; + char *zExtra; - int iDb; /* Index of the database that is being written */ - Token *pName = 0; /* Unqualified name of the index to create */ - - if( pParse->nErr || sqlite3_malloc_failed ) goto exit_create_index; + if( pParse->nErr || sqlite3MallocFailed() || IN_DECLARE_VTAB ){ + goto exit_create_index; + } /* ** Find the table that is to be indexed. Return early if not found. @@ -2060,7 +2284,7 @@ void sqlite3CreateIndex( ** is a temp table. If so, set the database to 1. */ pTab = sqlite3SrcListLookup(pParse, pTblName); - if( pName2 && pName2->n==0 && pTab && pTab->iDb==1 ){ + if( pName2 && pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } #endif @@ -2075,12 +2299,14 @@ void sqlite3CreateIndex( pTab = sqlite3LocateTable(pParse, pTblName->a[0].zName, pTblName->a[0].zDatabase); if( !pTab ) goto exit_create_index; - assert( iDb==pTab->iDb ); + assert( db->aDb[iDb].pSchema==pTab->pSchema ); }else{ assert( pName==0 ); - pTab = pParse->pNewTable; - iDb = pTab->iDb; + pTab = pParse->pNewTable; + if( !pTab ) goto exit_create_index; + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } + pDb = &db->aDb[iDb]; if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ @@ -2093,6 +2319,12 @@ void sqlite3CreateIndex( goto exit_create_index; } #endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + sqlite3ErrorMsg(pParse, "virtual tables may not be indexed"); + goto exit_create_index; + } +#endif /* ** Find the name of the index. Make sure there is not already another @@ -2116,8 +2348,10 @@ void sqlite3CreateIndex( } if( !db->init.busy ){ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; - if( sqlite3FindIndex(db, zName, db->aDb[iDb].zName)!=0 ){ - sqlite3ErrorMsg(pParse, "index %s already exists", zName); + if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ + if( !ifNotExist ){ + sqlite3ErrorMsg(pParse, "index %s already exists", zName); + } goto exit_create_index; } if( sqlite3FindTable(db, zName, 0)!=0 ){ @@ -2140,7 +2374,7 @@ void sqlite3CreateIndex( */ #ifndef SQLITE_OMIT_AUTHORIZATION { - const char *zDb = db->aDb[iDb].zName; + const char *zDb = pDb->zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ goto exit_create_index; } @@ -2157,56 +2391,96 @@ void sqlite3CreateIndex( ** So create a fake list to simulate this. */ if( pList==0 ){ - nullId.z = pTab->aCol[pTab->nCol-1].zName; - nullId.n = strlen(nullId.z); + nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName; + nullId.n = strlen((char*)nullId.z); pList = sqlite3ExprListAppend(0, 0, &nullId); if( pList==0 ) goto exit_create_index; + pList->a[0].sortOrder = sortOrder; + } + + /* Figure out how many bytes of space are required to store explicitly + ** specified collation sequence names. + */ + for(i=0; inExpr; i++){ + Expr *pExpr = pList->a[i].pExpr; + if( pExpr ){ + nExtra += (1 + strlen(pExpr->pColl->zName)); + } } /* ** Allocate the index structure. */ - pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + sizeof(int) + - (sizeof(int)*2 + sizeof(CollSeq*))*pList->nExpr ); - if( sqlite3_malloc_failed ) goto exit_create_index; - pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nExpr]; - pIndex->aiRowEst = (unsigned*)&pIndex->aiColumn[pList->nExpr]; - pIndex->zName = (char*)&pIndex->aiRowEst[pList->nExpr+1]; + nName = strlen(zName); + nCol = pList->nExpr; + pIndex = sqliteMalloc( + sizeof(Index) + /* Index structure */ + sizeof(int)*nCol + /* Index.aiColumn */ + sizeof(int)*(nCol+1) + /* Index.aiRowEst */ + sizeof(char *)*nCol + /* Index.azColl */ + sizeof(u8)*nCol + /* Index.aSortOrder */ + nName + 1 + /* Index.zName */ + nExtra /* Collation sequence names */ + ); + if( sqlite3MallocFailed() ) goto exit_create_index; + pIndex->azColl = (char**)(&pIndex[1]); + pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); + pIndex->aiRowEst = (unsigned *)(&pIndex->aiColumn[nCol]); + pIndex->aSortOrder = (u8 *)(&pIndex->aiRowEst[nCol+1]); + pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); + zExtra = (char *)(&pIndex->zName[nName+1]); strcpy(pIndex->zName, zName); pIndex->pTable = pTab; pIndex->nColumn = pList->nExpr; pIndex->onError = onError; pIndex->autoIndex = pName==0; - pIndex->iDb = iDb; + pIndex->pSchema = db->aDb[iDb].pSchema; + + /* Check to see if we should honor DESC requests on index columns + */ + if( pDb->pSchema->file_format>=4 ){ + sortOrderMask = -1; /* Honor DESC */ + }else{ + sortOrderMask = 0; /* Ignore DESC */ + } /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error ** if any column is not found. */ - for(i=0; inExpr; i++){ - for(j=0; jnCol; j++){ - if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break; + for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ + const char *zColName = pListItem->zName; + Column *pTabCol; + int requestedSortOrder; + char *zColl; /* Collation sequence */ + + for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ + if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; } if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", - pTab->zName, pList->a[i].zName); + pTab->zName, zColName); goto exit_create_index; } pIndex->aiColumn[i] = j; - if( pList->a[i].pExpr ){ - assert( pList->a[i].pExpr->pColl ); - pIndex->keyInfo.aColl[i] = pList->a[i].pExpr->pColl; + if( pListItem->pExpr ){ + assert( pListItem->pExpr->pColl ); + zColl = zExtra; + strcpy(zExtra, pListItem->pExpr->pColl->zName); + zExtra += (strlen(zColl) + 1); }else{ - pIndex->keyInfo.aColl[i] = pTab->aCol[j].pColl; + zColl = pTab->aCol[j].zColl; + if( !zColl ){ + zColl = db->pDfltColl->zName; + } } - assert( pIndex->keyInfo.aColl[i] ); - if( !db->init.busy && - sqlite3CheckCollSeq(pParse, pIndex->keyInfo.aColl[i]) - ){ + if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl, -1) ){ goto exit_create_index; } + pIndex->azColl[i] = zColl; + requestedSortOrder = pListItem->sortOrder & sortOrderMask; + pIndex->aSortOrder[i] = requestedSortOrder; } - pIndex->keyInfo.nField = pList->nExpr; sqlite3DefaultRowEst(pIndex); if( pTab==pParse->pNewTable ){ @@ -2232,8 +2506,11 @@ void sqlite3CreateIndex( if( pIdx->nColumn!=pIndex->nColumn ) continue; for(k=0; knColumn; k++){ + const char *z1 = pIdx->azColl[k]; + const char *z2 = pIndex->azColl[k]; if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; - if( pIdx->keyInfo.aColl[k]!=pIndex->keyInfo.aColl[k] ) break; + if( pIdx->aSortOrder[k]!=pIndex->aSortOrder[k] ) break; + if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break; } if( k==pIdx->nColumn ){ if( pIdx->onError!=pIndex->onError ){ @@ -2262,7 +2539,7 @@ void sqlite3CreateIndex( */ if( db->init.busy ){ Index *p; - p = sqlite3HashInsert(&db->aDb[pIndex->iDb].idxHash, + p = sqlite3HashInsert(&pIndex->pSchema->idxHash, pIndex->zName, strlen(pIndex->zName)+1, pIndex); if( p ){ assert( p==pIndex ); /* Malloc must have failed */ @@ -2297,6 +2574,7 @@ void sqlite3CreateIndex( v = sqlite3GetVdbe(pParse); if( v==0 ) goto exit_create_index; + /* Create the rootpage for the index */ sqlite3BeginWriteOperation(pParse, 1, iDb); @@ -2374,6 +2652,22 @@ exit_create_index: return; } +/* +** Generate code to make sure the file format number is at least minFormat. +** The generated code will increase the file format number if necessary. +*/ +void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ + Vdbe *v; + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); + sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); + sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); + } +} + /* ** Fill the Index.aiRowEst[] array with default information - information ** to be used when we have not run the ANALYZE command. @@ -2397,8 +2691,12 @@ void sqlite3DefaultRowEst(Index *pIdx){ int i; assert( a!=0 ); a[0] = 1000000; - for(i=pIdx->nColumn; i>=1; i--){ - a[i] = 10; + for(i=pIdx->nColumn; i>=5; i--){ + a[i] = 5; + } + while( i>=1 ){ + a[i] = 11 - i; + i--; } if( pIdx->onError!=OE_None ){ a[pIdx->nColumn] = 1; @@ -2409,12 +2707,13 @@ void sqlite3DefaultRowEst(Index *pIdx){ ** This routine will drop an existing named index. This routine ** implements the DROP INDEX statement. */ -void sqlite3DropIndex(Parse *pParse, SrcList *pName){ +void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ Index *pIndex; Vdbe *v; sqlite3 *db = pParse->db; + int iDb; - if( pParse->nErr || sqlite3_malloc_failed ){ + if( pParse->nErr || sqlite3MallocFailed() ){ goto exit_drop_index; } assert( pName->nSrc==1 ); @@ -2423,7 +2722,9 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){ } pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); if( pIndex==0 ){ - sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); + if( !ifExists ){ + sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); + } pParse->checkSchema = 1; goto exit_drop_index; } @@ -2432,16 +2733,17 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){ "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } + iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; - const char *zDb = db->aDb[pIndex->iDb].zName; - const char *zTab = SCHEMA_TABLE(pIndex->iDb); + const char *zDb = db->aDb[iDb].zName; + const char *zTab = SCHEMA_TABLE(iDb); if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ goto exit_drop_index; } - if( !OMIT_TEMPDB && pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX; + if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX; if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ goto exit_drop_index; } @@ -2451,7 +2753,6 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){ /* Generate code to remove the index and from the master table */ v = sqlite3GetVdbe(pParse); if( v ){ - int iDb = pIndex->iDb; sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), @@ -2611,6 +2912,7 @@ SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ pItem->zName = sqlite3NameFromToken(pTable); pItem->zDatabase = sqlite3NameFromToken(pDatabase); pItem->iCursor = -1; + pItem->isPopulated = 0; pList->nSrc++; return pList; } @@ -2621,11 +2923,14 @@ SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; struct SrcList_item *pItem; - for(i=0, pItem=pList->a; inSrc; i++, pItem++){ - if( pItem->iCursor>=0 ) break; - pItem->iCursor = pParse->nTab++; - if( pItem->pSelect ){ - sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); + assert(pList || sqlite3MallocFailed() ); + if( pList ){ + for(i=0, pItem=pList->a; inSrc; i++, pItem++){ + if( pItem->iCursor>=0 ) break; + pItem->iCursor = pParse->nTab++; + if( pItem->pSelect ){ + sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); + } } } } @@ -2667,7 +2972,7 @@ void sqlite3BeginTransaction(Parse *pParse, int type){ int i; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || sqlite3_malloc_failed ) return; + if( pParse->nErr || sqlite3MallocFailed() ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; v = sqlite3GetVdbe(pParse); @@ -2688,7 +2993,7 @@ void sqlite3CommitTransaction(Parse *pParse){ Vdbe *v; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || sqlite3_malloc_failed ) return; + if( pParse->nErr || sqlite3MallocFailed() ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; v = sqlite3GetVdbe(pParse); @@ -2705,7 +3010,7 @@ void sqlite3RollbackTransaction(Parse *pParse){ Vdbe *v; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || sqlite3_malloc_failed ) return; + if( pParse->nErr || sqlite3MallocFailed() ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; v = sqlite3GetVdbe(pParse); @@ -2718,7 +3023,7 @@ void sqlite3RollbackTransaction(Parse *pParse){ ** Make sure the TEMP database is open and available for use. Return ** the number of errors. Leave any error messages in the pParse structure. */ -static int sqlite3OpenTempDatabase(Parse *pParse){ +int sqlite3OpenTempDatabase(Parse *pParse){ sqlite3 *db = pParse->db; if( db->aDb[1].pBt==0 && !pParse->explain ){ int rc = sqlite3BtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt); @@ -2737,6 +3042,7 @@ static int sqlite3OpenTempDatabase(Parse *pParse){ return 1; } } + assert( db->aDb[1].pSchema ); } return 0; } @@ -2777,11 +3083,11 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ if( iDb>=0 ){ assert( iDbnDb ); assert( db->aDb[iDb].pBt!=0 || iDb==1 ); - assert( iDb<32 ); + assert( iDbcookieMask & mask)==0 ){ pParse->cookieMask |= mask; - pParse->cookieValue[iDb] = db->aDb[iDb].schema_cookie; + pParse->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; if( !OMIT_TEMPDB && iDb==1 ){ sqlite3OpenTempDatabase(pParse); } @@ -2825,12 +3131,13 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ ** true if it does and false if it does not. */ #ifndef SQLITE_OMIT_REINDEX -static int collationMatch(CollSeq *pColl, Index *pIndex){ - int n = pIndex->keyInfo.nField; - CollSeq **pp = pIndex->keyInfo.aColl; - while( n-- ){ - if( *pp==pColl ) return 1; - pp++; +static int collationMatch(const char *zColl, Index *pIndex){ + int i; + for(i=0; inColumn; i++){ + const char *z = pIndex->azColl[i]; + if( z==zColl || (z && zColl && 0==sqlite3StrICmp(z, zColl)) ){ + return 1; + } } return 0; } @@ -2841,12 +3148,13 @@ static int collationMatch(CollSeq *pColl, Index *pIndex){ ** If pColl==0 then recompute all indices of pTab. */ #ifndef SQLITE_OMIT_REINDEX -static void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){ +static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){ Index *pIndex; /* An index associated with pTab */ for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ - if( pColl==0 || collationMatch(pColl,pIndex) ){ - sqlite3BeginWriteOperation(pParse, 0, pTab->iDb); + if( zColl==0 || collationMatch(zColl, pIndex) ){ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, pIndex, -1); } } @@ -2859,7 +3167,7 @@ static void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){ ** all indices everywhere. */ #ifndef SQLITE_OMIT_REINDEX -static void reindexDatabases(Parse *pParse, CollSeq *pColl){ +static void reindexDatabases(Parse *pParse, char const *zColl){ Db *pDb; /* A single database */ int iDb; /* The database index number */ sqlite3 *db = pParse->db; /* The database connection */ @@ -2867,10 +3175,10 @@ static void reindexDatabases(Parse *pParse, CollSeq *pColl){ Table *pTab; /* A table in the database */ for(iDb=0, pDb=db->aDb; iDbnDb; iDb++, pDb++){ - if( pDb==0 ) continue; - for(k=sqliteHashFirst(&pDb->tblHash); k; k=sqliteHashNext(k)){ + assert( pDb!=0 ); + for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ pTab = (Table*)sqliteHashData(k); - reindexTable(pParse, pTab, pColl); + reindexTable(pParse, pTab, zColl); } } } @@ -2910,9 +3218,14 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ reindexDatabases(pParse, 0); return; }else if( pName2==0 || pName2->z==0 ){ - pColl = sqlite3FindCollSeq(db, db->enc, pName1->z, pName1->n, 0); + assert( pName1->z ); + pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0); if( pColl ){ - reindexDatabases(pParse, pColl); + char *zColl = sqliteStrNDup((const char *)pName1->z, pName1->n); + if( zColl ){ + reindexDatabases(pParse, zColl); + sqliteFree(zColl); + } return; } } @@ -2936,3 +3249,38 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); } #endif + +/* +** Return a dynamicly allocated KeyInfo structure that can be used +** with OP_OpenRead or OP_OpenWrite to access database index pIdx. +** +** If successful, a pointer to the new structure is returned. In this case +** the caller is responsible for calling sqliteFree() on the returned +** pointer. If an error occurs (out of memory or missing collation +** sequence), NULL is returned and the state of pParse updated to reflect +** the error. +*/ +KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ + int i; + int nCol = pIdx->nColumn; + int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol; + KeyInfo *pKey = (KeyInfo *)sqliteMalloc(nBytes); + + if( pKey ){ + pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]); + assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) ); + for(i=0; iazColl[i]; + assert( zColl ); + pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl, -1); + pKey->aSortOrder[i] = pIdx->aSortOrder[i]; + } + pKey->nField = nCol; + } + + if( pParse->nErr ){ + sqliteFree(pKey); + pKey = 0; + } + return pKey; +} diff --git a/ext/pdo_sqlite/sqlite/src/callback.c b/ext/pdo_sqlite/sqlite/src/callback.c index 2103c3f711..ac748361bb 100644 --- a/ext/pdo_sqlite/sqlite/src/callback.c +++ b/ext/pdo_sqlite/sqlite/src/callback.c @@ -29,17 +29,19 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){ if( db->xCollNeeded ){ char *zExternal = sqliteStrNDup(zName, nName); if( !zExternal ) return; - db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal); + db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal); sqliteFree(zExternal); } #ifndef SQLITE_OMIT_UTF16 if( db->xCollNeeded16 ){ char const *zExternal; - sqlite3_value *pTmp = sqlite3GetTransientValue(db); - sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC); + sqlite3_value *pTmp = sqlite3ValueNew(); + sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC); zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); - if( !zExternal ) return; - db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal); + if( zExternal ){ + db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal); + } + sqlite3ValueFree(pTmp); } #endif } @@ -90,14 +92,14 @@ CollSeq *sqlite3GetCollSeq( p = pColl; if( !p ){ - p = sqlite3FindCollSeq(db, db->enc, zName, nName, 0); + p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0); } if( !p || !p->xCmp ){ /* No collation sequence of this type for this encoding is registered. ** Call the collation factory to see if it can supply us with one. */ callCollNeeded(db, zName, nName); - p = sqlite3FindCollSeq(db, db->enc, zName, nName, 0); + p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0); } if( p && !p->xCmp && synthCollSeq(db, p) ){ p = 0; @@ -128,6 +130,7 @@ int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ pParse->nErr++; return SQLITE_ERROR; } + assert( p==pColl ); } return SQLITE_OK; } @@ -175,8 +178,11 @@ static CollSeq *findCollSeqEntry( ** return the pColl pointer to be deleted (because it wasn't added ** to the hash table). */ - assert( !pDel || (sqlite3_malloc_failed && pDel==pColl) ); - sqliteFree(pDel); + assert( !pDel || (sqlite3MallocFailed() && pDel==pColl) ); + if( pDel ){ + sqliteFree(pDel); + pColl = 0; + } } } return pColl; @@ -197,7 +203,12 @@ CollSeq *sqlite3FindCollSeq( int nName, int create ){ - CollSeq *pColl = findCollSeqEntry(db, zName, nName, create); + CollSeq *pColl; + if( zName ){ + pColl = findCollSeqEntry(db, zName, nName, create); + }else{ + pColl = db->pDfltColl; + } assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); if( pColl ) pColl += enc-1; @@ -286,7 +297,7 @@ FuncDef *sqlite3FindFunction( ** new entry to the hash table and return it. */ if( createFlag && bestmatch<6 && - (pBest = sqliteMalloc(sizeof(*pBest)+nName)) ){ + (pBest = sqliteMalloc(sizeof(*pBest)+nName))!=0 ){ pBest->nArg = nArg; pBest->pNext = pFirst; pBest->iPrefEnc = enc; @@ -303,3 +314,55 @@ FuncDef *sqlite3FindFunction( } return 0; } + +/* +** Free all resources held by the schema structure. The void* argument points +** at a Schema struct. This function does not call sqliteFree() on the +** pointer itself, it just cleans up subsiduary resources (i.e. the contents +** of the schema hash tables). +*/ +void sqlite3SchemaFree(void *p){ + Hash temp1; + Hash temp2; + HashElem *pElem; + Schema *pSchema = (Schema *)p; + + temp1 = pSchema->tblHash; + temp2 = pSchema->trigHash; + sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0); + sqlite3HashClear(&pSchema->aFKey); + sqlite3HashClear(&pSchema->idxHash); + for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ + sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem)); + } + sqlite3HashClear(&temp2); + sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0); + for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ + Table *pTab = sqliteHashData(pElem); + sqlite3DeleteTable(0, pTab); + } + sqlite3HashClear(&temp1); + pSchema->pSeqTab = 0; + pSchema->flags &= ~DB_SchemaLoaded; +} + +/* +** Find and return the schema associated with a BTree. Create +** a new one if necessary. +*/ +Schema *sqlite3SchemaGet(Btree *pBt){ + Schema * p; + if( pBt ){ + p = (Schema *)sqlite3BtreeSchema(pBt,sizeof(Schema),sqlite3SchemaFree); + }else{ + p = (Schema *)sqliteMalloc(sizeof(Schema)); + } + if( p && 0==p->file_format ){ + sqlite3HashInit(&p->tblHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&p->aFKey, SQLITE_HASH_STRING, 1); + p->enc = SQLITE_UTF8; + } + return p; +} diff --git a/ext/pdo_sqlite/sqlite/src/complete.c b/ext/pdo_sqlite/sqlite/src/complete.c new file mode 100644 index 0000000000..660417b066 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/complete.c @@ -0,0 +1,263 @@ +/* +** 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. +** +************************************************************************* +** An tokenizer for SQL +** +** This file contains C code that implements the sqlite3_complete() API. +** This code used to be part of the tokenizer.c source file. But by +** separating it out, the code will be automatically omitted from +** static links that do not use it. +** +** $Id$ +*/ +#include "sqliteInt.h" +#ifndef SQLITE_OMIT_COMPLETE + +/* +** This is defined in tokenize.c. We just have to import the definition. +*/ +extern const char sqlite3IsIdChar[]; +#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20])) + + +/* +** Token types used by the sqlite3_complete() routine. See the header +** comments on that procedure for additional information. +*/ +#define tkSEMI 0 +#define tkWS 1 +#define tkOTHER 2 +#define tkEXPLAIN 3 +#define tkCREATE 4 +#define tkTEMP 5 +#define tkTRIGGER 6 +#define tkEND 7 + +/* +** Return TRUE if the given SQL string ends in a semicolon. +** +** Special handling is require for CREATE TRIGGER statements. +** Whenever the CREATE TRIGGER keywords are seen, the statement +** must end with ";END;". +** +** This implementation uses a state machine with 7 states: +** +** (0) START At the beginning or end of an SQL statement. This routine +** returns 1 if it ends in the START state and 0 if it ends +** in any other state. +** +** (1) NORMAL We are in the middle of statement which ends with a single +** semicolon. +** +** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of +** a statement. +** +** (3) CREATE The keyword CREATE has been seen at the beginning of a +** statement, possibly preceeded by EXPLAIN and/or followed by +** TEMP or TEMPORARY +** +** (4) TRIGGER We are in the middle of a trigger definition that must be +** ended by a semicolon, the keyword END, and another semicolon. +** +** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at +** the end of a trigger definition. +** +** (6) END We've seen the ";END" of the ";END;" that occurs at the end +** of a trigger difinition. +** +** Transitions between states above are determined by tokens extracted +** from the input. The following tokens are significant: +** +** (0) tkSEMI A semicolon. +** (1) tkWS Whitespace +** (2) tkOTHER Any other SQL token. +** (3) tkEXPLAIN The "explain" keyword. +** (4) tkCREATE The "create" keyword. +** (5) tkTEMP The "temp" or "temporary" keyword. +** (6) tkTRIGGER The "trigger" keyword. +** (7) tkEND The "end" keyword. +** +** Whitespace never causes a state transition and is always ignored. +** +** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed +** to recognize the end of a trigger can be omitted. All we have to do +** is look for a semicolon that is not part of an string or comment. +*/ +int sqlite3_complete(const char *zSql){ + u8 state = 0; /* Current state, using numbers defined in header comment */ + u8 token; /* Value of the next token */ + +#ifndef SQLITE_OMIT_TRIGGER + /* A complex statement machine used to detect the end of a CREATE TRIGGER + ** statement. This is the normal case. + */ + static const u8 trans[7][8] = { + /* Token: */ + /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ + /* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, }, + /* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, }, + /* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, }, + /* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, }, + /* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, }, + /* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, }, + /* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, }, + }; +#else + /* If triggers are not suppored by this compile then the statement machine + ** used to detect the end of a statement is much simplier + */ + static const u8 trans[2][3] = { + /* Token: */ + /* State: ** SEMI WS OTHER */ + /* 0 START: */ { 0, 0, 1, }, + /* 1 NORMAL: */ { 0, 1, 1, }, + }; +#endif /* SQLITE_OMIT_TRIGGER */ + + while( *zSql ){ + switch( *zSql ){ + case ';': { /* A semicolon */ + token = tkSEMI; + break; + } + case ' ': + case '\r': + case '\t': + case '\n': + case '\f': { /* White space is ignored */ + token = tkWS; + break; + } + case '/': { /* C-style comments */ + if( zSql[1]!='*' ){ + token = tkOTHER; + break; + } + zSql += 2; + while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } + if( zSql[0]==0 ) return 0; + zSql++; + token = tkWS; + break; + } + case '-': { /* SQL-style comments from "--" to end of line */ + if( zSql[1]!='-' ){ + token = tkOTHER; + break; + } + while( *zSql && *zSql!='\n' ){ zSql++; } + if( *zSql==0 ) return state==0; + token = tkWS; + break; + } + case '[': { /* Microsoft-style identifiers in [...] */ + zSql++; + while( *zSql && *zSql!=']' ){ zSql++; } + if( *zSql==0 ) return 0; + token = tkOTHER; + break; + } + case '`': /* Grave-accent quoted symbols used by MySQL */ + case '"': /* single- and double-quoted strings */ + case '\'': { + int c = *zSql; + zSql++; + while( *zSql && *zSql!=c ){ zSql++; } + if( *zSql==0 ) return 0; + token = tkOTHER; + break; + } + default: { + int c; + if( IdChar((u8)*zSql) ){ + /* Keywords and unquoted identifiers */ + int nId; + for(nId=1; IdChar(zSql[nId]); nId++){} +#ifdef SQLITE_OMIT_TRIGGER + token = tkOTHER; +#else + switch( *zSql ){ + case 'c': case 'C': { + if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){ + token = tkCREATE; + }else{ + token = tkOTHER; + } + break; + } + case 't': case 'T': { + if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){ + token = tkTRIGGER; + }else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){ + token = tkTEMP; + }else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){ + token = tkTEMP; + }else{ + token = tkOTHER; + } + break; + } + case 'e': case 'E': { + if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){ + token = tkEND; + }else +#ifndef SQLITE_OMIT_EXPLAIN + if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){ + token = tkEXPLAIN; + }else +#endif + { + token = tkOTHER; + } + break; + } + default: { + token = tkOTHER; + break; + } + } +#endif /* SQLITE_OMIT_TRIGGER */ + zSql += nId-1; + }else{ + /* Operators and special symbols */ + token = tkOTHER; + } + break; + } + } + state = trans[state][token]; + zSql++; + } + return state==0; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** This routine is the same as the sqlite3_complete() routine described +** above, except that the parameter is required to be UTF-16 encoded, not +** UTF-8. +*/ +int sqlite3_complete16(const void *zSql){ + sqlite3_value *pVal; + char const *zSql8; + int rc = 0; + + pVal = sqlite3ValueNew(); + sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); + zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); + if( zSql8 ){ + rc = sqlite3_complete(zSql8); + } + sqlite3ValueFree(pVal); + return sqlite3ApiExit(0, rc); +} +#endif /* SQLITE_OMIT_UTF16 */ +#endif /* SQLITE_OMIT_COMPLETE */ diff --git a/ext/pdo_sqlite/sqlite/src/date.c b/ext/pdo_sqlite/sqlite/src/date.c index 7d398df489..9146906181 100644 --- a/ext/pdo_sqlite/sqlite/src/date.c +++ b/ext/pdo_sqlite/sqlite/src/date.c @@ -105,18 +105,20 @@ static int getDigits(const char *zDate, ...){ val = 0; while( N-- ){ if( !isdigit(*(u8*)zDate) ){ - return cnt; + goto end_getDigits; } val = val*10 + *zDate - '0'; zDate++; } if( valmax || (nextC!=0 && nextC!=*zDate) ){ - return cnt; + goto end_getDigits; } *pVal = val; zDate++; cnt++; }while( nextC ); +end_getDigits: + va_end(ap); return cnt; } @@ -236,7 +238,7 @@ static void computeJD(DateTime *p){ if( p->validHMS ){ p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0; if( p->validTZ ){ - p->rJD += p->tz*60/86400.0; + p->rJD -= p->tz*60/86400.0; p->validHMS = 0; p->validTZ = 0; } @@ -639,10 +641,10 @@ static int isDate(int argc, sqlite3_value **argv, DateTime *p){ int i; if( argc==0 ) return 1; if( SQLITE_NULL==sqlite3_value_type(argv[0]) || - parseDateOrTime(sqlite3_value_text(argv[0]), p) ) return 1; + parseDateOrTime((char*)sqlite3_value_text(argv[0]), p) ) return 1; for(i=1; ireadOnly && (pParse->db->flags & SQLITE_WriteSchema)==0 - && pParse->nested==0 ){ + if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0 + && pParse->nested==0) +#ifndef SQLITE_OMIT_VIRTUALTABLE + || (pTab->pMod && pTab->pMod->pModule->xUpdate==0) +#endif + ){ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } @@ -59,14 +63,21 @@ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ /* ** Generate code that will open a table for reading. */ -void sqlite3OpenTableForReading( - Vdbe *v, /* Generate code into this VDBE */ +void sqlite3OpenTable( + Parse *p, /* Generate code into this VDBE */ int iCur, /* The cursor number of the table */ - Table *pTab /* The table to be opened */ + int iDb, /* The database index in sqlite3.aDb[] */ + Table *pTab, /* The table to be opened */ + int opcode /* OP_OpenRead or OP_OpenWrite */ ){ - sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); + Vdbe *v; + if( IsVirtual(pTab) ) return; + v = sqlite3GetVdbe(p); + assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); + sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); VdbeComment((v, "# %s", pTab->zName)); - sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); + sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum); sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol); } @@ -95,6 +106,7 @@ void sqlite3DeleteFrom( AuthContext sContext; /* Authorization context */ int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ NameContext sNC; /* Name context to resolve expressions in */ + int iDb; #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ @@ -102,7 +114,7 @@ void sqlite3DeleteFrom( #endif sContext.pParse = 0; - if( pParse->nErr || sqlite3_malloc_failed ){ + if( pParse->nErr || sqlite3MallocFailed() ){ goto delete_from_cleanup; } db = pParse->db; @@ -134,15 +146,16 @@ void sqlite3DeleteFrom( if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ goto delete_from_cleanup; } - assert( pTab->iDbnDb ); - zDb = db->aDb[pTab->iDb].zName; + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDbnDb ); + zDb = db->aDb[iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ goto delete_from_cleanup; } /* If pTab is really a view, make sure it has been initialized. */ - if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto delete_from_cleanup; } @@ -176,14 +189,14 @@ void sqlite3DeleteFrom( goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb); + sqlite3BeginWriteOperation(pParse, triggers_exist, iDb); /* If we are trying to delete from a view, realize that view into ** a ephemeral table. */ if( isView ){ Select *pView = sqlite3SelectDup(pTab->pSelect); - sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0); + sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0); sqlite3SelectDelete(pView); } @@ -198,40 +211,36 @@ void sqlite3DeleteFrom( ** It is easier just to erase the whole table. Note, however, that ** this means that the row change count will be incorrect. */ - if( pWhere==0 && !triggers_exist ){ + if( pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){ if( db->flags & SQLITE_CountRows ){ /* If counting rows deleted, just count the total number of ** entries in the table. */ int endOfLoop = sqlite3VdbeMakeLabel(v); - int addr; + int addr2; if( !isView ){ - sqlite3OpenTableForReading(v, iCur, pTab); + sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); } sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2); - addr = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); - sqlite3VdbeAddOp(v, OP_Next, iCur, addr); + addr2 = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); + sqlite3VdbeAddOp(v, OP_Next, iCur, addr2); sqlite3VdbeResolveLabel(v, endOfLoop); sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } if( !isView ){ - sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb); + sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, iDb); + if( !pParse->nested ){ + sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); + } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb); + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, iDb); } } - } - + } /* The usual case: There is a WHERE clause so we have to scan through ** the table and pick which records to delete. */ else{ - /* Ensure all required collation sequences are available. */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){ - goto delete_from_cleanup; - } - } - /* Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0); @@ -239,7 +248,7 @@ void sqlite3DeleteFrom( /* Remember the rowid of every item to be deleted. */ - sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); + sqlite3VdbeAddOp(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, 0); sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0); if( db->flags & SQLITE_CountRows ){ sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); @@ -269,7 +278,7 @@ void sqlite3DeleteFrom( addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end); if( !isView ){ sqlite3VdbeAddOp(v, OP_Dup, 0, 0); - sqlite3OpenTableForReading(v, iCur, pTab); + sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); } sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); @@ -300,7 +309,15 @@ void sqlite3DeleteFrom( } /* Delete the row */ - sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0); +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + pParse->pVirtualLock = pTab; + sqlite3VdbeOp3(v, OP_VUpdate, 0, 1, (const char*)pTab->pVtab, P3_VTAB); + }else +#endif + { + sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0); + } } /* If there are row triggers, close all cursors then invoke @@ -323,7 +340,7 @@ void sqlite3DeleteFrom( sqlite3VdbeResolveLabel(v, end); /* Close the cursors after the loop if there are no row triggers */ - if( !triggers_exist ){ + if( !triggers_exist && !IsVirtual(pTab) ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } @@ -339,7 +356,7 @@ void sqlite3DeleteFrom( if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ sqlite3VdbeAddOp(v, OP_Callback, 1, 0); sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "rows deleted", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC); } delete_from_cleanup: @@ -378,8 +395,11 @@ void sqlite3GenerateRowDelete( ){ int addr; addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0); - sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0); + sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0); sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); + if( count ){ + sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); + } sqlite3VdbeJumpHere(v, addr); } @@ -400,7 +420,6 @@ void sqlite3GenerateRowDelete( ** deleted. */ void sqlite3GenerateRowIndexDelete( - sqlite3 *db, /* The database containing the index */ Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ int iCur, /* Cursor number for the table */ diff --git a/ext/pdo_sqlite/sqlite/src/experimental.c b/ext/pdo_sqlite/sqlite/src/experimental.c deleted file mode 100644 index ec40891a3a..0000000000 --- a/ext/pdo_sqlite/sqlite/src/experimental.c +++ /dev/null @@ -1,37 +0,0 @@ -/* -** 2005 January 20 -** -** 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 not a part of the official -** SQLite API. These routines are unsupported. -** -** $Id$ -*/ -#include "sqliteInt.h" -#include "os.h" - -/* -** Set all the parameters in the compiled SQL statement to NULL. -*/ -int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ - int i; - int rc = SQLITE_OK; - for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){ - rc = sqlite3_bind_null(pStmt, i); - } - return rc; -} - -/* -** Sleep for a little while. Return the amount of time slept. -*/ -int sqlite3_sleep(int ms){ - return sqlite3OsSleep(ms); -} diff --git a/ext/pdo_sqlite/sqlite/src/expr.c b/ext/pdo_sqlite/sqlite/src/expr.c index 1276fe9f6a..e26aba5b38 100644 --- a/ext/pdo_sqlite/sqlite/src/expr.c +++ b/ext/pdo_sqlite/sqlite/src/expr.c @@ -75,12 +75,10 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ char sqlite3CompareAffinity(Expr *pExpr, char aff2){ char aff1 = sqlite3ExprAffinity(pExpr); if( aff1 && aff2 ){ - /* Both sides of the comparison are columns. If one has numeric or - ** integer affinity, use that. Otherwise use no affinity. + /* Both sides of the comparison are columns. If one has numeric + ** affinity, use that. Otherwise use no affinity. */ - if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){ - return SQLITE_AFF_INTEGER; - }else if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){ + if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ return SQLITE_AFF_NUMERIC; }else{ return SQLITE_AFF_NONE; @@ -89,7 +87,6 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){ /* Neither side of the comparison is a column. Compare the ** results directly. */ - /* return SQLITE_AFF_NUMERIC; // Ticket #805 */ return SQLITE_AFF_NONE; }else{ /* One side is a column, the other is not. Use the columns affinity. */ @@ -129,11 +126,14 @@ static char comparisonAffinity(Expr *pExpr){ */ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ char aff = comparisonAffinity(pExpr); - return - (aff==SQLITE_AFF_NONE) || - (aff==SQLITE_AFF_NUMERIC && idx_affinity==SQLITE_AFF_INTEGER) || - (aff==SQLITE_AFF_INTEGER && idx_affinity==SQLITE_AFF_NUMERIC) || - (aff==idx_affinity); + switch( aff ){ + case SQLITE_AFF_NONE: + return 1; + case SQLITE_AFF_TEXT: + return idx_affinity==SQLITE_AFF_TEXT; + default: + return sqlite3IsNumericAffinity(idx_affinity); + } } /* @@ -211,6 +211,19 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){ return pNew; } +/* +** Works like sqlite3Expr() but frees its pLeft and pRight arguments +** if it fails due to a malloc problem. +*/ +Expr *sqlite3ExprOrFree(int op, Expr *pLeft, Expr *pRight, const Token *pToken){ + Expr *pNew = sqlite3Expr(op, pLeft, pRight, pToken); + if( pNew==0 ){ + sqlite3ExprDelete(pLeft); + sqlite3ExprDelete(pRight); + } + return pNew; +} + /* ** When doing a nested parse, you can include terms in an expression ** that look like this: #0 #1 #2 ... These terms refer to elements @@ -235,7 +248,7 @@ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){ if( p==0 ){ return 0; /* Malloc failed */ } - depth = atoi(&pToken->z[1]); + depth = atoi((char*)&pToken->z[1]); p->iTable = pParse->nMem++; sqlite3VdbeAddOp(v, OP_Dup, depth, 0); sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1); @@ -263,7 +276,7 @@ Expr *sqlite3ExprAnd(Expr *pLeft, Expr *pRight){ void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ assert( pRight!=0 ); assert( pLeft!=0 ); - if( !sqlite3_malloc_failed && pRight->z && pLeft->z ){ + if( !sqlite3MallocFailed() && pRight->z && pLeft->z ){ assert( pLeft->dyn==0 || pLeft->z[pLeft->n]==0 ); if( pLeft->dyn==0 && pRight->dyn==0 ){ pExpr->span.z = pLeft->z; @@ -280,6 +293,7 @@ void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ */ Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){ Expr *pNew; + assert( pToken ); pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ sqlite3ExprListDelete(pList); /* Avoid leaking memory when malloc fails */ @@ -287,12 +301,8 @@ Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){ } pNew->op = TK_FUNCTION; pNew->pList = pList; - if( pToken ){ - assert( pToken->dyn==0 ); - pNew->token = *pToken; - }else{ - pNew->token.z = 0; - } + assert( pToken->dyn==0 ); + pNew->token = *pToken; pNew->span = pNew->token; return pNew; } @@ -327,7 +337,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ /* Wildcard of the form "?nnn". Convert "nnn" to an integer and ** use it as the variable number */ int i; - pExpr->iTable = i = atoi(&pToken->z[1]); + pExpr->iTable = i = atoi((char*)&pToken->z[1]); if( i<1 || i>SQLITE_MAX_VARIABLE_NUMBER ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", SQLITE_MAX_VARIABLE_NUMBER); @@ -355,10 +365,10 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ pExpr->iTable = ++pParse->nVar; if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; - sqlite3ReallocOrFree((void**)&pParse->apVarExpr, + sqliteReallocOrFree((void**)&pParse->apVarExpr, pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) ); } - if( !sqlite3_malloc_failed ){ + if( !sqlite3MallocFailed() ){ assert( pParse->apVarExpr!=0 ); pParse->apVarExpr[pParse->nVarExpr++] = pExpr; } @@ -415,7 +425,7 @@ Expr *sqlite3ExprDup(Expr *p){ if( pNew==0 ) return 0; memcpy(pNew, p, sizeof(*pNew)); if( p->token.z!=0 ){ - pNew->token.z = sqliteStrNDup(p->token.z, p->token.n); + pNew->token.z = (u8*)sqliteStrNDup((char*)p->token.z, p->token.n); pNew->token.dyn = 1; }else{ assert( pNew->token.z==0 ); @@ -432,7 +442,7 @@ void sqlite3TokenCopy(Token *pTo, Token *pFrom){ if( pTo->dyn ) sqliteFree((char*)pTo->z); if( pFrom->z ){ pTo->n = pFrom->n; - pTo->z = sqliteStrNDup(pFrom->z, pFrom->n); + pTo->z = (u8*)sqliteStrNDup((char*)pFrom->z, pFrom->n); pTo->dyn = 1; }else{ pTo->z = 0; @@ -462,7 +472,8 @@ ExprList *sqlite3ExprListDup(ExprList *p){ sqlite3TokenCopy(&pNewExpr->span, &pOldExpr->span); } assert( pNewExpr==0 || pNewExpr->span.z!=0 - || pOldExpr->span.z==0 || sqlite3_malloc_failed ); + || pOldExpr->span.z==0 + || sqlite3MallocFailed() ); pItem->zName = sqliteStrDup(pOldItem->zName); pItem->sortOrder = pOldItem->sortOrder; pItem->isAgg = pOldItem->isAgg; @@ -497,6 +508,7 @@ SrcList *sqlite3SrcListDup(SrcList *p){ pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; + pNewItem->isPopulated = pOldItem->isPopulated; pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nRef++; @@ -548,12 +560,12 @@ Select *sqlite3SelectDup(Select *p){ pNew->iOffset = -1; pNew->isResolved = p->isResolved; pNew->isAgg = p->isAgg; - pNew->usesVirt = 0; + pNew->usesEphm = 0; pNew->disallowOrderBy = 0; pNew->pRightmost = 0; - pNew->addrOpenVirt[0] = -1; - pNew->addrOpenVirt[1] = -1; - pNew->addrOpenVirt[2] = -1; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->addrOpenEphm[2] = -1; return pNew; } #else @@ -752,7 +764,7 @@ int sqlite3ExprIsConstantOrFunction(Expr *p){ int sqlite3ExprIsInteger(Expr *p, int *pValue){ switch( p->op ){ case TK_INTEGER: { - if( sqlite3GetInt32(p->token.z, pValue) ){ + if( sqlite3GetInt32((char*)p->token.z, pValue) ){ return 1; } break; @@ -809,7 +821,7 @@ int sqlite3IsRowid(const char *z){ ** in pParse and return non-zero. Return zero on success. */ static int lookupName( - Parse *pParse, /* The parsing context */ + Parse *pParse, /* The parsing context */ Token *pDbToken, /* Name of the database containing table, or NULL */ Token *pTableToken, /* Name of table containing column, or NULL */ Token *pColumnToken, /* Name of the column. */ @@ -831,22 +843,24 @@ static int lookupName( zDb = sqlite3NameFromToken(pDbToken); zTab = sqlite3NameFromToken(pTableToken); zCol = sqlite3NameFromToken(pColumnToken); - if( sqlite3_malloc_failed ){ + if( sqlite3MallocFailed() ){ goto lookupname_end; } pExpr->iTable = -1; while( pNC && cnt==0 ){ + ExprList *pEList; SrcList *pSrcList = pNC->pSrcList; - ExprList *pEList = pNC->pEList; - /* assert( zTab==0 || pEList==0 ); */ if( pSrcList ){ for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ - Table *pTab = pItem->pTab; + Table *pTab; + int iDb; Column *pCol; - if( pTab==0 ) continue; + pTab = pItem->pTab; + assert( pTab!=0 ); + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( pTab->nCol>0 ); if( zTab ){ if( pItem->zAlias ){ @@ -855,27 +869,28 @@ static int lookupName( }else{ char *zTabName = pTab->zName; if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue; - if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){ + if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ continue; } } } if( 0==(cntTab++) ){ pExpr->iTable = pItem->iCursor; - pExpr->iDb = pTab->iDb; + pExpr->pSchema = pTab->pSchema; pMatch = pItem; } for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + const char *zColl = pTab->aCol[j].zColl; IdList *pUsing; cnt++; pExpr->iTable = pItem->iCursor; pMatch = pItem; - pExpr->iDb = pTab->iDb; + pExpr->pSchema = pTab->pSchema; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->affinity = pTab->aCol[j].affinity; - pExpr->pColl = pTab->aCol[j].pColl; + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); if( pItem->jointype & JT_NATURAL ){ /* If this match occurred in the left table of a natural join, ** then skip the right table to avoid a duplicate match */ @@ -919,17 +934,18 @@ static int lookupName( } if( pTab ){ - int j; + int iCol; Column *pCol = pTab->aCol; - pExpr->iDb = pTab->iDb; + pExpr->pSchema = pTab->pSchema; cntTab++; - for(j=0; j < pTab->nCol; j++, pCol++) { + for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) { if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + const char *zColl = pTab->aCol[iCol].zColl; cnt++; - pExpr->iColumn = j==pTab->iPKey ? -1 : j; - pExpr->affinity = pTab->aCol[j].affinity; - pExpr->pColl = pTab->aCol[j].pColl; + pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol; + pExpr->affinity = pTab->aCol[iCol].affinity; + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); pExpr->pTab = pTab; break; } @@ -959,7 +975,7 @@ static int lookupName( ** Note that the expression in the result set should have already been ** resolved by the time the WHERE clause is resolved. */ - if( cnt==0 && pEList!=0 && zTab==0 ){ + if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){ for(j=0; jnExpr; j++){ char *zAs = pEList->a[j].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ @@ -1006,9 +1022,9 @@ static int lookupName( char *zErr; zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s"; if( zDb ){ - sqlite3SetString(&z, zDb, ".", zTab, ".", zCol, 0); + sqlite3SetString(&z, zDb, ".", zTab, ".", zCol, (char*)0); }else if( zTab ){ - sqlite3SetString(&z, zTab, ".", zCol, 0); + sqlite3SetString(&z, zTab, ".", zCol, (char*)0); }else{ z = sqliteStrDup(zCol); } @@ -1077,20 +1093,19 @@ lookupname_end_2: */ static int nameResolverStep(void *pArg, Expr *pExpr){ NameContext *pNC = (NameContext*)pArg; - SrcList *pSrcList; Parse *pParse; if( pExpr==0 ) return 1; assert( pNC!=0 ); - pSrcList = pNC->pSrcList; pParse = pNC->pParse; if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1; ExprSetProperty(pExpr, EP_Resolved); #ifndef NDEBUG - if( pSrcList ){ + if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ + SrcList *pSrcList = pNC->pSrcList; int i; - for(i=0; inSrc; i++){ + for(i=0; ipSrcList->nSrc; i++){ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab); } } @@ -1149,9 +1164,9 @@ static int nameResolverStep(void *pArg, Expr *pExpr){ int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ - int enc = pParse->db->enc; /* The database encoding */ + int enc = ENC(pParse->db); /* The database encoding */ - zId = pExpr->token.z; + zId = (char*)pExpr->token.z; nId = pExpr->token.n; pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ @@ -1197,13 +1212,27 @@ static int nameResolverStep(void *pArg, Expr *pExpr){ case TK_IN: { if( pExpr->pSelect ){ int nRef = pNC->nRef; +#ifndef SQLITE_OMIT_CHECK + if( pNC->isCheck ){ + sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints"); + } +#endif sqlite3SelectResolve(pParse, pExpr->pSelect, pNC); assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); } } + break; + } +#ifndef SQLITE_OMIT_CHECK + case TK_VARIABLE: { + if( pNC->isCheck ){ + sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints"); + } + break; } +#endif } return 0; } @@ -1261,17 +1290,16 @@ struct QueryCoder { /* -** Generate code for subqueries and IN operators. +** Generate code for scalar subqueries used as an expression +** and IN operators. Examples: ** -** IN operators comes in two forms: +** (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 ** -** expr IN (exprlist) -** and -** expr IN (SELECT ...) -** -** The first form is handled by creating a set holding the list -** of allowed values. The second form causes the SELECT to generate -** a temporary table. +** The pExpr parameter describes the expression that contains the IN +** operator or subquery. */ #ifndef SQLITE_OMIT_SUBQUERY void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ @@ -1293,7 +1321,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ int mem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0); testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0); - assert( testAddr>0 || sqlite3_malloc_failed ); + assert( testAddr>0 || sqlite3MallocFailed() ); sqlite3VdbeAddOp(v, OP_MemInt, 1, mem); } @@ -1301,7 +1329,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ case TK_IN: { char affinity; KeyInfo keyInfo; - int addr; /* Address of OP_OpenVirtual instruction */ + int addr; /* Address of OP_OpenEphemeral instruction */ affinity = sqlite3ExprAffinity(pExpr->pLeft); @@ -1319,7 +1347,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ ** is used. */ pExpr->iTable = pParse->nTab++; - addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, pExpr->iTable, 0); + addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, pExpr->iTable, 0); memset(&keyInfo, 0, sizeof(keyInfo)); keyInfo.nField = 1; sqlite3VdbeAddOp(v, OP_SetNumColumns, pExpr->iTable, 1); @@ -1352,7 +1380,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ struct ExprList_item *pItem; if( !affinity ){ - affinity = SQLITE_AFF_NUMERIC; + affinity = SQLITE_AFF_NONE; } keyInfo.aColl[0] = pExpr->pLeft->pColl; @@ -1366,11 +1394,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ ** expression we need to rerun this code each time. */ if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){ - VdbeOp *aOp = sqlite3VdbeGetOp(v, testAddr-1); - int i; - for(i=0; i<3; i++){ - aOp[i].opcode = OP_Noop; - } + sqlite3VdbeChangeToNoop(v, testAddr-1, 3); testAddr = 0; } @@ -1390,21 +1414,25 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ - int sop; + static const Token one = { (u8*)"1", 0, 1 }; Select *pSel; + int iMem; + int sop; - pExpr->iColumn = pParse->nMem++; + pExpr->iColumn = iMem = pParse->nMem++; pSel = pExpr->pSelect; if( pExpr->op==TK_SELECT ){ sop = SRT_Mem; + sqlite3VdbeAddOp(v, OP_MemNull, iMem, 0); + VdbeComment((v, "# Init subquery result")); }else{ - static const Token one = { "1", 0, 1 }; sop = SRT_Exists; - sqlite3ExprListDelete(pSel->pEList); - pSel->pEList = sqlite3ExprListAppend(0, - sqlite3Expr(TK_INTEGER, 0, 0, &one), 0); + sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem); + VdbeComment((v, "# Init EXISTS result")); } - sqlite3Select(pParse, pSel, sop, pExpr->iColumn, 0, 0, 0, 0); + sqlite3ExprDelete(pSel->pLimit); + pSel->pLimit = sqlite3Expr(TK_INTEGER, 0, 0, &one); + sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0); break; } } @@ -1444,6 +1472,8 @@ static void codeInteger(Vdbe *v, const char *z, int n){ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ Vdbe *v = pParse->pVdbe; int op; + int stackChng = 1; /* Amount of change to stack depth */ + if( v==0 ) return; if( pExpr==0 ){ sqlite3VdbeAddOp(v, OP_Null, 0, 0); @@ -1465,16 +1495,30 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ /* Otherwise, fall thru into the TK_COLUMN case */ } case TK_COLUMN: { - if( pExpr->iColumn>=0 ){ - sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); - sqlite3ColumnDefault(v, pExpr->pTab, pExpr->iColumn); + if( pExpr->iTable<0 ){ + /* This only happens when coding check constraints */ + assert( pParse->ckOffset>0 ); + sqlite3VdbeAddOp(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1); + }else if( pExpr->iColumn>=0 ){ + Table *pTab = pExpr->pTab; + int iCol = pExpr->iColumn; + int op = (pTab && IsVirtual(pTab)) ? OP_VColumn : OP_Column; + sqlite3VdbeAddOp(v, op, pExpr->iTable, iCol); + sqlite3ColumnDefault(v, pTab, iCol); +#ifndef SQLITE_OMIT_FLOATING_POINT + if( pTab && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp(v, OP_RealAffinity, 0, 0); + } +#endif }else{ - sqlite3VdbeAddOp(v, OP_Rowid, pExpr->iTable, 0); + Table *pTab = pExpr->pTab; + int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid; + sqlite3VdbeAddOp(v, op, pExpr->iTable, 0); } break; } case TK_INTEGER: { - codeInteger(v, pExpr->token.z, pExpr->token.n); + codeInteger(v, (char*)pExpr->token.z, pExpr->token.n); break; } case TK_FLOAT: @@ -1482,7 +1526,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ assert( TK_FLOAT==OP_Real ); assert( TK_STRING==OP_String8 ); sqlite3DequoteExpr(pExpr); - sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z, pExpr->token.n); + sqlite3VdbeOp3(v, op, 0, 0, (char*)pExpr->token.z, pExpr->token.n); break; } case TK_NULL: { @@ -1495,7 +1539,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ const char *z; assert( TK_BLOB==OP_HexBlob ); n = pExpr->token.n - 3; - z = pExpr->token.z + 2; + z = (char*)pExpr->token.z + 2; assert( n>=0 ); if( n==0 ){ z = ""; @@ -1507,7 +1551,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ case TK_VARIABLE: { sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0); if( pExpr->token.n>1 ){ - sqlite3VdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n); + sqlite3VdbeChangeP3(v, -1, (char*)pExpr->token.z, pExpr->token.n); } break; } @@ -1518,16 +1562,17 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ - int aff, op; + int aff, to_op; sqlite3ExprCode(pParse, pExpr->pLeft); aff = sqlite3AffinityType(&pExpr->token); - switch( aff ){ - case SQLITE_AFF_INTEGER: op = OP_ToInt; break; - case SQLITE_AFF_NUMERIC: op = OP_ToNumeric; break; - case SQLITE_AFF_TEXT: op = OP_ToText; break; - case SQLITE_AFF_NONE: op = OP_ToBlob; break; - } - sqlite3VdbeAddOp(v, op, 0, 0); + to_op = aff - SQLITE_AFF_TEXT + OP_ToText; + assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); + assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); + assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); + assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); + assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL ); + sqlite3VdbeAddOp(v, to_op, 0, 0); + stackChng = 0; break; } #endif /* SQLITE_OMIT_CAST */ @@ -1546,6 +1591,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0); + stackChng = -1; break; } case TK_AND: @@ -1574,6 +1620,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); sqlite3VdbeAddOp(v, op, 0, 0); + stackChng = -1; break; } case TK_UMINUS: { @@ -1581,8 +1628,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ assert( pLeft ); if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){ Token *p = &pLeft->token; - char *z = sqliteMalloc( p->n + 2 ); - sprintf(z, "-%.*s", p->n, p->z); + char *z = sqlite3MPrintf("-%.*s", p->n, p->z); if( pLeft->op==TK_FLOAT ){ sqlite3VdbeOp3(v, OP_Real, 0, 0, z, p->n+1); }else{ @@ -1599,6 +1645,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ assert( TK_NOT==OP_Not ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3VdbeAddOp(v, op, 0, 0); + stackChng = 0; break; } case TK_ISNULL: @@ -1611,11 +1658,17 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ dest = sqlite3VdbeCurrentAddr(v) + 2; sqlite3VdbeAddOp(v, op, 1, dest); sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); + stackChng = 0; break; } case TK_AGG_FUNCTION: { AggInfo *pInfo = pExpr->pAggInfo; - sqlite3VdbeAddOp(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem, 0); + if( pInfo==0 ){ + sqlite3ErrorMsg(pParse, "misuse of aggregate: %T", + &pExpr->span); + }else{ + sqlite3VdbeAddOp(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem, 0); + } break; } case TK_CONST_FUNC: @@ -1627,13 +1680,32 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ const char *zId; int constMask = 0; int i; - u8 enc = pParse->db->enc; + u8 enc = ENC(pParse->db); CollSeq *pColl = 0; - zId = pExpr->token.z; + zId = (char*)pExpr->token.z; nId = pExpr->token.n; pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0); assert( pDef!=0 ); nExpr = sqlite3ExprCodeExprList(pParse, pList); +#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( nExpr>=2 && (pExpr->flags & EP_InfixFunc) ){ + pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[1].pExpr); + }else if( nExpr>0 ){ + pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[0].pExpr); + } +#endif for(i=0; ia[i].pExpr) ){ constMask |= (1<iColumn==0 ){ + sqlite3CodeSubselect(pParse, pExpr); + } sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); VdbeComment((v, "# load subquery result")); break; @@ -1660,6 +1735,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ case TK_IN: { int addr; char affinity; + int ckOffset = pParse->ckOffset; sqlite3CodeSubselect(pParse, pExpr); /* Figure out the affinity to use to create a key from the results @@ -1669,6 +1745,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ affinity = comparisonAffinity(pExpr); sqlite3VdbeAddOp(v, OP_Integer, 1, 0); + pParse->ckOffset = ckOffset+1; /* Code the from " IN (...)". The temporary table ** pExpr->iTable contains the values that make up the (...) set. @@ -1705,6 +1782,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ case TK_UPLUS: case TK_AS: { sqlite3ExprCode(pParse, pExpr->pLeft); + stackChng = 0; break; } case TK_CASE: { @@ -1763,16 +1841,22 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ pExpr->iColumn == OE_Fail ); sqlite3DequoteExpr(pExpr); sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, - pExpr->token.z, pExpr->token.n); + (char*)pExpr->token.z, pExpr->token.n); } else { assert( pExpr->iColumn == OE_Ignore ); sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump); VdbeComment((v, "# raise(IGNORE)")); } + stackChng = 0; + break; } #endif - break; + } + + if( pParse->ckOffset ){ + pParse->ckOffset += stackChng; + assert( pParse->ckOffset ); } } @@ -1840,6 +1924,7 @@ int sqlite3ExprCodeExprList( void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; + int ckOffset = pParse->ckOffset; if( v==0 || pExpr==0 ) return; op = pExpr->op; switch( op ){ @@ -1914,6 +1999,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ break; } } + pParse->ckOffset = ckOffset; } /* @@ -1927,6 +2013,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; + int ckOffset = pParse->ckOffset; if( v==0 || pExpr==0 ) return; /* The value of pExpr->op and op are related as follows: @@ -2023,6 +2110,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ break; } } + pParse->ckOffset = ckOffset; } /* @@ -2031,10 +2119,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ */ int sqlite3ExprCompare(Expr *pA, Expr *pB){ int i; - if( pA==0 ){ - return pB==0; - }else if( pB==0 ){ - return 0; + if( pA==0||pB==0 ){ + return pB==pA; } if( pA->op!=pB->op ) return 0; if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0; @@ -2056,7 +2142,9 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ if( pA->token.z ){ if( pB->token.z==0 ) return 0; if( pB->token.n!=pA->token.n ) return 0; - if( sqlite3StrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0; + if( sqlite3StrNICmp((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){ + return 0; + } } return 1; } @@ -2180,14 +2268,14 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){ if( i>=pAggInfo->nFunc ){ /* pExpr is original. Make a new entry in pAggInfo->aFunc[] */ - u8 enc = pParse->db->enc; + u8 enc = ENC(pParse->db); i = addAggInfoFunc(pAggInfo); if( i>=0 ){ pItem = &pAggInfo->aFunc[i]; pItem->pExpr = pExpr; pItem->iMem = pParse->nMem++; pItem->pFunc = sqlite3FindFunction(pParse->db, - pExpr->token.z, pExpr->token.n, + (char*)pExpr->token.z, pExpr->token.n, pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); if( pExpr->flags & EP_Distinct ){ pItem->iDistinct = pParse->nTab++; diff --git a/ext/pdo_sqlite/sqlite/src/func.c b/ext/pdo_sqlite/sqlite/src/func.c index cdb674fa28..bf422f92c5 100644 --- a/ext/pdo_sqlite/sqlite/src/func.c +++ b/ext/pdo_sqlite/sqlite/src/func.c @@ -20,7 +20,6 @@ */ #include "sqliteInt.h" #include -#include #include #include #include "vdbeInt.h" @@ -101,7 +100,7 @@ static void lengthFunc( break; } case SQLITE_TEXT: { - const char *z = sqlite3_value_text(argv[0]); + const unsigned char *z = sqlite3_value_text(argv[0]); for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; } sqlite3_result_int(context, len); break; @@ -121,7 +120,13 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ switch( sqlite3_value_type(argv[0]) ){ case SQLITE_INTEGER: { i64 iVal = sqlite3_value_int64(argv[0]); - if( iVal<0 ) iVal = iVal * -1; + if( iVal<0 ){ + if( (iVal<<1)==0 ){ + sqlite3_result_error(context, "integer overflow", -1); + return; + } + iVal = -iVal; + } sqlite3_result_int64(context, iVal); break; } @@ -131,7 +136,7 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ } default: { double rVal = sqlite3_value_double(argv[0]); - if( rVal<0 ) rVal = rVal * -1.0; + if( rVal<0 ) rVal = -rVal; sqlite3_result_double(context, rVal); break; } @@ -146,8 +151,8 @@ static void substrFunc( int argc, sqlite3_value **argv ){ - const char *z; - const char *z2; + const unsigned char *z; + const unsigned char *z2; int i; int p1, p2, len; @@ -178,7 +183,7 @@ static void substrFunc( } while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; } if( p2<0 ) p2 = 0; - sqlite3_result_text(context, &z[p1], p2, SQLITE_TRANSIENT); + sqlite3_result_text(context, (char*)&z[p1], p2, SQLITE_TRANSIENT); } /* @@ -195,10 +200,11 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ if( n>30 ) n = 30; if( n<0 ) n = 0; } - if( SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; r = sqlite3_value_double(argv[0]); sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r); - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + sqlite3AtoF(zBuf, &r); + sqlite3_result_double(context, r); } /* @@ -210,11 +216,11 @@ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1); if( z==0 ) return; - strcpy(z, sqlite3_value_text(argv[0])); + strcpy((char*)z, (char*)sqlite3_value_text(argv[0])); for(i=0; z[i]; i++){ z[i] = toupper(z[i]); } - sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); + sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT); sqliteFree(z); } static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ @@ -223,11 +229,11 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1); if( z==0 ) return; - strcpy(z, sqlite3_value_text(argv[0])); + strcpy((char*)z, (char*)sqlite3_value_text(argv[0])); for(i=0; z[i]; i++){ z[i] = tolower(z[i]); } - sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); + sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT); sqliteFree(z); } @@ -258,9 +264,11 @@ static void randomFunc( int argc, sqlite3_value **argv ){ - int r; + sqlite_int64 r; sqlite3Randomness(sizeof(r), &r); - sqlite3_result_int(context, r); + if( (r<<1)==0 ) r = 0; /* Prevent 0x8000.... as the result so that we */ + /* can always do abs() of the result */ + sqlite3_result_int64(context, r); } /* @@ -495,7 +503,7 @@ static void likeFunc( ** Otherwise, return an error. */ const unsigned char *zEsc = sqlite3_value_text(argv[2]); - if( sqlite3utf8CharLen(zEsc, -1)!=1 ){ + if( sqlite3utf8CharLen((char*)zEsc, -1)!=1 ){ sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; @@ -539,6 +547,19 @@ static void versionFunc( sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC); } +/* +** The MATCH() function is unimplemented. If anybody tries to use it, +** return an error. +*/ +static void matchStub( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + static const char zErr[] = "MATCH is not implemented"; + sqlite3_result_error(context, zErr, sizeof(zErr)-1); +} + /* ** EXPERIMENTAL - This is not an official function. The interface may @@ -592,7 +613,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ } case SQLITE_TEXT: { int i,j,n; - const char *zArg = sqlite3_value_text(argv[0]); + const unsigned char *zArg = sqlite3_value_text(argv[0]); char *z; for(i=n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } @@ -633,6 +654,7 @@ static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv }; assert( argc==1 ); zIn = (u8*)sqlite3_value_text(argv[0]); + if( zIn==0 ) zIn = ""; for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} if( zIn[i] ){ zResult[0] = toupper(zIn[i]); @@ -653,6 +675,26 @@ static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv } #endif +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** A function that loads a shared-library extension then returns NULL. +*/ +static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *zFile = (const char *)sqlite3_value_text(argv[0]); + const char *zProc = 0; + sqlite3 *db = sqlite3_user_data(context); + char *zErrMsg = 0; + + if( argc==2 ){ + zProc = (const char *)sqlite3_value_text(argv[1]); + } + if( sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){ + sqlite3_result_error(context, zErrMsg, -1); + sqlite3_free(zErrMsg); + } +} +#endif + #ifdef SQLITE_TEST /* ** This function generates a string of random characters. Used for @@ -692,7 +734,7 @@ static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)]; } zBuf[n] = 0; - sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT); + sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT); } #endif /* SQLITE_TEST */ @@ -728,17 +770,17 @@ static void test_destructor( test_destructor_count_var++; assert( nArg==1 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - len = sqlite3ValueBytes(argv[0], db->enc); + len = sqlite3ValueBytes(argv[0], ENC(db)); zVal = sqliteMalloc(len+3); zVal[len] = 0; zVal[len-1] = 0; assert( zVal ); zVal++; - memcpy(zVal, sqlite3ValueText(argv[0], db->enc), len); - if( db->enc==SQLITE_UTF8 ){ + memcpy(zVal, sqlite3ValueText(argv[0], ENC(db)), len); + if( ENC(db)==SQLITE_UTF8 ){ sqlite3_result_text(pCtx, zVal, -1, destructor); #ifndef SQLITE_OMIT_UTF16 - }else if( db->enc==SQLITE_UTF16LE ){ + }else if( ENC(db)==SQLITE_UTF16LE ){ sqlite3_result_text16le(pCtx, zVal, -1, destructor); }else{ sqlite3_result_text16be(pCtx, zVal, -1, destructor); @@ -776,7 +818,7 @@ static void test_auxdata( char *zRet = sqliteMalloc(nArg*2); if( !zRet ) return; for(i=0; isum += sqlite3_value_double(argv[0]); p->cnt++; - if( type==SQLITE_FLOAT ){ - p->seenFloat = 1; + if( type==SQLITE_INTEGER ){ + i64 v = sqlite3_value_int64(argv[0]); + p->rSum += v; + if( (p->approx|p->overflow)==0 ){ + i64 iNewSum = p->iSum + v; + int s1 = p->iSum >> (sizeof(i64)*8-1); + int s2 = v >> (sizeof(i64)*8-1); + int s3 = iNewSum >> (sizeof(i64)*8-1); + p->overflow = (s1&s2&~s3) | (~s1&~s2&s3); + p->iSum = iNewSum; + } + }else{ + p->rSum += sqlite3_value_double(argv[0]); + p->approx = 1; } } } @@ -843,10 +905,12 @@ static void sumFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ - if( p->seenFloat ){ - sqlite3_result_double(context, p->sum); + if( p->overflow ){ + sqlite3_result_error(context,"integer overflow",-1); + }else if( p->approx ){ + sqlite3_result_double(context, p->rSum); }else{ - sqlite3_result_int64(context, (i64)p->sum); + sqlite3_result_int64(context, p->iSum); } } } @@ -854,20 +918,14 @@ static void avgFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ - sqlite3_result_double(context, p->sum/(double)p->cnt); + sqlite3_result_double(context, p->rSum/(double)p->cnt); } } - -/* -** An instance of the following structure holds the context of a -** variance or standard deviation computation. -*/ -typedef struct StdDevCtx StdDevCtx; -struct StdDevCtx { - double sum; /* Sum of terms */ - double sum2; /* Sum of the squares of terms */ - int cnt; /* Number of terms counted */ -}; +static void totalFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_double(context, p ? p->rSum : 0.0); +} /* ** The following structure keeps track of state information for the @@ -875,7 +933,7 @@ struct StdDevCtx { */ typedef struct CountCtx CountCtx; struct CountCtx { - int n; + i64 n; }; /* @@ -891,7 +949,7 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ static void countFinalize(sqlite3_context *context){ CountCtx *p; p = sqlite3_aggregate_context(context, 0); - sqlite3_result_int(context, p ? p->n : 0); + sqlite3_result_int64(context, p ? p->n : 0); } /* @@ -978,9 +1036,14 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, { "changes", 0, 1, SQLITE_UTF8, 0, changes }, { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, + { "match", 2, 0, SQLITE_UTF8, 0, matchStub }, #ifdef SQLITE_SOUNDEX { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, #endif +#ifndef SQLITE_OMIT_LOAD_EXTENSION + { "load_extension", 1, 1, SQLITE_UTF8, 0, loadExt }, + { "load_extension", 2, 1, SQLITE_UTF8, 0, loadExt }, +#endif #ifdef SQLITE_TEST { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, { "test_destructor", 1, 1, SQLITE_UTF8, 0, test_destructor}, @@ -1000,6 +1063,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, { "max", 1, 2, 1, minmaxStep, minMaxFinalize }, { "sum", 1, 0, 0, sumStep, sumFinalize }, + { "total", 1, 0, 0, sumStep, totalFinalize }, { "avg", 1, 0, 0, sumStep, avgFinalize }, { "count", 0, 0, 0, countStep, countFinalize }, { "count", 1, 0, 0, countStep, countFinalize }, @@ -1012,7 +1076,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ case 1: pArg = db; break; case 2: pArg = (void *)(-1); break; } - sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, + sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg, aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0); if( aFuncs[i].needCollSeq ){ FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName, @@ -1024,6 +1088,9 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ } #ifndef SQLITE_OMIT_ALTERTABLE sqlite3AlterFunctions(db); +#endif +#ifndef SQLITE_OMIT_PARSER + sqlite3AttachFunctions(db); #endif for(i=0; ipList->nExpr!=2 ){ return 0; } - pDef = sqlite3FindFunction(db, pExpr->token.z, pExpr->token.n, 2, + pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2, SQLITE_UTF8, 0); if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){ return 0; diff --git a/ext/pdo_sqlite/sqlite/src/hash.c b/ext/pdo_sqlite/sqlite/src/hash.c index e01aae7163..1c32c1b7cc 100644 --- a/ext/pdo_sqlite/sqlite/src/hash.c +++ b/ext/pdo_sqlite/sqlite/src/hash.c @@ -41,6 +41,8 @@ void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){ pNew->count = 0; pNew->htsize = 0; pNew->ht = 0; + pNew->xMalloc = sqlite3MallocX; + pNew->xFree = sqlite3FreeX; } /* Remove all entries from a hash table. Reclaim all memory. @@ -53,15 +55,15 @@ void sqlite3HashClear(Hash *pH){ assert( pH!=0 ); elem = pH->first; pH->first = 0; - if( pH->ht ) sqliteFree(pH->ht); + if( pH->ht ) pH->xFree(pH->ht); pH->ht = 0; pH->htsize = 0; while( elem ){ HashElem *next_elem = elem->next; if( pH->copyKey && elem->pKey ){ - sqliteFree(elem->pKey); + pH->xFree(elem->pKey); } - sqliteFree(elem); + pH->xFree(elem); elem = next_elem; } pH->count = 0; @@ -222,9 +224,9 @@ static void rehash(Hash *pH, int new_size){ int (*xHash)(const void*,int); /* The hash function */ assert( (new_size & (new_size-1))==0 ); - new_ht = (struct _ht *)sqliteMalloc( new_size*sizeof(struct _ht) ); + new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) ); if( new_ht==0 ) return; - if( pH->ht ) sqliteFree(pH->ht); + if( pH->ht ) pH->xFree(pH->ht); pH->ht = new_ht; pH->htsize = new_size; xHash = hashFunction(pH->keyClass); @@ -290,10 +292,15 @@ static void removeElementGivenHash( pEntry->chain = 0; } if( pH->copyKey && elem->pKey ){ - sqliteFree(elem->pKey); + pH->xFree(elem->pKey); } - sqliteFree( elem ); + pH->xFree( 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 @@ -353,12 +360,12 @@ void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){ return old_data; } if( data==0 ) return 0; - new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) ); + new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) ); if( new_elem==0 ) return data; if( pH->copyKey && pKey!=0 ){ - new_elem->pKey = sqliteMallocRaw( nKey ); + new_elem->pKey = pH->xMalloc( nKey ); if( new_elem->pKey==0 ){ - sqliteFree(new_elem); + pH->xFree(new_elem); return data; } memcpy((void*)new_elem->pKey, pKey, nKey); @@ -371,7 +378,7 @@ void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){ rehash(pH,8); if( pH->htsize==0 ){ pH->count = 0; - sqliteFree(new_elem); + pH->xFree(new_elem); return data; } } diff --git a/ext/pdo_sqlite/sqlite/src/hash.h b/ext/pdo_sqlite/sqlite/src/hash.h index cf004ddc53..4707649489 100644 --- a/ext/pdo_sqlite/sqlite/src/hash.h +++ b/ext/pdo_sqlite/sqlite/src/hash.h @@ -34,6 +34,8 @@ struct Hash { char copyKey; /* True if copy of key made on insert */ int count; /* Number of entries in this table */ HashElem *first; /* The first element of the array */ + void *(*xMalloc)(int); /* malloc() function to use */ + void (*xFree)(void *); /* free() function to use */ int htsize; /* Number of buckets in the hash table */ struct _ht { /* the hash table */ int count; /* Number of entries with this hash */ diff --git a/ext/pdo_sqlite/sqlite/src/insert.c b/ext/pdo_sqlite/sqlite/src/insert.c index 37f9f4ee57..d4cf74a3d7 100644 --- a/ext/pdo_sqlite/sqlite/src/insert.c +++ b/ext/pdo_sqlite/sqlite/src/insert.c @@ -23,10 +23,11 @@ ** ** Character Column affinity ** ------------------------------ -** 'n' NUMERIC -** 'i' INTEGER -** 't' TEXT -** 'o' NONE +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL */ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ if( !pIdx->zColAff ){ @@ -61,10 +62,11 @@ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ ** ** Character Column affinity ** ------------------------------ -** 'n' NUMERIC -** 'i' INTEGER -** 't' TEXT -** 'o' NONE +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL */ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ /* The first time a column affinity string for a particular table @@ -102,15 +104,15 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ ** ** No checking is done for sub-selects that are part of expressions. */ -static int selectReadsTable(Select *p, int iDb, int iTab){ +static int selectReadsTable(Select *p, Schema *pSchema, int iTab){ int i; struct SrcList_item *pItem; if( p->pSrc==0 ) return 0; for(i=0, pItem=p->pSrc->a; ipSrc->nSrc; i++, pItem++){ if( pItem->pSelect ){ - if( selectReadsTable(pItem->pSelect, iDb, iTab) ) return 1; + if( selectReadsTable(pItem->pSelect, pSchema, iTab) ) return 1; }else{ - if( pItem->pTab->iDb==iDb && pItem->pTab->tnum==iTab ) return 1; + if( pItem->pTab->pSchema==pSchema && pItem->pTab->tnum==iTab ) return 1; } } return 0; @@ -212,6 +214,7 @@ void sqlite3Insert( int newIdx = -1; /* Cursor for the NEW table */ Db *pDb; /* The database containing table being inserted into */ int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */ + int iDb; #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ @@ -219,10 +222,12 @@ void sqlite3Insert( #endif #ifndef SQLITE_OMIT_AUTOINCREMENT - int counterRowid; /* Memory cell holding rowid of autoinc counter */ + int counterRowid = 0; /* Memory cell holding rowid of autoinc counter */ #endif - if( pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup; + if( pParse->nErr || sqlite3MallocFailed() ){ + goto insert_cleanup; + } db = pParse->db; /* Locate the table into which we will be inserting new information. @@ -234,8 +239,9 @@ void sqlite3Insert( if( pTab==0 ){ goto insert_cleanup; } - assert( pTab->iDbnDb ); - pDb = &db->aDb[pTab->iDb]; + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDbnDb ); + pDb = &db->aDb[iDb]; zDb = pDb->zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ goto insert_cleanup; @@ -263,27 +269,22 @@ void sqlite3Insert( if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ goto insert_cleanup; } - if( pTab==0 ) goto insert_cleanup; + assert( pTab!=0 ); /* If pTab is really a view, make sure it has been initialized. + ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual + ** module table). */ - if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto insert_cleanup; } - /* Ensure all required collation sequences are available. */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){ - goto insert_cleanup; - } - } - /* Allocate a VDBE */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, pTab->iDb); + sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, iDb); /* if there are row triggers, allocate a temp table for new.* references. */ if( triggers_exist ){ @@ -298,22 +299,20 @@ void sqlite3Insert( */ if( pTab->autoInc ){ int iCur = pParse->nTab; - int base = sqlite3VdbeCurrentAddr(v); + int addr = sqlite3VdbeCurrentAddr(v); counterRowid = pParse->nMem++; counterMem = pParse->nMem++; - sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pDb->pSeqTab->tnum); - sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, 2); - sqlite3VdbeAddOp(v, OP_Rewind, iCur, base+13); + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); + sqlite3VdbeAddOp(v, OP_Rewind, iCur, addr+13); sqlite3VdbeAddOp(v, OP_Column, iCur, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); - sqlite3VdbeAddOp(v, OP_Ne, 28417, base+12); + sqlite3VdbeAddOp(v, OP_Ne, 0x100, addr+12); sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); sqlite3VdbeAddOp(v, OP_MemStore, counterRowid, 1); sqlite3VdbeAddOp(v, OP_Column, iCur, 1); sqlite3VdbeAddOp(v, OP_MemStore, counterMem, 1); - sqlite3VdbeAddOp(v, OP_Goto, 0, base+13); - sqlite3VdbeAddOp(v, OP_Next, iCur, base+4); + sqlite3VdbeAddOp(v, OP_Goto, 0, addr+13); + sqlite3VdbeAddOp(v, OP_Next, iCur, addr+4); sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } #endif /* SQLITE_OMIT_AUTOINCREMENT */ @@ -336,7 +335,9 @@ void sqlite3Insert( /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0); - if( rc || pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup; + if( rc || pParse->nErr || sqlite3MallocFailed() ){ + goto insert_cleanup; + } iCleanup = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup); @@ -351,7 +352,7 @@ void sqlite3Insert( ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ - if( triggers_exist || selectReadsTable(pSelect, pTab->iDb, pTab->tnum) ){ + if( triggers_exist || selectReadsTable(pSelect,pTab->pSchema,pTab->tnum) ){ useTempTable = 1; } @@ -362,7 +363,6 @@ void sqlite3Insert( srcTab = pParse->nTab++; sqlite3VdbeResolveLabel(v, iInsertBlock); sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); - sqlite3TableAffinityStr(v, pTab); sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeAddOp(v, OP_Insert, srcTab, 0); @@ -373,7 +373,7 @@ void sqlite3Insert( ** back up and execute the SELECT code above. */ sqlite3VdbeJumpHere(v, iInitCode); - sqlite3VdbeAddOp(v, OP_OpenVirtual, srcTab, 0); + sqlite3VdbeAddOp(v, OP_OpenEphemeral, srcTab, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn); sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop); sqlite3VdbeResolveLabel(v, iCleanup); @@ -569,6 +569,10 @@ void sqlite3Insert( ** case the record number is the same as that column. */ if( !isView ){ + if( IsVirtual(pTab) ){ + /* The row that the VUpdate opcode will delete: none */ + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + } if( keyColumn>=0 ){ if( useTempTable ){ sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn); @@ -584,6 +588,8 @@ void sqlite3Insert( sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); + }else if( IsVirtual(pTab) ){ + sqlite3VdbeAddOp(v, OP_Null, 0, 0); }else{ sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem); } @@ -626,16 +632,25 @@ void sqlite3Insert( /* Generate code to check constraints and generate index keys and ** do the insertion. */ - sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, - 0, onError, endOfLoop); - sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + pParse->pVirtualLock = pTab; + sqlite3VdbeOp3(v, OP_VUpdate, 1, pTab->nCol+2, + (const char*)pTab->pVtab, P3_VTAB); + }else +#endif + { + sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, + 0, onError, endOfLoop); + sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1); + } } /* Update the count of rows that are inserted */ if( (db->flags & SQLITE_CountRows)!=0 ){ - sqlite3VdbeAddOp(v, OP_MemIncr, iCntMem, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, 1, iCntMem); } if( triggers_exist ){ @@ -667,7 +682,7 @@ void sqlite3Insert( sqlite3VdbeResolveLabel(v, iCleanup); } - if( !triggers_exist ){ + if( !triggers_exist && !IsVirtual(pTab) ){ /* Close all tables opened */ sqlite3VdbeAddOp(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ @@ -682,12 +697,10 @@ void sqlite3Insert( */ if( pTab->autoInc ){ int iCur = pParse->nTab; - int base = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); - sqlite3VdbeAddOp(v, OP_OpenWrite, iCur, pDb->pSeqTab->tnum); - sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, 2); + int addr = sqlite3VdbeCurrentAddr(v); + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0); - sqlite3VdbeAddOp(v, OP_NotNull, -1, base+7); + sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+7); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); @@ -707,7 +720,7 @@ void sqlite3Insert( sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "rows inserted", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P3_STATIC); } insert_cleanup: @@ -870,7 +883,24 @@ void sqlite3GenerateConstraintChecks( /* Test all CHECK constraints */ - /**** TBD ****/ +#ifndef SQLITE_OMIT_CHECK + if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){ + int allOk = sqlite3VdbeMakeLabel(v); + assert( pParse->ckOffset==0 ); + pParse->ckOffset = nCol; + sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1); + assert( pParse->ckOffset==nCol ); + pParse->ckOffset = 0; + onError = overrideError!=OE_Default ? overrideError : OE_Abort; + if( onError==OE_Ignore || onError==OE_Replace ){ + sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); + }else{ + sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError); + } + sqlite3VdbeResolveLabel(v, allOk); + } +#endif /* !defined(SQLITE_OMIT_CHECK) */ /* If we have an INTEGER PRIMARY KEY, make sure the primary key ** of the new record does not previously exist. Except, if this @@ -904,7 +934,7 @@ void sqlite3GenerateConstraintChecks( break; } case OE_Replace: { - sqlite3GenerateRowIndexDelete(pParse->db, v, pTab, base, 0); + sqlite3GenerateRowIndexDelete(v, pTab, base, 0); if( isUpdate ){ sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRowids, 1); sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); @@ -1067,9 +1097,13 @@ void sqlite3CompleteInsertion( if( pParse->nested ){ pik_flags = 0; }else{ - pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID)); + pik_flags = OPFLAG_NCHANGE; + pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); } sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags); + if( !pParse->nested ){ + sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); + } if( isUpdate && rowidChng ){ sqlite3VdbeAddOp(v, OP_Pop, 1, 0); @@ -1088,18 +1122,21 @@ void sqlite3OpenTableAndIndices( int op /* OP_OpenRead or OP_OpenWrite */ ){ int i; + int iDb; Index *pIdx; - Vdbe *v = sqlite3GetVdbe(pParse); + Vdbe *v; + + if( IsVirtual(pTab) ) return; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + v = sqlite3GetVdbe(pParse); assert( v!=0 ); - sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); - VdbeComment((v, "# %s", pTab->zName)); - sqlite3VdbeAddOp(v, op, base, pTab->tnum); - sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol); + sqlite3OpenTable(pParse, base, iDb, pTab, op); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); VdbeComment((v, "# %s", pIdx->zName)); - sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, - (char*)&pIdx->keyInfo, P3_KEYINFO); + sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF); } if( pParse->nTab<=base+i ){ pParse->nTab = base+i; diff --git a/ext/pdo_sqlite/sqlite/src/keywordhash.h b/ext/pdo_sqlite/sqlite/src/keywordhash.h index f825ba977c..bc0898f3be 100644 --- a/ext/pdo_sqlite/sqlite/src/keywordhash.h +++ b/ext/pdo_sqlite/sqlite/src/keywordhash.h @@ -1,61 +1,61 @@ -/* Hash score: 156 */ +/* Hash score: 167 */ static int keywordCode(const char *z, int n){ - static const char zText[526] = + static const char zText[544] = "ABORTABLEFTEMPORARYADDATABASELECTHENDEFAULTRANSACTIONATURALTER" "AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYANALYZE" "XCLUSIVEXISTSTATEMENTANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEX" "AUTOINCREMENTBEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETE" "CASECASTCOLLATECOLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSS" - "CURRENT_DATECURRENT_TIMESTAMPRAGMATCHDESCDETACHDISTINCTDROPRIMARY" - "FAILIMITFROMFULLGROUPDATEIMMEDIATEINSERTINSTEADINTOFFSETISNULL" - "JOINORDEREPLACEOUTERESTRICTRIGHTROLLBACKROWHENUNIONUNIQUEUSING" - "VACUUMVALUESVIEWHERE"; + "CURRENT_DATECURRENT_TIMESTAMPLANDESCDETACHDISTINCTDROPRAGMATCH" + "FAILIMITFROMFULLGROUPDATEIFIMMEDIATEINSERTINSTEADINTOFFSETISNULL" + "JOINORDEREPLACEOUTERESTRICTPRIMARYQUERYRIGHTROLLBACKROWHENUNION" + "UNIQUEUSINGVACUUMVALUESVIEWHEREVIRTUAL"; static const unsigned char aHash[127] = { - 91, 81, 104, 90, 0, 4, 0, 0, 111, 0, 77, 0, 0, - 94, 44, 0, 92, 0, 103, 106, 96, 0, 0, 10, 0, 0, - 110, 0, 107, 102, 0, 28, 48, 0, 41, 0, 0, 65, 71, - 0, 63, 19, 0, 0, 36, 83, 0, 105, 74, 0, 0, 33, - 0, 61, 37, 0, 8, 0, 112, 38, 12, 0, 78, 40, 25, - 66, 0, 0, 31, 82, 53, 30, 50, 20, 88, 0, 34, 0, + 92, 80, 107, 91, 0, 4, 0, 0, 114, 0, 83, 0, 0, + 95, 44, 76, 93, 0, 106, 109, 97, 90, 0, 10, 0, 0, + 113, 0, 117, 103, 0, 28, 48, 0, 41, 0, 0, 65, 71, + 0, 63, 19, 0, 105, 36, 104, 0, 108, 74, 0, 0, 33, + 0, 61, 37, 0, 8, 0, 115, 38, 12, 0, 77, 40, 25, + 66, 0, 0, 31, 81, 53, 30, 50, 20, 88, 0, 34, 0, 75, 26, 0, 72, 0, 0, 0, 64, 47, 67, 22, 87, 29, - 69, 86, 0, 1, 0, 9, 100, 58, 18, 0, 109, 76, 98, - 54, 6, 85, 0, 0, 49, 93, 0, 101, 0, 70, 0, 0, - 15, 0, 113, 51, 56, 0, 2, 55, 0, 108, + 69, 86, 0, 1, 0, 9, 101, 58, 18, 0, 112, 82, 99, + 54, 6, 85, 0, 0, 49, 94, 0, 102, 0, 70, 0, 0, + 15, 0, 116, 51, 56, 0, 2, 55, 0, 111, }; - static const unsigned char aNext[113] = { + static const unsigned char aNext[117] = { 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 5, 13, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 16, 0, 23, 52, 0, 0, 0, 0, 45, 0, 59, - 0, 0, 0, 0, 0, 0, 0, 0, 73, 42, 0, 0, 24, - 60, 21, 0, 80, 32, 68, 0, 0, 84, 46, 0, 0, 0, - 0, 0, 0, 0, 39, 95, 97, 0, 0, 99, 0, 14, 27, - 79, 0, 57, 89, 0, 35, 0, 62, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 73, 42, 0, 24, 60, + 21, 0, 79, 0, 0, 68, 0, 0, 84, 46, 0, 0, 0, + 0, 0, 0, 0, 0, 39, 96, 98, 0, 0, 100, 0, 32, + 0, 14, 27, 78, 0, 57, 89, 0, 35, 0, 62, 0, 110, }; - static const unsigned char aLen[113] = { + static const unsigned char aLen[117] = { 5, 5, 4, 4, 9, 2, 3, 8, 2, 6, 4, 3, 7, 11, 2, 7, 5, 5, 4, 5, 3, 5, 10, 6, 4, 6, 7, 6, 7, 9, 3, 7, 9, 6, 9, 3, 10, 6, 6, 4, 6, 3, 7, 6, 7, 5, 13, 2, 2, 5, 5, 6, 7, 3, 7, 4, 4, 2, 7, 3, 8, 6, 4, 4, 7, - 6, 6, 8, 10, 9, 6, 5, 12, 12, 17, 6, 5, 4, - 6, 8, 2, 4, 7, 4, 5, 4, 4, 5, 6, 9, 6, - 7, 4, 2, 6, 3, 6, 4, 5, 7, 5, 8, 5, 8, - 3, 4, 5, 6, 5, 6, 6, 4, 5, + 6, 6, 8, 10, 9, 6, 5, 12, 12, 17, 4, 4, 6, + 8, 2, 4, 6, 5, 4, 5, 4, 4, 5, 6, 2, 9, + 6, 7, 4, 2, 6, 3, 6, 4, 5, 7, 5, 8, 7, + 5, 5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5, 7, }; - static const unsigned short int aOffset[113] = { + static const unsigned short int aOffset[117] = { 0, 4, 7, 10, 10, 14, 19, 21, 26, 27, 32, 34, 36, 42, 51, 52, 57, 61, 65, 67, 71, 74, 78, 86, 91, 94, 99, 105, 108, 113, 118, 122, 128, 136, 141, 150, 152, 162, 167, 172, 175, 177, 177, 181, 185, 187, 192, 194, 196, 205, 208, 212, 218, 224, 224, 227, 230, 234, 236, 237, 241, 248, 254, 258, 262, - 269, 275, 281, 289, 296, 305, 311, 316, 328, 328, 344, 348, 353, - 357, 363, 364, 371, 374, 381, 384, 389, 393, 397, 400, 406, 415, - 421, 428, 431, 431, 434, 437, 443, 447, 451, 458, 462, 470, 475, - 483, 485, 489, 494, 500, 505, 511, 517, 520, + 269, 275, 281, 289, 296, 305, 311, 316, 328, 328, 344, 348, 352, + 358, 359, 366, 369, 373, 378, 381, 386, 390, 394, 397, 403, 405, + 414, 420, 427, 430, 430, 433, 436, 442, 446, 450, 457, 461, 469, + 476, 481, 486, 494, 496, 500, 505, 511, 516, 522, 528, 531, 536, }; - static const unsigned char aCode[113] = { + static const unsigned char aCode[117] = { TK_ABORT, TK_TABLE, TK_JOIN_KW, TK_TEMP, TK_TEMP, TK_OR, TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_THEN, TK_END, TK_DEFAULT, TK_TRANSACTION,TK_ON, @@ -71,19 +71,20 @@ static int keywordCode(const char *z, int n){ TK_DEFERRED, TK_DELETE, TK_CASE, TK_CAST, TK_COLLATE, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_CONSTRAINT, TK_INTERSECT, TK_CREATE, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CTIME_KW, - TK_PRAGMA, TK_MATCH, TK_DESC, TK_DETACH, TK_DISTINCT, - TK_IS, TK_DROP, TK_PRIMARY, TK_FAIL, TK_LIMIT, - TK_FROM, TK_JOIN_KW, TK_GROUP, TK_UPDATE, TK_IMMEDIATE, - TK_INSERT, TK_INSTEAD, TK_INTO, TK_OF, TK_OFFSET, - TK_SET, TK_ISNULL, TK_JOIN, TK_ORDER, TK_REPLACE, - TK_JOIN_KW, TK_RESTRICT, TK_JOIN_KW, TK_ROLLBACK, TK_ROW, - TK_WHEN, TK_UNION, TK_UNIQUE, TK_USING, TK_VACUUM, - TK_VALUES, TK_VIEW, TK_WHERE, + TK_PLAN, TK_DESC, TK_DETACH, TK_DISTINCT, TK_IS, + TK_DROP, TK_PRAGMA, TK_MATCH, TK_FAIL, TK_LIMIT, + TK_FROM, TK_JOIN_KW, TK_GROUP, TK_UPDATE, TK_IF, + TK_IMMEDIATE, TK_INSERT, TK_INSTEAD, TK_INTO, TK_OF, + TK_OFFSET, TK_SET, TK_ISNULL, TK_JOIN, TK_ORDER, + TK_REPLACE, TK_JOIN_KW, TK_RESTRICT, TK_PRIMARY, TK_QUERY, + TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION, + TK_UNIQUE, TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW, + TK_WHERE, TK_VIRTUAL, }; int h, i; if( n<2 ) return TK_ID; - h = ((sqlite3UpperToLower[((unsigned char*)z)[0]]*4) ^ - (sqlite3UpperToLower[((unsigned char*)z)[n-1]]*3) ^ + h = ((charMap(z[0])*4) ^ + (charMap(z[n-1])*3) ^ n) % 127; for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){ if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){ @@ -92,6 +93,6 @@ static int keywordCode(const char *z, int n){ } return TK_ID; } -int sqlite3KeywordCode(const char *z, int n){ - return keywordCode(z, n); +int sqlite3KeywordCode(const unsigned char *z, int n){ + return keywordCode((char*)z, n); } diff --git a/ext/pdo_sqlite/sqlite/src/legacy.c b/ext/pdo_sqlite/sqlite/src/legacy.c index f575f1f0ce..c75791e1bd 100644 --- a/ext/pdo_sqlite/sqlite/src/legacy.c +++ b/ext/pdo_sqlite/sqlite/src/legacy.c @@ -54,8 +54,8 @@ int sqlite3_exec( pStmt = 0; rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover); + assert( rc==SQLITE_OK || pStmt==0 ); if( rc!=SQLITE_OK ){ - if( pStmt ) sqlite3_finalize(pStmt); continue; } if( !pStmt ){ @@ -68,9 +68,8 @@ int sqlite3_exec( nCallback = 0; nCol = sqlite3_column_count(pStmt); - azCols = sqliteMalloc(2*nCol*sizeof(const char *)); - if( nCol && !azCols ){ - rc = SQLITE_NOMEM; + azCols = sqliteMalloc(2*nCol*sizeof(const char *) + 1); + if( azCols==0 ){ goto exec_out; } @@ -122,11 +121,9 @@ exec_out: if( pStmt ) sqlite3_finalize(pStmt); if( azCols ) sqliteFree(azCols); - if( sqlite3_malloc_failed ){ - rc = SQLITE_NOMEM; - } + rc = sqlite3ApiExit(0, rc); if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){ - *pzErrMsg = malloc(1+strlen(sqlite3_errmsg(db))); + *pzErrMsg = sqlite3_malloc(1+strlen(sqlite3_errmsg(db))); if( *pzErrMsg ){ strcpy(*pzErrMsg, sqlite3_errmsg(db)); } diff --git a/ext/pdo_sqlite/sqlite/src/loadext.c b/ext/pdo_sqlite/sqlite/src/loadext.c new file mode 100644 index 0000000000..60ec053cfb --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/loadext.c @@ -0,0 +1,355 @@ +/* +** 2006 June 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 used to dynamically load extensions into +** the SQLite library. +*/ +#ifndef SQLITE_OMIT_LOAD_EXTENSION + +#define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */ +#include "sqlite3ext.h" +#include "sqliteInt.h" +#include +#include + +/* +** Some API routines are omitted when various features are +** excluded from a build of SQLite. Substitute a NULL pointer +** for any missing APIs. +*/ +#ifndef SQLITE_ENABLE_COLUMN_METADATA +# define sqlite3_column_database_name 0 +# define sqlite3_column_database_name16 0 +# define sqlite3_column_table_name 0 +# define sqlite3_column_table_name16 0 +# define sqlite3_column_origin_name 0 +# define sqlite3_column_origin_name16 0 +# define sqlite3_table_column_metadata 0 +#endif + +#ifdef SQLITE_OMIT_AUTHORIZATION +# define sqlite3_set_authorizer 0 +#endif + +#ifdef SQLITE_OMIT_UTF16 +# define sqlite3_bind_text16 0 +# define sqlite3_collation_needed16 0 +# define sqlite3_column_decltype16 0 +# define sqlite3_column_name16 0 +# define sqlite3_column_text16 0 +# define sqlite3_complete16 0 +# define sqlite3_create_collation16 0 +# define sqlite3_create_function16 0 +# define sqlite3_errmsg16 0 +# define sqlite3_open16 0 +# define sqlite3_prepare16 0 +# define sqlite3_result_error16 0 +# define sqlite3_result_text16 0 +# define sqlite3_result_text16be 0 +# define sqlite3_result_text16le 0 +# define sqlite3_value_text16 0 +# define sqlite3_value_text16be 0 +# define sqlite3_value_text16le 0 +#endif + +#ifdef SQLITE_OMIT_COMPLETE +# define sqlite3_complete 0 +# define sqlite3_complete16 0 +#endif + +#ifdef SQLITE_OMIT_PROGRESS_CALLBACK +# define sqlite3_progress_handler 0 +#endif + +#ifdef SQLITE_OMIT_VIRTUALTABLE +# define sqlite3_create_module 0 +# define sqlite3_declare_vtab 0 +#endif + +/* +** The following structure contains pointers to all SQLite API routines. +** A pointer to this structure is passed into extensions when they are +** loaded so that the extension can make calls back into the SQLite +** library. +** +** When adding new APIs, add them to the bottom of this structure +** in order to preserve backwards compatibility. +** +** Extensions that use newer APIs should first call the +** sqlite3_libversion_number() to make sure that the API they +** intend to use is supported by the library. Extensions should +** also check to make sure that the pointer to the function is +** not NULL before calling it. +*/ +const sqlite3_api_routines sqlite3_api = { + sqlite3_aggregate_context, + sqlite3_aggregate_count, + 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_busy_handler, + sqlite3_busy_timeout, + sqlite3_changes, + 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_complete, + sqlite3_complete16, + sqlite3_create_collation, + sqlite3_create_collation16, + sqlite3_create_function, + sqlite3_create_function16, + sqlite3_create_module, + sqlite3_data_count, + sqlite3_db_handle, + sqlite3_declare_vtab, + sqlite3_enable_shared_cache, + sqlite3_errcode, + sqlite3_errmsg, + sqlite3_errmsg16, + sqlite3_exec, + sqlite3_expired, + sqlite3_finalize, + sqlite3_free, + sqlite3_free_table, + sqlite3_get_autocommit, + sqlite3_get_auxdata, + sqlite3_get_table, + sqlite3_global_recover, + sqlite3_interrupt, + sqlite3_last_insert_rowid, + sqlite3_libversion, + sqlite3_libversion_number, + sqlite3_malloc, + sqlite3_mprintf, + sqlite3_open, + sqlite3_open16, + sqlite3_prepare, + sqlite3_prepare16, + sqlite3_profile, + sqlite3_progress_handler, + sqlite3_realloc, + sqlite3_reset, + sqlite3_result_blob, + sqlite3_result_double, + sqlite3_result_error, + sqlite3_result_error16, + 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_rollback_hook, + sqlite3_set_authorizer, + sqlite3_set_auxdata, + sqlite3_snprintf, + sqlite3_step, + sqlite3_table_column_metadata, + sqlite3_thread_cleanup, + sqlite3_total_changes, + sqlite3_trace, + sqlite3_transfer_bindings, + sqlite3_update_hook, + 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_vmprintf, + /* + ** The original API set ends here. All extensions can call any + ** of the APIs above provided that the pointer is not NULL. But + ** before calling APIs that follow, extension should check the + ** sqlite3_libversion_number() to make sure they are dealing with + ** a library that is new enough to support that API. + ************************************************************************* + */ +}; + +/* +** The windows implementation of shared-library loaders +*/ +#if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__) || defined(__BORLANDC__) +# include +# define SQLITE_LIBRARY_TYPE HANDLE +# define SQLITE_OPEN_LIBRARY(A) LoadLibrary(A) +# define SQLITE_FIND_SYMBOL(A,B) GetProcAddress(A,B) +# define SQLITE_CLOSE_LIBRARY(A) FreeLibrary(A) +#endif /* windows */ + +/* +** The unix implementation of shared-library loaders +*/ +#if defined(HAVE_DLOPEN) && !defined(SQLITE_LIBRARY_TYPE) +# include +# define SQLITE_LIBRARY_TYPE void* +# define SQLITE_OPEN_LIBRARY(A) dlopen(A, RTLD_NOW | RTLD_GLOBAL) +# define SQLITE_FIND_SYMBOL(A,B) dlsym(A,B) +# define SQLITE_CLOSE_LIBRARY(A) dlclose(A) +#endif + +/* +** Attempt to load an SQLite extension library contained in the file +** zFile. The entry point is zProc. zProc may be 0 in which case a +** default entry point name (sqlite3_extension_init) is used. Use +** of the default name is recommended. +** +** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong. +** +** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with +** error message text. The calling function should free this memory +** by calling sqlite3_free(). +*/ +int 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. Use "sqlite3_extension_init" if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +){ +#ifdef SQLITE_LIBRARY_TYPE + SQLITE_LIBRARY_TYPE handle; + int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); + char *zErrmsg = 0; + SQLITE_LIBRARY_TYPE *aHandle; + + /* Ticket #1863. To avoid a creating security problems for older + ** applications that relink against newer versions of SQLite, the + ** ability to run load_extension is turned off by default. One + ** must call sqlite3_enable_load_extension() to turn on extension + ** loading. Otherwise you get the following error. + */ + if( (db->flags & SQLITE_LoadExtension)==0 ){ + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("not authorized"); + } + return SQLITE_ERROR; + } + + if( zProc==0 ){ + zProc = "sqlite3_extension_init"; + } + + handle = SQLITE_OPEN_LIBRARY(zFile); + if( handle==0 ){ + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("unable to open shared library [%s]", zFile); + } + return SQLITE_ERROR; + } + xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) + SQLITE_FIND_SYMBOL(handle, zProc); + if( xInit==0 ){ + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("no entry point [%s] in shared library [%s]", + zProc, zFile); + } + SQLITE_CLOSE_LIBRARY(handle); + return SQLITE_ERROR; + }else if( xInit(db, &zErrmsg, &sqlite3_api) ){ + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg); + } + sqlite3_free(zErrmsg); + SQLITE_CLOSE_LIBRARY(handle); + return SQLITE_ERROR; + } + + /* Append the new shared library handle to the db->aExtension array. */ + db->nExtension++; + aHandle = sqliteMalloc(sizeof(handle)*db->nExtension); + if( aHandle==0 ){ + return SQLITE_NOMEM; + } + if( db->nExtension>0 ){ + memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1)); + } + sqliteFree(db->aExtension); + db->aExtension = aHandle; + + ((SQLITE_LIBRARY_TYPE*)db->aExtension)[db->nExtension-1] = handle; + return SQLITE_OK; +#else + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("extension loading is disabled"); + } + return SQLITE_ERROR; +#endif +} + +/* +** Call this routine when the database connection is closing in order +** to clean up loaded extensions +*/ +void sqlite3CloseExtensions(sqlite3 *db){ +#ifdef SQLITE_LIBRARY_TYPE + int i; + for(i=0; inExtension; i++){ + SQLITE_CLOSE_LIBRARY(((SQLITE_LIBRARY_TYPE*)db->aExtension)[i]); + } + sqliteFree(db->aExtension); +#endif +} + +/* +** Enable or disable extension loading. Extension loading is disabled by +** default so as not to open security holes in older applications. +*/ +int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ + if( onoff ){ + db->flags |= SQLITE_LoadExtension; + }else{ + db->flags &= ~SQLITE_LoadExtension; + } + return SQLITE_OK; +} + +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ diff --git a/ext/pdo_sqlite/sqlite/src/main.c b/ext/pdo_sqlite/sqlite/src/main.c index c42df158e4..eccf83be69 100644 --- a/ext/pdo_sqlite/sqlite/src/main.c +++ b/ext/pdo_sqlite/sqlite/src/main.c @@ -26,32 +26,9 @@ */ const int sqlite3one = 1; -#ifndef SQLITE_OMIT_GLOBALRECOVER -/* -** Linked list of all open database handles. This is used by the -** sqlite3_global_recover() function. Entries are added to the list -** by openDatabase() and removed by sqlite3_close(). -*/ -static sqlite3 *pDbList = 0; -#endif - -#ifndef SQLITE_OMIT_UTF16 -/* -** Return the transient sqlite3_value object used for encoding conversions -** during SQL compilation. -*/ -sqlite3_value *sqlite3GetTransientValue(sqlite3 *db){ - if( !db->pValue ){ - db->pValue = sqlite3ValueNew(); - } - return db->pValue; -} -#endif - /* ** The version of the library */ -const char rcsid3[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $"; const char sqlite3_version[] = SQLITE_VERSION; const char *sqlite3_libversion(void){ return sqlite3_version; } int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } @@ -132,10 +109,14 @@ int sqlite3_close(sqlite3 *db){ } #ifdef SQLITE_SSE - sqlite3_finalize(db->pFetch); + { + extern void sqlite3SseCleanup(sqlite3*); + sqlite3SseCleanup(db); + } #endif /* If there are any outstanding VMs, return SQLITE_BUSY. */ + sqlite3ResetInternalSchema(db, 0); if( db->pVdbe ){ sqlite3Error(db, SQLITE_BUSY, "Unable to close due to unfinalised statements"); @@ -153,11 +134,16 @@ int sqlite3_close(sqlite3 *db){ return SQLITE_ERROR; } + sqlite3VtabRollback(db); + for(j=0; jnDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; + if( j!=1 ){ + pDb->pSchema = 0; + } } } sqlite3ResetInternalSchema(db, 0); @@ -176,36 +162,32 @@ int sqlite3_close(sqlite3 *db){ sqliteFree(pColl); } sqlite3HashClear(&db->aCollSeq); +#ifndef SQLITE_OMIT_VIRTUALTABLE + for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ + Module *pMod = (Module *)sqliteHashData(i); + sqliteFree(pMod); + } + sqlite3HashClear(&db->aModule); +#endif sqlite3HashClear(&db->aFunc); sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ - if( db->pValue ){ - sqlite3ValueFree(db->pValue); - } if( db->pErr ){ sqlite3ValueFree(db->pErr); } - -#ifndef SQLITE_OMIT_GLOBALRECOVER - { - sqlite3 *pPrev; - sqlite3OsEnterMutex(); - pPrev = pDbList; - while( pPrev && pPrev->pNext!=db ){ - pPrev = pPrev->pNext; - } - if( pPrev ){ - pPrev->pNext = db->pNext; - }else{ - assert( pDbList==db ); - pDbList = db->pNext; - } - sqlite3OsLeaveMutex(); - } -#endif + sqlite3CloseExtensions(db); db->magic = SQLITE_MAGIC_ERROR; + + /* The temp-database schema is allocated differently from the other schema + ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()). + ** So it needs to be freed here. Todo: Why not roll the temp schema into + ** the same sqliteMalloc() as the one that allocates the database + ** structure? + */ + sqliteFree(db->aDb[1].pSchema); sqliteFree(db); + sqlite3ReleaseThreadData(); return SQLITE_OK; } @@ -214,13 +196,25 @@ int sqlite3_close(sqlite3 *db){ */ void sqlite3RollbackAll(sqlite3 *db){ int i; + int inTrans = 0; for(i=0; inDb; i++){ if( db->aDb[i].pBt ){ + if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ + inTrans = 1; + } sqlite3BtreeRollback(db->aDb[i].pBt); db->aDb[i].inTrans = 0; } } - sqlite3ResetInternalSchema(db, 0); + sqlite3VtabRollback(db); + if( db->flags&SQLITE_InternChanges ){ + sqlite3ResetInternalSchema(db, 0); + } + + /* If one has been configured, invoke the rollback-hook callback */ + if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ + db->xRollbackCallback(db->pRollbackArg); + } } /* @@ -271,7 +265,7 @@ static int sqliteDefaultBusyCallback( void *ptr, /* Database connection */ int count /* Number of times table has been busy */ ){ -#if SQLITE_MIN_SLEEP_MS==1 +#if OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP) static const u8 delays[] = { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; static const u8 totals[] = @@ -373,6 +367,9 @@ void sqlite3_progress_handler( ** specified number of milliseconds before returning 0. */ int sqlite3_busy_timeout(sqlite3 *db, int ms){ + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } if( ms>0 ){ db->busyTimeout = ms; sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); @@ -386,25 +383,43 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){ ** Cause any pending operation to stop at its earliest opportunity. */ void sqlite3_interrupt(sqlite3 *db){ - if( !sqlite3SafetyCheck(db) ){ - db->flags |= SQLITE_Interrupt; + if( db && (db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_BUSY) ){ + db->u1.isInterrupted = 1; } } /* -** Windows systems should call this routine to free memory that -** is returned in the in the errmsg parameter of sqlite3_open() when -** SQLite is a DLL. For some reason, it does not work to call free() -** directly. +** Memory allocation routines that use SQLites internal memory +** memory allocator. Depending on how SQLite is compiled, the +** internal memory allocator might be just an alias for the +** system default malloc/realloc/free. Or the built-in allocator +** might do extra stuff like put sentinals around buffers to +** check for overruns or look for memory leaks. ** -** Note that we need to call free() not sqliteFree() here. +** Use sqlite3_free() to free memory returned by sqlite3_mprintf(). */ -void sqlite3_free(char *p){ free(p); } +void sqlite3_free(void *p){ if( p ) sqlite3OsFree(p); } +void *sqlite3_malloc(int nByte){ return nByte>0 ? sqlite3OsMalloc(nByte) : 0; } +void *sqlite3_realloc(void *pOld, int nByte){ + if( pOld ){ + if( nByte>0 ){ + return sqlite3OsRealloc(pOld, nByte); + }else{ + sqlite3OsFree(pOld); + return 0; + } + }else{ + return sqlite3_malloc(nByte); + } +} /* -** Create new user functions. +** This function is exactly the same as sqlite3_create_function(), except +** that it is designed to be called by internal code. The difference is +** that if a malloc() fails in sqlite3_create_function(), an error code +** is returned and the mallocFailed flag cleared. */ -int sqlite3_create_function( +int sqlite3CreateFunc( sqlite3 *db, const char *zFunctionName, int nArg, @@ -426,6 +441,7 @@ int sqlite3_create_function( (!xFunc && (!xFinal && xStep)) || (nArg<-1 || nArg>127) || (255<(nName = strlen(zFunctionName))) ){ + sqlite3Error(db, SQLITE_ERROR, "bad parameters"); return SQLITE_ERROR; } @@ -441,10 +457,10 @@ int sqlite3_create_function( enc = SQLITE_UTF16NATIVE; }else if( enc==SQLITE_ANY ){ int rc; - rc = sqlite3_create_function(db, zFunctionName, nArg, SQLITE_UTF8, + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, pUserData, xFunc, xStep, xFinal); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3_create_function(db, zFunctionName, nArg, SQLITE_UTF16LE, + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, pUserData, xFunc, xStep, xFinal); if( rc!=SQLITE_OK ) return rc; enc = SQLITE_UTF16BE; @@ -463,6 +479,7 @@ int sqlite3_create_function( if( db->activeVdbeCnt ){ sqlite3Error(db, SQLITE_BUSY, "Unable to delete/modify user-function due to active statements"); + assert( !sqlite3MallocFailed() ); return SQLITE_BUSY; }else{ sqlite3ExpirePreparedStatements(db); @@ -470,42 +487,57 @@ int sqlite3_create_function( } p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); - if( p==0 ) return SQLITE_NOMEM; - p->flags = 0; - p->xFunc = xFunc; - p->xStep = xStep; - p->xFinalize = xFinal; - p->pUserData = pUserData; + if( p ){ + p->flags = 0; + p->xFunc = xFunc; + p->xStep = xStep; + p->xFinalize = xFinal; + p->pUserData = pUserData; + p->nArg = nArg; + } return SQLITE_OK; } + +/* +** Create new user functions. +*/ +int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int enc, + void *p, + void (*xFunc)(sqlite3_context*,int,sqlite3_value **), + void (*xStep)(sqlite3_context*,int,sqlite3_value **), + void (*xFinal)(sqlite3_context*) +){ + int rc; + assert( !sqlite3MallocFailed() ); + rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal); + + return sqlite3ApiExit(db, rc); +} + #ifndef SQLITE_OMIT_UTF16 int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, int eTextRep, - void *pUserData, + void *p, void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ){ int rc; - char const *zFunc8; - sqlite3_value *pTmp; + char *zFunc8; + assert( !sqlite3MallocFailed() ); - if( sqlite3SafetyCheck(db) ){ - return SQLITE_MISUSE; - } - pTmp = sqlite3GetTransientValue(db); - sqlite3ValueSetStr(pTmp, -1, zFunctionName, SQLITE_UTF16NATIVE,SQLITE_STATIC); - zFunc8 = sqlite3ValueText(pTmp, SQLITE_UTF8); + zFunc8 = sqlite3utf16to8(zFunctionName, -1); + rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); + sqliteFree(zFunc8); - if( !zFunc8 ){ - return SQLITE_NOMEM; - } - rc = sqlite3_create_function(db, zFunc8, nArg, eTextRep, - pUserData, xFunc, xStep, xFinal); - return rc; + return sqlite3ApiExit(db, rc); } #endif @@ -547,7 +579,7 @@ void *sqlite3_profile( /*** EXPERIMENTAL *** ** ** Register a function to be invoked when a transaction comments. -** If either function returns non-zero, then the commit becomes a +** If the invoked function returns non-zero, then the commit becomes a ** rollback. */ void *sqlite3_commit_hook( @@ -561,6 +593,35 @@ void *sqlite3_commit_hook( return pOld; } +/* +** Register a callback to be invoked each time a row is updated, +** inserted or deleted using this database connection. +*/ +void *sqlite3_update_hook( + sqlite3 *db, /* Attach the hook to this database */ + void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), + void *pArg /* Argument to the function */ +){ + void *pRet = db->pUpdateArg; + db->xUpdateCallback = xCallback; + db->pUpdateArg = pArg; + return pRet; +} + +/* +** Register a callback to be invoked each time a transaction is rolled +** back by this database connection. +*/ +void *sqlite3_rollback_hook( + sqlite3 *db, /* Attach the hook to this database */ + void (*xCallback)(void*), /* Callback function */ + void *pArg /* Argument to the function */ +){ + void *pRet = db->pRollbackArg; + db->xRollbackCallback = xCallback; + db->pRollbackArg = pArg; + return pRet; +} /* ** This routine is called to create a connection to a database BTree @@ -621,7 +682,7 @@ int sqlite3BtreeFactory( #endif /* SQLITE_OMIT_MEMORYDB */ } - rc = sqlite3BtreeOpen(zFilename, ppBtree, btree_flags); + rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btree_flags); if( rc==SQLITE_OK ){ sqlite3BtreeSetBusyHandler(*ppBtree, (void*)&db->busyHandler); sqlite3BtreeSetCacheSize(*ppBtree, nCache); @@ -635,13 +696,13 @@ int sqlite3BtreeFactory( */ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; - if( sqlite3_malloc_failed ){ + if( !db || sqlite3MallocFailed() ){ return sqlite3ErrStr(SQLITE_NOMEM); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return sqlite3ErrStr(SQLITE_MISUSE); } - z = sqlite3_value_text(db->pErr); + z = (char*)sqlite3_value_text(db->pErr); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } @@ -674,7 +735,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){ }; const void *z; - if( sqlite3_malloc_failed ){ + if( sqlite3MallocFailed() ){ return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ @@ -686,15 +747,17 @@ const void *sqlite3_errmsg16(sqlite3 *db){ SQLITE_UTF8, SQLITE_STATIC); z = sqlite3_value_text16(db->pErr); } + sqlite3ApiExit(0, 0); return z; } #endif /* SQLITE_OMIT_UTF16 */ /* -** Return the most recent error code generated by an SQLite routine. +** Return the most recent error code generated by an SQLite routine. If NULL is +** passed to this function, we assume a malloc() failed during sqlite3_open(). */ int sqlite3_errcode(sqlite3 *db){ - if( sqlite3_malloc_failed ){ + if( !db || sqlite3MallocFailed() ){ return SQLITE_NOMEM; } if( sqlite3SafetyCheck(db) ){ @@ -703,6 +766,63 @@ int sqlite3_errcode(sqlite3 *db){ return db->errCode; } +/* +** Create a new collating function for database "db". The name is zName +** and the encoding is enc. +*/ +static int createCollation( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*) +){ + CollSeq *pColl; + int enc2; + + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } + + /* If SQLITE_UTF16 is specified as the encoding type, transform this + ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the + ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. + */ + enc2 = enc & ~SQLITE_UTF16_ALIGNED; + if( enc2==SQLITE_UTF16 ){ + enc2 = SQLITE_UTF16NATIVE; + } + + if( (enc2&~3)!=0 ){ + sqlite3Error(db, SQLITE_ERROR, "unknown encoding"); + return SQLITE_ERROR; + } + + /* Check if this call is removing or replacing an existing collation + ** sequence. If so, and there are active VMs, return busy. If there + ** are no active VMs, invalidate any pre-compiled statements. + */ + pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 0); + if( pColl && pColl->xCmp ){ + if( db->activeVdbeCnt ){ + sqlite3Error(db, SQLITE_BUSY, + "Unable to delete/modify collation sequence due to active statements"); + return SQLITE_BUSY; + } + sqlite3ExpirePreparedStatements(db); + } + + pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 1); + if( pColl ){ + pColl->xCmp = xCompare; + pColl->pUser = pCtx; + pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED); + } + sqlite3Error(db, SQLITE_OK, 0); + return SQLITE_OK; +} + + /* ** This routine does the work of opening a database on behalf of ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" @@ -713,9 +833,11 @@ static int openDatabase( sqlite3 **ppDb /* OUT: Returned database handle */ ){ sqlite3 *db; - int rc, i; + int rc; CollSeq *pColl; + assert( !sqlite3MallocFailed() ); + /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; @@ -723,33 +845,34 @@ static int openDatabase( db->magic = SQLITE_MAGIC_BUSY; db->nDb = 2; db->aDb = db->aDbStatic; - db->enc = SQLITE_UTF8; db->autoCommit = 1; - db->flags |= SQLITE_ShortColNames; + db->flags |= SQLITE_ShortColNames +#if SQLITE_DEFAULT_FILE_FORMAT<4 + | SQLITE_LegacyFileFmt +#endif + ; sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0); sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); - for(i=0; inDb; i++){ - sqlite3HashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1); - } - +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0); +#endif + /* Add the default collation sequence BINARY. BINARY works for both UTF-8 ** and UTF-16, so add a version for each to avoid any unnecessary ** conversions. The only error that can occur here is a malloc() failure. */ - if( sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binCollFunc) || - sqlite3_create_collation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) || - !(db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0)) ){ - rc = db->errCode; - assert( rc!=SQLITE_OK ); + if( createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc) || + createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc) || + createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc) || + (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0 + ){ + assert( sqlite3MallocFailed() ); db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; } /* Also add a UTF-8 case-insensitive collation sequence. */ - sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc); + createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc); /* Set flags on the built-in collating sequences */ db->pDfltColl->type = SQLITE_COLL_BINARY; @@ -765,6 +888,9 @@ static int openDatabase( db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; } + db->aDb[0].pSchema = sqlite3SchemaGet(db->aDb[0].pBt); + db->aDb[1].pSchema = sqlite3SchemaGet(0); + /* The default safety_level for the main database is 'full'; for the temp ** database it is 'NONE'. This matches the pager layer defaults. @@ -776,29 +902,23 @@ static int openDatabase( db->aDb[1].safety_level = 1; #endif - /* Register all built-in functions, but do not attempt to read the ** database schema yet. This is delayed until the first time the database ** is accessed. */ - sqlite3RegisterBuiltinFunctions(db); - sqlite3Error(db, SQLITE_OK, 0); + if( !sqlite3MallocFailed() ){ + sqlite3RegisterBuiltinFunctions(db); + sqlite3Error(db, SQLITE_OK, 0); + } db->magic = SQLITE_MAGIC_OPEN; opendb_out: - if( sqlite3_errcode(db)==SQLITE_OK && sqlite3_malloc_failed ){ - sqlite3Error(db, SQLITE_NOMEM, 0); + if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){ + sqlite3_close(db); + db = 0; } *ppDb = db; -#ifndef SQLITE_OMIT_GLOBALRECOVER - if( db ){ - sqlite3OsEnterMutex(); - db->pNext = pDbList; - pDbList = db; - sqlite3OsLeaveMutex(); - } -#endif - return sqlite3_errcode(db); + return sqlite3ApiExit(0, rc); } /* @@ -820,9 +940,10 @@ int sqlite3_open16( sqlite3 **ppDb ){ char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ - int rc = SQLITE_NOMEM; + int rc = SQLITE_OK; sqlite3_value *pVal; + assert( zFilename ); assert( ppDb ); *ppDb = 0; pVal = sqlite3ValueNew(); @@ -831,14 +952,16 @@ int sqlite3_open16( if( zFilename8 ){ rc = openDatabase(zFilename8, ppDb); if( rc==SQLITE_OK && *ppDb ){ - sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); + rc = sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); + if( rc!=SQLITE_OK ){ + sqlite3_close(*ppDb); + *ppDb = 0; + } } } - if( pVal ){ - sqlite3ValueFree(pVal); - } + sqlite3ValueFree(pVal); - return rc; + return sqlite3ApiExit(0, rc); } #endif /* SQLITE_OMIT_UTF16 */ @@ -890,53 +1013,10 @@ int sqlite3_create_collation( void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*) ){ - CollSeq *pColl; - int rc = SQLITE_OK; - - if( sqlite3SafetyCheck(db) ){ - return SQLITE_MISUSE; - } - - /* If SQLITE_UTF16 is specified as the encoding type, transform this - ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the - ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. - */ - if( enc==SQLITE_UTF16 ){ - enc = SQLITE_UTF16NATIVE; - } - - if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16LE && enc!=SQLITE_UTF16BE ){ - sqlite3Error(db, SQLITE_ERROR, - "Param 3 to sqlite3_create_collation() must be one of " - "SQLITE_UTF8, SQLITE_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE" - ); - return SQLITE_ERROR; - } - - /* Check if this call is removing or replacing an existing collation - ** sequence. If so, and there are active VMs, return busy. If there - ** are no active VMs, invalidate any pre-compiled statements. - */ - pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 0); - if( pColl && pColl->xCmp ){ - if( db->activeVdbeCnt ){ - sqlite3Error(db, SQLITE_BUSY, - "Unable to delete/modify collation sequence due to active statements"); - return SQLITE_BUSY; - } - sqlite3ExpirePreparedStatements(db); - } - - pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1); - if( 0==pColl ){ - rc = SQLITE_NOMEM; - }else{ - pColl->xCmp = xCompare; - pColl->pUser = pCtx; - pColl->enc = enc; - } - sqlite3Error(db, rc, 0); - return rc; + int rc; + assert( !sqlite3MallocFailed() ); + rc = createCollation(db, zName, enc, pCtx, xCompare); + return sqlite3ApiExit(db, rc); } #ifndef SQLITE_OMIT_UTF16 @@ -950,15 +1030,15 @@ int sqlite3_create_collation16( void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*) ){ - char const *zName8; - sqlite3_value *pTmp; - if( sqlite3SafetyCheck(db) ){ - return SQLITE_MISUSE; + int rc = SQLITE_OK; + char *zName8; + assert( !sqlite3MallocFailed() ); + zName8 = sqlite3utf16to8(zName, -1); + if( zName8 ){ + rc = createCollation(db, zName8, enc, pCtx, xCompare); + sqliteFree(zName8); } - pTmp = sqlite3GetTransientValue(db); - sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF16NATIVE, SQLITE_STATIC); - zName8 = sqlite3ValueText(pTmp, SQLITE_UTF8); - return sqlite3_create_collation(db, zName8, enc, pCtx, xCompare); + return sqlite3ApiExit(db, rc); } #endif /* SQLITE_OMIT_UTF16 */ @@ -1002,37 +1082,11 @@ int sqlite3_collation_needed16( #ifndef SQLITE_OMIT_GLOBALRECOVER /* -** This function is called to recover from a malloc failure that occured -** within SQLite. -** -** This function is *not* threadsafe. Calling this from within a threaded -** application when threads other than the caller have used SQLite is -** dangerous and will almost certainly result in malfunctions. +** This function is now an anachronism. It used to be used to recover from a +** malloc() failure, but SQLite now does this automatically. */ int sqlite3_global_recover(){ - int rc = SQLITE_OK; - - if( sqlite3_malloc_failed ){ - sqlite3 *db; - int i; - sqlite3_malloc_failed = 0; - for(db=pDbList; db; db=db->pNext ){ - sqlite3ExpirePreparedStatements(db); - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt && (rc=sqlite3BtreeReset(pBt)) ){ - goto recover_out; - } - } - db->autoCommit = 1; - } - } - -recover_out: - if( rc!=SQLITE_OK ){ - sqlite3_malloc_failed = 1; - } - return rc; + return SQLITE_OK; } #endif @@ -1058,3 +1112,176 @@ int sqlite3Corrupt(void){ return SQLITE_CORRUPT; } #endif + + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Enable or disable the shared pager and schema features for the +** current thread. +** +** This routine should only be called when there are no open +** database connections. +*/ +int sqlite3_enable_shared_cache(int enable){ + ThreadData *pTd = sqlite3ThreadData(); + if( pTd ){ + /* It is only legal to call sqlite3_enable_shared_cache() when there + ** are no currently open b-trees that were opened by the calling thread. + ** This condition is only easy to detect if the shared-cache were + ** previously enabled (and is being disabled). + */ + if( pTd->pBtree && !enable ){ + assert( pTd->useSharedData ); + return SQLITE_MISUSE; + } + + pTd->useSharedData = enable; + sqlite3ReleaseThreadData(); + } + return sqlite3ApiExit(0, SQLITE_OK); +} +#endif + +/* +** This is a convenience routine that makes sure that all thread-specific +** data for this thread has been deallocated. +*/ +void sqlite3_thread_cleanup(void){ + ThreadData *pTd = sqlite3OsThreadSpecificData(0); + if( pTd ){ + memset(pTd, 0, sizeof(*pTd)); + sqlite3OsThreadSpecificData(-1); + } +} + +/* +** Return meta information about a specific column of a database table. +** See comment in sqlite3.h (sqlite.h.in) for details. +*/ +#ifdef SQLITE_ENABLE_COLUMN_METADATA +int 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 colums is auto-increment */ +){ + int rc; + char *zErrMsg = 0; + Table *pTab = 0; + Column *pCol = 0; + int iCol; + + char const *zDataType = 0; + char const *zCollSeq = 0; + int notnull = 0; + int primarykey = 0; + int autoinc = 0; + + /* Ensure the database schema has been loaded */ + if( sqlite3SafetyOn(db) ){ + return SQLITE_MISUSE; + } + rc = sqlite3Init(db, &zErrMsg); + if( SQLITE_OK!=rc ){ + goto error_out; + } + + /* Locate the table in question */ + pTab = sqlite3FindTable(db, zTableName, zDbName); + if( !pTab || pTab->pSelect ){ + pTab = 0; + goto error_out; + } + + /* Find the column for which info is requested */ + if( sqlite3IsRowid(zColumnName) ){ + iCol = pTab->iPKey; + if( iCol>=0 ){ + pCol = &pTab->aCol[iCol]; + } + }else{ + for(iCol=0; iColnCol; iCol++){ + pCol = &pTab->aCol[iCol]; + if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ + break; + } + } + if( iCol==pTab->nCol ){ + pTab = 0; + goto error_out; + } + } + + /* The following block stores the meta information that will be returned + ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey + ** and autoinc. At this point there are two possibilities: + ** + ** 1. The specified column name was rowid", "oid" or "_rowid_" + ** and there is no explicitly declared IPK column. + ** + ** 2. The table is not a view and the column name identified an + ** explicitly declared column. Copy meta information from *pCol. + */ + if( pCol ){ + zDataType = pCol->zType; + zCollSeq = pCol->zColl; + notnull = (pCol->notNull?1:0); + primarykey = (pCol->isPrimKey?1:0); + autoinc = ((pTab->iPKey==iCol && pTab->autoInc)?1:0); + }else{ + zDataType = "INTEGER"; + primarykey = 1; + } + if( !zCollSeq ){ + zCollSeq = "BINARY"; + } + +error_out: + if( sqlite3SafetyOff(db) ){ + rc = SQLITE_MISUSE; + } + + /* Whether the function call succeeded or failed, set the output parameters + ** to whatever their local counterparts contain. If an error did occur, + ** this has the effect of zeroing all output parameters. + */ + if( pzDataType ) *pzDataType = zDataType; + if( pzCollSeq ) *pzCollSeq = zCollSeq; + if( pNotNull ) *pNotNull = notnull; + if( pPrimaryKey ) *pPrimaryKey = primarykey; + if( pAutoinc ) *pAutoinc = autoinc; + + if( SQLITE_OK==rc && !pTab ){ + sqlite3SetString(&zErrMsg, "no such table column: ", zTableName, ".", + zColumnName, 0); + rc = SQLITE_ERROR; + } + sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); + sqliteFree(zErrMsg); + return sqlite3ApiExit(db, rc); +} +#endif + +/* +** Set all the parameters in the compiled SQL statement to NULL. +*/ +int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ + int i; + int rc = SQLITE_OK; + for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){ + rc = sqlite3_bind_null(pStmt, i); + } + return rc; +} + +/* +** Sleep for a little while. Return the amount of time slept. +*/ +int sqlite3_sleep(int ms){ + return sqlite3OsSleep(ms); +} diff --git a/ext/pdo_sqlite/sqlite/src/opcodes.h b/ext/pdo_sqlite/sqlite/src/opcodes.h index 4db3ec1639..c113f8f1c1 100644 --- a/ext/pdo_sqlite/sqlite/src/opcodes.h +++ b/ext/pdo_sqlite/sqlite/src/opcodes.h @@ -1,149 +1,161 @@ /* Automatically generated. Do not edit */ /* See the mkopcodeh.awk script for details */ #define OP_MemLoad 1 -#define OP_HexBlob 134 /* same as TK_BLOB */ -#define OP_Column 2 -#define OP_SetCookie 3 -#define OP_IfMemPos 4 -#define OP_Real 133 /* same as TK_FLOAT */ -#define OP_Sequence 5 -#define OP_MoveGt 6 -#define OP_Ge 80 /* same as TK_GE */ -#define OP_RowKey 7 -#define OP_Eq 76 /* same as TK_EQ */ -#define OP_OpenWrite 8 -#define OP_NotNull 74 /* same as TK_NOTNULL */ -#define OP_If 9 -#define OP_ToInt 10 -#define OP_String8 95 /* same as TK_STRING */ +#define OP_VNext 2 +#define OP_HexBlob 127 /* same as TK_BLOB */ +#define OP_Column 3 +#define OP_SetCookie 4 +#define OP_IfMemPos 5 +#define OP_Real 126 /* same as TK_FLOAT */ +#define OP_Sequence 6 +#define OP_MoveGt 7 +#define OP_Ge 73 /* same as TK_GE */ +#define OP_RowKey 8 +#define OP_Eq 69 /* same as TK_EQ */ +#define OP_OpenWrite 9 +#define OP_NotNull 67 /* same as TK_NOTNULL */ +#define OP_If 10 +#define OP_ToInt 142 /* same as TK_TO_INT */ +#define OP_String8 88 /* same as TK_STRING */ #define OP_Pop 11 -#define OP_CollSeq 12 -#define OP_OpenRead 13 -#define OP_Expire 14 -#define OP_AutoCommit 15 -#define OP_Gt 77 /* same as TK_GT */ -#define OP_IntegrityCk 16 -#define OP_Sort 17 -#define OP_Function 18 -#define OP_And 68 /* same as TK_AND */ -#define OP_Subtract 87 /* same as TK_MINUS */ -#define OP_Noop 19 -#define OP_Return 20 -#define OP_Remainder 90 /* same as TK_REM */ -#define OP_NewRowid 21 -#define OP_Multiply 88 /* same as TK_STAR */ -#define OP_Variable 22 -#define OP_String 23 -#define OP_ParseSchema 24 -#define OP_Close 25 -#define OP_CreateIndex 26 -#define OP_IsUnique 27 -#define OP_IdxIsNull 28 -#define OP_NotFound 29 -#define OP_Int64 30 -#define OP_MustBeInt 31 -#define OP_Halt 32 -#define OP_Rowid 33 -#define OP_IdxLT 34 -#define OP_AddImm 35 -#define OP_Statement 36 -#define OP_RowData 37 -#define OP_MemMax 38 -#define OP_Push 39 -#define OP_Or 67 /* same as TK_OR */ -#define OP_NotExists 40 -#define OP_MemIncr 41 -#define OP_Gosub 42 -#define OP_Divide 89 /* same as TK_SLASH */ -#define OP_Integer 43 -#define OP_ToNumeric 44 -#define OP_MemInt 45 -#define OP_Prev 46 -#define OP_Concat 91 /* same as TK_CONCAT */ -#define OP_BitAnd 82 /* same as TK_BITAND */ -#define OP_CreateTable 47 -#define OP_Last 48 -#define OP_IsNull 73 /* same as TK_ISNULL */ -#define OP_IdxRowid 49 -#define OP_MakeIdxRec 50 -#define OP_ShiftRight 85 /* same as TK_RSHIFT */ -#define OP_ResetCount 51 -#define OP_FifoWrite 52 -#define OP_Callback 53 -#define OP_ContextPush 54 -#define OP_DropTrigger 55 -#define OP_DropIndex 56 -#define OP_IdxGE 57 -#define OP_IdxDelete 58 -#define OP_Vacuum 59 -#define OP_MoveLe 60 -#define OP_IfNot 61 -#define OP_DropTable 62 -#define OP_MakeRecord 63 -#define OP_ToBlob 64 -#define OP_Delete 65 -#define OP_AggFinal 66 -#define OP_ShiftLeft 84 /* same as TK_LSHIFT */ -#define OP_Dup 70 -#define OP_Goto 71 -#define OP_FifoRead 72 -#define OP_Clear 81 -#define OP_IdxGT 93 -#define OP_MoveLt 96 -#define OP_Le 78 /* same as TK_LE */ -#define OP_VerifyCookie 97 -#define OP_AggStep 98 -#define OP_Pull 99 -#define OP_ToText 100 -#define OP_Not 69 /* same as TK_NOT */ -#define OP_SetNumColumns 101 -#define OP_AbsValue 102 -#define OP_Transaction 103 -#define OP_Negative 92 /* same as TK_UMINUS */ -#define OP_Ne 75 /* same as TK_NE */ -#define OP_ContextPop 104 -#define OP_BitOr 83 /* same as TK_BITOR */ -#define OP_Next 105 -#define OP_IdxInsert 106 -#define OP_Distinct 107 -#define OP_Lt 79 /* same as TK_LT */ -#define OP_Insert 108 -#define OP_Destroy 109 -#define OP_ReadCookie 110 -#define OP_ForceInt 111 -#define OP_LoadAnalysis 112 -#define OP_OpenVirtual 113 -#define OP_Explain 114 -#define OP_OpenPseudo 115 -#define OP_Null 116 -#define OP_Blob 117 -#define OP_Add 86 /* same as TK_PLUS */ -#define OP_MemStore 118 -#define OP_Rewind 119 -#define OP_MoveGe 120 -#define OP_BitNot 94 /* same as TK_BITNOT */ -#define OP_MemMove 121 -#define OP_MemNull 122 -#define OP_Found 123 -#define OP_NullRow 124 +#define OP_VRowid 12 +#define OP_CollSeq 13 +#define OP_OpenRead 14 +#define OP_Expire 15 +#define OP_AutoCommit 17 +#define OP_Gt 70 /* same as TK_GT */ +#define OP_IntegrityCk 18 +#define OP_Sort 19 +#define OP_Function 20 +#define OP_And 62 /* same as TK_AND */ +#define OP_Subtract 80 /* same as TK_MINUS */ +#define OP_Noop 21 +#define OP_Return 22 +#define OP_Remainder 83 /* same as TK_REM */ +#define OP_NewRowid 23 +#define OP_Multiply 81 /* same as TK_STAR */ +#define OP_IfMemNeg 24 +#define OP_Variable 25 +#define OP_String 26 +#define OP_RealAffinity 27 +#define OP_ParseSchema 28 +#define OP_VOpen 29 +#define OP_Close 30 +#define OP_CreateIndex 31 +#define OP_IsUnique 32 +#define OP_IdxIsNull 33 +#define OP_NotFound 34 +#define OP_Int64 35 +#define OP_MustBeInt 36 +#define OP_Halt 37 +#define OP_Rowid 38 +#define OP_IdxLT 39 +#define OP_AddImm 40 +#define OP_Statement 41 +#define OP_RowData 42 +#define OP_MemMax 43 +#define OP_Push 44 +#define OP_Or 61 /* same as TK_OR */ +#define OP_NotExists 45 +#define OP_MemIncr 46 +#define OP_Gosub 47 +#define OP_Divide 82 /* same as TK_SLASH */ +#define OP_Integer 48 +#define OP_ToNumeric 141 /* same as TK_TO_NUMERIC*/ +#define OP_MemInt 49 +#define OP_Prev 50 +#define OP_Concat 84 /* same as TK_CONCAT */ +#define OP_BitAnd 75 /* same as TK_BITAND */ +#define OP_VColumn 51 +#define OP_CreateTable 52 +#define OP_Last 53 +#define OP_IsNull 66 /* same as TK_ISNULL */ +#define OP_IdxRowid 54 +#define OP_MakeIdxRec 55 +#define OP_ShiftRight 78 /* same as TK_RSHIFT */ +#define OP_ResetCount 56 +#define OP_FifoWrite 57 +#define OP_Callback 58 +#define OP_ContextPush 59 +#define OP_DropTrigger 60 +#define OP_DropIndex 63 +#define OP_IdxGE 64 +#define OP_IdxDelete 65 +#define OP_Vacuum 74 +#define OP_MoveLe 86 +#define OP_IfNot 89 +#define OP_DropTable 90 +#define OP_MakeRecord 91 +#define OP_ToBlob 140 /* same as TK_TO_BLOB */ +#define OP_Delete 92 +#define OP_AggFinal 93 +#define OP_ShiftLeft 77 /* same as TK_LSHIFT */ +#define OP_Dup 94 +#define OP_Goto 95 +#define OP_TableLock 96 +#define OP_FifoRead 97 +#define OP_Clear 98 +#define OP_IdxGT 99 +#define OP_MoveLt 100 +#define OP_Le 71 /* same as TK_LE */ +#define OP_VerifyCookie 101 +#define OP_AggStep 102 +#define OP_Pull 103 +#define OP_ToText 139 /* same as TK_TO_TEXT */ +#define OP_Not 16 /* same as TK_NOT */ +#define OP_ToReal 143 /* same as TK_TO_REAL */ +#define OP_SetNumColumns 104 +#define OP_AbsValue 105 +#define OP_Transaction 106 +#define OP_VFilter 107 +#define OP_Negative 85 /* same as TK_UMINUS */ +#define OP_Ne 68 /* same as TK_NE */ +#define OP_VDestroy 108 +#define OP_ContextPop 109 +#define OP_BitOr 76 /* same as TK_BITOR */ +#define OP_Next 110 +#define OP_IdxInsert 111 +#define OP_Distinct 112 +#define OP_Lt 72 /* same as TK_LT */ +#define OP_Insert 113 +#define OP_Destroy 114 +#define OP_ReadCookie 115 +#define OP_ForceInt 116 +#define OP_LoadAnalysis 117 +#define OP_Explain 118 +#define OP_IfMemZero 119 +#define OP_OpenPseudo 120 +#define OP_OpenEphemeral 121 +#define OP_Null 122 +#define OP_Blob 123 +#define OP_Add 79 /* same as TK_PLUS */ +#define OP_MemStore 124 +#define OP_Rewind 125 +#define OP_MoveGe 128 +#define OP_VBegin 129 +#define OP_VUpdate 130 +#define OP_BitNot 87 /* same as TK_BITNOT */ +#define OP_VCreate 131 +#define OP_MemMove 132 +#define OP_MemNull 133 +#define OP_Found 134 +#define OP_NullRow 135 /* The following opcode values are never used */ -#define OP_NotUsed_125 125 -#define OP_NotUsed_126 126 -#define OP_NotUsed_127 127 -#define OP_NotUsed_128 128 -#define OP_NotUsed_129 129 -#define OP_NotUsed_130 130 -#define OP_NotUsed_131 131 -#define OP_NotUsed_132 132 +#define OP_NotUsed_136 136 +#define OP_NotUsed_137 137 +#define OP_NotUsed_138 138 -#define NOPUSH_MASK_0 65368 -#define NOPUSH_MASK_1 47898 -#define NOPUSH_MASK_2 22493 -#define NOPUSH_MASK_3 32761 -#define NOPUSH_MASK_4 65215 -#define NOPUSH_MASK_5 30719 -#define NOPUSH_MASK_6 40895 -#define NOPUSH_MASK_7 6603 -#define NOPUSH_MASK_8 0 -#define NOPUSH_MASK_9 0 +/* Opcodes that are guaranteed to never push a value onto the stack +** contain a 1 their corresponding position of the following mask +** set. See the opcodeNoPush() function in vdbeaux.c */ +#define NOPUSH_MASK_0 0xeeb4 +#define NOPUSH_MASK_1 0x796b +#define NOPUSH_MASK_2 0xfbb7 +#define NOPUSH_MASK_3 0xff24 +#define NOPUSH_MASK_4 0xffff +#define NOPUSH_MASK_5 0xb6ef +#define NOPUSH_MASK_6 0xfdfd +#define NOPUSH_MASK_7 0x33b3 +#define NOPUSH_MASK_8 0xf8cf +#define NOPUSH_MASK_9 0x0000 diff --git a/ext/pdo_sqlite/sqlite/src/os.c b/ext/pdo_sqlite/sqlite/src/os.c new file mode 100644 index 0000000000..ec482fe0e7 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/os.c @@ -0,0 +1,92 @@ +/* +** 2005 November 29 +** +** 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 OS interface code that is common to all +** architectures. +*/ +#define _SQLITE_OS_C_ 1 +#include "sqliteInt.h" +#include "os.h" + +/* +** The following routines are convenience wrappers around methods +** of the OsFile object. This is mostly just syntactic sugar. All +** of this would be completely automatic if SQLite were coded using +** C++ instead of plain old C. +*/ +int sqlite3OsClose(OsFile **pId){ + OsFile *id; + if( pId!=0 && (id = *pId)!=0 ){ + return id->pMethod->xClose(pId); + }else{ + return SQLITE_OK; + } +} +int sqlite3OsOpenDirectory(OsFile *id, const char *zName){ + return id->pMethod->xOpenDirectory(id, zName); +} +int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ + return id->pMethod->xRead(id, pBuf, amt); +} +int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ + return id->pMethod->xWrite(id, pBuf, amt); +} +int sqlite3OsSeek(OsFile *id, i64 offset){ + return id->pMethod->xSeek(id, offset); +} +int sqlite3OsTruncate(OsFile *id, i64 size){ + return id->pMethod->xTruncate(id, size); +} +int sqlite3OsSync(OsFile *id, int fullsync){ + return id->pMethod->xSync(id, fullsync); +} +void sqlite3OsSetFullSync(OsFile *id, int value){ + id->pMethod->xSetFullSync(id, value); +} +#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) +/* This method is currently only used while interactively debugging the +** pager. More specificly, it can only be used when sqlite3DebugPrintf() is +** included in the build. */ +int sqlite3OsFileHandle(OsFile *id){ + return id->pMethod->xFileHandle(id); +} +#endif +int sqlite3OsFileSize(OsFile *id, i64 *pSize){ + return id->pMethod->xFileSize(id, pSize); +} +int sqlite3OsLock(OsFile *id, int lockType){ + return id->pMethod->xLock(id, lockType); +} +int sqlite3OsUnlock(OsFile *id, int lockType){ + return id->pMethod->xUnlock(id, lockType); +} +int sqlite3OsLockState(OsFile *id){ + return id->pMethod->xLockState(id); +} +int sqlite3OsCheckReservedLock(OsFile *id){ + return id->pMethod->xCheckReservedLock(id); +} + +#ifdef SQLITE_ENABLE_REDEF_IO +/* +** A function to return a pointer to the virtual function table. +** This routine really does not accomplish very much since the +** virtual function table is a global variable and anybody who +** can call this function can just as easily access the variable +** for themselves. Nevertheless, we include this routine for +** backwards compatibility with an earlier redefinable I/O +** interface design. +*/ +struct sqlite3OsVtbl *sqlite3_os_switch(void){ + return &sqlite3Os; +} +#endif diff --git a/ext/pdo_sqlite/sqlite/src/os.h b/ext/pdo_sqlite/sqlite/src/os.h index a161d134a6..4433f5d022 100644 --- a/ext/pdo_sqlite/sqlite/src/os.h +++ b/ext/pdo_sqlite/sqlite/src/os.h @@ -18,23 +18,28 @@ #define _SQLITE_OS_H_ /* -** Figure out if we are dealing with Unix, Windows or MacOS. -** -** N.B. MacOS means Mac Classic (or Carbon). Treat Darwin (OS X) as Unix. -** The MacOS build is designed to use CodeWarrior (tested with v8) +** Figure out if we are dealing with Unix, Windows, or some other +** operating system. */ -#if !defined(OS_UNIX) && !defined(OS_TEST) && !defined(OS_OTHER) +#if !defined(OS_UNIX) && !defined(OS_OTHER) # define OS_OTHER 0 # ifndef OS_WIN # if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) # define OS_WIN 1 # define OS_UNIX 0 +# define OS_OS2 0 +# elif defined(_EMX_) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__) +# define OS_WIN 0 +# define OS_UNIX 0 +# define OS_OS2 1 # else # define OS_WIN 0 # define OS_UNIX 1 +# define OS_OS2 0 # endif # else # define OS_UNIX 0 +# define OS_OS2 0 # endif #else # ifndef OS_WIN @@ -42,25 +47,23 @@ # endif #endif + /* -** Invoke the appropriate operating-system specific header file. +** Define the maximum size of a temporary filename */ -#if OS_TEST -# include "os_test.h" -#endif -#if OS_UNIX -# include "os_unix.h" -#endif #if OS_WIN -# include "os_win.h" -#endif - -/* os_other.c and os_other.h are not delivered with SQLite. These files -** are place-holders that can be filled in by third-party developers to -** implement backends to their on proprietary operating systems. -*/ -#if OS_OTHER -# include "os_other.h" +# include +# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) +#elif OS_OS2 +# define INCL_DOSDATETIME +# define INCL_DOSFILEMGR +# define INCL_DOSERRORS +# define INCL_DOSMISC +# define INCL_DOSPROCESS +# include +# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP) +#else +# define SQLITE_TEMPNAME_SIZE 200 #endif /* If the SET_FULLSYNC macro is not defined above, then make it @@ -83,6 +86,129 @@ # define TEMP_FILE_PREFIX "sqlite_" #endif +/* +** Define the interfaces for Unix, Windows, and OS/2. +*/ +#if OS_UNIX +#define sqlite3OsOpenReadWrite sqlite3UnixOpenReadWrite +#define sqlite3OsOpenExclusive sqlite3UnixOpenExclusive +#define sqlite3OsOpenReadOnly sqlite3UnixOpenReadOnly +#define sqlite3OsDelete sqlite3UnixDelete +#define sqlite3OsFileExists sqlite3UnixFileExists +#define sqlite3OsFullPathname sqlite3UnixFullPathname +#define sqlite3OsIsDirWritable sqlite3UnixIsDirWritable +#define sqlite3OsSyncDirectory sqlite3UnixSyncDirectory +#define sqlite3OsTempFileName sqlite3UnixTempFileName +#define sqlite3OsRandomSeed sqlite3UnixRandomSeed +#define sqlite3OsSleep sqlite3UnixSleep +#define sqlite3OsCurrentTime sqlite3UnixCurrentTime +#define sqlite3OsEnterMutex sqlite3UnixEnterMutex +#define sqlite3OsLeaveMutex sqlite3UnixLeaveMutex +#define sqlite3OsInMutex sqlite3UnixInMutex +#define sqlite3OsThreadSpecificData sqlite3UnixThreadSpecificData +#define sqlite3OsMalloc sqlite3GenericMalloc +#define sqlite3OsRealloc sqlite3GenericRealloc +#define sqlite3OsFree sqlite3GenericFree +#define sqlite3OsAllocationSize sqlite3GenericAllocationSize +#endif +#if OS_WIN +#define sqlite3OsOpenReadWrite sqlite3WinOpenReadWrite +#define sqlite3OsOpenExclusive sqlite3WinOpenExclusive +#define sqlite3OsOpenReadOnly sqlite3WinOpenReadOnly +#define sqlite3OsDelete sqlite3WinDelete +#define sqlite3OsFileExists sqlite3WinFileExists +#define sqlite3OsFullPathname sqlite3WinFullPathname +#define sqlite3OsIsDirWritable sqlite3WinIsDirWritable +#define sqlite3OsSyncDirectory sqlite3WinSyncDirectory +#define sqlite3OsTempFileName sqlite3WinTempFileName +#define sqlite3OsRandomSeed sqlite3WinRandomSeed +#define sqlite3OsSleep sqlite3WinSleep +#define sqlite3OsCurrentTime sqlite3WinCurrentTime +#define sqlite3OsEnterMutex sqlite3WinEnterMutex +#define sqlite3OsLeaveMutex sqlite3WinLeaveMutex +#define sqlite3OsInMutex sqlite3WinInMutex +#define sqlite3OsThreadSpecificData sqlite3WinThreadSpecificData +#define sqlite3OsMalloc sqlite3GenericMalloc +#define sqlite3OsRealloc sqlite3GenericRealloc +#define sqlite3OsFree sqlite3GenericFree +#define sqlite3OsAllocationSize sqlite3GenericAllocationSize +#endif +#if OS_OS2 +#define sqlite3OsOpenReadWrite sqlite3Os2OpenReadWrite +#define sqlite3OsOpenExclusive sqlite3Os2OpenExclusive +#define sqlite3OsOpenReadOnly sqlite3Os2OpenReadOnly +#define sqlite3OsDelete sqlite3Os2Delete +#define sqlite3OsFileExists sqlite3Os2FileExists +#define sqlite3OsFullPathname sqlite3Os2FullPathname +#define sqlite3OsIsDirWritable sqlite3Os2IsDirWritable +#define sqlite3OsSyncDirectory sqlite3Os2SyncDirectory +#define sqlite3OsTempFileName sqlite3Os2TempFileName +#define sqlite3OsRandomSeed sqlite3Os2RandomSeed +#define sqlite3OsSleep sqlite3Os2Sleep +#define sqlite3OsCurrentTime sqlite3Os2CurrentTime +#define sqlite3OsEnterMutex sqlite3Os2EnterMutex +#define sqlite3OsLeaveMutex sqlite3Os2LeaveMutex +#define sqlite3OsInMutex sqlite3Os2InMutex +#define sqlite3OsThreadSpecificData sqlite3Os2ThreadSpecificData +#define sqlite3OsMalloc sqlite3GenericMalloc +#define sqlite3OsRealloc sqlite3GenericRealloc +#define sqlite3OsFree sqlite3GenericFree +#define sqlite3OsAllocationSize sqlite3GenericAllocationSize +#endif + + + + +/* +** If using an alternative OS interface, then we must have an "os_other.h" +** header file available for that interface. Presumably the "os_other.h" +** header file contains #defines similar to those above. +*/ +#if OS_OTHER +# include "os_other.h" +#endif + + + +/* +** Forward declarations +*/ +typedef struct OsFile OsFile; +typedef struct IoMethod IoMethod; + +/* +** An instance of the following structure contains pointers to all +** methods on an OsFile object. +*/ +struct IoMethod { + int (*xClose)(OsFile**); + int (*xOpenDirectory)(OsFile*, const char*); + int (*xRead)(OsFile*, void*, int amt); + int (*xWrite)(OsFile*, const void*, int amt); + int (*xSeek)(OsFile*, i64 offset); + int (*xTruncate)(OsFile*, i64 size); + int (*xSync)(OsFile*, int); + void (*xSetFullSync)(OsFile *id, int setting); + int (*xFileHandle)(OsFile *id); + int (*xFileSize)(OsFile*, i64 *pSize); + int (*xLock)(OsFile*, int); + int (*xUnlock)(OsFile*, int); + int (*xLockState)(OsFile *id); + int (*xCheckReservedLock)(OsFile *id); +}; + +/* +** The OsFile object describes an open disk file in an OS-dependent way. +** The version of OsFile defined here is a generic version. Each OS +** implementation defines its own subclass of this structure that contains +** additional information needed to handle file I/O. But the pMethod +** entry (pointing to the virtual function table) always occurs first +** so that we can always find the appropriate methods. +*/ +struct OsFile { + IoMethod const *pMethod; +}; + /* ** The following values may be passed as the second argument to ** sqlite3OsLock(). The various locks exhibit the following semantics: @@ -137,8 +263,10 @@ ** a random byte is selected for a shared lock. The pool of bytes for ** shared locks begins at SHARED_FIRST. ** -** These #defines are available in os.h so that Unix can use the same -** byte ranges for locking. This leaves open the possiblity of having +** These #defines are available in sqlite_aux.h so that adaptors for +** connecting SQLite to other operating systems can use the same byte +** ranges for locking. In particular, the same locking strategy and +** byte ranges are used for Unix. This leaves open the possiblity 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 @@ -172,36 +300,181 @@ extern unsigned int sqlite3_pending_byte; #define SHARED_FIRST (PENDING_BYTE+2) #define SHARED_SIZE 510 - -int sqlite3OsDelete(const char*); -int sqlite3OsFileExists(const char*); -int sqlite3OsOpenReadWrite(const char*, OsFile*, int*); -int sqlite3OsOpenExclusive(const char*, OsFile*, int); -int sqlite3OsOpenReadOnly(const char*, OsFile*); -int sqlite3OsOpenDirectory(const char*, OsFile*); -int sqlite3OsSyncDirectory(const char*); -int sqlite3OsTempFileName(char*); -int sqlite3OsIsDirWritable(char*); -int sqlite3OsClose(OsFile*); +/* +** Prototypes for operating system interface routines. +*/ +int sqlite3OsClose(OsFile**); +int sqlite3OsOpenDirectory(OsFile*, const char*); int sqlite3OsRead(OsFile*, void*, int amt); int sqlite3OsWrite(OsFile*, const void*, int amt); int sqlite3OsSeek(OsFile*, i64 offset); -int sqlite3OsSync(OsFile*, int); int sqlite3OsTruncate(OsFile*, i64 size); +int sqlite3OsSync(OsFile*, int); +void sqlite3OsSetFullSync(OsFile *id, int setting); +int sqlite3OsFileHandle(OsFile *id); int sqlite3OsFileSize(OsFile*, i64 *pSize); -char *sqlite3OsFullPathname(const char*); int sqlite3OsLock(OsFile*, int); int sqlite3OsUnlock(OsFile*, int); +int sqlite3OsLockState(OsFile *id); int sqlite3OsCheckReservedLock(OsFile *id); - - -/* The interface for file I/O is above. Other miscellaneous functions -** are below */ - +int sqlite3OsOpenReadWrite(const char*, OsFile**, int*); +int sqlite3OsOpenExclusive(const char*, OsFile**, int); +int sqlite3OsOpenReadOnly(const char*, OsFile**); +int sqlite3OsDelete(const char*); +int sqlite3OsFileExists(const char*); +char *sqlite3OsFullPathname(const char*); +int sqlite3OsIsDirWritable(char*); +int sqlite3OsSyncDirectory(const char*); +int sqlite3OsTempFileName(char*); int sqlite3OsRandomSeed(char*); int sqlite3OsSleep(int ms); int sqlite3OsCurrentTime(double*); void sqlite3OsEnterMutex(void); void sqlite3OsLeaveMutex(void); +int sqlite3OsInMutex(int); +ThreadData *sqlite3OsThreadSpecificData(int); +void *sqlite3OsMalloc(int); +void *sqlite3OsRealloc(void *, int); +void sqlite3OsFree(void *); +int sqlite3OsAllocationSize(void *); + +/* +** If the SQLITE_ENABLE_REDEF_IO macro is defined, then the OS-layer +** interface routines are not called directly but are invoked using +** pointers to functions. This allows the implementation of various +** OS-layer interface routines to be modified at run-time. There are +** obscure but legitimate reasons for wanting to do this. But for +** most users, a direct call to the underlying interface is preferable +** so the the redefinable I/O interface is turned off by default. +*/ +#ifdef SQLITE_ENABLE_REDEF_IO + +/* +** When redefinable I/O is enabled, a single global instance of the +** following structure holds pointers to the routines that SQLite +** uses to talk with the underlying operating system. Modify this +** structure (before using any SQLite API!) to accomodate perculiar +** operating system interfaces or behaviors. +*/ +struct sqlite3OsVtbl { + int (*xOpenReadWrite)(const char*, OsFile**, int*); + int (*xOpenExclusive)(const char*, OsFile**, int); + int (*xOpenReadOnly)(const char*, OsFile**); + + int (*xDelete)(const char*); + int (*xFileExists)(const char*); + char *(*xFullPathname)(const char*); + int (*xIsDirWritable)(char*); + int (*xSyncDirectory)(const char*); + int (*xTempFileName)(char*); + + int (*xRandomSeed)(char*); + int (*xSleep)(int ms); + int (*xCurrentTime)(double*); + + void (*xEnterMutex)(void); + void (*xLeaveMutex)(void); + int (*xInMutex)(int); + ThreadData *(*xThreadSpecificData)(int); + + void *(*xMalloc)(int); + void *(*xRealloc)(void *, int); + void (*xFree)(void *); + int (*xAllocationSize)(void *); +}; + +/* Macro used to comment out routines that do not exists when there is +** no disk I/O +*/ +#ifdef SQLITE_OMIT_DISKIO +# define IF_DISKIO(X) 0 +#else +# define IF_DISKIO(X) X +#endif + +#ifdef _SQLITE_OS_C_ + /* + ** The os.c file implements the global virtual function table. + */ + struct sqlite3OsVtbl sqlite3Os = { + IF_DISKIO( sqlite3OsOpenReadWrite ), + IF_DISKIO( sqlite3OsOpenExclusive ), + IF_DISKIO( sqlite3OsOpenReadOnly ), + IF_DISKIO( sqlite3OsDelete ), + IF_DISKIO( sqlite3OsFileExists ), + IF_DISKIO( sqlite3OsFullPathname ), + IF_DISKIO( sqlite3OsIsDirWritable ), + IF_DISKIO( sqlite3OsSyncDirectory ), + IF_DISKIO( sqlite3OsTempFileName ), + sqlite3OsRandomSeed, + sqlite3OsSleep, + sqlite3OsCurrentTime, + sqlite3OsEnterMutex, + sqlite3OsLeaveMutex, + sqlite3OsInMutex, + sqlite3OsThreadSpecificData, + sqlite3OsMalloc, + sqlite3OsRealloc, + sqlite3OsFree, + sqlite3OsAllocationSize + }; +#else + /* + ** Files other than os.c just reference the global virtual function table. + */ + extern struct sqlite3OsVtbl sqlite3Os; +#endif /* _SQLITE_OS_C_ */ + + +/* This additional API routine is available with redefinable I/O */ +struct sqlite3OsVtbl *sqlite3_os_switch(void); + + +/* +** Redefine the OS interface to go through the virtual function table +** rather than calling routines directly. +*/ +#undef sqlite3OsOpenReadWrite +#undef sqlite3OsOpenExclusive +#undef sqlite3OsOpenReadOnly +#undef sqlite3OsDelete +#undef sqlite3OsFileExists +#undef sqlite3OsFullPathname +#undef sqlite3OsIsDirWritable +#undef sqlite3OsSyncDirectory +#undef sqlite3OsTempFileName +#undef sqlite3OsRandomSeed +#undef sqlite3OsSleep +#undef sqlite3OsCurrentTime +#undef sqlite3OsEnterMutex +#undef sqlite3OsLeaveMutex +#undef sqlite3OsInMutex +#undef sqlite3OsThreadSpecificData +#undef sqlite3OsMalloc +#undef sqlite3OsRealloc +#undef sqlite3OsFree +#undef sqlite3OsAllocationSize +#define sqlite3OsOpenReadWrite sqlite3Os.xOpenReadWrite +#define sqlite3OsOpenExclusive sqlite3Os.xOpenExclusive +#define sqlite3OsOpenReadOnly sqlite3Os.xOpenReadOnly +#define sqlite3OsDelete sqlite3Os.xDelete +#define sqlite3OsFileExists sqlite3Os.xFileExists +#define sqlite3OsFullPathname sqlite3Os.xFullPathname +#define sqlite3OsIsDirWritable sqlite3Os.xIsDirWritable +#define sqlite3OsSyncDirectory sqlite3Os.xSyncDirectory +#define sqlite3OsTempFileName sqlite3Os.xTempFileName +#define sqlite3OsRandomSeed sqlite3Os.xRandomSeed +#define sqlite3OsSleep sqlite3Os.xSleep +#define sqlite3OsCurrentTime sqlite3Os.xCurrentTime +#define sqlite3OsEnterMutex sqlite3Os.xEnterMutex +#define sqlite3OsLeaveMutex sqlite3Os.xLeaveMutex +#define sqlite3OsInMutex sqlite3Os.xInMutex +#define sqlite3OsThreadSpecificData sqlite3Os.xThreadSpecificData +#define sqlite3OsMalloc sqlite3Os.xMalloc +#define sqlite3OsRealloc sqlite3Os.xRealloc +#define sqlite3OsFree sqlite3Os.xFree +#define sqlite3OsAllocationSize sqlite3Os.xAllocationSize + +#endif /* SQLITE_ENABLE_REDEF_IO */ #endif /* _SQLITE_OS_H_ */ diff --git a/ext/pdo_sqlite/sqlite/src/os_common.h b/ext/pdo_sqlite/sqlite/src/os_common.h index b19ff05906..d65c352ddf 100644 --- a/ext/pdo_sqlite/sqlite/src/os_common.h +++ b/ext/pdo_sqlite/sqlite/src/os_common.h @@ -88,6 +88,7 @@ static unsigned int elapse; ** is used for testing the I/O recovery logic. */ #ifdef SQLITE_TEST +int sqlite3_io_error_hit = 0; int sqlite3_io_error_pending = 0; int sqlite3_diskfull_pending = 0; int sqlite3_diskfull = 0; @@ -95,7 +96,7 @@ int sqlite3_diskfull = 0; if( sqlite3_io_error_pending ) \ if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); return A; } static void local_ioerr(){ - sqlite3_io_error_pending = 0; /* Really just a place to set a breakpoint */ + sqlite3_io_error_hit = 1; /* Really just a place to set a breakpoint */ } #define SimulateDiskfullError \ if( sqlite3_diskfull_pending ){ \ @@ -121,3 +122,67 @@ int sqlite3_open_file_count = 0; #else #define OpenCounter(X) #endif + +/* +** sqlite3GenericMalloc +** sqlite3GenericRealloc +** sqlite3GenericOsFree +** sqlite3GenericAllocationSize +** +** Implementation of the os level dynamic memory allocation interface in terms +** of the standard malloc(), realloc() and free() found in many operating +** systems. No rocket science here. +** +** There are two versions of these four functions here. The version +** implemented here is only used if memory-management or memory-debugging is +** enabled. This version allocates an extra 8-bytes at the beginning of each +** block and stores the size of the allocation there. +** +** If neither memory-management or debugging is enabled, the second +** set of implementations is used instead. +*/ +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || defined (SQLITE_MEMDEBUG) +void *sqlite3GenericMalloc(int n){ + char *p = (char *)malloc(n+8); + assert(n>0); + assert(sizeof(int)<=8); + if( p ){ + *(int *)p = n; + p += 8; + } + return (void *)p; +} +void *sqlite3GenericRealloc(void *p, int n){ + char *p2 = ((char *)p - 8); + assert(n>0); + p2 = (char*)realloc(p2, n+8); + if( p2 ){ + *(int *)p2 = n; + p2 += 8; + } + return (void *)p2; +} +void sqlite3GenericFree(void *p){ + assert(p); + free((void *)((char *)p - 8)); +} +int sqlite3GenericAllocationSize(void *p){ + return p ? *(int *)((char *)p - 8) : 0; +} +#else +void *sqlite3GenericMalloc(int n){ + char *p = (char *)malloc(n); + return (void *)p; +} +void *sqlite3GenericRealloc(void *p, int n){ + assert(n>0); + p = realloc(p, n); + return p; +} +void sqlite3GenericFree(void *p){ + assert(p); + free(p); +} +/* Never actually used, but needed for the linker */ +int sqlite3GenericAllocationSize(void *p){ return 0; } +#endif diff --git a/ext/pdo_sqlite/sqlite/src/os_mac.c b/ext/pdo_sqlite/sqlite/src/os_mac.c deleted file mode 100644 index f84c168d4a..0000000000 --- a/ext/pdo_sqlite/sqlite/src/os_mac.c +++ /dev/null @@ -1,738 +0,0 @@ -/* -** 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 classic mac. Mac OS X -** uses the os_unix.c file, not this one. -*/ -#include "sqliteInt.h" -#include "os.h" -#if OS_MAC /* This file used on classic mac only */ - -#include -#include -#include -#include -#include -#include -#include - -/* -** Macros used to determine whether or not to use threads. -*/ -#if defined(THREADSAFE) && THREADSAFE -# include -# define SQLITE_MACOS_MULTITASKING 1 -#endif - -/* -** Include code that is common to all os_*.c files -*/ -#include "os_common.h" - -/* -** Delete the named file -*/ -int sqlite3OsDelete(const char *zFilename){ - unlink(zFilename); - return SQLITE_OK; -} - -/* -** Return TRUE if the named file exists. -*/ -int sqlite3OsFileExists(const char *zFilename){ - return access(zFilename, 0)==0; -} - -/* -** Attempt to open a file for both reading and writing. If that -** fails, try opening it read-only. If the file does not exist, -** try to create it. -** -** On success, a handle for the open file is written to *id -** and *pReadonly is set to 0 if the file was opened for reading and -** writing or 1 if the file was opened read-only. The function returns -** SQLITE_OK. -** -** On failure, the function returns SQLITE_CANTOPEN and leaves -** *id and *pReadonly unchanged. -*/ -int sqlite3OsOpenReadWrite( - const char *zFilename, - OsFile *id, - int *pReadonly -){ - FSSpec fsSpec; -# ifdef _LARGE_FILE - HFSUniStr255 dfName; - FSRef fsRef; - if( __path2fss(zFilename, &fsSpec) != noErr ){ - if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) - return SQLITE_CANTOPEN; - } - if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) - return SQLITE_CANTOPEN; - FSGetDataForkName(&dfName); - if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, - fsRdWrShPerm, &(id->refNum)) != noErr ){ - if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, - fsRdWrPerm, &(id->refNum)) != noErr ){ - if (FSOpenFork(&fsRef, dfName.length, dfName.unicode, - fsRdPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; - else - *pReadonly = 1; - } else - *pReadonly = 0; - } else - *pReadonly = 0; -# else - __path2fss(zFilename, &fsSpec); - if( !sqlite3OsFileExists(zFilename) ){ - if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) - return SQLITE_CANTOPEN; - } - if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNum)) != noErr ){ - if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ){ - if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; - else - *pReadonly = 1; - } else - *pReadonly = 0; - } else - *pReadonly = 0; -# endif - if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){ - id->refNumRF = -1; - } - id->locked = 0; - id->delOnClose = 0; - OpenCounter(+1); - return SQLITE_OK; -} - - -/* -** Attempt to open a new file for exclusive access by this process. -** The file will be opened for both reading and writing. To avoid -** a potential security problem, we do not allow the file to have -** previously existed. Nor do we allow the file to be a symbolic -** link. -** -** If delFlag is true, then make arrangements to automatically delete -** the file when it is closed. -** -** On success, write the file handle into *id and return SQLITE_OK. -** -** On failure, return SQLITE_CANTOPEN. -*/ -int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ - FSSpec fsSpec; -# ifdef _LARGE_FILE - HFSUniStr255 dfName; - FSRef fsRef; - __path2fss(zFilename, &fsSpec); - if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) - return SQLITE_CANTOPEN; - if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) - return SQLITE_CANTOPEN; - FSGetDataForkName(&dfName); - if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, - fsRdWrPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; -# else - __path2fss(zFilename, &fsSpec); - if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) - return SQLITE_CANTOPEN; - if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; -# endif - id->refNumRF = -1; - id->locked = 0; - id->delOnClose = delFlag; - if (delFlag) - id->pathToDel = sqlite3OsFullPathname(zFilename); - OpenCounter(+1); - return SQLITE_OK; -} - -/* -** Attempt to open a new file for read-only access. -** -** On success, write the file handle into *id and return SQLITE_OK. -** -** On failure, return SQLITE_CANTOPEN. -*/ -int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ - FSSpec fsSpec; -# ifdef _LARGE_FILE - HFSUniStr255 dfName; - FSRef fsRef; - if( __path2fss(zFilename, &fsSpec) != noErr ) - return SQLITE_CANTOPEN; - if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) - return SQLITE_CANTOPEN; - FSGetDataForkName(&dfName); - if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, - fsRdPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; -# else - __path2fss(zFilename, &fsSpec); - if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr ) - return SQLITE_CANTOPEN; -# endif - if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){ - id->refNumRF = -1; - } - id->locked = 0; - id->delOnClose = 0; - OpenCounter(+1); - return SQLITE_OK; -} - -/* -** Attempt to open a file descriptor for the directory that contains a -** file. This file descriptor can be used to fsync() the directory -** in order to make sure the creation of a new file is actually written -** to disk. -** -** This routine is only meaningful for Unix. It is a no-op under -** windows since windows does not support hard links. -** -** On success, a handle for a previously open file is at *id is -** updated with the new directory file descriptor and SQLITE_OK is -** returned. -** -** On failure, the function returns SQLITE_CANTOPEN and leaves -** *id unchanged. -*/ -int sqlite3OsOpenDirectory( - const char *zDirname, - OsFile *id -){ - return SQLITE_OK; -} - -/* -** Create a temporary file name in zBuf. zBuf must be big enough to -** hold at least SQLITE_TEMPNAME_SIZE characters. -*/ -int sqlite3OsTempFileName(char *zBuf){ - static char zChars[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - int i, j; - char zTempPath[SQLITE_TEMPNAME_SIZE]; - char zdirName[32]; - CInfoPBRec infoRec; - Str31 dirName; - memset(&infoRec, 0, sizeof(infoRec)); - memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE); - if( FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, - &(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){ - infoRec.dirInfo.ioNamePtr = dirName; - do{ - infoRec.dirInfo.ioFDirIndex = -1; - infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID; - if( PBGetCatInfoSync(&infoRec) == noErr ){ - CopyPascalStringToC(dirName, zdirName); - i = strlen(zdirName); - memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath)); - strcpy(zTempPath, zdirName); - zTempPath[i] = ':'; - }else{ - *zTempPath = 0; - break; - } - } while( infoRec.dirInfo.ioDrDirID != fsRtDirID ); - } - if( *zTempPath == 0 ) - getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24); - for(;;){ - sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zTempPath); - j = strlen(zBuf); - sqlite3Randomness(15, &zBuf[j]); - for(i=0; i<15; i++, j++){ - zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; - } - zBuf[j] = 0; - if( !sqlite3OsFileExists(zBuf) ) break; - } - return SQLITE_OK; -} - -/* -** Close a file. -*/ -int sqlite3OsClose(OsFile *id){ - if( id->refNumRF!=-1 ) - FSClose(id->refNumRF); -# ifdef _LARGE_FILE - FSCloseFork(id->refNum); -# else - FSClose(id->refNum); -# endif - if( id->delOnClose ){ - unlink(id->pathToDel); - sqliteFree(id->pathToDel); - } - OpenCounter(-1); - return SQLITE_OK; -} - -/* -** Read data from a file into a buffer. Return SQLITE_OK if all -** bytes were read successfully and SQLITE_IOERR if anything goes -** wrong. -*/ -int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ - int got; - SimulateIOError(SQLITE_IOERR); - TRACE2("READ %d\n", last_page); -# ifdef _LARGE_FILE - FSReadFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&got); -# else - got = amt; - FSRead(id->refNum, &got, pBuf); -# endif - if( got==amt ){ - return SQLITE_OK; - }else{ - return SQLITE_IOERR; - } -} - -/* -** Write data from a buffer into a file. Return SQLITE_OK on success -** or some other error code on failure. -*/ -int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ - OSErr oserr; - int wrote = 0; - SimulateIOError(SQLITE_IOERR); - TRACE2("WRITE %d\n", last_page); - while( amt>0 ){ -# ifdef _LARGE_FILE - oserr = FSWriteFork(id->refNum, fsAtMark, 0, - (ByteCount)amt, pBuf, (ByteCount*)&wrote); -# else - wrote = amt; - oserr = FSWrite(id->refNum, &wrote, pBuf); -# endif - if( wrote == 0 || oserr != noErr) - break; - amt -= wrote; - pBuf = &((char*)pBuf)[wrote]; - } - if( oserr != noErr || amt>wrote ){ - return SQLITE_FULL; - } - return SQLITE_OK; -} - -/* -** Move the read/write pointer in a file. -*/ -int sqlite3OsSeek(OsFile *id, off_t offset){ - off_t curSize; - SEEK(offset/1024 + 1); - if( sqlite3OsFileSize(id, &curSize) != SQLITE_OK ){ - return SQLITE_IOERR; - } - if( offset >= curSize ){ - if( sqlite3OsTruncate(id, offset+1) != SQLITE_OK ){ - return SQLITE_IOERR; - } - } -# ifdef _LARGE_FILE - if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){ -# else - if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){ -# endif - return SQLITE_IOERR; - }else{ - return SQLITE_OK; - } -} - -/* -** Make sure all writes to a particular file are committed to disk. -** -** 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. -*/ -int sqlite3OsSync(OsFile *id){ -# ifdef _LARGE_FILE - if( FSFlushFork(id->refNum) != noErr ){ -# else - ParamBlockRec params; - memset(¶ms, 0, sizeof(ParamBlockRec)); - params.ioParam.ioRefNum = id->refNum; - if( PBFlushFileSync(¶ms) != noErr ){ -# endif - return SQLITE_IOERR; - }else{ - return SQLITE_OK; - } -} - -/* -** Sync the directory zDirname. This is a no-op on operating systems other -** than UNIX. -*/ -int sqlite3OsSyncDirectory(const char *zDirname){ - SimulateIOError(SQLITE_IOERR); - return SQLITE_OK; -} - -/* -** Truncate an open file to a specified size -*/ -int sqlite3OsTruncate(OsFile *id, off_t nByte){ - SimulateIOError(SQLITE_IOERR); -# ifdef _LARGE_FILE - if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){ -# else - if( SetEOF(id->refNum, nByte) != noErr ){ -# endif - return SQLITE_IOERR; - }else{ - return SQLITE_OK; - } -} - -/* -** Determine the current size of a file in bytes -*/ -int sqlite3OsFileSize(OsFile *id, off_t *pSize){ -# ifdef _LARGE_FILE - if( FSGetForkSize(id->refNum, pSize) != noErr){ -# else - if( GetEOF(id->refNum, pSize) != noErr ){ -# endif - return SQLITE_IOERR; - }else{ - return SQLITE_OK; - } -} - -/* -** Windows file locking notes: [similar issues apply to MacOS] -** -** 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. -** (This is a design error on the part of Windows, but there is nothing -** we can do about that.) So the region used for locking is at the -** end of the file where it is unlikely to ever interfere with an -** actual read attempt. -** -** A database read 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. -** A database write lock is obtained by locking all bytes in the range. -** There can only be one writer. -** -** A lock is obtained on the first byte of the lock range before acquiring -** either a read lock or a write lock. This prevents two processes from -** attempting to get a lock at a same time. The semantics of -** sqlite3OsReadLock() require that if there is already a write lock, that -** lock is converted into a read lock atomically. The lock on the first -** byte allows us to drop the old write lock and get the read lock without -** another process jumping into the middle and messing us up. The same -** argument applies to sqlite3OsWriteLock(). -** -** 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. -** -** Note: On MacOS we use the resource fork for locking. -** -** The following #defines specify the range of bytes used for locking. -** N_LOCKBYTE is the number of bytes available for doing the locking. -** The first byte used to hold the lock while the lock is changing does -** not count toward this number. FIRST_LOCKBYTE is the address of -** the first byte in the range of bytes used for locking. -*/ -#define N_LOCKBYTE 10239 -#define FIRST_LOCKBYTE (0x000fffff - N_LOCKBYTE) - -/* -** Change the status of the lock on the file "id" to be a readlock. -** If the file was write locked, then this reduces the lock to a read. -** If the file was read locked, then this acquires a new read lock. -** -** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this -** library was compiled with large file support (LFS) but LFS is not -** available on the host, then an SQLITE_NOLFS is returned. -*/ -int sqlite3OsReadLock(OsFile *id){ - int rc; - if( id->locked>0 || id->refNumRF == -1 ){ - rc = SQLITE_OK; - }else{ - int lk; - OSErr res; - int cnt = 5; - ParamBlockRec params; - sqlite3Randomness(sizeof(lk), &lk); - lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1; - memset(¶ms, 0, sizeof(params)); - params.ioParam.ioRefNum = id->refNumRF; - params.ioParam.ioPosMode = fsFromStart; - params.ioParam.ioPosOffset = FIRST_LOCKBYTE; - params.ioParam.ioReqCount = 1; - while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){ - UInt32 finalTicks; - Delay(1, &finalTicks); /* 1/60 sec */ - } - if( res == noErr ){ - params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; - params.ioParam.ioReqCount = N_LOCKBYTE; - PBUnlockRangeSync(¶ms); - params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk; - params.ioParam.ioReqCount = 1; - res = PBLockRangeSync(¶ms); - params.ioParam.ioPosOffset = FIRST_LOCKBYTE; - params.ioParam.ioReqCount = 1; - PBUnlockRangeSync(¶ms); - } - if( res == noErr ){ - id->locked = lk; - rc = SQLITE_OK; - }else{ - rc = SQLITE_BUSY; - } - } - return rc; -} - -/* -** Change the lock status to be an exclusive or write lock. Return -** SQLITE_OK on success and SQLITE_BUSY on a failure. If this -** library was compiled with large file support (LFS) but LFS is not -** available on the host, then an SQLITE_NOLFS is returned. -*/ -int sqlite3OsWriteLock(OsFile *id){ - int rc; - if( id->locked<0 || id->refNumRF == -1 ){ - rc = SQLITE_OK; - }else{ - OSErr res; - int cnt = 5; - ParamBlockRec params; - memset(¶ms, 0, sizeof(params)); - params.ioParam.ioRefNum = id->refNumRF; - params.ioParam.ioPosMode = fsFromStart; - params.ioParam.ioPosOffset = FIRST_LOCKBYTE; - params.ioParam.ioReqCount = 1; - while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){ - UInt32 finalTicks; - Delay(1, &finalTicks); /* 1/60 sec */ - } - if( res == noErr ){ - params.ioParam.ioPosOffset = FIRST_LOCKBYTE + id->locked; - params.ioParam.ioReqCount = 1; - if( id->locked==0 - || PBUnlockRangeSync(¶ms)==noErr ){ - params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; - params.ioParam.ioReqCount = N_LOCKBYTE; - res = PBLockRangeSync(¶ms); - }else{ - res = afpRangeNotLocked; - } - params.ioParam.ioPosOffset = FIRST_LOCKBYTE; - params.ioParam.ioReqCount = 1; - PBUnlockRangeSync(¶ms); - } - if( res == noErr ){ - id->locked = -1; - rc = SQLITE_OK; - }else{ - rc = SQLITE_BUSY; - } - } - return rc; -} - -/* -** Unlock the given file descriptor. If the file descriptor was -** not previously locked, then this routine is a no-op. If this -** library was compiled with large file support (LFS) but LFS is not -** available on the host, then an SQLITE_NOLFS is returned. -*/ -int sqlite3OsUnlock(OsFile *id){ - int rc; - ParamBlockRec params; - memset(¶ms, 0, sizeof(params)); - params.ioParam.ioRefNum = id->refNumRF; - params.ioParam.ioPosMode = fsFromStart; - if( id->locked==0 || id->refNumRF == -1 ){ - rc = SQLITE_OK; - }else if( id->locked<0 ){ - params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; - params.ioParam.ioReqCount = N_LOCKBYTE; - PBUnlockRangeSync(¶ms); - rc = SQLITE_OK; - id->locked = 0; - }else{ - params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked; - params.ioParam.ioReqCount = 1; - PBUnlockRangeSync(¶ms); - rc = SQLITE_OK; - id->locked = 0; - } - return rc; -} - -/* -** Get information to seed the random number generator. The seed -** is written into the buffer zBuf[256]. The calling function must -** supply a sufficiently large buffer. -*/ -int sqlite3OsRandomSeed(char *zBuf){ - /* 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, 256); -#if !defined(SQLITE_TEST) - { - int pid; - Microseconds((UnsignedWide*)zBuf); - pid = getpid(); - memcpy(&zBuf[sizeof(UnsignedWide)], &pid, sizeof(pid)); - } -#endif - return SQLITE_OK; -} - -/* -** Sleep for a little while. Return the amount of time slept. -*/ -int sqlite3OsSleep(int ms){ - UInt32 finalTicks; - UInt32 ticks = (((UInt32)ms+16)*3)/50; /* 1/60 sec per tick */ - Delay(ticks, &finalTicks); - return (int)((ticks*50)/3); -} - -/* -** Static variables used for thread synchronization -*/ -static int inMutex = 0; -#ifdef SQLITE_MACOS_MULTITASKING - static MPCriticalRegionID criticalRegion; -#endif - -/* -** The following pair of routine implement mutual exclusion for -** multi-threaded processes. Only a single thread is allowed to -** executed code that is surrounded by EnterMutex() and LeaveMutex(). -** -** SQLite uses only a single Mutex. There is not much critical -** code and what little there is executes quickly and without blocking. -*/ -void sqlite3OsEnterMutex(){ -#ifdef SQLITE_MACOS_MULTITASKING - static volatile int notInit = 1; - if( notInit ){ - if( notInit == 2 ) /* as close as you can get to thread safe init */ - MPYield(); - else{ - notInit = 2; - MPCreateCriticalRegion(&criticalRegion); - notInit = 0; - } - } - MPEnterCriticalRegion(criticalRegion, kDurationForever); -#endif - assert( !inMutex ); - inMutex = 1; -} -void sqlite3OsLeaveMutex(){ - assert( inMutex ); - inMutex = 0; -#ifdef SQLITE_MACOS_MULTITASKING - MPExitCriticalRegion(criticalRegion); -#endif -} - -/* -** Turn a relative pathname into a full pathname. Return a pointer -** to the full pathname stored in space obtained from sqliteMalloc(). -** The calling function is responsible for freeing this space once it -** is no longer needed. -*/ -char *sqlite3OsFullPathname(const char *zRelative){ - char *zFull = 0; - if( zRelative[0]==':' ){ - char zBuf[_MAX_PATH+1]; - sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), &(zRelative[1]), - (char*)0); - }else{ - if( strchr(zRelative, ':') ){ - sqlite3SetString(&zFull, zRelative, (char*)0); - }else{ - char zBuf[_MAX_PATH+1]; - sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), zRelative, (char*)0); - } - } - return zFull; -} - -/* -** The following variable, if set to a non-zero value, becomes the result -** returned from sqlite3OsCurrentTime(). This is used for testing. -*/ -#ifdef SQLITE_TEST -int sqlite3_current_time = 0; -#endif - -/* -** 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. -*/ -int sqlite3OsCurrentTime(double *prNow){ - *prNow = 0.0; /**** FIX ME *****/ -#ifdef SQLITE_TEST - if( sqlite3_current_time ){ - *prNow = sqlite3_current_time/86400.0 + 2440587.5; - } -#endif - return 0; -} - -#endif /* OS_MAC */ diff --git a/ext/pdo_sqlite/sqlite/src/os_mac.h b/ext/pdo_sqlite/sqlite/src/os_mac.h deleted file mode 100644 index 5b60f81837..0000000000 --- a/ext/pdo_sqlite/sqlite/src/os_mac.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -** 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 header file defines OS-specific features of classic Mac. -** OS X uses the os_unix.h file, not this one. -*/ -#ifndef _SQLITE_OS_MAC_H_ -#define _SQLITE_OS_MAC_H_ - - -#include -#include -#define SQLITE_TEMPNAME_SIZE _MAX_PATH -#define SQLITE_MIN_SLEEP_MS 17 - -/* -** The OsFile structure is a operating-system independing representation -** of an open file handle. It is defined differently for each architecture. -** -** This is the definition for class Mac. -*/ -typedef struct OsFile OsFile; -struct OsFile { - SInt16 refNum; /* Data fork/file reference number */ - SInt16 refNumRF; /* Resource fork reference number (for locking) */ - int locked; /* 0: unlocked, <0: write lock, >0: read lock */ - int delOnClose; /* True if file is to be deleted on close */ - char *pathToDel; /* Name of file to delete on close */ -}; - - -#endif /* _SQLITE_OS_MAC_H_ */ diff --git a/ext/pdo_sqlite/sqlite/src/os_unix.c b/ext/pdo_sqlite/sqlite/src/os_unix.c index f4e09b5364..5b58cb7aac 100644 --- a/ext/pdo_sqlite/sqlite/src/os_unix.c +++ b/ext/pdo_sqlite/sqlite/src/os_unix.c @@ -16,15 +16,101 @@ #include "os.h" #if OS_UNIX /* This file is used on unix only */ +/* +** These #defines should enable >2GB file support on Posix if the +** underlying operating system supports it. If the OS lacks +** large file support, these should be no-ops. +** +** 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: RedHat 7.2) but you want your code to work +** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in RedHat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif +/* +** standard include files. +*/ +#include +#include +#include +#include #include #include #include -#include + +/* +** If we are to be thread-safe, include the pthreads header and define +** the SQLITE_UNIX_THREADS macro. +*/ +#if defined(THREADSAFE) && 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 + + + +/* +** The unixFile structure is subclass of OsFile specific for the unix +** protability layer. +*/ +typedef struct unixFile unixFile; +struct unixFile { + IoMethod const *pMethod; /* Always the first entry */ + struct openCnt *pOpen; /* Info about all open fd's on this inode */ + struct lockInfo *pLock; /* Info about locks on this inode */ + int h; /* The file descriptor */ + unsigned char locktype; /* The type of lock held on this fd */ + unsigned char isOpen; /* True if needs to be closed */ + unsigned char fullSync; /* Use F_FULLSYNC if available */ + int dirfd; /* File descriptor for the directory */ + i64 offset; /* Seek offset */ +#ifdef SQLITE_UNIX_THREADS + pthread_t tid; /* The thread that "owns" this OsFile */ +#endif +}; + +/* +** Provide the ability to override some OS-layer functions during +** testing. This is used to simulate OS crashes to verify that +** commits are atomic even in the event of an OS crash. +*/ +#ifdef SQLITE_CRASH_TEST + extern int sqlite3CrashTestEnable; + extern int sqlite3CrashOpenReadWrite(const char*, OsFile**, int*); + extern int sqlite3CrashOpenExclusive(const char*, OsFile**, int); + extern int sqlite3CrashOpenReadOnly(const char*, OsFile**, int); +# define CRASH_TEST_OVERRIDE(X,A,B,C) \ + if(sqlite3CrashTestEnable){ return X(A,B,C); } +#else +# define CRASH_TEST_OVERRIDE(X,A,B,C) /* no-op */ +#endif + + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" /* ** Do not include any of the File I/O interface procedures if the -** SQLITE_OMIT_DISKIO macro is defined (indicating that there database +** SQLITE_OMIT_DISKIO macro is defined (indicating that the database ** will be in-memory only) */ #ifndef SQLITE_OMIT_DISKIO @@ -51,17 +137,12 @@ ** 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 its DOS - what did you expect? +** DJGPP. But it's DOS - what did you expect? */ #ifdef __DJGPP__ # define fcntl(A,B,C) 0 #endif -/* -** Include code that is common to all os_*.c files -*/ -#include "os_common.h" - /* ** The threadid macro resolves to the thread-id or to 0. Used for ** testing and debugging only. @@ -80,10 +161,18 @@ ** means that sqlite3* database handles cannot be moved from one thread ** to another. This logic makes sure a user does not try to do that ** by mistake. +** +** Version 3.3.1 (2006-01-15): OsFiles can be moved from one thread to +** another as long as we are running on a system that supports threads +** overriding each others locks (which now the most common behavior) +** or if no locks are held. But the OsFile.pLock field needs to be +** recomputed because its key includes the thread-id. See the +** transferOwnership() function below for additional information */ -#ifdef SQLITE_UNIX_THREADS -# define SET_THREADID(X) X->tid = pthread_self() -# define CHECK_THREADID(X) (!pthread_equal(X->tid, pthread_self())) +#if defined(SQLITE_UNIX_THREADS) +# define SET_THREADID(X) (X)->tid = pthread_self() +# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \ + !pthread_equal((X)->tid, pthread_self())) #else # define SET_THREADID(X) # define CHECK_THREADID(X) 0 @@ -195,14 +284,14 @@ ** ** If threads cannot override each others locks, then we set the ** lockKey.tid field to the thread ID. If threads can override -** each others locks then tid is always set to zero. tid is also -** set to zero if we compile without threading support. +** each others locks then tid is always set to zero. tid is omitted +** if we compile without threading support. */ struct lockKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ #ifdef SQLITE_UNIX_THREADS - pthread_t tid; /* Thread ID or zero if threads cannot override each other */ + pthread_t tid; /* Thread ID or zero if threads can override each other */ #endif }; @@ -248,12 +337,14 @@ struct openCnt { }; /* -** These hash table maps inodes and process IDs into lockInfo and openCnt -** structures. Access to these hash tables must be protected by a mutex. +** These hash tables map inodes and file descriptors (really, lockKey and +** openKey structures) into lockInfo and openCnt structures. Access to +** these hash tables must be protected by a mutex. */ -static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; -static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; - +static Hash lockHash = {SQLITE_HASH_BINARY, 0, 0, 0, + sqlite3ThreadSafeMalloc, sqlite3ThreadSafeFree, 0, 0}; +static Hash openHash = {SQLITE_HASH_BINARY, 0, 0, 0, + sqlite3ThreadSafeMalloc, sqlite3ThreadSafeFree, 0, 0}; #ifdef SQLITE_UNIX_THREADS /* @@ -263,8 +354,25 @@ static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; ** 0: No. Threads cannot override each others locks. ** 1: Yes. Threads can override each others locks. ** -1: We don't know yet. +** +** On some systems, we know at compile-time if threads can override each +** others locks. On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro +** will be set appropriately. On other systems, we have to check at +** runtime. On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is +** undefined. +** +** This variable normally has file scope only. But during testing, we make +** it a global so that the test code can change its value in order to verify +** that the right stuff happens in either case. */ -static int threadsOverrideEachOthersLocks = -1; +#ifndef SQLITE_THREAD_OVERRIDE_LOCK +# define SQLITE_THREAD_OVERRIDE_LOCK -1 +#endif +#ifdef SQLITE_TEST +int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK; +#else +static int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK; +#endif /* ** This structure holds information passed into individual test @@ -283,7 +391,7 @@ struct threadTestData { ** 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 -** turnned off. +** turned off. */ static int lockTrace(int fd, int op, struct flock *p){ char *zOpName, *zType; @@ -353,7 +461,7 @@ static void *threadLockingTest(void *pArg){ ** can override each others locks then sets the ** threadsOverrideEachOthersLocks variable appropriately. */ -static void testThreadLockingBehavior(fd_orig){ +static void testThreadLockingBehavior(int fd_orig){ int fd; struct threadTestData d[2]; pthread_t t[2]; @@ -381,10 +489,11 @@ static void testThreadLockingBehavior(fd_orig){ ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ + assert( sqlite3OsInMutex(1) ); pLock->nRef--; if( pLock->nRef==0 ){ sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); - sqliteFree(pLock); + sqlite3ThreadSafeFree(pLock); } } @@ -392,18 +501,19 @@ static void releaseLockInfo(struct lockInfo *pLock){ ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ + assert( sqlite3OsInMutex(1) ); pOpen->nRef--; if( pOpen->nRef==0 ){ sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); - sqliteFree(pOpen->aPending); - sqliteFree(pOpen); + free(pOpen->aPending); + sqlite3ThreadSafeFree(pOpen); } } /* ** Given a file descriptor, locate lockInfo and openCnt structures that -** describes that file descriptor. Create a new ones if necessary. The -** return values might be unset if an error occurs. +** describes that file descriptor. Create new ones if necessary. The +** return values might be uninitialized if an error occurs. ** ** Return the number of errors. */ @@ -420,6 +530,8 @@ static int findLockInfo( struct openCnt *pOpen; rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; + + assert( sqlite3OsInMutex(1) ); memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; @@ -435,8 +547,11 @@ static int findLockInfo( pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1)); if( pLock==0 ){ struct lockInfo *pOld; - pLock = sqliteMallocRaw( sizeof(*pLock) ); - if( pLock==0 ) return 1; + pLock = sqlite3ThreadSafeMalloc( sizeof(*pLock) ); + if( pLock==0 ){ + rc = 1; + goto exit_findlockinfo; + } pLock->key = key1; pLock->nRef = 1; pLock->cnt = 0; @@ -444,44 +559,114 @@ static int findLockInfo( pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); if( pOld!=0 ){ assert( pOld==pLock ); - sqliteFree(pLock); - return 1; + sqlite3ThreadSafeFree(pLock); + rc = 1; + goto exit_findlockinfo; } }else{ pLock->nRef++; } *ppLock = pLock; - pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); - if( pOpen==0 ){ - struct openCnt *pOld; - pOpen = sqliteMallocRaw( sizeof(*pOpen) ); + if( ppOpen!=0 ){ + pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); if( pOpen==0 ){ - releaseLockInfo(pLock); - return 1; - } - pOpen->key = key2; - pOpen->nRef = 1; - pOpen->nLock = 0; - pOpen->nPending = 0; - pOpen->aPending = 0; - pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); - if( pOld!=0 ){ - assert( pOld==pOpen ); - sqliteFree(pOpen); - releaseLockInfo(pLock); - return 1; + struct openCnt *pOld; + pOpen = sqlite3ThreadSafeMalloc( sizeof(*pOpen) ); + if( pOpen==0 ){ + releaseLockInfo(pLock); + rc = 1; + goto exit_findlockinfo; + } + pOpen->key = key2; + pOpen->nRef = 1; + pOpen->nLock = 0; + pOpen->nPending = 0; + pOpen->aPending = 0; + pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); + if( pOld!=0 ){ + assert( pOld==pOpen ); + sqlite3ThreadSafeFree(pOpen); + releaseLockInfo(pLock); + rc = 1; + goto exit_findlockinfo; + } + }else{ + pOpen->nRef++; } - }else{ - pOpen->nRef++; + *ppOpen = pOpen; } - *ppOpen = pOpen; - return 0; + +exit_findlockinfo: + return rc; +} + +#ifdef SQLITE_DEBUG +/* +** Helper function for printing out trace information from debugging +** binaries. This returns the string represetation of the supplied +** integer lock-type. +*/ +static const char *locktypeName(int locktype){ + switch( locktype ){ + 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 + +/* +** If we are currently in a different thread than the thread that the +** unixFile argument belongs to, then transfer ownership of the unixFile +** over to the current thread. +** +** A unixFile is only owned by a thread on systems where one thread is +** unable to override locks created by a different thread. RedHat9 is +** an example of such a system. +** +** Ownership transfer is only allowed if the unixFile is currently unlocked. +** If the unixFile is locked and an ownership is wrong, then return +** SQLITE_MISUSE. SQLITE_OK is returned if everything works. +*/ +#ifdef SQLITE_UNIX_THREADS +static int transferOwnership(unixFile *pFile){ + int rc; + pthread_t hSelf; + if( threadsOverrideEachOthersLocks ){ + /* Ownership transfers not needed on this system */ + return SQLITE_OK; + } + hSelf = pthread_self(); + if( pthread_equal(pFile->tid, hSelf) ){ + /* We are still in the same thread */ + TRACE1("No-transfer, same thread\n"); + return SQLITE_OK; + } + if( pFile->locktype!=NO_LOCK ){ + /* We cannot change ownership while we are holding a lock! */ + return SQLITE_MISUSE; + } + TRACE4("Transfer ownership of %d from %d to %d\n", pFile->h,pFile->tid,hSelf); + pFile->tid = hSelf; + releaseLockInfo(pFile->pLock); + rc = findLockInfo(pFile->h, &pFile->pLock, 0); + TRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, + locktypeName(pFile->locktype), + locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); + return rc; +} +#else + /* On single-threaded builds, ownership transfer is a no-op */ +# define transferOwnership(X) SQLITE_OK +#endif /* ** Delete the named file */ -int sqlite3OsDelete(const char *zFilename){ +int sqlite3UnixDelete(const char *zFilename){ unlink(zFilename); return SQLITE_OK; } @@ -489,10 +674,13 @@ int sqlite3OsDelete(const char *zFilename){ /* ** Return TRUE if the named file exists. */ -int sqlite3OsFileExists(const char *zFilename){ +int sqlite3UnixFileExists(const char *zFilename){ return access(zFilename, 0)==0; } +/* Forward declaration */ +static int allocateUnixFile(unixFile *pInit, OsFile **pId); + /* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, @@ -506,25 +694,26 @@ int sqlite3OsFileExists(const char *zFilename){ ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id and *pReadonly unchanged. */ -int sqlite3OsOpenReadWrite( +int sqlite3UnixOpenReadWrite( const char *zFilename, - OsFile *id, + OsFile **pId, int *pReadonly ){ int rc; - assert( !id->isOpen ); - id->dirfd = -1; - SET_THREADID(id); - id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, + unixFile f; + + CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadWrite, zFilename, pId, pReadonly); + assert( 0==*pId ); + f.h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, SQLITE_DEFAULT_FILE_PERMISSIONS); - if( id->h<0 ){ + if( f.h<0 ){ #ifdef EISDIR if( errno==EISDIR ){ return SQLITE_CANTOPEN; } #endif - id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); - if( id->h<0 ){ + f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); + if( f.h<0 ){ return SQLITE_CANTOPEN; } *pReadonly = 1; @@ -532,17 +721,14 @@ int sqlite3OsOpenReadWrite( *pReadonly = 0; } sqlite3OsEnterMutex(); - rc = findLockInfo(id->h, &id->pLock, &id->pOpen); + rc = findLockInfo(f.h, &f.pLock, &f.pOpen); sqlite3OsLeaveMutex(); if( rc ){ - close(id->h); + close(f.h); return SQLITE_NOMEM; } - id->locktype = 0; - id->isOpen = 1; - TRACE3("OPEN %-3d %s\n", id->h, zFilename); - OpenCounter(+1); - return SQLITE_OK; + TRACE3("OPEN %-3d %s\n", f.h, zFilename); + return allocateUnixFile(&f, pId); } @@ -560,36 +746,31 @@ int sqlite3OsOpenReadWrite( ** ** On failure, return SQLITE_CANTOPEN. */ -int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ +int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ int rc; - assert( !id->isOpen ); - if( access(zFilename, 0)==0 ){ - return SQLITE_CANTOPEN; - } - SET_THREADID(id); - id->dirfd = -1; - id->h = open(zFilename, + unixFile f; + + CRASH_TEST_OVERRIDE(sqlite3CrashOpenExclusive, zFilename, pId, delFlag); + assert( 0==*pId ); + f.h = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, SQLITE_DEFAULT_FILE_PERMISSIONS); - if( id->h<0 ){ + if( f.h<0 ){ return SQLITE_CANTOPEN; } sqlite3OsEnterMutex(); - rc = findLockInfo(id->h, &id->pLock, &id->pOpen); + rc = findLockInfo(f.h, &f.pLock, &f.pOpen); sqlite3OsLeaveMutex(); if( rc ){ - close(id->h); + close(f.h); unlink(zFilename); return SQLITE_NOMEM; } - id->locktype = 0; - id->isOpen = 1; if( delFlag ){ unlink(zFilename); } - TRACE3("OPEN-EX %-3d %s\n", id->h, zFilename); - OpenCounter(+1); - return SQLITE_OK; + TRACE3("OPEN-EX %-3d %s\n", f.h, zFilename); + return allocateUnixFile(&f, pId); } /* @@ -599,27 +780,25 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ ** ** On failure, return SQLITE_CANTOPEN. */ -int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ +int sqlite3UnixOpenReadOnly(const char *zFilename, OsFile **pId){ int rc; - assert( !id->isOpen ); - SET_THREADID(id); - id->dirfd = -1; - id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); - if( id->h<0 ){ + unixFile f; + + CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadOnly, zFilename, pId, 0); + assert( 0==*pId ); + f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); + if( f.h<0 ){ return SQLITE_CANTOPEN; } sqlite3OsEnterMutex(); - rc = findLockInfo(id->h, &id->pLock, &id->pOpen); + rc = findLockInfo(f.h, &f.pLock, &f.pOpen); sqlite3OsLeaveMutex(); if( rc ){ - close(id->h); + close(f.h); return SQLITE_NOMEM; } - id->locktype = 0; - id->isOpen = 1; - TRACE3("OPEN-RO %-3d %s\n", id->h, zFilename); - OpenCounter(+1); - return SQLITE_OK; + TRACE3("OPEN-RO %-3d %s\n", f.h, zFilename); + return allocateUnixFile(&f, pId); } /* @@ -631,29 +810,30 @@ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ ** This routine is only meaningful for Unix. It is a no-op under ** windows since windows does not support hard links. ** -** On success, a handle for a previously open file is at *id is +** On success, a handle for a previously open file at *id is ** updated with the new directory file descriptor and SQLITE_OK is ** returned. ** ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id unchanged. */ -int sqlite3OsOpenDirectory( - const char *zDirname, - OsFile *id +static int unixOpenDirectory( + OsFile *id, + const char *zDirname ){ - if( !id->isOpen ){ + unixFile *pFile = (unixFile*)id; + if( pFile==0 ){ /* Do not open the directory if the corresponding file is not already ** open. */ return SQLITE_CANTOPEN; } - SET_THREADID(id); - assert( id->dirfd<0 ); - id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0); - if( id->dirfd<0 ){ + SET_THREADID(pFile); + assert( pFile->dirfd<0 ); + pFile->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0); + if( pFile->dirfd<0 ){ return SQLITE_CANTOPEN; } - TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname); + TRACE3("OPENDIR %-3d %s\n", pFile->dirfd, zDirname); return SQLITE_OK; } @@ -661,6 +841,8 @@ int sqlite3OsOpenDirectory( ** If the following global variable points to a string which is the ** name of a directory, then that directory will be used to store ** temporary files. +** +** See also the "PRAGMA temp_store_directory" SQL command. */ char *sqlite3_temp_directory = 0; @@ -668,7 +850,7 @@ char *sqlite3_temp_directory = 0; ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ -int sqlite3OsTempFileName(char *zBuf){ +int sqlite3UnixTempFileName(char *zBuf){ static const char *azDirs[] = { 0, "/var/tmp", @@ -704,35 +886,54 @@ int sqlite3OsTempFileName(char *zBuf){ return SQLITE_OK; } -#ifndef SQLITE_OMIT_PAGER_PRAGMAS /* ** Check that a given pathname is a directory and is writable ** */ -int sqlite3OsIsDirWritable(char *zBuf){ +int sqlite3UnixIsDirWritable(char *zBuf){ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS struct stat buf; if( zBuf==0 ) return 0; if( zBuf[0]==0 ) return 0; if( stat(zBuf, &buf) ) return 0; if( !S_ISDIR(buf.st_mode) ) return 0; if( access(zBuf, 07) ) return 0; +#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ return 1; } -#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ + +/* +** Seek to the offset in id->offset then read cnt bytes into pBuf. +** Return the number of bytes actually read. Update the offset. +*/ +static int seekAndRead(unixFile *id, void *pBuf, int cnt){ + int got; +#ifdef USE_PREAD + got = pread(id->h, pBuf, cnt, id->offset); +#else + lseek(id->h, id->offset, SEEK_SET); + got = read(id->h, pBuf, cnt); +#endif + if( got>0 ){ + id->offset += got; + } + return got; +} /* ** Read data from a file into a buffer. Return SQLITE_OK if all ** bytes were read successfully and SQLITE_IOERR if anything goes ** wrong. */ -int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ +static int unixRead(OsFile *id, void *pBuf, int amt){ int got; - assert( id->isOpen ); + assert( id ); SimulateIOError(SQLITE_IOERR); TIMER_START; - got = read(id->h, pBuf, amt); + got = seekAndRead((unixFile*)id, pBuf, amt); TIMER_END; - TRACE5("READ %-3d %5d %7d %d\n", id->h, got, last_page, TIMER_ELAPSED); + TRACE5("READ %-3d %5d %7d %d\n", ((unixFile*)id)->h, got, + last_page, TIMER_ELAPSED); SEEK(0); /* if( got<0 ) got = 0; */ if( got==amt ){ @@ -742,23 +943,43 @@ int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ } } +/* +** Seek to the offset in id->offset then read cnt bytes into pBuf. +** Return the number of bytes actually read. Update the offset. +*/ +static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){ + int got; +#ifdef USE_PREAD + got = pwrite(id->h, pBuf, cnt, id->offset); +#else + lseek(id->h, id->offset, SEEK_SET); + got = write(id->h, pBuf, cnt); +#endif + if( got>0 ){ + id->offset += got; + } + return got; +} + + /* ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ -int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ +static int unixWrite(OsFile *id, const void *pBuf, int amt){ int wrote = 0; - assert( id->isOpen ); + assert( id ); assert( amt>0 ); SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; TIMER_START; - while( amt>0 && (wrote = write(id->h, pBuf, amt))>0 ){ + while( amt>0 && (wrote = seekAndWrite((unixFile*)id, pBuf, amt))>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } TIMER_END; - TRACE5("WRITE %-3d %5d %7d %d\n", id->h, wrote, last_page, TIMER_ELAPSED); + TRACE5("WRITE %-3d %5d %7d %d\n", ((unixFile*)id)->h, wrote, + last_page, TIMER_ELAPSED); SEEK(0); if( amt>0 ){ return SQLITE_FULL; @@ -769,13 +990,13 @@ int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ /* ** Move the read/write pointer in a file. */ -int sqlite3OsSeek(OsFile *id, i64 offset){ - assert( id->isOpen ); +static int unixSeek(OsFile *id, i64 offset){ + assert( id ); SEEK(offset/1024 + 1); #ifdef SQLITE_TEST if( offset ) SimulateDiskfullError #endif - lseek(id->h, offset, SEEK_SET); + ((unixFile*)id)->offset = offset; return SQLITE_OK; } @@ -788,6 +1009,25 @@ int sqlite3_sync_count = 0; int sqlite3_fullsync_count = 0; #endif +/* +** Use the fdatasync() API only if the HAVE_FDATASYNC macro is defined. +** Otherwise use fsync() in its place. +*/ +#ifndef 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 @@ -819,7 +1059,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ rc = SQLITE_OK; #else -#ifdef F_FULLFSYNC +#if HAVE_FULLFSYNC if( fullSync ){ rc = fcntl(fd, F_FULLFSYNC, 0); }else{ @@ -829,12 +1069,9 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ if( rc ) rc = fsync(fd); #else /* if !defined(F_FULLSYNC) */ -#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO>0 if( dataOnly ){ rc = fdatasync(fd); - }else -#endif /* _POSIX_SYNCHRONIZED_IO > 0 */ - { + }else{ rc = fsync(fd); } #endif /* defined(F_FULLFSYNC) */ @@ -858,18 +1095,34 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ ** the directory entry for the journal was never created) and the transaction ** will not roll back - possibly leading to database corruption. */ -int sqlite3OsSync(OsFile *id, int dataOnly){ - assert( id->isOpen ); +static int unixSync(OsFile *id, int dataOnly){ + unixFile *pFile = (unixFile*)id; + assert( pFile ); SimulateIOError(SQLITE_IOERR); - TRACE2("SYNC %-3d\n", id->h); - if( full_fsync(id->h, id->fullSync, dataOnly) ){ + TRACE2("SYNC %-3d\n", pFile->h); + if( full_fsync(pFile->h, pFile->fullSync, dataOnly) ){ return SQLITE_IOERR; } - if( id->dirfd>=0 ){ - TRACE2("DIRSYNC %-3d\n", id->dirfd); - full_fsync(id->dirfd, id->fullSync, 0); - close(id->dirfd); /* Only need to sync once, so close the directory */ - id->dirfd = -1; /* when we are done. */ + if( pFile->dirfd>=0 ){ + TRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, + HAVE_FULLFSYNC, pFile->fullSync); +#ifndef SQLITE_DISABLE_DIRSYNC + /* The directory sync is only attempted if full_fsync is + ** turned off or unavailable. If a full_fsync occurred above, + ** then the directory sync is superfluous. + */ + if( (!HAVE_FULLFSYNC || !pFile->fullSync) && full_fsync(pFile->dirfd,0,0) ){ + /* + ** We have received multiple reports of fsync() returning + ** errors when applied to directories on certain file systems. + ** A failed directory sync is not a big deal. So it seems + ** better to ignore the error. Ticket #1657 + */ + /* return SQLITE_IOERR; */ + } +#endif + close(pFile->dirfd); /* Only need to sync once, so close the directory */ + pFile->dirfd = -1; /* when we are done. */ } return SQLITE_OK; } @@ -882,7 +1135,10 @@ int sqlite3OsSync(OsFile *id, int dataOnly){ ** before making changes to individual journals on a multi-database commit. ** The F_FULLFSYNC option is not needed here. */ -int sqlite3OsSyncDirectory(const char *zDirname){ +int sqlite3UnixSyncDirectory(const char *zDirname){ +#ifdef SQLITE_DISABLE_DIRSYNC + return SQLITE_OK; +#else int fd; int r; SimulateIOError(SQLITE_IOERR); @@ -894,25 +1150,26 @@ int sqlite3OsSyncDirectory(const char *zDirname){ r = fsync(fd); close(fd); return ((r==0)?SQLITE_OK:SQLITE_IOERR); +#endif } /* ** Truncate an open file to a specified size */ -int sqlite3OsTruncate(OsFile *id, i64 nByte){ - assert( id->isOpen ); +static int unixTruncate(OsFile *id, i64 nByte){ + assert( id ); SimulateIOError(SQLITE_IOERR); - return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; + return ftruncate(((unixFile*)id)->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; } /* ** Determine the current size of a file in bytes */ -int sqlite3OsFileSize(OsFile *id, i64 *pSize){ +static int unixFileSize(OsFile *id, i64 *pSize){ struct stat buf; - assert( id->isOpen ); + assert( id ); SimulateIOError(SQLITE_IOERR); - if( fstat(id->h, &buf)!=0 ){ + if( fstat(((unixFile*)id)->h, &buf)!=0 ){ return SQLITE_IOERR; } *pSize = buf.st_size; @@ -925,15 +1182,15 @@ int sqlite3OsFileSize(OsFile *id, i64 *pSize){ ** non-zero. If the file is unlocked or holds only SHARED locks, then ** return zero. */ -int sqlite3OsCheckReservedLock(OsFile *id){ +static int unixCheckReservedLock(OsFile *id){ int r = 0; + unixFile *pFile = (unixFile*)id; - assert( id->isOpen ); - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; - sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */ + assert( pFile ); + sqlite3OsEnterMutex(); /* Because pFile->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ - if( id->pLock->locktype>SHARED_LOCK ){ + if( pFile->pLock->locktype>SHARED_LOCK ){ r = 1; } @@ -945,36 +1202,18 @@ int sqlite3OsCheckReservedLock(OsFile *id){ lock.l_start = RESERVED_BYTE; lock.l_len = 1; lock.l_type = F_WRLCK; - fcntl(id->h, F_GETLK, &lock); + fcntl(pFile->h, F_GETLK, &lock); if( lock.l_type!=F_UNLCK ){ r = 1; } } sqlite3OsLeaveMutex(); - TRACE3("TEST WR-LOCK %d %d\n", id->h, r); + TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; } -#ifdef SQLITE_DEBUG -/* -** Helper function for printing out trace information from debugging -** binaries. This returns the string represetation of the supplied -** integer lock-type. -*/ -static const char * locktypeName(int locktype){ - switch( locktype ){ - 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 - /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: @@ -999,7 +1238,7 @@ static const char * locktypeName(int locktype){ ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ -int sqlite3OsLock(OsFile *id, int locktype){ +static int unixLock(OsFile *id, int locktype){ /* 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 @@ -1039,39 +1278,49 @@ int sqlite3OsLock(OsFile *id, int locktype){ ** even if the locking primitive used is always a write-lock. */ int rc = SQLITE_OK; - struct lockInfo *pLock = id->pLock; + unixFile *pFile = (unixFile*)id; + struct lockInfo *pLock = pFile->pLock; struct flock lock; int s; - assert( id->isOpen ); - TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", id->h, locktypeName(locktype), - locktypeName(id->locktype), locktypeName(pLock->locktype), pLock->cnt - ,getpid() ); - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; + assert( pFile ); + TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, + locktypeName(locktype), locktypeName(pFile->locktype), + locktypeName(pLock->locktype), pLock->cnt , getpid()); /* 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( id->locktype>=locktype ){ - TRACE3("LOCK %d %s ok (already held)\n", id->h, locktypeName(locktype)); + if( pFile->locktype>=locktype ){ + TRACE3("LOCK %d %s ok (already held)\n", pFile->h, + locktypeName(locktype)); return SQLITE_OK; } /* Make sure the locking sequence is correct */ - assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); - assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); - /* This mutex is needed because id->pLock is shared across threads + /* This mutex is needed because pFile->pLock is shared across threads */ sqlite3OsEnterMutex(); + /* Make sure the current thread owns the pFile. + */ + rc = transferOwnership(pFile); + if( rc!=SQLITE_OK ){ + sqlite3OsLeaveMutex(); + return rc; + } + pLock = pFile->pLock; + /* If some thread using this PID has a lock via a different OsFile* ** handle that precludes the requested lock, return BUSY. */ - if( (id->locktype!=pLock->locktype && + if( (pFile->locktype!=pLock->locktype && (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) ){ rc = SQLITE_BUSY; @@ -1085,11 +1334,11 @@ int sqlite3OsLock(OsFile *id, int locktype){ if( locktype==SHARED_LOCK && (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ assert( locktype==SHARED_LOCK ); - assert( id->locktype==0 ); + assert( pFile->locktype==0 ); assert( pLock->cnt>0 ); - id->locktype = SHARED_LOCK; + pFile->locktype = SHARED_LOCK; pLock->cnt++; - id->pOpen->nLock++; + pFile->pOpen->nLock++; goto end_lock; } @@ -1102,11 +1351,11 @@ int sqlite3OsLock(OsFile *id, int locktype){ ** be released. */ if( locktype==SHARED_LOCK - || (locktype==EXCLUSIVE_LOCK && id->locktypelocktypeh, F_SETLK, &lock); + s = fcntl(pFile->h, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; goto end_lock; @@ -1124,21 +1373,21 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Now get the read-lock */ lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; - s = fcntl(id->h, F_SETLK, &lock); + s = fcntl(pFile->h, F_SETLK, &lock); /* Drop the temporary PENDING lock */ lock.l_start = PENDING_BYTE; lock.l_len = 1L; lock.l_type = F_UNLCK; - if( fcntl(id->h, F_SETLK, &lock)!=0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ rc = SQLITE_IOERR; /* This should never happen */ goto end_lock; } if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; }else{ - id->locktype = SHARED_LOCK; - id->pOpen->nLock++; + pFile->locktype = SHARED_LOCK; + pFile->pOpen->nLock++; pLock->cnt = 1; } }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){ @@ -1150,7 +1399,7 @@ int sqlite3OsLock(OsFile *id, int locktype){ ** assumed that there is a SHARED or greater lock on the file ** already. */ - assert( 0!=id->locktype ); + assert( 0!=pFile->locktype ); lock.l_type = F_WRLCK; switch( locktype ){ case RESERVED_LOCK: @@ -1163,63 +1412,62 @@ int sqlite3OsLock(OsFile *id, int locktype){ default: assert(0); } - s = fcntl(id->h, F_SETLK, &lock); + s = fcntl(pFile->h, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; } } if( rc==SQLITE_OK ){ - id->locktype = locktype; + pFile->locktype = locktype; pLock->locktype = locktype; }else if( locktype==EXCLUSIVE_LOCK ){ - id->locktype = PENDING_LOCK; + pFile->locktype = PENDING_LOCK; pLock->locktype = PENDING_LOCK; } end_lock: sqlite3OsLeaveMutex(); - TRACE4("LOCK %d %s %s\n", id->h, locktypeName(locktype), + TRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; } /* -** Lower the locking level on file descriptor id to locktype. locktype +** Lower the locking level on file descriptor pFile 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, this routine -** might return SQLITE_IOERR instead of SQLITE_OK. */ -int sqlite3OsUnlock(OsFile *id, int locktype){ +static int unixUnlock(OsFile *id, int locktype){ struct lockInfo *pLock; struct flock lock; int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; - assert( id->isOpen ); - TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype, - id->pLock->locktype, id->pLock->cnt, getpid()); - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; + assert( pFile ); + TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, + pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); assert( locktype<=SHARED_LOCK ); - if( id->locktype<=locktype ){ + if( pFile->locktype<=locktype ){ return SQLITE_OK; } + if( CHECK_THREADID(pFile) ){ + return SQLITE_MISUSE; + } sqlite3OsEnterMutex(); - pLock = id->pLock; + pLock = pFile->pLock; assert( pLock->cnt!=0 ); - if( id->locktype>SHARED_LOCK ){ - assert( pLock->locktype==id->locktype ); + if( pFile->locktype>SHARED_LOCK ){ + assert( pLock->locktype==pFile->locktype ); if( locktype==SHARED_LOCK ){ lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; - if( fcntl(id->h, F_SETLK, &lock)!=0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ /* This should never happen */ rc = SQLITE_IOERR; } @@ -1228,7 +1476,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ lock.l_whence = SEEK_SET; lock.l_start = PENDING_BYTE; lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); - if( fcntl(id->h, F_SETLK, &lock)==0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)==0 ){ pLock->locktype = SHARED_LOCK; }else{ rc = SQLITE_IOERR; /* This should never happen */ @@ -1246,7 +1494,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; - if( fcntl(id->h, F_SETLK, &lock)==0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)==0 ){ pLock->locktype = NO_LOCK; }else{ rc = SQLITE_IOERR; /* This should never happen */ @@ -1257,7 +1505,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ ** count reaches zero, close any other file descriptors whose close ** was deferred because of outstanding locks. */ - pOpen = id->pOpen; + pOpen = pFile->pOpen; pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 && pOpen->nPending>0 ){ @@ -1265,26 +1513,28 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ for(i=0; inPending; i++){ close(pOpen->aPending[i]); } - sqliteFree(pOpen->aPending); + free(pOpen->aPending); pOpen->nPending = 0; pOpen->aPending = 0; } } sqlite3OsLeaveMutex(); - id->locktype = locktype; + pFile->locktype = locktype; return rc; } /* ** Close a file. */ -int sqlite3OsClose(OsFile *id){ - if( !id->isOpen ) return SQLITE_OK; - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; - sqlite3OsUnlock(id, NO_LOCK); +static int unixClose(OsFile **pId){ + unixFile *id = (unixFile*)*pId; + + if( !id ) return SQLITE_OK; + unixUnlock(*pId, NO_LOCK); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqlite3OsEnterMutex(); + if( id->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file @@ -1293,7 +1543,7 @@ int sqlite3OsClose(OsFile *id){ */ int *aNew; struct openCnt *pOpen = id->pOpen; - aNew = sqliteRealloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); + aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ }else{ @@ -1307,10 +1557,13 @@ int sqlite3OsClose(OsFile *id){ } releaseLockInfo(id->pLock); releaseOpenCnt(id->pOpen); + sqlite3OsLeaveMutex(); id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); + sqlite3ThreadSafeFree(id); + *pId = 0; return SQLITE_OK; } @@ -1320,7 +1573,7 @@ int sqlite3OsClose(OsFile *id){ ** The calling function is responsible for freeing this space once it ** is no longer needed. */ -char *sqlite3OsFullPathname(const char *zRelative){ +char *sqlite3UnixFullPathname(const char *zRelative){ char *zFull = 0; if( zRelative[0]=='/' ){ sqlite3SetString(&zFull, zRelative, (char*)0); @@ -1334,9 +1587,109 @@ char *sqlite3OsFullPathname(const char *zRelative){ (char*)0); sqliteFree(zBuf); } + +#if 0 + /* + ** Remove "/./" path elements and convert "/A/./" path elements + ** to just "/". + */ + if( zFull ){ + int i, j; + for(i=j=0; zFull[i]; i++){ + if( zFull[i]=='/' ){ + if( zFull[i+1]=='/' ) continue; + if( zFull[i+1]=='.' && zFull[i+2]=='/' ){ + i += 1; + continue; + } + if( zFull[i+1]=='.' && zFull[i+2]=='.' && zFull[i+3]=='/' ){ + while( j>0 && zFull[j-1]!='/' ){ j--; } + i += 3; + continue; + } + } + zFull[j++] = zFull[i]; + } + zFull[j] = 0; + } +#endif + return zFull; } +/* +** Change the value of the fullsync flag in the given file descriptor. +*/ +static void unixSetFullSync(OsFile *id, int v){ + ((unixFile*)id)->fullSync = v; +} + +/* +** Return the underlying file handle for an OsFile +*/ +static int unixFileHandle(OsFile *id){ + return ((unixFile*)id)->h; +} + +/* +** Return an integer that indices the type of lock currently held +** by this handle. (Used for testing and analysis only.) +*/ +static int unixLockState(OsFile *id){ + return ((unixFile*)id)->locktype; +} + +/* +** This vector defines all the methods that can operate on an OsFile +** for unix. +*/ +static const IoMethod sqlite3UnixIoMethod = { + unixClose, + unixOpenDirectory, + unixRead, + unixWrite, + unixSeek, + unixTruncate, + unixSync, + unixSetFullSync, + unixFileHandle, + unixFileSize, + unixLock, + unixUnlock, + unixLockState, + unixCheckReservedLock, +}; + +/* +** Allocate memory for a unixFile. Initialize the new unixFile +** to the value given in pInit and return a pointer to the new +** OsFile. If we run out of memory, close the file and return NULL. +*/ +static int allocateUnixFile(unixFile *pInit, OsFile **pId){ + unixFile *pNew; + pInit->dirfd = -1; + pInit->fullSync = 0; + pInit->locktype = 0; + pInit->offset = 0; + SET_THREADID(pInit); + pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) ); + if( pNew==0 ){ + close(pInit->h); + sqlite3OsEnterMutex(); + releaseLockInfo(pInit->pLock); + releaseOpenCnt(pInit->pOpen); + sqlite3OsLeaveMutex(); + *pId = 0; + return SQLITE_NOMEM; + }else{ + *pNew = *pInit; + pNew->pMethod = &sqlite3UnixIoMethod; + *pId = (OsFile*)pNew; + OpenCounter(+1); + return SQLITE_OK; + } +} + #endif /* SQLITE_OMIT_DISKIO */ /*************************************************************************** @@ -1350,7 +1703,7 @@ char *sqlite3OsFullPathname(const char *zRelative){ ** is written into the buffer zBuf[256]. The calling function must ** supply a sufficiently large buffer. */ -int sqlite3OsRandomSeed(char *zBuf){ +int sqlite3UnixRandomSeed(char *zBuf){ /* 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 @@ -1360,7 +1713,7 @@ int sqlite3OsRandomSeed(char *zBuf){ ** 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 + ** that we always use the same random number sequence. This makes the ** tests repeatable. */ memset(zBuf, 0, 256); @@ -1369,7 +1722,9 @@ int sqlite3OsRandomSeed(char *zBuf){ int pid, fd; fd = open("/dev/urandom", O_RDONLY); if( fd<0 ){ - time((time_t*)zBuf); + time_t t; + time(&t); + memcpy(zBuf, &t, sizeof(t)); pid = getpid(); memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid)); }else{ @@ -1383,8 +1738,9 @@ int sqlite3OsRandomSeed(char *zBuf){ /* ** Sleep for a little while. Return the amount of time slept. +** The argument is the number of milliseconds we want to sleep. */ -int sqlite3OsSleep(int ms){ +int sqlite3UnixSleep(int ms){ #if defined(HAVE_USLEEP) && HAVE_USLEEP usleep(ms*1000); return ms; @@ -1395,11 +1751,42 @@ int sqlite3OsSleep(int ms){ } /* -** Static variables used for thread synchronization +** Static variables used for thread synchronization. +** +** inMutex the nesting depth of the recursive mutex. The thread +** holding mutexMain can read this variable at any time. +** But is must hold mutexAux to change this variable. Other +** threads must hold mutexAux to read the variable and can +** never write. +** +** mutexOwner The thread id of the thread holding mutexMain. Same +** access rules as for inMutex. +** +** mutexOwnerValid True if the value in mutexOwner is valid. The same +** access rules apply as for inMutex. +** +** mutexMain The main mutex. Hold this mutex in order to get exclusive +** access to SQLite data structures. +** +** mutexAux An auxiliary mutex needed to access variables defined above. +** +** Mutexes are always acquired in this order: mutexMain mutexAux. It +** is not necessary to acquire mutexMain in order to get mutexAux - just +** do not attempt to acquire them in the reverse order: mutexAux mutexMain. +** Either get the mutexes with mutexMain first or get mutexAux only. +** +** When running on a platform where the three variables inMutex, mutexOwner, +** and mutexOwnerValid can be set atomically, the mutexAux is not required. +** On many systems, all three are 32-bit integers and writing to a 32-bit +** integer is atomic. I think. But there are no guarantees. So it seems +** safer to protect them using mutexAux. */ static int inMutex = 0; #ifdef SQLITE_UNIX_THREADS -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_t mutexOwner; /* Thread holding mutexMain */ +static int mutexOwnerValid = 0; /* True if mutexOwner is valid */ +static pthread_mutex_t mutexMain = PTHREAD_MUTEX_INITIALIZER; /* The mutex */ +static pthread_mutex_t mutexAux = PTHREAD_MUTEX_INITIALIZER; /* Aux mutex */ #endif /* @@ -1409,19 +1796,164 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. +** +** As of version 3.3.2, this mutex must be recursive. */ -void sqlite3OsEnterMutex(){ +void sqlite3UnixEnterMutex(){ +#ifdef SQLITE_UNIX_THREADS + pthread_mutex_lock(&mutexAux); + if( !mutexOwnerValid || !pthread_equal(mutexOwner, pthread_self()) ){ + pthread_mutex_unlock(&mutexAux); + pthread_mutex_lock(&mutexMain); + assert( inMutex==0 ); + assert( !mutexOwnerValid ); + pthread_mutex_lock(&mutexAux); + mutexOwner = pthread_self(); + mutexOwnerValid = 1; + } + inMutex++; + pthread_mutex_unlock(&mutexAux); +#else + inMutex++; +#endif +} +void sqlite3UnixLeaveMutex(){ + assert( inMutex>0 ); #ifdef SQLITE_UNIX_THREADS - pthread_mutex_lock(&mutex); + pthread_mutex_lock(&mutexAux); + inMutex--; + assert( pthread_equal(mutexOwner, pthread_self()) ); + if( inMutex==0 ){ + assert( mutexOwnerValid ); + mutexOwnerValid = 0; + pthread_mutex_unlock(&mutexMain); + } + pthread_mutex_unlock(&mutexAux); +#else + inMutex--; #endif - assert( !inMutex ); - inMutex = 1; } -void sqlite3OsLeaveMutex(){ - assert( inMutex ); - inMutex = 0; + +/* +** Return TRUE if the mutex is currently held. +** +** If the thisThrd parameter is true, return true only if the +** calling thread holds the mutex. If the parameter is false, return +** true if any thread holds the mutex. +*/ +int sqlite3UnixInMutex(int thisThrd){ #ifdef SQLITE_UNIX_THREADS - pthread_mutex_unlock(&mutex); + int rc; + pthread_mutex_lock(&mutexAux); + rc = inMutex>0 && (thisThrd==0 || pthread_equal(mutexOwner,pthread_self())); + pthread_mutex_unlock(&mutexAux); + return rc; +#else + return inMutex>0; +#endif +} + +/* +** Remember the number of thread-specific-data blocks allocated. +** Use this to verify that we are not leaking thread-specific-data. +** Ticket #1601 +*/ +#ifdef SQLITE_TEST +int sqlite3_tsd_count = 0; +# ifdef SQLITE_UNIX_THREADS + static pthread_mutex_t tsd_counter_mutex = PTHREAD_MUTEX_INITIALIZER; +# define TSD_COUNTER(N) \ + pthread_mutex_lock(&tsd_counter_mutex); \ + sqlite3_tsd_count += N; \ + pthread_mutex_unlock(&tsd_counter_mutex); +# else +# define TSD_COUNTER(N) sqlite3_tsd_count += N +# endif +#else +# define TSD_COUNTER(N) /* no-op */ +#endif + +/* +** If called with allocateFlag>0, then return a pointer to thread +** specific data for the current thread. Allocate and zero the +** thread-specific data if it does not already exist. +** +** If called with allocateFlag==0, then check the current thread +** specific data. Return it if it exists. If it does not exist, +** then return NULL. +** +** If called with allocateFlag<0, check to see if the thread specific +** data is allocated and is all zero. If it is then deallocate it. +** Return a pointer to the thread specific data or NULL if it is +** unallocated or gets deallocated. +*/ +ThreadData *sqlite3UnixThreadSpecificData(int allocateFlag){ + static const ThreadData zeroData = {0}; /* Initializer to silence warnings + ** from broken compilers */ +#ifdef SQLITE_UNIX_THREADS + static pthread_key_t key; + static int keyInit = 0; + ThreadData *pTsd; + + if( !keyInit ){ + sqlite3OsEnterMutex(); + if( !keyInit ){ + int rc; + rc = pthread_key_create(&key, 0); + if( rc ){ + sqlite3OsLeaveMutex(); + return 0; + } + keyInit = 1; + } + sqlite3OsLeaveMutex(); + } + + pTsd = pthread_getspecific(key); + if( allocateFlag>0 ){ + if( pTsd==0 ){ + if( !sqlite3TestMallocFail() ){ + pTsd = sqlite3OsMalloc(sizeof(zeroData)); + } +#ifdef SQLITE_MEMDEBUG + sqlite3_isFail = 0; +#endif + if( pTsd ){ + *pTsd = zeroData; + pthread_setspecific(key, pTsd); + TSD_COUNTER(+1); + } + } + }else if( pTsd!=0 && allocateFlag<0 + && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ + sqlite3OsFree(pTsd); + pthread_setspecific(key, 0); + TSD_COUNTER(-1); + pTsd = 0; + } + return pTsd; +#else + static ThreadData *pTsd = 0; + if( allocateFlag>0 ){ + if( pTsd==0 ){ + if( !sqlite3TestMallocFail() ){ + pTsd = sqlite3OsMalloc( sizeof(zeroData) ); + } +#ifdef SQLITE_MEMDEBUG + sqlite3_isFail = 0; +#endif + if( pTsd ){ + *pTsd = zeroData; + TSD_COUNTER(+1); + } + } + }else if( pTsd!=0 && allocateFlag<0 + && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ + sqlite3OsFree(pTsd); + TSD_COUNTER(-1); + pTsd = 0; + } + return pTsd; #endif } @@ -1438,7 +1970,7 @@ int sqlite3_current_time = 0; ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ -int sqlite3OsCurrentTime(double *prNow){ +int sqlite3UnixCurrentTime(double *prNow){ #ifdef NO_GETTOD time_t t; time(&t); diff --git a/ext/pdo_sqlite/sqlite/src/os_win.c b/ext/pdo_sqlite/sqlite/src/os_win.c index ad874ae633..6c167ab5b8 100644 --- a/ext/pdo_sqlite/sqlite/src/os_win.c +++ b/ext/pdo_sqlite/sqlite/src/os_win.c @@ -34,6 +34,49 @@ */ #include "os_common.h" +/* +** Determine if we are dealing with WindowsCE - which has a much +** reduced API. +*/ +#if defined(_WIN32_WCE) +# define OS_WINCE 1 +#else +# define OS_WINCE 0 +#endif + +/* +** WinCE lacks native support for file locking so we have to fake it +** with some code of our own. +*/ +#if 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 OsFile specific to the win32 +** portability layer. +*/ +typedef struct winFile winFile; +struct winFile { + IoMethod const *pMethod;/* Must be first */ + HANDLE h; /* Handle for accessing the file */ + unsigned char locktype; /* Type of lock currently held on this file */ + short sharedLockByte; /* Randomly chosen byte used as a shared lock */ +#if OS_WINCE + WCHAR *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 +}; + + /* ** Do not include any of the File I/O interface procedures if the ** SQLITE_OMIT_DISKIO macro is defined (indicating that there database @@ -56,8 +99,8 @@ int sqlite3_os_type = 0; /* -** Return true (non-zero) if we are running under WinNT, Win2K or WinXP. -** Return false (zero) for Win95, Win98, or WinME. +** 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 @@ -66,34 +109,38 @@ int sqlite3_os_type = 0; ** WinNT/2K/XP so that we will know whether or not we can safely call ** the LockFileEx() API. */ -static int isNT(void){ - if( sqlite3_os_type==0 ){ - OSVERSIONINFO sInfo; - sInfo.dwOSVersionInfoSize = sizeof(sInfo); - GetVersionEx(&sInfo); - sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; +#if OS_WINCE +# define isNT() (1) +#else + static int isNT(void){ + if( sqlite3_os_type==0 ){ + OSVERSIONINFO sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + GetVersionEx(&sInfo); + sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; + } + return sqlite3_os_type==2; } - return sqlite3_os_type==2; -} +#endif /* OS_WINCE */ /* ** Convert a UTF-8 string to UTF-32. Space to hold the returned string ** is obtained from sqliteMalloc. */ static WCHAR *utf8ToUnicode(const char *zFilename){ - int nByte; + int nChar; WCHAR *zWideFilename; if( !isNT() ){ return 0; } - nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR); - zWideFilename = sqliteMalloc( nByte*sizeof(zWideFilename[0]) ); + nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); + zWideFilename = sqliteMalloc( nChar*sizeof(zWideFilename[0]) ); if( zWideFilename==0 ){ return 0; } - nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nByte); - if( nByte==0 ){ + nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); + if( nChar==0 ){ sqliteFree(zWideFilename); zWideFilename = 0; } @@ -122,37 +169,369 @@ static char *unicodeToUtf8(const WCHAR *zWideFilename){ return zFilename; } +#if OS_WINCE +/************************************************************************* +** This section contains code for WinCE only. +*/ +/* +** WindowsCE does 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; + i64 t64; + t64 = *t; + t64 = (t64 + 11644473600)*10000000; + uTm.dwLowDateTime = t64 & 0xFFFFFFFF; + uTm.dwHighDateTime= t64 >> 32; + FileTimeToLocalFileTime(&uTm,&lTm); + FileTimeToSystemTime(&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; +} + +/* This will never be called, but defined to make the code compile */ +#define GetTempPathA(a,b) + +#define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e) +#define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e) +#define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f) + +#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-offsetof(winFile,h)] + +/* +** Acquire a lock on the handle h +*/ +static void winceMutexAcquire(HANDLE h){ + DWORD dwErr; + do { + dwErr = WaitForSingleObject(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 BOOL winceCreateLock(const char *zFilename, winFile *pFile){ + WCHAR *zTok; + WCHAR *zName = utf8ToUnicode(zFilename); + BOOL bInit = TRUE; + + /* Initialize the local lockdata */ + ZeroMemory(&pFile->local, sizeof(pFile->local)); + + /* Replace the backslashes from the filename and lowercase it + ** to derive a mutex name. */ + zTok = CharLowerW(zName); + for (;*zTok;zTok++){ + if (*zTok == '\\') *zTok = '_'; + } + + /* Create/open the named mutex */ + pFile->hMutex = CreateMutexW(NULL, FALSE, zName); + if (!pFile->hMutex){ + sqliteFree(zName); + return FALSE; + } + + /* 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. + */ + CharUpperW(zName); + pFile->hShared = CreateFileMappingW(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 */ + if (GetLastError() == ERROR_ALREADY_EXISTS){ + bInit = FALSE; + } + + sqliteFree(zName); + + /* If we succeeded in making the shared memory handle, map it. */ + if (pFile->hShared){ + pFile->shared = (winceLock*)MapViewOfFile(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){ + CloseHandle(pFile->hShared); + pFile->hShared = NULL; + } + } + + /* If shared memory could not be created, then close the mutex and fail */ + if (pFile->hShared == NULL){ + winceMutexRelease(pFile->hMutex); + CloseHandle(pFile->hMutex); + pFile->hMutex = NULL; + return FALSE; + } + + /* Initialize the shared memory if we're supposed to */ + if (bInit) { + ZeroMemory(pFile->shared, sizeof(winceLock)); + } + + winceMutexRelease(pFile->hMutex); + return TRUE; +} + +/* +** 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 */ + UnmapViewOfFile(pFile->shared); + CloseHandle(pFile->hShared); + + /* Done with the mutex */ + winceMutexRelease(pFile->hMutex); + CloseHandle(pFile->hMutex); + pFile->hMutex = NULL; + } +} + +/* +** An implementation of the LockFile() API of windows for wince +*/ +static BOOL winceLockFile( + HANDLE *phFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh +){ + winFile *pFile = HANDLE_TO_WINFILE(phFile); + BOOL bReturn = FALSE; + + if (!pFile->hMutex) return TRUE; + winceMutexAcquire(pFile->hMutex); + + /* Wanting an exclusive lock? */ + if (dwFileOffsetLow == SHARED_FIRST + && nNumberOfBytesToLockLow == 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 >= SHARED_FIRST && + dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) && + 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 == 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 == 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 wince +*/ +static BOOL winceUnlockFile( + HANDLE *phFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh +){ + winFile *pFile = HANDLE_TO_WINFILE(phFile); + BOOL bReturn = FALSE; + + if (!pFile->hMutex) return TRUE; + winceMutexAcquire(pFile->hMutex); + + /* Releasing a reader lock or an exclusive lock */ + if (dwFileOffsetLow >= SHARED_FIRST && + dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){ + /* Did we have an exclusive lock? */ + if (pFile->local.bExclusive){ + pFile->local.bExclusive = FALSE; + pFile->shared->bExclusive = FALSE; + bReturn = TRUE; + } + + /* Did we just have a reader lock? */ + else if (pFile->local.nReaders){ + pFile->local.nReaders --; + if (pFile->local.nReaders == 0) + { + pFile->shared->nReaders --; + } + bReturn = TRUE; + } + } + + /* Releasing a pending lock */ + else if (dwFileOffsetLow == 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 == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){ + if (pFile->local.bReserved) { + pFile->local.bReserved = FALSE; + pFile->shared->bReserved = FALSE; + bReturn = TRUE; + } + } + + winceMutexRelease(pFile->hMutex); + return bReturn; +} + +/* +** An implementation of the LockFileEx() API of windows for wince +*/ +static BOOL winceLockFileEx( + HANDLE *phFile, + DWORD dwFlags, + DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped +){ + /* If the caller wants a shared read lock, forward this call + ** to winceLockFile */ + if (lpOverlapped->Offset == SHARED_FIRST && + dwFlags == 1 && + nNumberOfBytesToLockLow == SHARED_SIZE){ + return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); + } + return FALSE; +} +/* +** End of the special code for wince +*****************************************************************************/ +#endif /* OS_WINCE */ /* -** Delete the named file +** 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 is 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. */ -int sqlite3OsDelete(const char *zFilename){ +#define MX_DELETION_ATTEMPTS 3 +int sqlite3WinDelete(const char *zFilename){ WCHAR *zWide = utf8ToUnicode(zFilename); + int cnt = 0; + int rc; if( zWide ){ - DeleteFileW(zWide); + do{ + rc = DeleteFileW(zWide); + }while( rc==0 && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); sqliteFree(zWide); }else{ - DeleteFileA(zFilename); +#if OS_WINCE + return SQLITE_NOMEM; +#else + do{ + rc = DeleteFileA(zFilename); + }while( rc==0 && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); +#endif } TRACE2("DELETE \"%s\"\n", zFilename); - return SQLITE_OK; + return rc==0 ? SQLITE_OK : SQLITE_IOERR; } /* ** Return TRUE if the named file exists. */ -int sqlite3OsFileExists(const char *zFilename){ +int sqlite3WinFileExists(const char *zFilename){ int exists = 0; WCHAR *zWide = utf8ToUnicode(zFilename); if( zWide ){ exists = GetFileAttributesW(zWide) != 0xffffffff; sqliteFree(zWide); }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else exists = GetFileAttributesA(zFilename) != 0xffffffff; +#endif } return exists; } +/* Forward declaration */ +static int allocateWinFile(winFile *pInit, OsFile **pId); + /* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, @@ -166,14 +545,15 @@ int sqlite3OsFileExists(const char *zFilename){ ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id and *pReadonly unchanged. */ -int sqlite3OsOpenReadWrite( +int sqlite3WinOpenReadWrite( const char *zFilename, - OsFile *id, + OsFile **pId, int *pReadonly ){ + winFile f; HANDLE h; WCHAR *zWide = utf8ToUnicode(zFilename); - assert( !id->isOpen ); + assert( *pId==0 ); if( zWide ){ h = CreateFileW(zWide, GENERIC_READ | GENERIC_WRITE, @@ -186,7 +566,7 @@ int sqlite3OsOpenReadWrite( if( h==INVALID_HANDLE_VALUE ){ h = CreateFileW(zWide, GENERIC_READ, - FILE_SHARE_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, @@ -200,8 +580,18 @@ int sqlite3OsOpenReadWrite( }else{ *pReadonly = 0; } +#if OS_WINCE + if (!winceCreateLock(zFilename, &f)){ + CloseHandle(h); + sqliteFree(zWide); + return SQLITE_CANTOPEN; + } +#endif sqliteFree(zWide); }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else h = CreateFileA(zFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -213,7 +603,7 @@ int sqlite3OsOpenReadWrite( if( h==INVALID_HANDLE_VALUE ){ h = CreateFileA(zFilename, GENERIC_READ, - FILE_SHARE_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, @@ -226,14 +616,14 @@ int sqlite3OsOpenReadWrite( }else{ *pReadonly = 0; } +#endif /* OS_WINCE */ } - id->h = h; - id->locktype = NO_LOCK; - id->sharedLockByte = 0; - id->isOpen = 1; - OpenCounter(+1); + f.h = h; +#if OS_WINCE + f.zDeleteOnClose = 0; +#endif TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); - return SQLITE_OK; + return allocateWinFile(&f, pId); } @@ -250,48 +640,65 @@ int sqlite3OsOpenReadWrite( ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. +** +** Sometimes if we have just deleted a prior journal file, windows +** will fail to open a new one because there is a "pending delete". +** To work around this bug, we pause for 100 milliseconds and attempt +** a second open after the first one fails. The whole operation only +** fails if both open attempts are unsuccessful. */ -int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ +int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ + winFile f; HANDLE h; int fileflags; WCHAR *zWide = utf8ToUnicode(zFilename); - assert( !id->isOpen ); + assert( *pId == 0 ); + fileflags = FILE_FLAG_RANDOM_ACCESS; +#if !OS_WINCE if( delFlag ){ - fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS - | FILE_FLAG_DELETE_ON_CLOSE; - }else{ - fileflags = FILE_FLAG_RANDOM_ACCESS; + fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE; } +#endif if( zWide ){ - h = CreateFileW(zWide, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - fileflags, - NULL - ); + int cnt = 0; + do{ + h = CreateFileW(zWide, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + fileflags, + NULL + ); + }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) ); sqliteFree(zWide); }else{ - h = CreateFileA(zFilename, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - fileflags, - NULL - ); +#if OS_WINCE + return SQLITE_NOMEM; +#else + int cnt = 0; + do{ + h = CreateFileA(zFilename, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + fileflags, + NULL + ); + }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) ); +#endif /* OS_WINCE */ } if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } - id->h = h; - id->locktype = NO_LOCK; - id->sharedLockByte = 0; - id->isOpen = 1; - OpenCounter(+1); + f.h = h; +#if OS_WINCE + f.zDeleteOnClose = delFlag ? utf8ToUnicode(zFilename) : 0; + f.hMutex = NULL; +#endif TRACE3("OPEN EX %d \"%s\"\n", h, zFilename); - return SQLITE_OK; + return allocateWinFile(&f, pId); } /* @@ -301,10 +708,11 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ ** ** On failure, return SQLITE_CANTOPEN. */ -int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ +int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){ + winFile f; HANDLE h; WCHAR *zWide = utf8ToUnicode(zFilename); - assert( !id->isOpen ); + assert( *pId==0 ); if( zWide ){ h = CreateFileW(zWide, GENERIC_READ, @@ -316,6 +724,9 @@ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ ); sqliteFree(zWide); }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else h = CreateFileA(zFilename, GENERIC_READ, 0, @@ -324,17 +735,18 @@ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); +#endif } if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } - id->h = h; - id->locktype = NO_LOCK; - id->sharedLockByte = 0; - id->isOpen = 1; - OpenCounter(+1); + f.h = h; +#if OS_WINCE + f.zDeleteOnClose = 0; + f.hMutex = NULL; +#endif TRACE3("OPEN RO %d \"%s\"\n", h, zFilename); - return SQLITE_OK; + return allocateWinFile(&f, pId); } /* @@ -353,9 +765,9 @@ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id unchanged. */ -int sqlite3OsOpenDirectory( - const char *zDirname, - OsFile *id +static int winOpenDirectory( + OsFile *id, + const char *zDirname ){ return SQLITE_OK; } @@ -371,7 +783,7 @@ char *sqlite3_temp_directory = 0; ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ -int sqlite3OsTempFileName(char *zBuf){ +int sqlite3WinTempFileName(char *zBuf){ static char zChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -412,15 +824,36 @@ int sqlite3OsTempFileName(char *zBuf){ /* ** 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. */ -int sqlite3OsClose(OsFile *id){ - if( id->isOpen ){ - TRACE2("CLOSE %d\n", id->h); - CloseHandle(id->h); +#define MX_CLOSE_ATTEMPT 3 +static int winClose(OsFile **pId){ + winFile *pFile; + int rc = 1; + if( pId && (pFile = (winFile*)*pId)!=0 ){ + int rc, cnt = 0; + TRACE2("CLOSE %d\n", pFile->h); + do{ + rc = CloseHandle(pFile->h); + }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); +#if OS_WINCE + winceDestroyLock(pFile); + if( pFile->zDeleteOnClose ){ + DeleteFileW(pFile->zDeleteOnClose); + sqliteFree(pFile->zDeleteOnClose); + } +#endif OpenCounter(-1); - id->isOpen = 0; + sqliteFree(pFile); + *pId = 0; } - return SQLITE_OK; + return rc ? SQLITE_OK : SQLITE_IOERR; } /* @@ -428,12 +861,12 @@ int sqlite3OsClose(OsFile *id){ ** bytes were read successfully and SQLITE_IOERR if anything goes ** wrong. */ -int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ +static int winRead(OsFile *id, void *pBuf, int amt){ DWORD got; - assert( id->isOpen ); + assert( id!=0 ); SimulateIOError(SQLITE_IOERR); - TRACE3("READ %d lock=%d\n", id->h, id->locktype); - if( !ReadFile(id->h, pBuf, amt, &got, 0) ){ + TRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){ got = 0; } if( got==(DWORD)amt ){ @@ -447,15 +880,16 @@ int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ -int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ +static int winWrite(OsFile *id, const void *pBuf, int amt){ int rc = 0; DWORD wrote; - assert( id->isOpen ); + assert( id!=0 ); SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; - TRACE3("WRITE %d lock=%d\n", id->h, id->locktype); + TRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); assert( amt>0 ); - while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){ + while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0 + && wrote>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } @@ -475,17 +909,17 @@ int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ /* ** Move the read/write pointer in a file. */ -int sqlite3OsSeek(OsFile *id, i64 offset){ +static int winSeek(OsFile *id, i64 offset){ LONG upperBits = offset>>32; LONG lowerBits = offset & 0xffffffff; DWORD rc; - assert( id->isOpen ); + assert( id!=0 ); #ifdef SQLITE_TEST if( offset ) SimulateDiskfullError #endif SEEK(offset/1024 + 1); - rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN); - TRACE3("SEEK %d %lld\n", id->h, offset); + rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN); + TRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset); if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ return SQLITE_FULL; } @@ -495,10 +929,10 @@ int sqlite3OsSeek(OsFile *id, i64 offset){ /* ** Make sure all writes to a particular file are committed to disk. */ -int sqlite3OsSync(OsFile *id, int dataOnly){ - assert( id->isOpen ); - TRACE3("SYNC %d lock=%d\n", id->h, id->locktype); - if( FlushFileBuffers(id->h) ){ +static int winSync(OsFile *id, int dataOnly){ + assert( id!=0 ); + TRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + if( FlushFileBuffers(((winFile*)id)->h) ){ return SQLITE_OK; }else{ return SQLITE_IOERR; @@ -509,7 +943,7 @@ int sqlite3OsSync(OsFile *id, int dataOnly){ ** Sync the directory zDirname. This is a no-op on operating systems other ** than UNIX. */ -int sqlite3OsSyncDirectory(const char *zDirname){ +int sqlite3WinSyncDirectory(const char *zDirname){ SimulateIOError(SQLITE_IOERR); return SQLITE_OK; } @@ -517,34 +951,41 @@ int sqlite3OsSyncDirectory(const char *zDirname){ /* ** Truncate an open file to a specified size */ -int sqlite3OsTruncate(OsFile *id, i64 nByte){ +static int winTruncate(OsFile *id, i64 nByte){ LONG upperBits = nByte>>32; - assert( id->isOpen ); - TRACE3("TRUNCATE %d %lld\n", id->h, nByte); + assert( id!=0 ); + TRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte); SimulateIOError(SQLITE_IOERR); - SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN); - SetEndOfFile(id->h); + SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN); + SetEndOfFile(((winFile*)id)->h); return SQLITE_OK; } /* ** Determine the current size of a file in bytes */ -int sqlite3OsFileSize(OsFile *id, i64 *pSize){ +static int winFileSize(OsFile *id, i64 *pSize){ DWORD upperBits, lowerBits; - assert( id->isOpen ); + assert( id!=0 ); SimulateIOError(SQLITE_IOERR); - lowerBits = GetFileSize(id->h, &upperBits); + lowerBits = GetFileSize(((winFile*)id)->h, &upperBits); *pSize = (((i64)upperBits)<<32) + lowerBits; return SQLITE_OK; } +/* +** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. +*/ +#ifndef LOCKFILE_FAIL_IMMEDIATELY +# define LOCKFILE_FAIL_IMMEDIATELY 1 +#endif + /* ** Acquire a reader lock. ** Different API routines are called depending on whether or not this ** is Win95 or WinNT. */ -static int getReadLock(OsFile *id){ +static int getReadLock(winFile *id){ int res; if( isNT() ){ OVERLAPPED ovlp; @@ -564,12 +1005,12 @@ static int getReadLock(OsFile *id){ /* ** Undo a readlock */ -static int unlockReadLock(OsFile *id){ +static int unlockReadLock(winFile *pFile){ int res; if( isNT() ){ - res = UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); }else{ - res = UnlockFile(id->h, SHARED_FIRST + id->sharedLockByte, 0, 1, 0); + res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); } return res; } @@ -579,7 +1020,7 @@ static int unlockReadLock(OsFile *id){ ** Check that a given pathname is a directory and is writable ** */ -int sqlite3OsIsDirWritable(char *zDirname){ +int sqlite3WinIsDirWritable(char *zDirname){ int fileAttr; WCHAR *zWide; if( zDirname==0 ) return 0; @@ -589,7 +1030,11 @@ int sqlite3OsIsDirWritable(char *zDirname){ fileAttr = GetFileAttributesW(zWide); sqliteFree(zWide); }else{ +#if OS_WINCE + return 0; +#else fileAttr = GetFileAttributesA(zDirname); +#endif } if( fileAttr == 0xffffffff ) return 0; if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){ @@ -620,45 +1065,46 @@ int sqlite3OsIsDirWritable(char *zDirname){ ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** -** This routine will only increase a lock. The sqlite3OsUnlock() routine +** 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. */ -int sqlite3OsLock(OsFile *id, int locktype){ +static int winLock(OsFile *id, int locktype){ int rc = SQLITE_OK; /* Return code from subroutines */ int res = 1; /* Result of a windows lock call */ int newLocktype; /* Set id->locktype to this value before exiting */ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ + winFile *pFile = (winFile*)id; - assert( id->isOpen ); + assert( pFile!=0 ); TRACE5("LOCK %d %d was %d(%d)\n", - id->h, locktype, id->locktype, id->sharedLockByte); + pFile->h, locktype, pFile->locktype, pFile->sharedLockByte); /* 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( id->locktype>=locktype ){ + if( pFile->locktype>=locktype ){ return SQLITE_OK; } /* Make sure the locking sequence is correct */ - assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); - assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_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 = id->locktype; - if( id->locktype==NO_LOCK - || (locktype==EXCLUSIVE_LOCK && id->locktype==RESERVED_LOCK) + newLocktype = pFile->locktype; + if( pFile->locktype==NO_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) ){ int cnt = 3; - while( cnt-->0 && (res = LockFile(id->h, PENDING_BYTE, 0, 1, 0))==0 ){ + while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){ /* Try 3 times to get the pending lock. The pending lock might be ** held by another reader process who will release it momentarily. */ @@ -671,8 +1117,8 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Acquire a shared lock */ if( locktype==SHARED_LOCK && res ){ - assert( id->locktype==NO_LOCK ); - res = getReadLock(id); + assert( pFile->locktype==NO_LOCK ); + res = getReadLock(pFile); if( res ){ newLocktype = SHARED_LOCK; } @@ -681,8 +1127,8 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Acquire a RESERVED lock */ if( locktype==RESERVED_LOCK && res ){ - assert( id->locktype==SHARED_LOCK ); - res = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); + assert( pFile->locktype==SHARED_LOCK ); + res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); if( res ){ newLocktype = RESERVED_LOCK; } @@ -698,10 +1144,10 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Acquire an EXCLUSIVE lock */ if( locktype==EXCLUSIVE_LOCK && res ){ - assert( id->locktype>=SHARED_LOCK ); - res = unlockReadLock(id); + assert( pFile->locktype>=SHARED_LOCK ); + res = unlockReadLock(pFile); TRACE2("unreadlock = %d\n", res); - res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ newLocktype = EXCLUSIVE_LOCK; }else{ @@ -713,7 +1159,7 @@ int sqlite3OsLock(OsFile *id, int locktype){ ** release it now. */ if( gotPendingLock && locktype==SHARED_LOCK ){ - UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); } /* Update the state of the lock has held in the file descriptor then @@ -722,11 +1168,11 @@ int sqlite3OsLock(OsFile *id, int locktype){ if( res ){ rc = SQLITE_OK; }else{ - TRACE4("LOCK FAILED %d trying for %d but got %d\n", id->h, + TRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h, locktype, newLocktype); rc = SQLITE_BUSY; } - id->locktype = newLocktype; + pFile->locktype = newLocktype; return rc; } @@ -735,19 +1181,20 @@ int sqlite3OsLock(OsFile *id, int locktype){ ** file by this or any other process. If such a lock is held, return ** non-zero, otherwise zero. */ -int sqlite3OsCheckReservedLock(OsFile *id){ +static int winCheckReservedLock(OsFile *id){ int rc; - assert( id->isOpen ); - if( id->locktype>=RESERVED_LOCK ){ + winFile *pFile = (winFile*)id; + assert( pFile!=0 ); + if( pFile->locktype>=RESERVED_LOCK ){ rc = 1; - TRACE3("TEST WR-LOCK %d %d (local)\n", id->h, rc); + TRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); }else{ - rc = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); + rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); if( rc ){ - UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); } rc = !rc; - TRACE3("TEST WR-LOCK %d %d (remote)\n", id->h, rc); + TRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); } return rc; } @@ -763,32 +1210,33 @@ int sqlite3OsCheckReservedLock(OsFile *id){ ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine ** might return SQLITE_IOERR; */ -int sqlite3OsUnlock(OsFile *id, int locktype){ +static int winUnlock(OsFile *id, int locktype){ int type; int rc = SQLITE_OK; - assert( id->isOpen ); + winFile *pFile = (winFile*)id; + assert( pFile!=0 ); assert( locktype<=SHARED_LOCK ); - TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype, - id->locktype, id->sharedLockByte); - type = id->locktype; + TRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, + pFile->locktype, pFile->sharedLockByte); + type = pFile->locktype; if( type>=EXCLUSIVE_LOCK ){ - UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); - if( locktype==SHARED_LOCK && !getReadLock(id) ){ + UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ /* This should never happen. We should always be able to ** reacquire the read lock */ rc = SQLITE_IOERR; } } if( type>=RESERVED_LOCK ){ - UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); } if( locktype==NO_LOCK && type>=SHARED_LOCK ){ - unlockReadLock(id); + unlockReadLock(pFile); } if( type>=PENDING_LOCK ){ - UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); } - id->locktype = locktype; + pFile->locktype = locktype; return rc; } @@ -798,17 +1246,21 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ ** The calling function is responsible for freeing this space once it ** is no longer needed. */ -char *sqlite3OsFullPathname(const char *zRelative){ - char *zNotUsed; +char *sqlite3WinFullPathname(const char *zRelative){ char *zFull; - WCHAR *zWide; +#if defined(__CYGWIN__) int nByte; -#ifdef __CYGWIN__ nByte = strlen(zRelative) + MAX_PATH + 1001; zFull = sqliteMalloc( nByte ); if( zFull==0 ) return 0; if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; +#elif OS_WINCE + /* WinCE has no concept of a relative pathname, or so I am told. */ + zFull = sqliteStrDup(zRelative); #else + char *zNotUsed; + WCHAR *zWide; + int nByte; zWide = utf8ToUnicode(zRelative); if( zWide ){ WCHAR *zTemp, *zNotUsedW; @@ -829,6 +1281,76 @@ char *sqlite3OsFullPathname(const char *zRelative){ return zFull; } +/* +** The fullSync option is meaningless on windows. This is a no-op. +*/ +static void winSetFullSync(OsFile *id, int v){ + return; +} + +/* +** Return the underlying file handle for an OsFile +*/ +static int winFileHandle(OsFile *id){ + return (int)((winFile*)id)->h; +} + +/* +** Return an integer that indices the type of lock currently held +** by this handle. (Used for testing and analysis only.) +*/ +static int winLockState(OsFile *id){ + return ((winFile*)id)->locktype; +} + +/* +** This vector defines all the methods that can operate on an OsFile +** for win32. +*/ +static const IoMethod sqlite3WinIoMethod = { + winClose, + winOpenDirectory, + winRead, + winWrite, + winSeek, + winTruncate, + winSync, + winSetFullSync, + winFileHandle, + winFileSize, + winLock, + winUnlock, + winLockState, + winCheckReservedLock, +}; + +/* +** Allocate memory for an OsFile. Initialize the new OsFile +** to the value given in pInit and return a pointer to the new +** OsFile. If we run out of memory, close the file and return NULL. +*/ +static int allocateWinFile(winFile *pInit, OsFile **pId){ + winFile *pNew; + pNew = sqliteMalloc( sizeof(*pNew) ); + if( pNew==0 ){ + CloseHandle(pInit->h); +#if OS_WINCE + sqliteFree(pInit->zDeleteOnClose); +#endif + *pId = 0; + return SQLITE_NOMEM; + }else{ + *pNew = *pInit; + pNew->pMethod = &sqlite3WinIoMethod; + pNew->locktype = NO_LOCK; + pNew->sharedLockByte = 0; + *pId = (OsFile*)pNew; + OpenCounter(+1); + return SQLITE_OK; + } +} + + #endif /* SQLITE_OMIT_DISKIO */ /*************************************************************************** ** Everything above deals with file I/O. Everything that follows deals @@ -840,7 +1362,7 @@ char *sqlite3OsFullPathname(const char *zRelative){ ** is written into the buffer zBuf[256]. The calling function must ** supply a sufficiently large buffer. */ -int sqlite3OsRandomSeed(char *zBuf){ +int sqlite3WinRandomSeed(char *zBuf){ /* 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 @@ -861,7 +1383,7 @@ int sqlite3OsRandomSeed(char *zBuf){ /* ** Sleep for a little while. Return the amount of time slept. */ -int sqlite3OsSleep(int ms){ +int sqlite3WinSleep(int ms){ Sleep(ms); return ms; } @@ -871,18 +1393,22 @@ int sqlite3OsSleep(int ms){ */ static int inMutex = 0; #ifdef SQLITE_W32_THREADS + static DWORD mutexOwner; static CRITICAL_SECTION cs; #endif /* -** The following pair of routine implement mutual exclusion for +** The following pair of routines implement mutual exclusion for ** multi-threaded processes. Only a single thread is allowed to ** executed code that is surrounded by EnterMutex() and LeaveMutex(). ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. +** +** Version 3.3.1 and earlier used a simple mutex. Beginning with +** version 3.3.2, a recursive mutex is required. */ -void sqlite3OsEnterMutex(){ +void sqlite3WinEnterMutex(){ #ifdef SQLITE_W32_THREADS static int isInit = 0; while( !isInit ){ @@ -895,18 +1421,35 @@ void sqlite3OsEnterMutex(){ } } EnterCriticalSection(&cs); + mutexOwner = GetCurrentThreadId(); #endif - assert( !inMutex ); - inMutex = 1; + inMutex++; } -void sqlite3OsLeaveMutex(){ +void sqlite3WinLeaveMutex(){ assert( inMutex ); - inMutex = 0; + inMutex--; #ifdef SQLITE_W32_THREADS + assert( mutexOwner==GetCurrentThreadId() ); LeaveCriticalSection(&cs); #endif } +/* +** Return TRUE if the mutex is currently held. +** +** If the thisThreadOnly parameter is true, return true if and only if the +** calling thread holds the mutex. If the parameter is false, return +** true if any thread holds the mutex. +*/ +int sqlite3WinInMutex(int thisThreadOnly){ +#ifdef SQLITE_W32_THREADS + return inMutex>0 && (thisThreadOnly==0 || mutexOwner==GetCurrentThreadId()); +#else + return inMutex>0; +#endif +} + + /* ** The following variable, if set to a non-zero value, becomes the result ** returned from sqlite3OsCurrentTime(). This is used for testing. @@ -920,13 +1463,19 @@ int sqlite3_current_time = 0; ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ -int sqlite3OsCurrentTime(double *prNow){ +int sqlite3WinCurrentTime(double *prNow){ FILETIME ft; /* FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). */ double now; +#if OS_WINCE + SYSTEMTIME time; + GetSystemTime(&time); + SystemTimeToFileTime(&time,&ft); +#else GetSystemTimeAsFileTime( &ft ); +#endif now = ((double)ft.dwHighDateTime) * 4294967296.0; *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5; #ifdef SQLITE_TEST @@ -937,4 +1486,71 @@ int sqlite3OsCurrentTime(double *prNow){ return 0; } +/* +** Remember the number of thread-specific-data blocks allocated. +** Use this to verify that we are not leaking thread-specific-data. +** Ticket #1601 +*/ +#ifdef SQLITE_TEST +int sqlite3_tsd_count = 0; +# define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count) +# define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count) +#else +# define TSD_COUNTER_INCR /* no-op */ +# define TSD_COUNTER_DECR /* no-op */ +#endif + + + +/* +** If called with allocateFlag>1, then return a pointer to thread +** specific data for the current thread. Allocate and zero the +** thread-specific data if it does not already exist necessary. +** +** If called with allocateFlag==0, then check the current thread +** specific data. Return it if it exists. If it does not exist, +** then return NULL. +** +** If called with allocateFlag<0, check to see if the thread specific +** data is allocated and is all zero. If it is then deallocate it. +** Return a pointer to the thread specific data or NULL if it is +** unallocated or gets deallocated. +*/ +ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){ + static int key; + static int keyInit = 0; + static const ThreadData zeroData = {0}; + ThreadData *pTsd; + + if( !keyInit ){ + sqlite3OsEnterMutex(); + if( !keyInit ){ + key = TlsAlloc(); + if( key==0xffffffff ){ + sqlite3OsLeaveMutex(); + return 0; + } + keyInit = 1; + } + sqlite3OsLeaveMutex(); + } + pTsd = TlsGetValue(key); + if( allocateFlag>0 ){ + if( !pTsd ){ + pTsd = sqlite3OsMalloc( sizeof(zeroData) ); + if( pTsd ){ + *pTsd = zeroData; + TlsSetValue(key, pTsd); + TSD_COUNTER_INCR; + } + } + }else if( pTsd!=0 && allocateFlag<0 + && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ + sqlite3OsFree(pTsd); + TlsSetValue(key, 0); + TSD_COUNTER_DECR; + pTsd = 0; + } + return pTsd; +} #endif /* OS_WIN */ diff --git a/ext/pdo_sqlite/sqlite/src/pager.c b/ext/pdo_sqlite/sqlite/src/pager.c index f06d3fec6c..7f4b6f952f 100644 --- a/ext/pdo_sqlite/sqlite/src/pager.c +++ b/ext/pdo_sqlite/sqlite/src/pager.c @@ -46,21 +46,14 @@ /* ** The following two macros are used within the TRACEX() macros above -** to print out file-descriptors. They are required so that tracing -** can be turned on when using both the regular os_unix.c and os_test.c -** backends. +** to print out file-descriptors. ** ** PAGERID() takes a pointer to a Pager struct as it's argument. The ** associated file-descriptor is returned. FILEHANDLEID() takes an OsFile ** struct as it's argument. */ -#ifdef OS_TEST -#define PAGERID(p) (p->fd->fd.h) -#define FILEHANDLEID(fd) (fd->fd.h) -#else -#define PAGERID(p) (p->fd.h) -#define FILEHANDLEID(fd) (fd.h) -#endif +#define PAGERID(p) ((int)(p->fd)) +#define FILEHANDLEID(fd) ((int)fd) /* ** The page cache as a whole is always in one of the following @@ -168,7 +161,8 @@ struct PgHdr { u8 needSync; /* Sync journal before writing this page */ u8 alwaysRollback; /* Disable dont_rollback() for this page */ short int nRef; /* Number of users of this page */ - PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */ + PgHdr *pDirty, *pPrevDirty; /* Dirty pages */ + u32 notUsed; /* Buffer space */ #ifdef SQLITE_CHECK_PAGES u32 pageHash; #endif @@ -197,9 +191,11 @@ struct PgHistory { ** A macro used for invoking the codec if there is one */ #ifdef SQLITE_HAS_CODEC -# define CODEC(P,D,N,X) if( P->xCodec ){ P->xCodec(P->pCodecArg,D,N,X); } +# define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); } +# define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D)) #else -# define CODEC(P,D,N,X) +# define CODEC1(P,D,N,X) /* NO-OP */ +# define CODEC2(P,D,N,X) ((char*)D) #endif /* @@ -212,26 +208,16 @@ struct PgHistory { #define PGHDR_TO_HIST(P,PGR) \ ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra]) -/* -** How big to make the hash table used for locating in-memory pages -** by page number. This macro looks a little silly, but is evaluated -** at compile-time, not run-time (at least for gcc this is true). -*/ -#define N_PG_HASH (\ - (MAX_PAGES>1024)?2048: \ - (MAX_PAGES>512)?1024: \ - (MAX_PAGES>256)?512: \ - (MAX_PAGES>128)?256: \ - (MAX_PAGES>64)?128:64 \ -) - -/* -** Hash a page number -*/ -#define pager_hash(PN) ((PN)&(N_PG_HASH-1)) - /* ** A open page cache is an instance of the following structure. +** +** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, SQLITE_PROTOCOL +** or SQLITE_FULL. Once one of the first three errors occurs, it persists +** and is returned as the result of every major pager API call. The +** SQLITE_FULL return code is slightly different. It persists only until the +** next successful rollback is performed on the pager cache. Also, +** SQLITE_FULL does not affect the sqlite3pager_get() and sqlite3pager_lookup() +** APIs, they may still be used successfully. */ struct Pager { u8 journalOpen; /* True if journal file descriptors is valid */ @@ -243,8 +229,9 @@ struct Pager { u8 stmtAutoopen; /* Open stmt journal when main journal is opened*/ u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ + u8 full_fsync; /* Use F_FULLFSYNC when available */ u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ - u8 errMask; /* One of several kinds of errors */ + u8 errCode; /* One of several kinds of errors */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ u8 needSync; /* True if an fsync() is needed on the journal */ @@ -269,13 +256,14 @@ struct Pager { char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ char *zDirectory; /* Directory hold database and journal files */ - OsFile fd, jfd; /* File descriptors for database and journal */ - OsFile stfd; /* File descriptor for the statement subjournal*/ + OsFile *fd, *jfd; /* File descriptors for database and journal */ + OsFile *stfd; /* File descriptor for the statement subjournal*/ BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */ PgHdr *pFirst, *pLast; /* List of free pages */ PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */ PgHdr *pAll; /* List of all pages */ PgHdr *pStmt; /* List of pages in the statement subjournal */ + PgHdr *pDirty; /* List of all dirty pages */ i64 journalOff; /* Current byte offset in the journal file */ i64 journalHdr; /* Byte offset to previous journal header */ i64 stmtHdrOff; /* First journal header written this statement */ @@ -288,9 +276,13 @@ struct Pager { #endif void (*xDestructor)(void*,int); /* Call this routine when freeing pages */ void (*xReiniter)(void*,int); /* Call this routine when reloading pages */ - void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ + void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ - PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number to PgHdr */ + int nHash; /* Size of the pager hash table */ + PgHdr **aHash; /* Hash table to map page number to PgHdr */ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + Pager *pNext; /* Linked list of pagers in this thread */ +#endif }; /* @@ -303,15 +295,6 @@ struct Pager { # define TEST_INCR(x) #endif -/* -** These are bits that can be set in Pager.errMask. -*/ -#define PAGER_ERR_FULL 0x01 /* a write() failed */ -#define PAGER_ERR_MEM 0x02 /* malloc() failed */ -#define PAGER_ERR_LOCK 0x04 /* error in the locking protocol */ -#define PAGER_ERR_CORRUPT 0x08 /* database or journal corruption */ -#define PAGER_ERR_DISK 0x10 /* general disk I/O error - bad hard drive? */ - /* ** Journal files begin with the following magic string. The data ** was obtained from /dev/random. It is used only as a sanity check. @@ -387,7 +370,7 @@ static const unsigned char aJournalMagic[] = { /* ** Enable reference count tracking (for debugging) here: */ -#ifdef SQLITE_DEBUG +#ifdef SQLITE_TEST int pager3_refinfo_enable = 0; static void pager_refinfo(PgHdr *p){ static int cnt = 0; @@ -403,6 +386,38 @@ static const unsigned char aJournalMagic[] = { # define REFINFO(X) #endif + +/* +** Change the size of the pager hash table to N. N must be a power +** of two. +*/ +static void pager_resize_hash_table(Pager *pPager, int N){ + PgHdr **aHash, *pPg; + assert( N>0 && (N&(N-1))==0 ); + aHash = sqliteMalloc( sizeof(aHash[0])*N ); + if( aHash==0 ){ + /* Failure to rehash is not an error. It is only a performance hit. */ + return; + } + sqliteFree(pPager->aHash); + pPager->nHash = N; + pPager->aHash = aHash; + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + int h; + if( pPg->pgno==0 ){ + assert( pPg->pNextHash==0 && pPg->pPrevHash==0 ); + continue; + } + h = pPg->pgno & (N-1); + pPg->pNextHash = aHash[h]; + if( aHash[h] ){ + aHash[h]->pPrevHash = pPg; + } + aHash[h] = pPg; + pPg->pPrevHash = 0; + } +} + /* ** 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 @@ -411,42 +426,32 @@ static const unsigned char aJournalMagic[] = { ** All values are stored on disk as big-endian. */ static int read32bits(OsFile *fd, u32 *pRes){ - u32 res; - int rc; - rc = sqlite3OsRead(fd, &res, sizeof(res)); + unsigned char ac[4]; + int rc = sqlite3OsRead(fd, ac, sizeof(ac)); if( rc==SQLITE_OK ){ - unsigned char ac[4]; - memcpy(ac, &res, 4); - res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; + *pRes = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } - *pRes = res; return rc; } /* -** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK -** on success or an error code is something goes wrong. +** Write a 32-bit integer into a string buffer in big-endian byte order. */ -static int write32bits(OsFile *fd, u32 val){ - unsigned char ac[4]; +static void put32bits(char *ac, u32 val){ ac[0] = (val>>24) & 0xff; ac[1] = (val>>16) & 0xff; ac[2] = (val>>8) & 0xff; ac[3] = val & 0xff; - return sqlite3OsWrite(fd, ac, 4); } /* -** Write the 32-bit integer 'val' into the page identified by page header -** 'p' at offset 'offset'. +** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK +** on success or an error code is something goes wrong. */ -static void store32bits(u32 val, PgHdr *p, int offset){ - unsigned char *ac; - ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; - ac[0] = (val>>24) & 0xff; - ac[1] = (val>>16) & 0xff; - ac[2] = (val>>8) & 0xff; - ac[3] = val & 0xff; +static int write32bits(OsFile *fd, u32 val){ + char ac[4]; + put32bits(ac, val); + return sqlite3OsWrite(fd, ac, 4); } /* @@ -461,16 +466,25 @@ static u32 retrieve32bits(PgHdr *p, int offset){ /* -** Convert the bits in the pPager->errMask into an approprate -** return code. +** This function should be called when an error occurs within the pager +** code. 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_IOERR, SQLITE_CORRUPT or SQLITE_PROTOCOL, +** the error becomes persistent. All subsequent API calls on this Pager +** will immediately return the same error code. */ -static int pager_errcode(Pager *pPager){ - int rc = SQLITE_OK; - if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL; - if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR; - if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL; - if( pPager->errMask & PAGER_ERR_MEM ) rc = SQLITE_NOMEM; - if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT; +static int pager_error(Pager *pPager, int rc){ + assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK ); + if( + rc==SQLITE_FULL || + rc==SQLITE_IOERR || + rc==SQLITE_CORRUPT || + rc==SQLITE_PROTOCOL + ){ + pPager->errCode = rc; + } return rc; } @@ -496,7 +510,7 @@ static u32 pager_pagehash(PgHdr *pPage){ #define CHECK_PAGE(x) checkPage(x) static void checkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; - assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty || + assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty || pPg->pageHash==pager_pagehash(pPg) ); } @@ -597,7 +611,7 @@ static int seekJournalHdr(Pager *pPager){ assert( offset>=c ); assert( (offset-c)journalOff = offset; - return sqlite3OsSeek(&pPager->jfd, pPager->journalOff); + return sqlite3OsSeek(pPager->jfd, pPager->journalOff); } /* @@ -615,6 +629,7 @@ static int seekJournalHdr(Pager *pPager){ ** Followed by (JOURNAL_HDR_SZ - 24) bytes of unused space. */ static int writeJournalHdr(Pager *pPager){ + char zHeader[sizeof(aJournalMagic)+16]; int rc = seekJournalHdr(pPager); if( rc ) return rc; @@ -633,33 +648,25 @@ static int writeJournalHdr(Pager *pPager){ ** Actually maybe the whole journal header should be delayed until that ** point. Think about this. */ - rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); - - if( rc==SQLITE_OK ){ - /* The nRec Field. 0xFFFFFFFF for no-sync journals. */ - rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0); - } - if( rc==SQLITE_OK ){ - /* The random check-hash initialiser */ - sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); - rc = write32bits(&pPager->jfd, pPager->cksumInit); - } - if( rc==SQLITE_OK ){ - /* The initial database size */ - rc = write32bits(&pPager->jfd, pPager->dbSize); - } - if( rc==SQLITE_OK ){ - /* The assumed sector size for this process */ - rc = write32bits(&pPager->jfd, pPager->sectorSize); - } + memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); + /* The nRec Field. 0xFFFFFFFF for no-sync journals. */ + put32bits(&zHeader[sizeof(aJournalMagic)], pPager->noSync ? 0xffffffff : 0); + /* The random check-hash initialiser */ + sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); + put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); + /* The initial database size */ + put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize); + /* The assumed sector size for this process */ + put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); + rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader)); /* The journal header has been written successfully. Seek the journal ** file descriptor to the end of the journal header sector. */ if( rc==SQLITE_OK ){ - rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff-1); + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff-1); if( rc==SQLITE_OK ){ - rc = sqlite3OsWrite(&pPager->jfd, "\000", 1); + rc = sqlite3OsWrite(pPager->jfd, "\000", 1); } } return rc; @@ -697,20 +704,20 @@ static int readJournalHdr( return SQLITE_DONE; } - rc = sqlite3OsRead(&pPager->jfd, aMagic, sizeof(aMagic)); + rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic)); if( rc ) return rc; if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ return SQLITE_DONE; } - rc = read32bits(&pPager->jfd, pNRec); + rc = read32bits(pPager->jfd, pNRec); if( rc ) return rc; - rc = read32bits(&pPager->jfd, &pPager->cksumInit); + rc = read32bits(pPager->jfd, &pPager->cksumInit); if( rc ) return rc; - rc = read32bits(&pPager->jfd, pDbSize); + rc = read32bits(pPager->jfd, pDbSize); if( rc ) return rc; /* Update the assumed sector-size to match the value used by @@ -719,11 +726,11 @@ static int readJournalHdr( ** is being called from within pager_playback(). The local value ** of Pager.sectorSize is restored at the end of that routine. */ - rc = read32bits(&pPager->jfd, (u32 *)&pPager->sectorSize); + rc = read32bits(pPager->jfd, (u32 *)&pPager->sectorSize); if( rc ) return rc; pPager->journalOff += JOURNAL_HDR_SZ(pPager); - rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff); + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff); return rc; } @@ -743,12 +750,16 @@ static int readJournalHdr( ** ** The master journal page checksum is the sum of the bytes in the master ** journal name. +** +** 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; int len; int i; - u32 cksum = 0; + u32 cksum = 0; + char zBuf[sizeof(aJournalMagic)+2*4]; if( !zMaster || pPager->setMaster) return SQLITE_OK; pPager->setMaster = 1; @@ -768,19 +779,16 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ } pPager->journalOff += (len+20); - rc = write32bits(&pPager->jfd, PAGER_MJ_PGNO(pPager)); + rc = write32bits(pPager->jfd, PAGER_MJ_PGNO(pPager)); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3OsWrite(&pPager->jfd, zMaster, len); + rc = sqlite3OsWrite(pPager->jfd, zMaster, len); if( rc!=SQLITE_OK ) return rc; - rc = write32bits(&pPager->jfd, len); - if( rc!=SQLITE_OK ) return rc; - - rc = write32bits(&pPager->jfd, cksum); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); + put32bits(zBuf, len); + put32bits(&zBuf[4], cksum); + memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic)); + rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic)); pPager->needSync = !pPager->noSync; return rc; } @@ -829,7 +837,9 @@ static void page_remove_from_stmt_list(PgHdr *pPg){ ** a pointer to the page or NULL if not found. */ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ - PgHdr *p = pPager->aHash[pager_hash(pgno)]; + PgHdr *p; + if( pPager->aHash==0 ) return 0; + p = pPager->aHash[pgno & (pPager->nHash-1)]; while( p && p->pgno!=pgno ){ p = p->pNextHash; } @@ -844,7 +854,7 @@ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ */ static void pager_reset(Pager *pPager){ PgHdr *pPg, *pNext; - if( pPager->errMask ) return; + if( pPager->errCode ) return; for(pPg=pPager->pAll; pPg; pPg=pNext){ pNext = pPg->pNextAll; sqliteFree(pPg); @@ -853,41 +863,20 @@ static void pager_reset(Pager *pPager){ pPager->pFirstSynced = 0; pPager->pLast = 0; pPager->pAll = 0; - memset(pPager->aHash, 0, sizeof(pPager->aHash)); + pPager->nHash = 0; + sqliteFree(pPager->aHash); pPager->nPage = 0; + pPager->aHash = 0; if( pPager->state>=PAGER_RESERVED ){ sqlite3pager_rollback(pPager); } - sqlite3OsUnlock(&pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; pPager->dbSize = -1; pPager->nRef = 0; assert( pPager->journalOpen==0 ); } -/* -** This function is used to reset the pager after a malloc() failure. This -** doesn't work with in-memory databases. If a malloc() fails when an -** in-memory database is in use it is not possible to recover. -** -** If a transaction or statement transaction is active, it is rolled back. -** -** It is an error to call this function if any pages are in use. -*/ -#ifndef SQLITE_OMIT_GLOBALRECOVER -int sqlite3pager_reset(Pager *pPager){ - if( pPager ){ - if( pPager->nRef || MEMDB ){ - return SQLITE_ERROR; - } - pPager->errMask &= ~(PAGER_ERR_MEM); - pager_reset(pPager); - } - return SQLITE_OK; -} -#endif - - /* ** When this routine is called, the pager has the journal file open and ** a RESERVED or EXCLUSIVE lock on the database. This routine releases @@ -924,16 +913,19 @@ static int pager_unwritelock(Pager *pPager){ pPg->pageHash = pager_pagehash(pPg); #endif } + pPager->pDirty = 0; pPager->dirtyCache = 0; pPager->nRec = 0; }else{ assert( pPager->aInJournal==0 ); assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); } - rc = sqlite3OsUnlock(&pPager->fd, SHARED_LOCK); + rc = sqlite3OsUnlock(pPager->fd, SHARED_LOCK); pPager->state = PAGER_SHARED; pPager->origDbSize = 0; pPager->setMaster = 0; + pPager->needSync = 0; + pPager->pFirstSynced = pPager->pFirst; return rc; } @@ -957,7 +949,7 @@ static int pager_unwritelock(Pager *pPager){ ** only the middle sector is corrupt, we will still have a reasonable ** chance of failing the checksum and thus detecting the problem. */ -static u32 pager_cksum(Pager *pPager, Pgno pgno, const char *aData){ +static u32 pager_cksum(Pager *pPager, const u8 *aData){ u32 cksum = pPager->cksumInit; int i = pPager->pageSize-200; while( i>0 ){ @@ -967,6 +959,9 @@ static u32 pager_cksum(Pager *pPager, Pgno pgno, const char *aData){ return cksum; } +/* Forward declaration */ +static void makeClean(PgHdr*); + /* ** Read a single page from the journal file opened on file descriptor ** jfd. Playback this one page. @@ -985,7 +980,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ /* useCksum should be true for the main journal and false for ** statement journals. Verify that this is always the case */ - assert( jfd == (useCksum ? &pPager->jfd : &pPager->stfd) ); + assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) ); rc = read32bits(jfd, &pgno); @@ -1009,7 +1004,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ rc = read32bits(jfd, &cksum); if( rc ) return rc; pPager->journalOff += 4; - if( pager_cksum(pPager, pgno, aData)!=cksum ){ + if( pager_cksum(pPager, aData)!=cksum ){ return SQLITE_DONE; } } @@ -1040,11 +1035,13 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ assert( pPager->state>=PAGER_EXCLUSIVE || pPg!=0 ); TRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno); if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){ - rc = sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); + rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); if( rc==SQLITE_OK ){ - rc = sqlite3OsWrite(&pPager->fd, aData, pPager->pageSize); + rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize); + } + if( pPg ){ + makeClean(pPg); } - if( pPg ) pPg->dirty = 0; } if( pPg ){ /* No page should ever be explicitly rolled back that is in use, except @@ -1063,7 +1060,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif - CODEC(pPager, pData, pPg->pgno, 3); + CODEC1(pPager, pData, pPg->pgno, 3); } return rc; } @@ -1082,18 +1079,17 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ static int pager_delmaster(const char *zMaster){ int rc; int master_open = 0; - OsFile master; + OsFile *master = 0; char *zMasterJournal = 0; /* Contents of master journal file */ i64 nMasterJournal; /* Size of master journal file */ /* Open the master journal file exclusively in case some other process ** is running this routine also. Not that it makes too much difference. */ - memset(&master, 0, sizeof(master)); rc = sqlite3OsOpenReadOnly(zMaster, &master); if( rc!=SQLITE_OK ) goto delmaster_out; master_open = 1; - rc = sqlite3OsFileSize(&master, &nMasterJournal); + rc = sqlite3OsFileSize(master, &nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; if( nMasterJournal>0 ){ @@ -1108,7 +1104,7 @@ static int pager_delmaster(const char *zMaster){ rc = SQLITE_NOMEM; goto delmaster_out; } - rc = sqlite3OsRead(&master, zMasterJournal, nMasterJournal); + rc = sqlite3OsRead(master, zMasterJournal, nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; zJournal = zMasterJournal; @@ -1118,16 +1114,15 @@ static int pager_delmaster(const char *zMaster){ ** Open it and check if it points at the master journal. If ** so, return without deleting the master journal file. */ - OsFile journal; + OsFile *journal = 0; int c; - memset(&journal, 0, sizeof(journal)); rc = sqlite3OsOpenReadOnly(zJournal, &journal); if( rc!=SQLITE_OK ){ goto delmaster_out; } - rc = readMasterJournal(&journal, &zMasterPtr); + rc = readMasterJournal(journal, &zMasterPtr); sqlite3OsClose(&journal); if( rc!=SQLITE_OK ){ goto delmaster_out; @@ -1172,13 +1167,13 @@ static int pager_reload_cache(Pager *pPager){ char zBuf[SQLITE_MAX_PAGE_SIZE]; if( !pPg->dirty ) continue; if( (int)pPg->pgno <= pPager->origDbSize ){ - rc = sqlite3OsSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); + rc = sqlite3OsSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(&pPager->fd, zBuf, pPager->pageSize); + rc = sqlite3OsRead(pPager->fd, zBuf, pPager->pageSize); } TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc ) break; - CODEC(pPager, zBuf, pPg->pgno, 2); + CODEC1(pPager, zBuf, pPg->pgno, 2); }else{ memset(zBuf, 0, pPager->pageSize); } @@ -1196,6 +1191,7 @@ static int pager_reload_cache(Pager *pPager){ pPg->pageHash = pager_pagehash(pPg); #endif } + pPager->pDirty = 0; return rc; } @@ -1205,7 +1201,7 @@ static int pager_reload_cache(Pager *pPager){ */ static int pager_truncate(Pager *pPager, int nPage){ assert( pPager->state>=PAGER_EXCLUSIVE ); - return sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(i64)nPage); + return sqlite3OsTruncate(pPager->fd, pPager->pageSize*(i64)nPage); } /* @@ -1273,7 +1269,7 @@ static int pager_playback(Pager *pPager){ ** the journal is empty. */ assert( pPager->journalOpen ); - rc = sqlite3OsFileSize(&pPager->jfd, &szJ); + rc = sqlite3OsFileSize(pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ goto end_playback; } @@ -1283,7 +1279,7 @@ static int pager_playback(Pager *pPager){ ** present on disk, then the journal is not hot and does not need to be ** played back. */ - rc = readMasterJournal(&pPager->jfd, &zMaster); + rc = readMasterJournal(pPager->jfd, &zMaster); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK || (zMaster && !sqlite3OsFileExists(zMaster)) ){ sqliteFree(zMaster); @@ -1291,7 +1287,7 @@ static int pager_playback(Pager *pPager){ if( rc==SQLITE_DONE ) rc = SQLITE_OK; goto end_playback; } - sqlite3OsSeek(&pPager->jfd, 0); + sqlite3OsSeek(pPager->jfd, 0); pPager->journalOff = 0; /* This loop terminates either when the readJournalHdr() call returns @@ -1334,13 +1330,10 @@ static int pager_playback(Pager *pPager){ pPager->dbSize = mxPg; } - /* rc = sqlite3OsSeek(&pPager->jfd, JOURNAL_HDR_SZ(pPager)); */ - if( rc!=SQLITE_OK ) goto end_playback; - /* Copy original pages out of the journal and back into the database file. */ for(i=0; ijfd, 1); + rc = pager_playback_one_page(pPager, pPager->jfd, 1); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ rc = SQLITE_OK; @@ -1352,13 +1345,8 @@ static int pager_playback(Pager *pPager){ } } } - - /* Pages that have been written to the journal but never synced - ** where not restored by the loop above. We have to restore those - ** pages by reading them back from the original database. - */ - assert( rc==SQLITE_OK ); - pager_reload_cache(pPager); + /*NOTREACHED*/ + assert( 0 ); end_playback: if( rc==SQLITE_OK ){ @@ -1407,7 +1395,7 @@ static int pager_stmt_playback(Pager *pPager){ #ifndef NDEBUG { i64 os_szJ; - rc = sqlite3OsFileSize(&pPager->jfd, &os_szJ); + rc = sqlite3OsFileSize(pPager->jfd, &os_szJ); if( rc!=SQLITE_OK ) return rc; assert( szJ==os_szJ ); } @@ -1433,7 +1421,7 @@ static int pager_stmt_playback(Pager *pPager){ /* Figure out how many records are in the statement journal. */ assert( pPager->stmtInUse && pPager->journalOpen ); - sqlite3OsSeek(&pPager->stfd, 0); + sqlite3OsSeek(pPager->stfd, 0); nRec = pPager->stmtNRec; /* Copy original pages out of the statement journal and back into the @@ -1442,7 +1430,7 @@ static int pager_stmt_playback(Pager *pPager){ ** journals. */ for(i=nRec-1; i>=0; i--){ - rc = pager_playback_one_page(pPager, &pPager->stfd, 0); + rc = pager_playback_one_page(pPager, pPager->stfd, 0); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } @@ -1455,7 +1443,7 @@ static int pager_stmt_playback(Pager *pPager){ ** If it is not zero, then Pager.stmtHdrOff is the offset to the start ** of the first journal header written during this statement transaction. */ - rc = sqlite3OsSeek(&pPager->jfd, pPager->stmtJSize); + rc = sqlite3OsSeek(pPager->jfd, pPager->stmtJSize); if( rc!=SQLITE_OK ){ goto end_stmt_playback; } @@ -1463,24 +1451,24 @@ static int pager_stmt_playback(Pager *pPager){ pPager->cksumInit = pPager->stmtCksum; assert( JOURNAL_HDR_SZ(pPager)<(pPager->pageSize+8) ); while( pPager->journalOff <= (hdrOff-(pPager->pageSize+8)) ){ - rc = pager_playback_one_page(pPager, &pPager->jfd, 1); + rc = pager_playback_one_page(pPager, pPager->jfd, 1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } while( pPager->journalOff < szJ ){ - u32 nRec; + u32 nJRec; /* Number of Journal Records */ u32 dummy; - rc = readJournalHdr(pPager, szJ, &nRec, &dummy); + rc = readJournalHdr(pPager, szJ, &nJRec, &dummy); if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_DONE ); goto end_stmt_playback; } - if( nRec==0 ){ - nRec = (szJ - pPager->journalOff) / (pPager->pageSize+8); + if( nJRec==0 ){ + nJRec = (szJ - pPager->journalOff) / (pPager->pageSize+8); } - for(i=nRec-1; i>=0 && pPager->journalOff < szJ; i--){ - rc = pager_playback_one_page(pPager, &pPager->jfd, 1); + for(i=nJRec-1; i>=0 && pPager->journalOff < szJ; i--){ + rc = pager_playback_one_page(pPager, pPager->jfd, 1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } @@ -1489,10 +1477,7 @@ static int pager_stmt_playback(Pager *pPager){ pPager->journalOff = szJ; end_stmt_playback: - if( rc!=SQLITE_OK ){ - pPager->errMask |= PAGER_ERR_CORRUPT; - rc = SQLITE_CORRUPT; - }else{ + if( rc==SQLITE_OK) { pPager->journalOff = szJ; /* pager_reload_cache(pPager); */ } @@ -1537,9 +1522,10 @@ void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){ ** and FULL=3. */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS -void sqlite3pager_set_safety_level(Pager *pPager, int level){ +void sqlite3pager_set_safety_level(Pager *pPager, int level, int full_fsync){ pPager->noSync = level==1 || pPager->tempFile; pPager->fullSync = level==3 && !pPager->tempFile; + pPager->full_fsync = full_fsync; if( pPager->noSync ) pPager->needSync = 0; } #endif @@ -1549,7 +1535,9 @@ void sqlite3pager_set_safety_level(Pager *pPager, int level){ ** attempts to open a temporary file. This information is used for ** testing and analysis only. */ +#ifdef SQLITE_TEST int sqlite3_opentemp_count = 0; +#endif /* ** Open a temporary file. Write the name of the file into zFile @@ -1560,14 +1548,16 @@ int sqlite3_opentemp_count = 0; ** The OS will automatically delete the temporary file when it is ** closed. */ -static int sqlite3pager_opentemp(char *zFile, OsFile *fd){ +static int sqlite3pager_opentemp(char *zFile, OsFile **pFd){ int cnt = 8; int rc; +#ifdef SQLITE_TEST sqlite3_opentemp_count++; /* Used for testing and analysis only */ +#endif do{ cnt--; sqlite3OsTempFileName(zFile); - rc = sqlite3OsOpenExclusive(zFile, fd, 1); + rc = sqlite3OsOpenExclusive(zFile, pFd, 1); }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM ); return rc; } @@ -1592,10 +1582,10 @@ int sqlite3pager_open( int nExtra, /* Extra bytes append to each in-memory page */ int flags /* flags controlling this file */ ){ - Pager *pPager; + Pager *pPager = 0; char *zFullPathname = 0; - int nameLen; - OsFile fd; + int nameLen; /* Compiler is wrong. This is always initialized before use */ + OsFile *fd; int rc = SQLITE_OK; int i; int tempFile = 0; @@ -1604,18 +1594,36 @@ int sqlite3pager_open( int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; int noReadlock = (flags & PAGER_NO_READLOCK)!=0; char zTemp[SQLITE_TEMPNAME_SIZE]; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to + ** malloc() must have already been made by this thread before it gets + ** to this point. This means the ThreadData must have been allocated already + ** so that ThreadData.nAlloc can be set. It would be nice to assert + ** that ThreadData.nAlloc is non-zero, but alas this breaks test cases + ** written to invoke the pager directly. + */ + ThreadData *pTsd = sqlite3ThreadData(); + assert( pTsd ); +#endif + /* If malloc() has already failed return SQLITE_NOMEM. Before even + ** testing for this, set *ppPager to NULL so the caller knows the pager + ** structure was never allocated. + */ *ppPager = 0; - memset(&fd, 0, sizeof(fd)); - if( sqlite3_malloc_failed ){ + if( sqlite3MallocFailed() ){ return SQLITE_NOMEM; } + memset(&fd, 0, sizeof(fd)); + + /* Open the pager file and set zFullPathname to point at malloc()ed + ** memory containing the complete filename (i.e. including the directory). + */ if( zFilename && zFilename[0] ){ #ifndef SQLITE_OMIT_MEMORYDB if( strcmp(zFilename,":memory:")==0 ){ memDb = 1; zFullPathname = sqliteStrDup(""); - rc = SQLITE_OK; }else #endif { @@ -1632,66 +1640,75 @@ int sqlite3pager_open( tempFile = 1; } } - if( !zFullPathname ){ - sqlite3OsClose(&fd); - return SQLITE_NOMEM; - } - if( rc!=SQLITE_OK ){ - sqlite3OsClose(&fd); - sqliteFree(zFullPathname); - return rc; + + /* Allocate the Pager structure. As part of the same allocation, allocate + ** space for the full paths of the file, directory and journal + ** (Pager.zFilename, Pager.zDirectory and Pager.zJournal). + */ + if( zFullPathname ){ + nameLen = strlen(zFullPathname); + pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); } - nameLen = strlen(zFullPathname); - pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); - if( pPager==0 ){ + + /* If an error occured in either of the blocks above, free the memory + ** pointed to by zFullPathname, free the Pager structure and close the + ** file. Since the pager is not allocated there is no need to set + ** any Pager.errMask variables. + */ + if( !pPager || !zFullPathname || rc!=SQLITE_OK ){ sqlite3OsClose(&fd); sqliteFree(zFullPathname); - return SQLITE_NOMEM; + sqliteFree(pPager); + return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc); } + TRACE3("OPEN %d %s\n", FILEHANDLEID(fd), zFullPathname); pPager->zFilename = (char*)&pPager[1]; pPager->zDirectory = &pPager->zFilename[nameLen+1]; pPager->zJournal = &pPager->zDirectory[nameLen+1]; strcpy(pPager->zFilename, zFullPathname); strcpy(pPager->zDirectory, zFullPathname); + for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} if( i>0 ) pPager->zDirectory[i-1] = 0; strcpy(pPager->zJournal, zFullPathname); sqliteFree(zFullPathname); strcpy(&pPager->zJournal[nameLen], "-journal"); pPager->fd = fd; -#if OS_UNIX - pPager->fd.pPager = pPager; -#endif - pPager->journalOpen = 0; + /* pPager->journalOpen = 0; */ pPager->useJournal = useJournal && !memDb; pPager->noReadlock = noReadlock && readOnly; - pPager->stmtOpen = 0; - pPager->stmtInUse = 0; - pPager->nRef = 0; + /* pPager->stmtOpen = 0; */ + /* pPager->stmtInUse = 0; */ + /* pPager->nRef = 0; */ pPager->dbSize = memDb-1; pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE; - pPager->stmtSize = 0; - pPager->stmtJSize = 0; - pPager->nPage = 0; - pPager->nMaxPage = 0; + /* pPager->stmtSize = 0; */ + /* pPager->stmtJSize = 0; */ + /* pPager->nPage = 0; */ + /* pPager->nMaxPage = 0; */ pPager->mxPage = 100; - pPager->state = PAGER_UNLOCK; - pPager->errMask = 0; + assert( PAGER_UNLOCK==0 ); + /* pPager->state = PAGER_UNLOCK; */ + /* pPager->errMask = 0; */ pPager->tempFile = tempFile; pPager->memDb = memDb; pPager->readOnly = readOnly; - pPager->needSync = 0; + /* pPager->needSync = 0; */ pPager->noSync = pPager->tempFile || !useJournal; pPager->fullSync = (pPager->noSync?0:1); - pPager->pFirst = 0; - pPager->pFirstSynced = 0; - pPager->pLast = 0; + /* pPager->pFirst = 0; */ + /* pPager->pFirstSynced = 0; */ + /* pPager->pLast = 0; */ pPager->nExtra = FORCE_ALIGNMENT(nExtra); pPager->sectorSize = PAGER_SECTOR_SIZE; - pPager->pBusyHandler = 0; - memset(pPager->aHash, 0, sizeof(pPager->aHash)); + /* pPager->pBusyHandler = 0; */ + /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + pPager->pNext = pTsd->pPager; + pTsd->pPager = pPager; +#endif return SQLITE_OK; } @@ -1738,15 +1755,51 @@ int sqlite3pager_set_pagesize(Pager *pPager, int pageSize){ return pPager->pageSize; } +/* +** 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 +extern int sqlite3_io_error_pending; +extern int sqlite3_io_error_hit; +static int saved_cnt; +void clear_simulated_io_error(){ + sqlite3_io_error_hit = 0; +} +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 clear_simulated_io_error() +# 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. No error checking is done. +** that pDest points to. +** +** No error checking is done. The rational for this is that this function +** may be called even if the file does not exist or contain a header. In +** these cases sqlite3OsRead() will return an error, to which the correct +** response is to zero the memory at pDest and continue. A real IO error +** will presumably recur and be picked up later (Todo: Think about this). */ void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){ memset(pDest, 0, N); if( MEMDB==0 ){ - sqlite3OsSeek(&pPager->fd, 0); - sqlite3OsRead(&pPager->fd, pDest, N); + disable_simulated_io_errors(); + sqlite3OsSeek(pPager->fd, 0); + sqlite3OsRead(pPager->fd, pDest, N); + enable_simulated_io_errors(); } } @@ -1765,8 +1818,8 @@ int sqlite3pager_pagecount(Pager *pPager){ if( pPager->dbSize>=0 ){ n = pPager->dbSize; } else { - if( sqlite3OsFileSize(&pPager->fd, &n)!=SQLITE_OK ){ - pPager->errMask |= PAGER_ERR_DISK; + if( sqlite3OsFileSize(pPager->fd, &n)!=SQLITE_OK ){ + pager_error(pPager, SQLITE_IOERR); return 0; } if( n>0 && npageSize ){ @@ -1784,12 +1837,26 @@ int sqlite3pager_pagecount(Pager *pPager){ return n; } + +#ifndef SQLITE_OMIT_MEMORYDB +/* +** Clear a PgHistory block +*/ +static void clearHistory(PgHistory *pHist){ + sqliteFree(pHist->pOrig); + sqliteFree(pHist->pStmt); + pHist->pOrig = 0; + pHist->pStmt = 0; +} +#else +#define clearHistory(x) +#endif + /* ** Forward declaration */ static int syncJournal(Pager*); - /* ** Unlink pPg from it's hash chain. Also set the page number to 0 to indicate ** that the page is not part of any hash chain. This is required because the @@ -1798,21 +1865,22 @@ static int syncJournal(Pager*); */ static void unlinkHashChain(Pager *pPager, PgHdr *pPg){ if( pPg->pgno==0 ){ - /* If the page number is zero, then this page is not in any hash chain. */ + assert( pPg->pNextHash==0 && pPg->pPrevHash==0 ); return; } if( pPg->pNextHash ){ pPg->pNextHash->pPrevHash = pPg->pPrevHash; } if( pPg->pPrevHash ){ - assert( pPager->aHash[pager_hash(pPg->pgno)]!=pPg ); + assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg ); pPg->pPrevHash->pNextHash = pPg->pNextHash; }else{ - int h = pager_hash(pPg->pgno); - assert( pPager->aHash[h]==pPg ); + int h = pPg->pgno & (pPager->nHash-1); pPager->aHash[h] = pPg->pNextHash; } - + if( MEMDB ){ + clearHistory(PGHDR_TO_HIST(pPg, pPager)); + } pPg->pgno = 0; pPg->pNextHash = pPg->pPrevHash = 0; } @@ -1871,6 +1939,7 @@ static void memoryTruncate(Pager *pPager){ }else{ *ppPg = pPg->pNextAll; unlinkPage(pPg); + makeClean(pPg); sqliteFree(pPg); pPager->nPage--; } @@ -1897,7 +1966,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ rc = SQLITE_OK; }else{ do { - rc = sqlite3OsLock(&pPager->fd, locktype); + rc = sqlite3OsLock(pPager->fd, locktype); }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) ); if( rc==SQLITE_OK ){ pPager->state = locktype; @@ -1912,8 +1981,8 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ int rc; sqlite3pager_pagecount(pPager); - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); + if( pPager->errCode ){ + rc = pPager->errCode; return rc; } if( nPage>=(unsigned)pPager->dbSize ){ @@ -1950,9 +2019,25 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ ** 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. */ int sqlite3pager_close(Pager *pPager){ PgHdr *pPg, *pNext; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to + ** malloc() must have already been made by this thread before it gets + ** to this point. This means the ThreadData must have been allocated already + ** so that ThreadData.nAlloc can be set. + */ + ThreadData *pTsd = sqlite3ThreadData(); + assert( pPager ); + assert( pTsd && pTsd->nAlloc ); +#endif + switch( pPager->state ){ case PAGER_RESERVED: case PAGER_SYNCED: @@ -1961,24 +2046,18 @@ int sqlite3pager_close(Pager *pPager){ ** operation. So disable IO error simulation so that testing ** works more easily. */ -#if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN)) - extern int sqlite3_io_error_pending; - int ioerr_cnt = sqlite3_io_error_pending; - sqlite3_io_error_pending = -1; -#endif + disable_simulated_io_errors(); sqlite3pager_rollback(pPager); -#if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN)) - sqlite3_io_error_pending = ioerr_cnt; -#endif + enable_simulated_io_errors(); if( !MEMDB ){ - sqlite3OsUnlock(&pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); } - assert( pPager->errMask || pPager->journalOpen==0 ); + assert( pPager->errCode || pPager->journalOpen==0 ); break; } case PAGER_SHARED: { if( !MEMDB ){ - sqlite3OsUnlock(&pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); } break; } @@ -2000,7 +2079,7 @@ int sqlite3pager_close(Pager *pPager){ sqliteFree(pPg); } TRACE2("CLOSE %d\n", PAGERID(pPager)); - assert( pPager->errMask || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); + assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ sqlite3OsClose(&pPager->jfd); } @@ -2015,6 +2094,19 @@ int sqlite3pager_close(Pager *pPager){ ** } */ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* Remove the pager from the linked list of pagers starting at + ** ThreadData.pPager if memory-management is enabled. + */ + if( pPager==pTsd->pPager ){ + pTsd->pPager = pPager->pNext; + }else{ + Pager *pTmp; + for(pTmp = pTsd->pPager; pTmp->pNext!=pPager; pTmp=pTmp->pNext){} + pTmp->pNext = pPager->pNext; + } +#endif + sqliteFree(pPager->aHash); sqliteFree(pPager); return SQLITE_OK; } @@ -2120,7 +2212,7 @@ static int syncJournal(Pager *pPager){ ** with the nRec computed from the size of the journal file. */ i64 jSz; - rc = sqlite3OsFileSize(&pPager->jfd, &jSz); + rc = sqlite3OsFileSize(pPager->jfd, &jSz); if( rc!=0 ) return rc; assert( pPager->journalOff==jSz ); } @@ -2133,20 +2225,20 @@ static int syncJournal(Pager *pPager){ */ if( pPager->fullSync ){ TRACE2("SYNC journal of %d\n", PAGERID(pPager)); - rc = sqlite3OsSync(&pPager->jfd, 0); + rc = sqlite3OsSync(pPager->jfd, 0); if( rc!=0 ) return rc; } - rc = sqlite3OsSeek(&pPager->jfd, + rc = sqlite3OsSeek(pPager->jfd, pPager->journalHdr + sizeof(aJournalMagic)); if( rc ) return rc; - rc = write32bits(&pPager->jfd, pPager->nRec); + rc = write32bits(pPager->jfd, pPager->nRec); if( rc ) return rc; - rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff); + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff); if( rc ) return rc; } TRACE2("SYNC journal of %d\n", PAGERID(pPager)); - rc = sqlite3OsSync(&pPager->jfd, pPager->fullSync); + rc = sqlite3OsSync(pPager->jfd, pPager->full_fsync); if( rc!=0 ) return rc; pPager->journalStarted = 1; } @@ -2176,6 +2268,68 @@ static int syncJournal(Pager *pPager){ return rc; } +/* +** Merge two lists of pages connected by pDirty and in pgno order. +** Do not both fixing the pPrevDirty pointers. +*/ +static PgHdr *merge_pagelist(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 pPrevDirty pointers are +** corrupted by this sort. +*/ +#define N_SORT_BUCKET 25 +static PgHdr *sort_pagelist(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; idirty ); - rc = sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize); + rc = sqlite3OsSeek(pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize); if( rc ) return rc; /* If there are dirty pages in the page cache with page numbers greater ** than Pager.dbSize, this means sqlite3pager_truncate() was called to @@ -2219,10 +2374,9 @@ static int pager_write_pagelist(PgHdr *pList){ ** any such pages to the file. */ if( pList->pgno<=pPager->dbSize ){ - CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); + char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); TRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno); - rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize); - CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0); + rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize); TEST_INCR(pPager->nWrite); } #ifndef NDEBUG @@ -2246,15 +2400,7 @@ static int pager_write_pagelist(PgHdr *pList){ ** collected even if they are still in use. */ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ - PgHdr *p, *pList; - pList = 0; - for(p=pPager->pAll; p; p=p->pNextAll){ - if( p->dirty ){ - p->pDirty = pList; - pList = p; - } - } - return pList; + return pPager->pDirty; } /* @@ -2268,7 +2414,7 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ static int hasHotJournal(Pager *pPager){ if( !pPager->useJournal ) return 0; if( !sqlite3OsFileExists(pPager->zJournal) ) return 0; - if( sqlite3OsCheckReservedLock(&pPager->fd) ) return 0; + if( sqlite3OsCheckReservedLock(pPager->fd) ) return 0; if( sqlite3pager_pagecount(pPager)==0 ){ sqlite3OsDelete(pPager->zJournal); return 0; @@ -2277,6 +2423,172 @@ static int hasHotJournal(Pager *pPager){ } } +/* +** Try to find a page in the cache that can be recycled. +** +** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It +** does not set the pPager->errCode variable. +*/ +static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ + PgHdr *pPg; + *ppPg = 0; + + /* Find a page to recycle. Try to locate a page that does not + ** require us to do an fsync() on the journal. + */ + pPg = pPager->pFirstSynced; + + /* If we could not find a page that does not require an fsync() + ** on the journal file then fsync the journal file. This is a + ** very slow operation, so we work hard to avoid it. But sometimes + ** it can't be helped. + */ + if( pPg==0 && pPager->pFirst && syncOk && !MEMDB){ + int rc = syncJournal(pPager); + if( rc!=0 ){ + return rc; + } + if( pPager->fullSync ){ + /* If in full-sync mode, write a new journal header into the + ** journal file. This is done to avoid ever modifying a journal + ** header that is involved in the rollback of pages that have + ** already been written to the database (in case the header is + ** trashed when the nRec field is updated). + */ + pPager->nRec = 0; + assert( pPager->journalOff > 0 ); + rc = writeJournalHdr(pPager); + if( rc!=0 ){ + return rc; + } + } + pPg = pPager->pFirst; + } + if( pPg==0 ){ + return SQLITE_OK; + } + + assert( pPg->nRef==0 ); + + /* Write the page to the database file if it is dirty. + */ + if( pPg->dirty ){ + int rc; + assert( pPg->needSync==0 ); + makeClean(pPg); + pPg->dirty = 1; + pPg->pDirty = 0; + rc = pager_write_pagelist( pPg ); + if( rc!=SQLITE_OK ){ + return rc; + } + } + assert( pPg->dirty==0 ); + + /* If the page we are recycling is marked as alwaysRollback, then + ** set the global alwaysRollback flag, thus disabling the + ** sqlite_dont_rollback() optimization for the rest of this transaction. + ** It is necessary to do this because the page marked alwaysRollback + ** might be reloaded at a later time but at that point we won't remember + ** that is was marked alwaysRollback. This means that all pages must + ** be marked as alwaysRollback from here on out. + */ + if( pPg->alwaysRollback ){ + pPager->alwaysRollback = 1; + } + + /* Unlink the old page from the free list and the hash table + */ + unlinkPage(pPg); + TEST_INCR(pPager->nOvfl); + + *ppPg = pPg; + return SQLITE_OK; +} + +/* +** 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 sqliteFree()ed. +** +** nReq is the number of bytes of memory required. Once this much has +** been released, the function returns. A negative value for nReq means +** free as much memory as possible. The return value is the total number +** of bytes of memory released. +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +int sqlite3pager_release_memory(int nReq){ + const ThreadData *pTsdro = sqlite3ThreadDataReadOnly(); + Pager *p; + int nReleased = 0; + int i; + + /* If the the global mutex is held, this subroutine becomes a + ** o-op; zero bytes of memory are freed. This is because + ** some of the code invoked by this function may also + ** try to obtain the mutex, resulting in a deadlock. + */ + if( sqlite3OsInMutex(0) ){ + return 0; + } + + /* Outermost loop runs for at most two iterations. First iteration we + ** try to find memory that can be released without calling fsync(). Second + ** iteration (which only runs if the first failed to free nReq bytes of + ** memory) is permitted to call fsync(). This is of course much more + ** expensive. + */ + for(i=0; i<=1; i++){ + + /* Loop through all the SQLite pagers opened by the current thread. */ + for(p=pTsdro->pPager; p && (nReq<0 || nReleasedpNext){ + PgHdr *pPg; + int rc; + + /* For each pager, try to free as many pages as possible (without + ** calling fsync() if this is the first iteration of the outermost + ** loop). + */ + while( SQLITE_OK==(rc = pager_recycle(p, i, &pPg)) && pPg) { + /* We've found a page to free. At this point the page has been + ** removed from the page hash-table, free-list and synced-list + ** (pFirstSynced). It is still in the all pages (pAll) list. + ** Remove it from this list before freeing. + ** + ** Todo: Check the Pager.pStmt list to make sure this is Ok. It + ** probably is though. + */ + PgHdr *pTmp; + assert( pPg ); + page_remove_from_stmt_list(pPg); + if( pPg==p->pAll ){ + p->pAll = pPg->pNextAll; + }else{ + for( pTmp=p->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ){} + pTmp->pNextAll = pPg->pNextAll; + } + nReleased += sqliteAllocSize(pPg); + sqliteFree(pPg); + } + + if( rc!=SQLITE_OK ){ + /* An error occured whilst writing to the database file or + ** journal in pager_recycle(). The error is not returned to the + ** caller of this function. Instead, set the Pager.errCode variable. + ** The error will be returned to the user (or users, in the case + ** of a shared pager cache) of the pager for which the error occured. + */ + assert( rc==SQLITE_IOERR || rc==SQLITE_FULL ); + assert( p->state>=PAGER_RESERVED ); + pager_error(p, rc); + } + } + } + + return nReleased; +} +#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ + /* ** Acquire a page. ** @@ -2315,8 +2627,8 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ */ assert( pPager!=0 ); *ppPage = 0; - if( pPager->errMask & ~(PAGER_ERR_FULL) ){ - return pager_errcode(pPager); + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + return pPager->errCode; } /* If this is the first page accessed, then get a SHARED lock @@ -2326,7 +2638,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ if( !pPager->noReadlock ){ rc = pager_wait_on_lock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){ - return rc; + return pager_error(pPager, rc); } } @@ -2334,8 +2646,6 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ ** database file, then it either needs to be played back or deleted. */ if( hasHotJournal(pPager) ){ - int rc; - /* 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 @@ -2347,11 +2657,11 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ ** second process will get to this point in the code and fail to ** obtain it's own EXCLUSIVE lock on the database file. */ - rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK); + rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ - sqlite3OsUnlock(&pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; - return rc; + return pager_error(pPager, rc); } pPager->state = PAGER_EXCLUSIVE; @@ -2365,7 +2675,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ */ rc = sqlite3OsOpenReadOnly(pPager->zJournal, &pPager->jfd); if( rc!=SQLITE_OK ){ - sqlite3OsUnlock(&pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return SQLITE_BUSY; } @@ -2380,7 +2690,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ */ rc = pager_playback(pPager); if( rc!=SQLITE_OK ){ - return rc; + return pager_error(pPager, rc); } } pPg = 0; @@ -2397,11 +2707,17 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ TEST_INCR(pPager->nMiss); if( pPager->nPagemxPage || pPager->pFirst==0 || MEMDB ){ /* Create a new page */ + if( pPager->nPage>=pPager->nHash ){ + pager_resize_hash_table(pPager, + pPager->nHash<256 ? 256 : pPager->nHash*2); + if( pPager->nHash==0 ){ + return SQLITE_NOMEM; + } + } pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize + sizeof(u32) + pPager->nExtra + MEMDB*sizeof(PgHistory) ); if( pPg==0 ){ - pPager->errMask |= PAGER_ERR_MEM; return SQLITE_NOMEM; } memset(pPg, 0, sizeof(*pPg)); @@ -2417,70 +2733,11 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ pPager->nMaxPage++; } }else{ - /* Find a page to recycle. Try to locate a page that does not - ** require us to do an fsync() on the journal. - */ - pPg = pPager->pFirstSynced; - - /* If we could not find a page that does not require an fsync() - ** on the journal file then fsync the journal file. This is a - ** very slow operation, so we work hard to avoid it. But sometimes - ** it can't be helped. - */ - if( pPg==0 ){ - int rc = syncJournal(pPager); - if( rc!=0 ){ - sqlite3pager_rollback(pPager); - return SQLITE_IOERR; - } - if( pPager->fullSync ){ - /* If in full-sync mode, write a new journal header into the - ** journal file. This is done to avoid ever modifying a journal - ** header that is involved in the rollback of pages that have - ** already been written to the database (in case the header is - ** trashed when the nRec field is updated). - */ - pPager->nRec = 0; - assert( pPager->journalOff > 0 ); - rc = writeJournalHdr(pPager); - if( rc!=0 ){ - sqlite3pager_rollback(pPager); - return SQLITE_IOERR; - } - } - pPg = pPager->pFirst; - } - assert( pPg->nRef==0 ); - - /* Write the page to the database file if it is dirty. - */ - if( pPg->dirty ){ - assert( pPg->needSync==0 ); - pPg->pDirty = 0; - rc = pager_write_pagelist( pPg ); - if( rc!=SQLITE_OK ){ - sqlite3pager_rollback(pPager); - return SQLITE_IOERR; - } - } - assert( pPg->dirty==0 ); - - /* If the page we are recycling is marked as alwaysRollback, then - ** set the global alwaysRollback flag, thus disabling the - ** sqlite_dont_rollback() optimization for the rest of this transaction. - ** It is necessary to do this because the page marked alwaysRollback - ** might be reloaded at a later time but at that point we won't remember - ** that is was marked alwaysRollback. This means that all pages must - ** be marked as alwaysRollback from here on out. - */ - if( pPg->alwaysRollback ){ - pPager->alwaysRollback = 1; + rc = pager_recycle(pPager, 1, &pPg); + if( rc!=SQLITE_OK ){ + return rc; } - - /* Unlink the old page from the free list and the hash table - */ - unlinkPage(pPg); - TEST_INCR(pPager->nOvfl); + assert(pPg) ; } pPg->pgno = pgno; if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ @@ -2498,49 +2755,62 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ }else{ page_remove_from_stmt_list(pPg); } - pPg->dirty = 0; + makeClean(pPg); pPg->nRef = 1; REFINFO(pPg); + pPager->nRef++; - h = pager_hash(pgno); - pPg->pNextHash = pPager->aHash[h]; - pPager->aHash[h] = pPg; - if( pPg->pNextHash ){ - assert( pPg->pNextHash->pPrevHash==0 ); - pPg->pNextHash->pPrevHash = pPg; - } if( pPager->nExtra>0 ){ memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); } - if( pPager->errMask!=0 ){ + if( pPager->errCode ){ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); - rc = pager_errcode(pPager); + rc = pPager->errCode; return rc; } - if( sqlite3pager_pagecount(pPager)<(int)pgno ){ + + /* Populate the page with data, either by reading from the database + ** file, or by setting the entire page to zero. + */ + if( sqlite3pager_pagecount(pPager)<(int)pgno || MEMDB ){ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); }else{ - int rc; assert( MEMDB==0 ); - rc = sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); + rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize); + rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), + pPager->pageSize); } TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno); - CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); + CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); if( rc!=SQLITE_OK ){ i64 fileSize; - if( sqlite3OsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK - || fileSize>=pgno*pPager->pageSize ){ + int rc2 = sqlite3OsFileSize(pPager->fd, &fileSize); + if( rc2!=SQLITE_OK || fileSize>=pgno*pPager->pageSize ){ + /* An IO error occured in one of the the sqlite3OsSeek() or + ** sqlite3OsRead() calls above. */ + pPg->pgno = 0; sqlite3pager_unref(PGHDR_TO_DATA(pPg)); return rc; }else{ + clear_simulated_io_error(); memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); } }else{ TEST_INCR(pPager->nRead); } } + + /* Link the page into the page hash table */ + h = pgno & (pPager->nHash-1); + assert( pgno!=0 ); + pPg->pNextHash = pPager->aHash[h]; + pPager->aHash[h] = pPg; + if( pPg->pNextHash ){ + assert( pPg->pNextHash->pPrevHash==0 ); + pPg->pNextHash->pPrevHash = pPg; + } + #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif @@ -2569,7 +2839,7 @@ void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){ assert( pPager!=0 ); assert( pgno!=0 ); - if( pPager->errMask & ~(PAGER_ERR_FULL) ){ + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ return 0; } pPg = pager_lookup(pPager, pgno); @@ -2651,23 +2921,24 @@ static int pager_open_journal(Pager *pPager){ rc = SQLITE_NOMEM; goto failed_to_open_journal; } - rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile); + rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd, + pPager->tempFile); pPager->journalOff = 0; pPager->setMaster = 0; pPager->journalHdr = 0; if( rc!=SQLITE_OK ){ goto failed_to_open_journal; } - SET_FULLSYNC(pPager->jfd, pPager->fullSync); - SET_FULLSYNC(pPager->fd, pPager->fullSync); - sqlite3OsOpenDirectory(pPager->zDirectory, &pPager->jfd); + sqlite3OsSetFullSync(pPager->jfd, pPager->full_fsync); + sqlite3OsSetFullSync(pPager->fd, pPager->full_fsync); + sqlite3OsOpenDirectory(pPager->jfd, pPager->zDirectory); pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; pPager->alwaysRollback = 0; pPager->nRec = 0; - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); + if( pPager->errCode ){ + rc = pPager->errCode; goto failed_to_open_journal; } pPager->origDbSize = pPager->dbSize; @@ -2677,7 +2948,7 @@ static int pager_open_journal(Pager *pPager){ if( pPager->stmtAutoopen && rc==SQLITE_OK ){ rc = sqlite3pager_stmt_begin(pPager); } - if( rc!=SQLITE_OK ){ + if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ rc = pager_unwritelock(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; @@ -2688,8 +2959,17 @@ static int pager_open_journal(Pager *pPager){ failed_to_open_journal: sqliteFree(pPager->aInJournal); pPager->aInJournal = 0; - sqlite3OsUnlock(&pPager->fd, NO_LOCK); - pPager->state = PAGER_UNLOCK; + if( rc==SQLITE_NOMEM ){ + /* If this was a malloc() failure, then we will not be closing the pager + ** file. So delete any journal file we may have just created. Otherwise, + ** the system will get confused, we have a read-lock on the file and a + ** mysterious journal has appeared in the filesystem. + */ + sqlite3OsDelete(pPager->zJournal); + }else{ + sqlite3OsUnlock(pPager->fd, NO_LOCK); + pPager->state = PAGER_UNLOCK; + } return rc; } @@ -2732,7 +3012,7 @@ int sqlite3pager_begin(void *pData, int exFlag){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ - rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK); + rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK); if( rc==SQLITE_OK ){ pPager->state = PAGER_RESERVED; if( exFlag ){ @@ -2752,6 +3032,42 @@ int sqlite3pager_begin(void *pData, int exFlag){ return rc; } +/* +** Make a page dirty. Set its dirty flag and add it to the dirty +** page list. +*/ +static void makeDirty(PgHdr *pPg){ + if( pPg->dirty==0 ){ + Pager *pPager = pPg->pPager; + pPg->dirty = 1; + pPg->pDirty = pPager->pDirty; + if( pPager->pDirty ){ + pPager->pDirty->pPrevDirty = pPg; + } + pPg->pPrevDirty = 0; + pPager->pDirty = pPg; + } +} + +/* +** Make a page clean. Clear its dirty bit and remove it from the +** dirty page list. +*/ +static void makeClean(PgHdr *pPg){ + if( pPg->dirty ){ + pPg->dirty = 0; + if( pPg->pDirty ){ + pPg->pDirty->pPrevDirty = pPg->pPrevDirty; + } + if( pPg->pPrevDirty ){ + pPg->pPrevDirty->pDirty = pPg->pDirty; + }else{ + pPg->pPager->pDirty = pPg->pDirty; + } + } +} + + /* ** Mark a data page as writeable. The page is written into the journal ** if it is not there already. This routine must be called before making @@ -2776,8 +3092,8 @@ int sqlite3pager_write(void *pData){ /* Check for errors */ - if( pPager->errMask ){ - return pager_errcode(pPager); + if( pPager->errCode ){ + return pPager->errCode; } if( pPager->readOnly ){ return SQLITE_PERM; @@ -2790,7 +3106,7 @@ int sqlite3pager_write(void *pData){ /* Mark the page as dirty. If the page has already been written ** to the journal then we can return right away. */ - pPg->dirty = 1; + makeDirty(pPg); if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){ pPager->dirtyCache = 1; }else{ @@ -2822,7 +3138,6 @@ int sqlite3pager_write(void *pData){ if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){ if( (int)pPg->pgno <= pPager->origDbSize ){ int szPg; - u32 saved; if( MEMDB ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); TRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); @@ -2832,28 +3147,33 @@ int sqlite3pager_write(void *pData){ memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize); } }else{ - u32 cksum; + u32 cksum, saved; + char *pData2, *pEnd; /* 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) ); - CODEC(pPager, pData, pPg->pgno, 7); - cksum = pager_cksum(pPager, pPg->pgno, pData); - saved = *(u32*)PGHDR_TO_EXTRA(pPg, pPager); - store32bits(cksum, pPg, pPager->pageSize); + pData2 = CODEC2(pPager, pData, pPg->pgno, 7); + cksum = pager_cksum(pPager, (u8*)pData2); + pEnd = pData2 + pPager->pageSize; + pData2 -= 4; + saved = *(u32*)pEnd; + put32bits(pEnd, cksum); szPg = pPager->pageSize+8; - store32bits(pPg->pgno, pPg, -4); - rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], szPg); + put32bits(pData2, pPg->pgno); + rc = sqlite3OsWrite(pPager->jfd, pData2, szPg); pPager->journalOff += szPg; TRACE4("JOURNAL %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, pPg->needSync); - CODEC(pPager, pData, pPg->pgno, 0); - *(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved; + *(u32*)pEnd = saved; + + /* An error has occured writing to the journal file. The + ** transaction will be rolled back by the layer above. + */ if( rc!=SQLITE_OK ){ - sqlite3pager_rollback(pPager); - pPager->errMask |= PAGER_ERR_FULL; return rc; } + pPager->nRec++; assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); @@ -2890,14 +3210,11 @@ int sqlite3pager_write(void *pData){ } TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); }else{ - store32bits(pPg->pgno, pPg, -4); - CODEC(pPager, pData, pPg->pgno, 7); - rc = sqlite3OsWrite(&pPager->stfd,((char*)pData)-4, pPager->pageSize+4); + char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7)-4; + put32bits(pData2, pPg->pgno); + rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize+4); TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); - CODEC(pPager, pData, pPg->pgno, 0); if( rc!=SQLITE_OK ){ - sqlite3pager_rollback(pPager); - pPager->errMask |= PAGER_ERR_FULL; return rc; } pPager->stmtNRec++; @@ -2924,10 +3241,12 @@ int sqlite3pager_write(void *pData){ ** to sqlite3pager_write(). In other words, return TRUE if it is ok ** to change the content of the page. */ +#ifndef NDEBUG int sqlite3pager_iswriteable(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); return pPg->dirty; } +#endif #ifndef SQLITE_OMIT_VACUUM /* @@ -2980,8 +3299,9 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){ if( MEMDB ) return; pPg = pager_lookup(pPager, pgno); + assert( pPg!=0 ); /* We never call _dont_write unless the page is in mem */ pPg->alwaysRollback = 1; - if( pPg && pPg->dirty && !pPager->stmtInUse ){ + if( pPg->dirty && !pPager->stmtInUse ){ if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSizedbSize ){ /* If this pages is the last page in the file and the file has grown ** during the current transaction, then do NOT mark the page as clean. @@ -2993,7 +3313,7 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){ */ }else{ TRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager)); - pPg->dirty = 0; + makeClean(pPg); #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif @@ -3032,20 +3352,6 @@ void sqlite3pager_dont_rollback(void *pData){ } -#ifndef SQLITE_OMIT_MEMORYDB -/* -** Clear a PgHistory block -*/ -static void clearHistory(PgHistory *pHist){ - sqliteFree(pHist->pOrig); - sqliteFree(pHist->pStmt); - pHist->pOrig = 0; - pHist->pStmt = 0; -} -#else -#define clearHistory(x) -#endif - /* ** Commit all changes to the database and release the write lock. ** @@ -3057,16 +3363,8 @@ int sqlite3pager_commit(Pager *pPager){ int rc; PgHdr *pPg; - if( pPager->errMask==PAGER_ERR_FULL ){ - rc = sqlite3pager_rollback(pPager); - if( rc==SQLITE_OK ){ - rc = SQLITE_FULL; - } - return rc; - } - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); - return rc; + if( pPager->errCode ){ + return pPager->errCode; } if( pPager->statedirty = 0; pPg->inJournal = 0; pPg->inStmt = 0; + pPg->needSync = 0; pPg->pPrevStmt = pPg->pNextStmt = 0; pPg = pPg->pDirty; } + pPager->pDirty = 0; #ifndef NDEBUG for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); @@ -3104,17 +3404,10 @@ int sqlite3pager_commit(Pager *pPager){ } assert( pPager->journalOpen ); rc = sqlite3pager_sync(pPager, 0, 0); - if( rc!=SQLITE_OK ){ - goto commit_abort; + if( rc==SQLITE_OK ){ + rc = pager_unwritelock(pPager); + pPager->dbSize = -1; } - rc = pager_unwritelock(pPager); - pPager->dbSize = -1; - return rc; - - /* Jump here if anything goes wrong during the commit process. - */ -commit_abort: - sqlite3pager_rollback(pPager); return rc; } @@ -3156,12 +3449,11 @@ int sqlite3pager_rollback(Pager *pPager){ p->inJournal = 0; p->inStmt = 0; p->pPrevStmt = p->pNextStmt = 0; - if( pPager->xReiniter ){ pPager->xReiniter(PGHDR_TO_DATA(p), pPager->pageSize); } - } + pPager->pDirty = 0; pPager->pStmt = 0; pPager->dbSize = pPager->origDbSize; memoryTruncate(pPager); @@ -3176,11 +3468,11 @@ int sqlite3pager_rollback(Pager *pPager){ return rc; } - if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){ + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ if( pPager->state>=PAGER_EXCLUSIVE ){ pager_playback(pPager); } - return pager_errcode(pPager); + return pPager->errCode; } if( pPager->state==PAGER_RESERVED ){ int rc2; @@ -3192,12 +3484,13 @@ int sqlite3pager_rollback(Pager *pPager){ }else{ rc = pager_playback(pPager); } - if( rc!=SQLITE_OK ){ - rc = SQLITE_CORRUPT_BKPT; - pPager->errMask |= PAGER_ERR_CORRUPT; - } pPager->dbSize = -1; - return rc; + + /* 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); } /* @@ -3208,6 +3501,14 @@ int sqlite3pager_isreadonly(Pager *pPager){ return pPager->readOnly; } +/* +** Return the number of references to the pager. +*/ +int sqlite3pager_refcount(Pager *pPager){ + return pPager->nRef; +} + +#ifdef SQLITE_TEST /* ** This routine is used for testing and analysis only. */ @@ -3218,16 +3519,15 @@ int *sqlite3pager_stats(Pager *pPager){ a[2] = pPager->mxPage; a[3] = pPager->dbSize; a[4] = pPager->state; - a[5] = pPager->errMask; -#ifdef SQLITE_TEST + a[5] = pPager->errCode; a[6] = pPager->nHit; a[7] = pPager->nMiss; a[8] = pPager->nOvfl; a[9] = pPager->nRead; a[10] = pPager->nWrite; -#endif return a; } +#endif /* ** Set the statement rollback point. @@ -3254,11 +3554,11 @@ int sqlite3pager_stmt_begin(Pager *pPager){ assert( pPager->journalOpen ); pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInStmt==0 ){ - sqlite3OsLock(&pPager->fd, SHARED_LOCK); + /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */ return SQLITE_NOMEM; } #ifndef NDEBUG - rc = sqlite3OsFileSize(&pPager->jfd, &pPager->stmtJSize); + rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize); if( rc ) goto stmt_begin_failed; assert( pPager->stmtJSize == pPager->journalOff ); #endif @@ -3291,8 +3591,8 @@ int sqlite3pager_stmt_commit(Pager *pPager){ PgHdr *pPg, *pNext; TRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); if( !MEMDB ){ - sqlite3OsSeek(&pPager->stfd, 0); - /* sqlite3OsTruncate(&pPager->stfd, 0); */ + sqlite3OsSeek(pPager->stfd, 0); + /* sqlite3OsTruncate(pPager->stfd, 0); */ sqliteFree( pPager->aInStmt ); pPager->aInStmt = 0; } @@ -3380,7 +3680,7 @@ int sqlite3pager_nosync(Pager *pPager){ */ void sqlite3pager_set_codec( Pager *pPager, - void (*xCodec)(void*,void*,Pgno,int), + void *(*xCodec)(void*,void*,Pgno,int), void *pCodecArg ){ pPager->xCodec = xCodec; @@ -3409,7 +3709,7 @@ static int pager_incr_changecounter(Pager *pPager){ /* Increment the value just read and write it back to byte 24. */ change_counter++; - store32bits(change_counter, pPgHdr, 24); + put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter); /* Release the page reference. */ sqlite3pager_unref(pPage); @@ -3495,10 +3795,12 @@ int sqlite3pager_sync(Pager *pPager, const char *zMaster, Pgno nTrunc){ /* Sync the database file. */ if( !pPager->noSync ){ - rc = sqlite3OsSync(&pPager->fd, 0); + rc = sqlite3OsSync(pPager->fd, 0); } pPager->state = PAGER_SYNCED; + }else if( MEMDB && nTrunc!=0 ){ + rc = sqlite3pager_truncate(pPager, nTrunc); } sync_exit: @@ -3553,7 +3855,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ if( pPgOld ){ assert( pPgOld->nRef==0 ); unlinkHashChain(pPager, pPgOld); - pPgOld->dirty = 0; + makeClean(pPgOld); if( pPgOld->needSync ){ assert( pPgOld->inJournal ); pPg->inJournal = 1; @@ -3563,8 +3865,9 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ } /* Change the page number for pPg and insert it into the new hash-chain. */ + assert( pgno!=0 ); pPg->pgno = pgno; - h = pager_hash(pgno); + h = pgno & (pPager->nHash-1); if( pPager->aHash[h] ){ assert( pPager->aHash[h]->pPrevHash==0 ); pPager->aHash[h]->pPrevHash = pPg; @@ -3573,7 +3876,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ pPager->aHash[h] = pPg; pPg->pPrevHash = 0; - pPg->dirty = 1; + makeDirty(pPg); pPager->dirtyCache = 1; if( needSyncPgno ){ @@ -3594,7 +3897,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ pPager->needSync = 1; DATA_TO_PGHDR(pNeedSync)->needSync = 1; DATA_TO_PGHDR(pNeedSync)->inJournal = 1; - DATA_TO_PGHDR(pNeedSync)->dirty = 1; + makeDirty(DATA_TO_PGHDR(pNeedSync)); sqlite3pager_unref(pNeedSync); } @@ -3609,11 +3912,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ ** PENDING_LOCK, or EXCLUSIVE_LOCK. */ int sqlite3pager_lockstate(Pager *pPager){ -#ifdef OS_TEST - return pPager->fd->fd.locktype; -#else - return pPager->fd.locktype; -#endif + return sqlite3OsLockState(pPager->fd); } #endif diff --git a/ext/pdo_sqlite/sqlite/src/pager.h b/ext/pdo_sqlite/sqlite/src/pager.h index feba78a7ad..555e52a031 100644 --- a/ext/pdo_sqlite/sqlite/src/pager.h +++ b/ext/pdo_sqlite/sqlite/src/pager.h @@ -16,6 +16,9 @@ ** @(#) $Id$ */ +#ifndef _PAGER_H_ +#define _PAGER_H_ + /* ** The default size of a database page. */ @@ -95,16 +98,18 @@ int sqlite3pager_stmt_commit(Pager*); int sqlite3pager_stmt_rollback(Pager*); void sqlite3pager_dont_rollback(void*); void sqlite3pager_dont_write(Pager*, Pgno); +int sqlite3pager_refcount(Pager*); int *sqlite3pager_stats(Pager*); -void sqlite3pager_set_safety_level(Pager*,int); +void sqlite3pager_set_safety_level(Pager*,int,int); const char *sqlite3pager_filename(Pager*); const char *sqlite3pager_dirname(Pager*); const char *sqlite3pager_journalname(Pager*); int sqlite3pager_nosync(Pager*); int sqlite3pager_rename(Pager*, const char *zNewName); -void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*); +void sqlite3pager_set_codec(Pager*,void*(*)(void*,void*,Pgno,int),void*); int sqlite3pager_movepage(Pager*,void*,Pgno); int sqlite3pager_reset(Pager*); +int sqlite3pager_release_memory(int); #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) int sqlite3pager_lockstate(Pager*); @@ -114,3 +119,5 @@ int sqlite3pager_lockstate(Pager*); void sqlite3pager_refdump(Pager*); int pager3_refinfo_enable; #endif + +#endif /* _PAGER_H_ */ diff --git a/ext/pdo_sqlite/sqlite/src/parse.c b/ext/pdo_sqlite/sqlite/src/parse.c index 432a262fd4..3aa31ac144 100644 --- a/ext/pdo_sqlite/sqlite/src/parse.c +++ b/ext/pdo_sqlite/sqlite/src/parse.c @@ -4,7 +4,7 @@ /* First off, code is include which follows the "include" declaration ** in the input file. */ #include -#line 51 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 56 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" #include "sqliteInt.h" #include "parse.h" @@ -23,7 +23,7 @@ struct LimitVal { ** GLOB, NOT LIKE, and NOT GLOB operators. */ struct LikeOp { - Token operator; /* "like" or "glob" or "regexp" */ + Token eOperator; /* "like" or "glob" or "regexp" */ int not; /* True if the NOT keyword is present */ }; @@ -43,7 +43,7 @@ struct TrigEvent { int a; IdList * b; }; */ struct AttachKey { int type; Token key; }; -#line 48 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 48 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. */ @@ -93,25 +93,26 @@ struct AttachKey { int type; Token key; }; ** defined, then do no error processing. */ #define YYCODETYPE unsigned char -#define YYNOCODE 247 +#define YYNOCODE 248 #define YYACTIONTYPE unsigned short int +#define YYWILDCARD 60 #define sqlite3ParserTOKENTYPE Token typedef union { sqlite3ParserTOKENTYPE yy0; - struct TrigEvent yy30; - Expr* yy62; - SrcList* yy151; - Token yy198; - struct LimitVal yy220; - struct LikeOp yy222; - IdList* yy240; - int yy280; - struct {int value; int mask;} yy359; - TriggerStep* yy360; - struct AttachKey yy361; - Select* yy375; - ExprList* yy418; - int yy493; + int yy46; + struct LikeOp yy72; + Expr* yy172; + ExprList* yy174; + Select* yy219; + struct LimitVal yy234; + TriggerStep* yy243; + struct TrigEvent yy370; + SrcList* yy373; + Expr * yy386; + struct {int value; int mask;} yy405; + Token yy410; + IdList* yy432; + int yy495; } YYMINORTYPE; #define YYSTACKDEPTH 100 #define sqlite3ParserARG_SDECL Parse *pParse; @@ -119,9 +120,9 @@ typedef union { #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse #define YYNSTATE 581 -#define YYNRULE 311 -#define YYERRORSYMBOL 146 -#define YYERRSYMDT yy493 +#define YYNRULE 309 +#define YYERRORSYMBOL 139 +#define YYERRSYMDT yy495 #define YYFALLBACK 1 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) @@ -175,487 +176,411 @@ typedef union { ** yy_default[] Default action for each state. */ static const YYACTIONTYPE yy_action[] = { - /* 0 */ 286, 584, 113, 140, 142, 138, 144, 581, 150, 152, - /* 10 */ 154, 156, 158, 160, 162, 164, 166, 168, 3, 577, - /* 20 */ 740, 170, 178, 150, 152, 154, 156, 158, 160, 162, - /* 30 */ 164, 166, 168, 158, 160, 162, 164, 166, 168, 135, - /* 40 */ 97, 171, 181, 186, 191, 180, 185, 146, 148, 140, - /* 50 */ 142, 138, 144, 51, 150, 152, 154, 156, 158, 160, - /* 60 */ 162, 164, 166, 168, 16, 17, 18, 114, 7, 248, - /* 70 */ 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, - /* 80 */ 13, 37, 362, 40, 59, 67, 69, 326, 357, 170, - /* 90 */ 6, 5, 331, 95, 364, 359, 25, 374, 258, 893, - /* 100 */ 1, 580, 514, 13, 4, 575, 33, 135, 97, 171, - /* 110 */ 181, 186, 191, 180, 185, 146, 148, 140, 142, 138, - /* 120 */ 144, 9, 150, 152, 154, 156, 158, 160, 162, 164, - /* 130 */ 166, 168, 374, 136, 592, 80, 112, 99, 269, 34, - /* 140 */ 32, 33, 132, 373, 115, 14, 15, 378, 333, 99, - /* 150 */ 380, 387, 392, 13, 367, 370, 194, 170, 78, 500, - /* 160 */ 525, 315, 395, 369, 375, 408, 10, 98, 14, 15, - /* 170 */ 78, 200, 286, 864, 113, 135, 97, 171, 181, 186, - /* 180 */ 191, 180, 185, 146, 148, 140, 142, 138, 144, 80, - /* 190 */ 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, - /* 200 */ 104, 105, 106, 661, 496, 376, 374, 170, 467, 13, - /* 210 */ 2, 28, 237, 4, 409, 33, 3, 577, 14, 15, - /* 220 */ 51, 132, 133, 115, 241, 135, 97, 171, 181, 186, - /* 230 */ 191, 180, 185, 146, 148, 140, 142, 138, 144, 114, - /* 240 */ 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, - /* 250 */ 40, 59, 67, 69, 326, 357, 136, 44, 45, 501, - /* 260 */ 473, 463, 359, 36, 361, 130, 128, 660, 275, 31, - /* 270 */ 84, 99, 356, 378, 14, 15, 380, 387, 392, 52, - /* 280 */ 170, 117, 122, 123, 113, 541, 369, 643, 395, 348, - /* 290 */ 98, 54, 78, 200, 302, 57, 58, 819, 135, 97, - /* 300 */ 171, 181, 186, 191, 180, 185, 146, 148, 140, 142, - /* 310 */ 138, 144, 861, 150, 152, 154, 156, 158, 160, 162, - /* 320 */ 164, 166, 168, 104, 105, 106, 817, 80, 48, 316, - /* 330 */ 162, 164, 166, 168, 319, 277, 12, 49, 99, 303, - /* 340 */ 283, 818, 99, 124, 304, 99, 241, 172, 593, 114, - /* 350 */ 50, 193, 46, 378, 170, 13, 380, 387, 392, 78, - /* 360 */ 260, 276, 47, 78, 200, 64, 78, 260, 395, 174, - /* 370 */ 175, 221, 135, 97, 171, 181, 186, 191, 180, 185, - /* 380 */ 146, 148, 140, 142, 138, 144, 199, 150, 152, 154, - /* 390 */ 156, 158, 160, 162, 164, 166, 168, 173, 252, 261, - /* 400 */ 120, 122, 123, 212, 170, 268, 254, 130, 128, 288, - /* 410 */ 590, 176, 246, 187, 192, 414, 195, 241, 197, 198, - /* 420 */ 14, 15, 135, 97, 171, 181, 186, 191, 180, 185, - /* 430 */ 146, 148, 140, 142, 138, 144, 433, 150, 152, 154, - /* 440 */ 156, 158, 160, 162, 164, 166, 168, 311, 99, 707, - /* 450 */ 99, 422, 708, 417, 275, 81, 318, 598, 99, 219, - /* 460 */ 13, 231, 124, 13, 176, 48, 187, 192, 20, 78, - /* 470 */ 317, 78, 214, 195, 49, 197, 198, 462, 170, 78, - /* 480 */ 200, 116, 27, 13, 410, 113, 591, 50, 80, 225, - /* 490 */ 195, 11, 197, 198, 506, 235, 135, 97, 171, 181, - /* 500 */ 186, 191, 180, 185, 146, 148, 140, 142, 138, 144, - /* 510 */ 80, 150, 152, 154, 156, 158, 160, 162, 164, 166, - /* 520 */ 168, 277, 215, 324, 606, 14, 15, 301, 14, 15, - /* 530 */ 512, 13, 508, 240, 196, 486, 195, 685, 197, 198, - /* 540 */ 22, 834, 445, 331, 462, 170, 444, 276, 14, 15, - /* 550 */ 114, 468, 278, 394, 599, 280, 470, 288, 446, 680, - /* 560 */ 13, 321, 404, 135, 97, 171, 181, 186, 191, 180, - /* 570 */ 185, 146, 148, 140, 142, 138, 144, 80, 150, 152, - /* 580 */ 154, 156, 158, 160, 162, 164, 166, 168, 74, 99, - /* 590 */ 540, 366, 73, 99, 352, 289, 14, 15, 176, 333, - /* 600 */ 187, 192, 486, 869, 359, 273, 283, 542, 543, 867, - /* 610 */ 78, 500, 510, 170, 78, 323, 682, 176, 472, 187, - /* 620 */ 192, 746, 118, 470, 119, 14, 15, 195, 346, 197, - /* 630 */ 198, 135, 97, 171, 181, 186, 191, 180, 185, 146, - /* 640 */ 148, 140, 142, 138, 144, 99, 150, 152, 154, 156, - /* 650 */ 158, 160, 162, 164, 166, 168, 532, 334, 341, 343, - /* 660 */ 841, 39, 195, 170, 197, 198, 78, 94, 124, 356, - /* 670 */ 271, 353, 439, 441, 440, 544, 883, 428, 72, 862, - /* 680 */ 288, 135, 97, 171, 181, 186, 191, 180, 185, 146, - /* 690 */ 148, 140, 142, 138, 144, 13, 150, 152, 154, 156, - /* 700 */ 158, 160, 162, 164, 166, 168, 195, 99, 197, 198, - /* 710 */ 406, 330, 195, 170, 197, 198, 568, 405, 306, 195, - /* 720 */ 42, 197, 198, 65, 195, 539, 197, 198, 78, 96, - /* 730 */ 66, 135, 97, 171, 181, 186, 191, 180, 185, 146, - /* 740 */ 148, 140, 142, 138, 144, 885, 150, 152, 154, 156, - /* 750 */ 158, 160, 162, 164, 166, 168, 99, 740, 99, 298, - /* 760 */ 14, 15, 272, 170, 13, 74, 572, 86, 600, 73, - /* 770 */ 126, 127, 614, 709, 309, 478, 24, 78, 247, 78, - /* 780 */ 111, 135, 97, 171, 181, 186, 191, 180, 185, 146, - /* 790 */ 148, 140, 142, 138, 144, 99, 150, 152, 154, 156, - /* 800 */ 158, 160, 162, 164, 166, 168, 99, 238, 113, 239, - /* 810 */ 295, 26, 296, 170, 338, 337, 78, 137, 294, 320, - /* 820 */ 347, 239, 348, 390, 211, 348, 30, 78, 139, 14, - /* 830 */ 15, 135, 189, 171, 181, 186, 191, 180, 185, 146, - /* 840 */ 148, 140, 142, 138, 144, 99, 150, 152, 154, 156, - /* 850 */ 158, 160, 162, 164, 166, 168, 99, 80, 99, 372, - /* 860 */ 399, 442, 348, 170, 298, 243, 78, 141, 363, 601, - /* 870 */ 428, 437, 438, 114, 411, 269, 605, 78, 143, 78, - /* 880 */ 145, 448, 97, 171, 181, 186, 191, 180, 185, 146, - /* 890 */ 148, 140, 142, 138, 144, 99, 150, 152, 154, 156, - /* 900 */ 158, 160, 162, 164, 166, 168, 99, 80, 99, 430, - /* 910 */ 99, 296, 555, 170, 413, 856, 78, 147, 672, 457, - /* 920 */ 352, 348, 298, 443, 465, 45, 35, 78, 149, 78, - /* 930 */ 151, 78, 153, 171, 181, 186, 191, 180, 185, 146, - /* 940 */ 148, 140, 142, 138, 144, 99, 150, 152, 154, 156, - /* 950 */ 158, 160, 162, 164, 166, 168, 99, 459, 99, 29, - /* 960 */ 79, 464, 183, 483, 71, 339, 78, 155, 709, 421, - /* 970 */ 428, 79, 109, 99, 491, 71, 296, 78, 157, 78, - /* 980 */ 159, 490, 243, 109, 99, 340, 99, 449, 857, 223, - /* 990 */ 99, 460, 182, 709, 78, 161, 99, 349, 827, 136, - /* 1000 */ 223, 99, 80, 201, 99, 78, 163, 78, 165, 507, - /* 1010 */ 136, 78, 167, 42, 201, 38, 493, 78, 169, 569, - /* 1020 */ 207, 205, 78, 177, 674, 78, 179, 477, 203, 76, - /* 1030 */ 77, 207, 205, 98, 99, 84, 99, 42, 336, 203, - /* 1040 */ 76, 77, 99, 43, 98, 41, 428, 79, 494, 80, - /* 1050 */ 428, 71, 84, 99, 352, 78, 188, 78, 190, 109, - /* 1060 */ 499, 428, 497, 78, 202, 60, 104, 105, 106, 107, - /* 1070 */ 108, 209, 213, 99, 78, 204, 223, 104, 105, 106, - /* 1080 */ 107, 108, 209, 213, 820, 509, 136, 53, 383, 511, - /* 1090 */ 201, 99, 56, 61, 78, 206, 55, 428, 428, 889, - /* 1100 */ 513, 99, 243, 99, 352, 99, 79, 207, 205, 312, - /* 1110 */ 71, 99, 78, 208, 483, 203, 76, 77, 109, 533, - /* 1120 */ 98, 497, 78, 220, 78, 222, 78, 232, 84, 99, - /* 1130 */ 428, 353, 78, 234, 352, 223, 517, 521, 389, 99, - /* 1140 */ 62, 530, 99, 64, 63, 136, 68, 529, 70, 201, - /* 1150 */ 78, 236, 352, 104, 105, 106, 107, 108, 209, 213, - /* 1160 */ 78, 249, 99, 78, 265, 877, 207, 205, 398, 527, - /* 1170 */ 99, 615, 616, 313, 203, 76, 77, 99, 523, 98, - /* 1180 */ 80, 353, 8, 78, 270, 99, 456, 19, 21, 23, - /* 1190 */ 412, 78, 300, 75, 78, 310, 82, 84, 78, 365, - /* 1200 */ 563, 83, 547, 99, 87, 553, 78, 393, 85, 557, - /* 1210 */ 99, 353, 104, 105, 106, 107, 108, 209, 213, 99, - /* 1220 */ 269, 536, 99, 467, 78, 434, 88, 266, 534, 353, - /* 1230 */ 560, 78, 481, 566, 264, 89, 250, 90, 93, 91, - /* 1240 */ 78, 485, 101, 78, 498, 92, 100, 102, 103, 110, - /* 1250 */ 131, 121, 134, 125, 129, 168, 184, 242, 686, 687, - /* 1260 */ 688, 210, 233, 218, 224, 216, 227, 226, 217, 229, - /* 1270 */ 228, 230, 243, 251, 515, 519, 463, 245, 253, 244, - /* 1280 */ 505, 257, 255, 256, 258, 84, 259, 262, 263, 239, - /* 1290 */ 267, 279, 274, 281, 282, 299, 285, 292, 284, 287, - /* 1300 */ 290, 293, 297, 305, 314, 291, 307, 322, 308, 325, - /* 1310 */ 327, 345, 329, 328, 332, 350, 354, 330, 358, 335, - /* 1320 */ 342, 379, 381, 382, 344, 351, 368, 385, 355, 371, - /* 1330 */ 388, 360, 396, 397, 400, 401, 415, 54, 416, 386, - /* 1340 */ 384, 391, 418, 402, 407, 419, 377, 420, 423, 424, - /* 1350 */ 403, 426, 425, 427, 429, 435, 431, 849, 436, 854, - /* 1360 */ 432, 855, 450, 447, 451, 452, 454, 453, 825, 455, - /* 1370 */ 458, 826, 469, 461, 466, 747, 748, 848, 471, 464, - /* 1380 */ 863, 480, 474, 475, 476, 482, 865, 479, 487, 484, - /* 1390 */ 489, 488, 492, 866, 495, 868, 504, 679, 502, 681, - /* 1400 */ 833, 875, 518, 503, 516, 739, 520, 524, 522, 742, - /* 1410 */ 745, 531, 526, 835, 535, 528, 538, 537, 836, 837, - /* 1420 */ 838, 839, 545, 546, 840, 550, 876, 556, 551, 878, - /* 1430 */ 548, 549, 554, 879, 559, 882, 884, 562, 886, 561, - /* 1440 */ 552, 558, 564, 567, 570, 565, 571, 887, 576, 574, - /* 1450 */ 573, 888, 578, 559, 559, 579, + /* 0 */ 287, 67, 291, 69, 150, 168, 206, 431, 61, 61, + /* 10 */ 61, 61, 66, 63, 63, 63, 63, 64, 64, 65, + /* 20 */ 65, 65, 66, 441, 322, 164, 444, 450, 68, 63, + /* 30 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 64, + /* 40 */ 64, 65, 65, 65, 66, 60, 58, 295, 454, 455, + /* 50 */ 451, 451, 62, 62, 61, 61, 61, 61, 513, 63, + /* 60 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 287, + /* 70 */ 318, 67, 431, 69, 150, 79, 160, 114, 224, 314, + /* 80 */ 229, 315, 172, 249, 891, 120, 580, 515, 518, 2, + /* 90 */ 250, 566, 422, 35, 223, 444, 450, 528, 20, 57, + /* 100 */ 384, 381, 63, 63, 63, 63, 64, 64, 65, 65, + /* 110 */ 65, 66, 287, 473, 60, 58, 295, 454, 455, 451, + /* 120 */ 451, 62, 62, 61, 61, 61, 61, 389, 63, 63, + /* 130 */ 63, 63, 64, 64, 65, 65, 65, 66, 444, 450, + /* 140 */ 91, 311, 385, 480, 236, 383, 269, 204, 2, 83, + /* 150 */ 581, 384, 381, 470, 196, 439, 209, 60, 58, 295, + /* 160 */ 454, 455, 451, 451, 62, 62, 61, 61, 61, 61, + /* 170 */ 170, 63, 63, 63, 63, 64, 64, 65, 65, 65, + /* 180 */ 66, 287, 486, 439, 209, 132, 109, 270, 423, 443, + /* 190 */ 402, 281, 390, 391, 441, 517, 164, 318, 507, 67, + /* 200 */ 526, 69, 150, 562, 423, 143, 516, 444, 450, 145, + /* 210 */ 146, 578, 882, 373, 882, 511, 171, 156, 514, 422, + /* 220 */ 40, 337, 426, 19, 287, 140, 60, 58, 295, 454, + /* 230 */ 455, 451, 451, 62, 62, 61, 61, 61, 61, 380, + /* 240 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, + /* 250 */ 444, 450, 575, 404, 405, 428, 428, 428, 329, 332, + /* 260 */ 240, 545, 67, 468, 69, 150, 271, 287, 291, 60, + /* 270 */ 58, 295, 454, 455, 451, 451, 62, 62, 61, 61, + /* 280 */ 61, 61, 124, 63, 63, 63, 63, 64, 64, 65, + /* 290 */ 65, 65, 66, 444, 450, 401, 510, 389, 290, 544, + /* 300 */ 65, 65, 65, 66, 507, 389, 542, 405, 443, 294, + /* 310 */ 434, 435, 60, 58, 295, 454, 455, 451, 451, 62, + /* 320 */ 62, 61, 61, 61, 61, 206, 63, 63, 63, 63, + /* 330 */ 64, 64, 65, 65, 65, 66, 519, 514, 366, 287, + /* 340 */ 75, 426, 148, 490, 224, 314, 229, 315, 172, 249, + /* 350 */ 367, 265, 264, 1, 574, 286, 250, 389, 416, 445, + /* 360 */ 446, 206, 390, 391, 177, 444, 450, 340, 343, 344, + /* 370 */ 390, 391, 208, 357, 428, 428, 428, 360, 168, 345, + /* 380 */ 431, 448, 449, 78, 60, 58, 295, 454, 455, 451, + /* 390 */ 451, 62, 62, 61, 61, 61, 61, 476, 63, 63, + /* 400 */ 63, 63, 64, 64, 65, 65, 65, 66, 287, 447, + /* 410 */ 177, 561, 493, 340, 343, 344, 21, 318, 518, 318, + /* 420 */ 431, 318, 390, 391, 318, 345, 475, 400, 20, 563, + /* 430 */ 564, 489, 151, 177, 444, 450, 340, 343, 344, 422, + /* 440 */ 34, 422, 34, 422, 34, 431, 422, 34, 345, 192, + /* 450 */ 237, 147, 527, 60, 58, 295, 454, 455, 451, 451, + /* 460 */ 62, 62, 61, 61, 61, 61, 423, 63, 63, 63, + /* 470 */ 63, 64, 64, 65, 65, 65, 66, 287, 230, 348, + /* 480 */ 408, 512, 298, 423, 334, 431, 318, 206, 318, 296, + /* 490 */ 318, 208, 409, 154, 465, 9, 465, 458, 464, 389, + /* 500 */ 374, 465, 173, 444, 450, 410, 173, 406, 422, 40, + /* 510 */ 422, 48, 422, 48, 321, 434, 435, 407, 324, 475, + /* 520 */ 457, 457, 60, 58, 295, 454, 455, 451, 451, 62, + /* 530 */ 62, 61, 61, 61, 61, 459, 63, 63, 63, 63, + /* 540 */ 64, 64, 65, 65, 65, 66, 287, 318, 499, 238, + /* 550 */ 253, 480, 389, 338, 408, 149, 421, 306, 289, 307, + /* 560 */ 420, 389, 289, 389, 390, 391, 409, 250, 500, 422, + /* 570 */ 27, 155, 444, 450, 431, 422, 3, 208, 539, 410, + /* 580 */ 335, 328, 578, 881, 324, 881, 457, 457, 484, 423, + /* 590 */ 242, 60, 58, 295, 454, 455, 451, 451, 62, 62, + /* 600 */ 61, 61, 61, 61, 255, 63, 63, 63, 63, 64, + /* 610 */ 64, 65, 65, 65, 66, 287, 368, 390, 391, 488, + /* 620 */ 90, 299, 324, 575, 457, 457, 390, 391, 390, 391, + /* 630 */ 318, 525, 494, 318, 392, 393, 394, 518, 524, 431, + /* 640 */ 241, 444, 450, 183, 477, 181, 571, 20, 324, 297, + /* 650 */ 457, 457, 422, 28, 541, 422, 23, 505, 287, 339, + /* 660 */ 60, 58, 295, 454, 455, 451, 451, 62, 62, 61, + /* 670 */ 61, 61, 61, 318, 63, 63, 63, 63, 64, 64, + /* 680 */ 65, 65, 65, 66, 444, 450, 421, 535, 354, 535, + /* 690 */ 420, 259, 300, 505, 816, 422, 32, 74, 505, 76, + /* 700 */ 188, 287, 505, 60, 58, 295, 454, 455, 451, 451, + /* 710 */ 62, 62, 61, 61, 61, 61, 318, 63, 63, 63, + /* 720 */ 63, 64, 64, 65, 65, 65, 66, 444, 450, 174, + /* 730 */ 175, 176, 377, 216, 423, 480, 248, 301, 422, 53, + /* 740 */ 505, 505, 259, 259, 287, 259, 60, 70, 295, 454, + /* 750 */ 455, 451, 451, 62, 62, 61, 61, 61, 61, 365, + /* 760 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, + /* 770 */ 444, 450, 247, 319, 244, 302, 304, 248, 167, 156, + /* 780 */ 361, 248, 379, 260, 552, 259, 554, 287, 259, 219, + /* 790 */ 58, 295, 454, 455, 451, 451, 62, 62, 61, 61, + /* 800 */ 61, 61, 318, 63, 63, 63, 63, 64, 64, 65, + /* 810 */ 65, 65, 66, 444, 450, 484, 432, 484, 22, 248, + /* 820 */ 248, 207, 388, 364, 422, 24, 555, 364, 54, 556, + /* 830 */ 309, 119, 437, 437, 295, 454, 455, 451, 451, 62, + /* 840 */ 62, 61, 61, 61, 61, 318, 63, 63, 63, 63, + /* 850 */ 64, 64, 65, 65, 65, 66, 71, 325, 318, 4, + /* 860 */ 318, 537, 318, 293, 259, 536, 259, 422, 51, 318, + /* 870 */ 161, 320, 71, 325, 318, 4, 355, 356, 305, 293, + /* 880 */ 422, 96, 422, 93, 422, 98, 225, 320, 327, 217, + /* 890 */ 115, 422, 99, 218, 190, 318, 422, 110, 226, 443, + /* 900 */ 318, 259, 318, 417, 327, 272, 427, 372, 318, 5, + /* 910 */ 418, 318, 413, 414, 330, 443, 318, 422, 111, 73, + /* 920 */ 72, 197, 422, 16, 422, 97, 152, 71, 316, 317, + /* 930 */ 422, 33, 426, 422, 94, 73, 72, 487, 422, 52, + /* 940 */ 318, 200, 274, 71, 316, 317, 71, 325, 426, 4, + /* 950 */ 318, 206, 318, 293, 318, 423, 463, 318, 12, 179, + /* 960 */ 423, 320, 422, 112, 615, 428, 428, 428, 429, 430, + /* 970 */ 11, 323, 422, 113, 422, 25, 422, 36, 327, 422, + /* 980 */ 37, 428, 428, 428, 429, 430, 11, 498, 497, 443, + /* 990 */ 158, 18, 318, 423, 81, 220, 221, 222, 101, 182, + /* 1000 */ 482, 318, 169, 318, 491, 318, 12, 318, 440, 73, + /* 1010 */ 72, 202, 466, 276, 422, 26, 474, 71, 316, 317, + /* 1020 */ 277, 318, 426, 422, 38, 422, 39, 422, 41, 422, + /* 1030 */ 42, 318, 199, 423, 544, 503, 252, 124, 124, 198, + /* 1040 */ 318, 479, 201, 422, 43, 318, 483, 452, 318, 246, + /* 1050 */ 347, 318, 124, 422, 29, 428, 428, 428, 429, 430, + /* 1060 */ 11, 495, 422, 30, 496, 576, 318, 422, 44, 501, + /* 1070 */ 422, 45, 318, 422, 46, 520, 318, 533, 534, 318, + /* 1080 */ 540, 318, 124, 502, 185, 371, 273, 264, 422, 47, + /* 1090 */ 254, 288, 256, 257, 422, 31, 206, 258, 422, 10, + /* 1100 */ 352, 422, 49, 422, 50, 577, 548, 549, 169, 88, + /* 1110 */ 559, 263, 88, 359, 362, 573, 363, 285, 266, 267, + /* 1120 */ 376, 268, 551, 560, 275, 375, 278, 279, 231, 570, + /* 1130 */ 227, 142, 398, 326, 469, 436, 438, 472, 494, 159, + /* 1140 */ 504, 547, 506, 558, 387, 395, 342, 396, 397, 8, + /* 1150 */ 312, 313, 292, 416, 81, 403, 333, 232, 411, 80, + /* 1160 */ 228, 331, 419, 415, 56, 77, 210, 412, 239, 166, + /* 1170 */ 467, 211, 470, 471, 121, 82, 102, 336, 349, 282, + /* 1180 */ 508, 424, 521, 522, 529, 523, 351, 180, 233, 509, + /* 1190 */ 234, 184, 235, 283, 531, 425, 353, 85, 186, 117, + /* 1200 */ 358, 128, 369, 370, 308, 567, 568, 243, 543, 481, + /* 1210 */ 245, 212, 485, 189, 386, 569, 572, 129, 95, 214, + /* 1220 */ 215, 399, 550, 116, 130, 205, 55, 616, 131, 617, + /* 1230 */ 162, 163, 433, 134, 59, 213, 442, 557, 137, 100, + /* 1240 */ 138, 139, 453, 456, 460, 153, 165, 461, 261, 462, + /* 1250 */ 6, 122, 13, 12, 7, 532, 478, 123, 157, 492, + /* 1260 */ 103, 341, 89, 251, 104, 84, 105, 346, 226, 178, + /* 1270 */ 350, 141, 530, 125, 303, 169, 262, 187, 106, 126, + /* 1280 */ 538, 284, 546, 127, 191, 14, 194, 92, 17, 86, + /* 1290 */ 87, 193, 195, 133, 108, 553, 135, 565, 136, 15, + /* 1300 */ 107, 203, 378, 280, 144, 382, 558, 118, 579, 558, + /* 1310 */ 558, 310, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 28, 11, 30, 77, 78, 79, 80, 0, 82, 83, - /* 10 */ 84, 85, 86, 87, 88, 89, 90, 91, 11, 12, - /* 20 */ 11, 49, 81, 82, 83, 84, 85, 86, 87, 88, - /* 30 */ 89, 90, 91, 86, 87, 88, 89, 90, 91, 67, - /* 40 */ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - /* 50 */ 78, 79, 80, 69, 82, 83, 84, 85, 86, 87, - /* 60 */ 88, 89, 90, 91, 17, 18, 19, 95, 11, 29, - /* 70 */ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - /* 80 */ 30, 97, 98, 99, 100, 101, 102, 103, 104, 49, - /* 90 */ 150, 151, 50, 53, 26, 111, 156, 155, 30, 147, - /* 100 */ 148, 149, 162, 30, 152, 163, 164, 67, 68, 69, - /* 110 */ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - /* 120 */ 80, 153, 82, 83, 84, 85, 86, 87, 88, 89, - /* 130 */ 90, 91, 155, 65, 11, 195, 28, 155, 129, 165, - /* 140 */ 163, 164, 168, 169, 170, 95, 96, 97, 106, 155, - /* 150 */ 100, 101, 102, 30, 86, 87, 162, 49, 176, 177, - /* 160 */ 220, 88, 112, 95, 187, 188, 154, 99, 95, 96, - /* 170 */ 176, 177, 28, 21, 30, 67, 68, 69, 70, 71, - /* 180 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 195, - /* 190 */ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - /* 200 */ 132, 133, 134, 27, 222, 29, 155, 49, 56, 30, - /* 210 */ 149, 160, 218, 152, 163, 164, 11, 12, 95, 96, - /* 220 */ 69, 168, 169, 170, 230, 67, 68, 69, 70, 71, - /* 230 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 95, - /* 240 */ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - /* 250 */ 99, 100, 101, 102, 103, 104, 65, 192, 193, 107, - /* 260 */ 108, 109, 111, 174, 175, 86, 87, 27, 29, 29, - /* 270 */ 118, 155, 183, 97, 95, 96, 100, 101, 102, 99, - /* 280 */ 49, 171, 172, 173, 30, 106, 95, 27, 112, 29, - /* 290 */ 99, 111, 176, 177, 162, 17, 18, 139, 67, 68, - /* 300 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 310 */ 79, 80, 15, 82, 83, 84, 85, 86, 87, 88, - /* 320 */ 89, 90, 91, 132, 133, 134, 21, 195, 22, 27, - /* 330 */ 88, 89, 90, 91, 218, 96, 155, 31, 155, 207, - /* 340 */ 208, 21, 155, 233, 212, 155, 230, 49, 11, 95, - /* 350 */ 44, 26, 46, 97, 49, 30, 100, 101, 102, 176, - /* 360 */ 177, 122, 56, 176, 177, 105, 176, 177, 112, 71, - /* 370 */ 72, 140, 67, 68, 69, 70, 71, 72, 73, 74, - /* 380 */ 75, 76, 77, 78, 79, 80, 27, 82, 83, 84, - /* 390 */ 85, 86, 87, 88, 89, 90, 91, 99, 215, 216, - /* 400 */ 171, 172, 173, 27, 49, 218, 216, 86, 87, 168, - /* 410 */ 11, 223, 224, 225, 226, 24, 114, 230, 116, 117, - /* 420 */ 95, 96, 67, 68, 69, 70, 71, 72, 73, 74, - /* 430 */ 75, 76, 77, 78, 79, 80, 139, 82, 83, 84, - /* 440 */ 85, 86, 87, 88, 89, 90, 91, 206, 155, 27, - /* 450 */ 155, 60, 27, 62, 29, 162, 27, 11, 155, 139, - /* 460 */ 30, 141, 233, 30, 223, 22, 225, 226, 154, 176, - /* 470 */ 177, 176, 177, 114, 31, 116, 117, 162, 49, 176, - /* 480 */ 177, 26, 26, 30, 28, 30, 11, 44, 195, 46, - /* 490 */ 114, 16, 116, 117, 24, 140, 67, 68, 69, 70, - /* 500 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 510 */ 195, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 520 */ 91, 96, 227, 27, 11, 95, 96, 26, 95, 96, - /* 530 */ 60, 30, 62, 230, 115, 220, 114, 118, 116, 117, - /* 540 */ 154, 11, 32, 50, 162, 49, 36, 122, 95, 96, - /* 550 */ 95, 236, 122, 178, 11, 122, 241, 168, 48, 11, - /* 560 */ 30, 88, 69, 67, 68, 69, 70, 71, 72, 73, - /* 570 */ 74, 75, 76, 77, 78, 79, 80, 195, 82, 83, - /* 580 */ 84, 85, 86, 87, 88, 89, 90, 91, 115, 155, - /* 590 */ 155, 27, 119, 155, 155, 206, 95, 96, 223, 106, - /* 600 */ 225, 226, 220, 11, 111, 207, 208, 172, 173, 11, - /* 610 */ 176, 177, 142, 49, 176, 177, 11, 223, 236, 225, - /* 620 */ 226, 11, 27, 241, 29, 95, 96, 114, 189, 116, - /* 630 */ 117, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 640 */ 76, 77, 78, 79, 80, 155, 82, 83, 84, 85, - /* 650 */ 86, 87, 88, 89, 90, 91, 222, 107, 108, 109, - /* 660 */ 11, 175, 114, 49, 116, 117, 176, 177, 233, 183, - /* 670 */ 29, 232, 107, 108, 109, 26, 11, 155, 26, 15, - /* 680 */ 168, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 690 */ 76, 77, 78, 79, 80, 30, 82, 83, 84, 85, - /* 700 */ 86, 87, 88, 89, 90, 91, 114, 155, 116, 117, - /* 710 */ 183, 184, 114, 49, 116, 117, 194, 190, 206, 114, - /* 720 */ 106, 116, 117, 34, 114, 76, 116, 117, 176, 177, - /* 730 */ 41, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 740 */ 76, 77, 78, 79, 80, 11, 82, 83, 84, 85, - /* 750 */ 86, 87, 88, 89, 90, 91, 155, 11, 155, 155, - /* 760 */ 95, 96, 121, 49, 30, 115, 244, 198, 11, 119, - /* 770 */ 132, 133, 120, 28, 205, 29, 154, 176, 177, 176, - /* 780 */ 177, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 790 */ 76, 77, 78, 79, 80, 155, 82, 83, 84, 85, - /* 800 */ 86, 87, 88, 89, 90, 91, 155, 27, 30, 29, - /* 810 */ 27, 157, 29, 49, 98, 99, 176, 177, 214, 27, - /* 820 */ 27, 29, 29, 27, 162, 29, 27, 176, 177, 95, - /* 830 */ 96, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 840 */ 76, 77, 78, 79, 80, 155, 82, 83, 84, 85, - /* 850 */ 86, 87, 88, 89, 90, 91, 155, 195, 155, 167, - /* 860 */ 27, 52, 29, 49, 155, 120, 176, 177, 176, 11, - /* 870 */ 155, 58, 59, 95, 162, 129, 11, 176, 177, 176, - /* 880 */ 177, 25, 68, 69, 70, 71, 72, 73, 74, 75, - /* 890 */ 76, 77, 78, 79, 80, 155, 82, 83, 84, 85, - /* 900 */ 86, 87, 88, 89, 90, 91, 155, 195, 155, 194, - /* 910 */ 155, 29, 134, 49, 158, 106, 176, 177, 11, 27, - /* 920 */ 155, 29, 155, 214, 192, 193, 166, 176, 177, 176, - /* 930 */ 177, 176, 177, 69, 70, 71, 72, 73, 74, 75, - /* 940 */ 76, 77, 78, 79, 80, 155, 82, 83, 84, 85, - /* 950 */ 86, 87, 88, 89, 90, 91, 155, 101, 155, 161, - /* 960 */ 26, 67, 69, 155, 30, 37, 176, 177, 106, 162, - /* 970 */ 155, 26, 38, 155, 27, 30, 29, 176, 177, 176, - /* 980 */ 177, 214, 120, 38, 155, 57, 155, 231, 106, 55, - /* 990 */ 155, 235, 99, 11, 176, 177, 155, 232, 142, 65, - /* 1000 */ 55, 155, 195, 69, 155, 176, 177, 176, 177, 194, - /* 1010 */ 65, 176, 177, 106, 69, 155, 162, 176, 177, 64, - /* 1020 */ 86, 87, 176, 177, 130, 176, 177, 219, 94, 95, - /* 1030 */ 96, 86, 87, 99, 155, 118, 155, 106, 110, 94, - /* 1040 */ 95, 96, 155, 39, 99, 178, 155, 26, 131, 195, - /* 1050 */ 155, 30, 118, 155, 155, 176, 177, 176, 177, 38, - /* 1060 */ 27, 155, 29, 176, 177, 51, 132, 133, 134, 135, - /* 1070 */ 136, 137, 138, 155, 176, 177, 55, 132, 133, 134, - /* 1080 */ 135, 136, 137, 138, 139, 194, 65, 178, 189, 194, - /* 1090 */ 69, 155, 47, 179, 176, 177, 186, 155, 155, 144, - /* 1100 */ 194, 155, 120, 155, 155, 155, 26, 86, 87, 88, - /* 1110 */ 30, 155, 176, 177, 155, 94, 95, 96, 38, 27, - /* 1120 */ 99, 29, 176, 177, 176, 177, 176, 177, 118, 155, - /* 1130 */ 155, 232, 176, 177, 155, 55, 194, 194, 189, 155, - /* 1140 */ 178, 131, 155, 105, 180, 65, 178, 162, 26, 69, - /* 1150 */ 176, 177, 155, 132, 133, 134, 135, 136, 137, 138, - /* 1160 */ 176, 177, 155, 176, 177, 11, 86, 87, 189, 194, - /* 1170 */ 155, 120, 120, 155, 94, 95, 96, 155, 219, 99, - /* 1180 */ 195, 232, 15, 176, 177, 155, 189, 20, 21, 22, - /* 1190 */ 23, 176, 177, 197, 176, 177, 196, 118, 176, 177, - /* 1200 */ 33, 195, 35, 155, 199, 51, 176, 177, 197, 42, - /* 1210 */ 155, 232, 132, 133, 134, 135, 136, 137, 138, 155, - /* 1220 */ 129, 54, 155, 56, 176, 177, 200, 126, 61, 232, - /* 1230 */ 63, 176, 177, 66, 127, 201, 124, 202, 128, 203, - /* 1240 */ 176, 177, 155, 176, 177, 204, 120, 120, 155, 26, - /* 1250 */ 168, 27, 27, 234, 234, 91, 99, 155, 118, 118, - /* 1260 */ 118, 26, 139, 21, 26, 228, 193, 27, 229, 155, - /* 1270 */ 29, 27, 120, 125, 107, 108, 109, 159, 29, 155, - /* 1280 */ 113, 104, 217, 179, 30, 118, 167, 217, 179, 29, - /* 1290 */ 125, 155, 209, 155, 122, 106, 159, 123, 155, 155, - /* 1300 */ 210, 26, 155, 27, 120, 211, 210, 27, 211, 178, - /* 1310 */ 155, 26, 182, 181, 155, 217, 217, 184, 167, 185, - /* 1320 */ 185, 155, 51, 26, 185, 179, 176, 27, 179, 176, - /* 1330 */ 26, 186, 51, 26, 103, 155, 155, 111, 159, 178, - /* 1340 */ 180, 178, 155, 181, 188, 159, 188, 28, 155, 159, - /* 1350 */ 182, 238, 237, 106, 159, 45, 239, 15, 43, 106, - /* 1360 */ 240, 106, 142, 52, 155, 159, 155, 106, 11, 26, - /* 1370 */ 178, 142, 21, 15, 191, 130, 130, 11, 11, 67, - /* 1380 */ 21, 76, 191, 155, 110, 200, 11, 155, 130, 76, - /* 1390 */ 26, 155, 221, 11, 26, 11, 200, 11, 121, 11, - /* 1400 */ 11, 11, 200, 155, 121, 11, 191, 200, 110, 11, - /* 1410 */ 11, 26, 130, 11, 155, 221, 159, 155, 11, 11, - /* 1420 */ 11, 11, 155, 27, 11, 28, 11, 40, 155, 11, - /* 1430 */ 242, 168, 168, 11, 155, 11, 11, 159, 11, 155, - /* 1440 */ 243, 242, 155, 24, 143, 159, 155, 11, 145, 245, - /* 1450 */ 144, 11, 13, 246, 246, 14, + /* 0 */ 16, 218, 16, 220, 221, 21, 111, 23, 70, 71, + /* 10 */ 72, 73, 84, 75, 76, 77, 78, 79, 80, 81, + /* 20 */ 82, 83, 84, 162, 163, 164, 42, 43, 74, 75, + /* 30 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 79, + /* 40 */ 80, 81, 82, 83, 84, 61, 62, 63, 64, 65, + /* 50 */ 66, 67, 68, 69, 70, 71, 72, 73, 170, 75, + /* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16, + /* 70 */ 148, 218, 88, 220, 221, 22, 90, 91, 92, 93, + /* 80 */ 94, 95, 96, 97, 140, 141, 142, 170, 148, 145, + /* 90 */ 104, 238, 170, 171, 154, 42, 43, 157, 158, 46, + /* 100 */ 1, 2, 75, 76, 77, 78, 79, 80, 81, 82, + /* 110 */ 83, 84, 16, 22, 61, 62, 63, 64, 65, 66, + /* 120 */ 67, 68, 69, 70, 71, 72, 73, 23, 75, 76, + /* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43, + /* 140 */ 44, 143, 144, 162, 222, 142, 14, 149, 145, 19, + /* 150 */ 0, 1, 2, 23, 156, 79, 80, 61, 62, 63, + /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + /* 170 */ 156, 75, 76, 77, 78, 79, 80, 81, 82, 83, + /* 180 */ 84, 16, 201, 79, 80, 53, 21, 55, 190, 59, + /* 190 */ 169, 159, 88, 89, 162, 163, 164, 148, 177, 218, + /* 200 */ 182, 220, 221, 99, 190, 114, 161, 42, 43, 79, + /* 210 */ 80, 19, 20, 215, 22, 170, 202, 203, 88, 170, + /* 220 */ 171, 207, 92, 19, 16, 21, 61, 62, 63, 64, + /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 241, + /* 240 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + /* 250 */ 42, 43, 60, 186, 187, 125, 126, 127, 187, 210, + /* 260 */ 211, 11, 218, 219, 220, 221, 134, 16, 16, 61, + /* 270 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + /* 280 */ 72, 73, 22, 75, 76, 77, 78, 79, 80, 81, + /* 290 */ 82, 83, 84, 42, 43, 168, 169, 23, 151, 49, + /* 300 */ 81, 82, 83, 84, 177, 23, 186, 187, 59, 165, + /* 310 */ 166, 167, 61, 62, 63, 64, 65, 66, 67, 68, + /* 320 */ 69, 70, 71, 72, 73, 111, 75, 76, 77, 78, + /* 330 */ 79, 80, 81, 82, 83, 84, 182, 88, 124, 16, + /* 340 */ 132, 92, 22, 20, 92, 93, 94, 95, 96, 97, + /* 350 */ 100, 101, 102, 19, 244, 245, 104, 23, 98, 42, + /* 360 */ 43, 111, 88, 89, 90, 42, 43, 93, 94, 95, + /* 370 */ 88, 89, 228, 226, 125, 126, 127, 230, 21, 105, + /* 380 */ 23, 64, 65, 132, 61, 62, 63, 64, 65, 66, + /* 390 */ 67, 68, 69, 70, 71, 72, 73, 115, 75, 76, + /* 400 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 92, + /* 410 */ 90, 148, 20, 93, 94, 95, 19, 148, 148, 148, + /* 420 */ 23, 148, 88, 89, 148, 105, 22, 157, 158, 166, + /* 430 */ 167, 20, 156, 90, 42, 43, 93, 94, 95, 170, + /* 440 */ 171, 170, 171, 170, 171, 88, 170, 171, 105, 156, + /* 450 */ 148, 181, 182, 61, 62, 63, 64, 65, 66, 67, + /* 460 */ 68, 69, 70, 71, 72, 73, 190, 75, 76, 77, + /* 470 */ 78, 79, 80, 81, 82, 83, 84, 16, 191, 16, + /* 480 */ 12, 20, 213, 190, 213, 88, 148, 111, 148, 213, + /* 490 */ 148, 228, 24, 89, 225, 19, 225, 20, 225, 23, + /* 500 */ 124, 225, 43, 42, 43, 37, 43, 39, 170, 171, + /* 510 */ 170, 171, 170, 171, 165, 166, 167, 49, 107, 115, + /* 520 */ 109, 110, 61, 62, 63, 64, 65, 66, 67, 68, + /* 530 */ 69, 70, 71, 72, 73, 20, 75, 76, 77, 78, + /* 540 */ 79, 80, 81, 82, 83, 84, 16, 148, 30, 211, + /* 550 */ 20, 162, 23, 148, 12, 156, 108, 217, 99, 217, + /* 560 */ 112, 23, 99, 23, 88, 89, 24, 104, 50, 170, + /* 570 */ 171, 148, 42, 43, 23, 170, 171, 228, 18, 37, + /* 580 */ 148, 39, 19, 20, 107, 22, 109, 110, 148, 190, + /* 590 */ 201, 61, 62, 63, 64, 65, 66, 67, 68, 69, + /* 600 */ 70, 71, 72, 73, 14, 75, 76, 77, 78, 79, + /* 610 */ 80, 81, 82, 83, 84, 16, 56, 88, 89, 81, + /* 620 */ 21, 103, 107, 60, 109, 110, 88, 89, 88, 89, + /* 630 */ 148, 177, 178, 148, 7, 8, 9, 148, 184, 88, + /* 640 */ 148, 42, 43, 53, 115, 55, 157, 158, 107, 209, + /* 650 */ 109, 110, 170, 171, 94, 170, 171, 148, 16, 81, + /* 660 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + /* 670 */ 71, 72, 73, 148, 75, 76, 77, 78, 79, 80, + /* 680 */ 81, 82, 83, 84, 42, 43, 108, 100, 101, 102, + /* 690 */ 112, 148, 183, 148, 134, 170, 171, 131, 148, 133, + /* 700 */ 156, 16, 148, 61, 62, 63, 64, 65, 66, 67, + /* 710 */ 68, 69, 70, 71, 72, 73, 148, 75, 76, 77, + /* 720 */ 78, 79, 80, 81, 82, 83, 84, 42, 43, 100, + /* 730 */ 101, 102, 189, 183, 190, 162, 227, 183, 170, 171, + /* 740 */ 148, 148, 148, 148, 16, 148, 61, 62, 63, 64, + /* 750 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 215, + /* 760 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + /* 770 */ 42, 43, 227, 148, 201, 183, 183, 227, 202, 203, + /* 780 */ 236, 227, 239, 189, 189, 148, 189, 16, 148, 146, + /* 790 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + /* 800 */ 72, 73, 148, 75, 76, 77, 78, 79, 80, 81, + /* 810 */ 82, 83, 84, 42, 43, 148, 20, 148, 22, 227, + /* 820 */ 227, 193, 148, 148, 170, 171, 189, 148, 200, 189, + /* 830 */ 242, 243, 125, 126, 63, 64, 65, 66, 67, 68, + /* 840 */ 69, 70, 71, 72, 73, 148, 75, 76, 77, 78, + /* 850 */ 79, 80, 81, 82, 83, 84, 16, 17, 148, 19, + /* 860 */ 148, 25, 148, 23, 148, 29, 148, 170, 171, 148, + /* 870 */ 19, 31, 16, 17, 148, 19, 209, 41, 209, 23, + /* 880 */ 170, 171, 170, 171, 170, 171, 92, 31, 48, 214, + /* 890 */ 148, 170, 171, 214, 22, 148, 170, 171, 104, 59, + /* 900 */ 148, 148, 148, 27, 48, 189, 148, 189, 148, 192, + /* 910 */ 34, 148, 7, 8, 148, 59, 148, 170, 171, 79, + /* 920 */ 80, 156, 170, 171, 170, 171, 156, 87, 88, 89, + /* 930 */ 170, 171, 92, 170, 171, 79, 80, 81, 170, 171, + /* 940 */ 148, 19, 189, 87, 88, 89, 16, 17, 92, 19, + /* 950 */ 148, 111, 148, 23, 148, 190, 20, 148, 22, 156, + /* 960 */ 190, 31, 170, 171, 113, 125, 126, 127, 128, 129, + /* 970 */ 130, 16, 170, 171, 170, 171, 170, 171, 48, 170, + /* 980 */ 171, 125, 126, 127, 128, 129, 130, 91, 92, 59, + /* 990 */ 5, 69, 148, 190, 122, 10, 11, 12, 13, 156, + /* 1000 */ 20, 148, 22, 148, 20, 148, 22, 148, 162, 79, + /* 1010 */ 80, 26, 148, 28, 170, 171, 204, 87, 88, 89, + /* 1020 */ 35, 148, 92, 170, 171, 170, 171, 170, 171, 170, + /* 1030 */ 171, 148, 47, 190, 49, 20, 20, 22, 22, 54, + /* 1040 */ 148, 148, 57, 170, 171, 148, 148, 92, 148, 148, + /* 1050 */ 20, 148, 22, 170, 171, 125, 126, 127, 128, 129, + /* 1060 */ 130, 148, 170, 171, 179, 20, 148, 170, 171, 179, + /* 1070 */ 170, 171, 148, 170, 171, 148, 148, 51, 52, 148, + /* 1080 */ 20, 148, 22, 179, 232, 100, 101, 102, 170, 171, + /* 1090 */ 148, 106, 148, 148, 170, 171, 111, 148, 170, 171, + /* 1100 */ 233, 170, 171, 170, 171, 60, 20, 20, 22, 22, + /* 1110 */ 20, 148, 22, 148, 148, 20, 148, 22, 148, 148, + /* 1120 */ 135, 148, 148, 148, 148, 148, 148, 148, 194, 148, + /* 1130 */ 173, 192, 150, 224, 173, 229, 229, 173, 178, 6, + /* 1140 */ 173, 195, 173, 195, 147, 147, 174, 147, 147, 22, + /* 1150 */ 155, 99, 40, 98, 122, 172, 119, 195, 172, 120, + /* 1160 */ 172, 117, 172, 174, 121, 131, 223, 180, 97, 113, + /* 1170 */ 153, 212, 23, 161, 153, 99, 19, 116, 15, 175, + /* 1180 */ 161, 190, 172, 172, 153, 172, 153, 152, 196, 180, + /* 1190 */ 197, 153, 198, 175, 153, 199, 38, 131, 152, 61, + /* 1200 */ 153, 19, 153, 15, 153, 33, 153, 205, 185, 206, + /* 1210 */ 205, 212, 206, 185, 1, 153, 138, 188, 160, 212, + /* 1220 */ 212, 20, 195, 32, 188, 44, 19, 113, 188, 113, + /* 1230 */ 113, 113, 20, 185, 19, 176, 20, 195, 216, 176, + /* 1240 */ 216, 19, 92, 108, 11, 19, 22, 20, 234, 20, + /* 1250 */ 118, 19, 22, 22, 118, 235, 115, 20, 113, 20, + /* 1260 */ 19, 44, 237, 20, 19, 19, 19, 44, 104, 96, + /* 1270 */ 16, 21, 17, 99, 36, 22, 134, 99, 19, 45, + /* 1280 */ 45, 5, 1, 103, 123, 19, 14, 237, 231, 69, + /* 1290 */ 69, 114, 116, 114, 240, 17, 103, 20, 123, 19, + /* 1300 */ 14, 136, 58, 137, 19, 3, 247, 243, 4, 247, + /* 1310 */ 247, 246, }; -#define YY_SHIFT_USE_DFLT (-75) +#define YY_SHIFT_USE_DFLT (-106) +#define YY_SHIFT_MAX 382 static const short yy_shift_ofst[] = { - /* 0 */ 205, 7, -75, -75, 1167, -10, 57, -75, 47, 475, - /* 10 */ 399, 123, 337, -75, -75, -75, -75, -75, -75, 475, - /* 20 */ 446, 475, 543, 475, 757, 456, 858, 453, 240, 799, - /* 30 */ 865, 50, -75, 254, -75, -16, -75, 453, 151, -75, - /* 40 */ 931, -75, 1004, 306, -75, -75, -75, -75, -75, -75, - /* 50 */ -75, 180, 931, -75, 1045, -75, 278, -75, -75, 1014, - /* 60 */ 689, 931, 1038, -75, -75, -75, -75, 931, -75, 1122, - /* 70 */ 1080, 652, 473, -75, -75, 1080, 1051, 1052, -75, 934, - /* 80 */ -75, 302, 1079, -75, 650, -75, 641, 1091, 1101, 1107, - /* 90 */ 1112, 1110, -75, 1080, 40, 1080, 714, 1080, -75, 1126, - /* 100 */ 453, 1127, 453, -75, -75, -75, -75, -75, -75, 1223, - /* 110 */ 1080, 108, 254, -75, -75, 455, 321, 595, -75, 321, - /* 120 */ 1224, -75, -75, -75, 638, -75, -75, -75, 638, -75, - /* 130 */ -75, -75, -75, 1225, -75, 1080, -75, 814, 1080, -12, - /* 140 */ 1080, -12, 1080, -12, 1080, -12, 1080, -74, 1080, -74, - /* 150 */ 1080, -53, 1080, -53, 1080, -53, 1080, -53, 1080, 242, - /* 160 */ 1080, 242, 1080, 1164, 1080, 1164, 1080, 1164, 1080, -75, - /* 170 */ -75, 298, -75, -75, -75, -75, 1080, -59, 1080, -12, - /* 180 */ -75, 893, -75, 1157, -75, -75, -75, 1080, 764, 1080, - /* 190 */ -74, -75, 325, 934, 359, 419, 1140, 1141, 1142, -75, - /* 200 */ 714, 1080, 864, 1080, -75, 1080, -75, 1080, -75, 1235, - /* 210 */ 1079, 376, -75, 945, 158, 1123, 320, 1242, -75, 1080, - /* 220 */ 231, 1080, 714, 1238, 443, 1240, -75, 1241, 453, 1244, - /* 230 */ -75, 1080, 305, 1080, 355, 1080, 714, 780, -75, 1080, - /* 240 */ -75, -75, 1152, 453, -75, -75, -75, 864, 1080, 714, - /* 250 */ 1148, 1080, 1249, 1080, 1177, 689, -75, 1254, -75, -75, - /* 260 */ 714, 1177, 689, -75, 1080, 714, 1165, 1080, 1260, 1080, - /* 270 */ 714, -75, -75, 239, -75, -75, -75, 430, -75, 433, - /* 280 */ -75, 1172, -75, 501, 1152, 144, 453, -75, -75, 1189, - /* 290 */ 1174, -75, 1275, 453, 783, -75, 453, -75, -75, 1080, - /* 300 */ 714, 1079, 422, 425, 1276, 144, 1189, 1174, -75, 1021, - /* 310 */ -28, -75, -75, 1184, 73, -75, -75, 429, -75, 792, - /* 320 */ -75, 1280, -75, 496, 931, -75, 453, 1285, -75, 42, - /* 330 */ -75, 453, -75, 550, 928, -75, 716, -75, -75, -75, - /* 340 */ -75, 928, -75, 928, -75, 453, 793, -75, 453, 1177, - /* 350 */ 689, -75, -75, 1177, 689, -75, -75, 1254, -75, 1045, - /* 360 */ -75, -75, 68, -75, 1080, 564, -75, 191, -75, -75, - /* 370 */ 191, -75, -75, -75, -75, 176, 256, -75, 453, -75, - /* 380 */ 1271, 1297, 453, 260, 1300, 931, -75, 1304, 453, 796, - /* 390 */ 931, -75, 1080, 614, -75, 1281, 1307, 453, 833, 1231, - /* 400 */ 453, 1285, -75, 493, 1226, -75, -75, -75, -75, -75, - /* 410 */ 1079, 513, 856, 391, 453, 1152, -75, 453, 745, 1319, - /* 420 */ 1079, 548, 453, 1152, 510, 565, 1247, 453, 1152, -75, - /* 430 */ 1310, 297, 1342, 1080, 664, 1315, 813, -75, -75, 1253, - /* 440 */ 1255, 809, 453, 882, -75, -75, 1311, -75, -75, 1220, - /* 450 */ 453, 862, 1261, 453, 1343, 453, 892, 907, 1357, 1229, - /* 460 */ 1358, 152, 592, 894, 306, -75, 1245, 1246, 1351, 1366, - /* 470 */ 1367, 152, 1359, 1312, 453, 1274, 453, 746, 453, 1305, - /* 480 */ 1080, 714, 1375, 1313, 1080, 714, 1258, 453, 1364, 453, - /* 490 */ 947, -75, 917, 598, 1368, 1080, 1033, 1080, 714, 1382, - /* 500 */ 714, 1277, 453, 9, 1384, 470, 453, 1386, 453, 1388, - /* 510 */ 453, 1389, 453, 1390, 605, 1283, 453, 9, 1394, 1312, - /* 520 */ 453, 1298, 453, 746, 1398, 1282, 453, 1364, 1010, 610, - /* 530 */ 1385, 1080, 1092, 1399, 530, 1402, 453, 1152, 649, 179, - /* 540 */ 1407, 1408, 1409, 1410, 453, 1396, 1413, 1387, 254, 1397, - /* 550 */ 453, 1154, 1415, 778, 1418, 1422, -75, 1387, 453, 1424, - /* 560 */ 665, 982, 1425, 734, 982, 1427, 1419, 453, 955, 1301, - /* 570 */ 453, 1436, 1306, 1303, 453, 1440, -75, 1439, 1441, -75, - /* 580 */ -75, + /* 0 */ 99, 840, 985, -16, 840, 930, 930, 930, 274, -105, + /* 10 */ 96, 930, 930, 930, 930, 930, -46, 250, 104, 540, + /* 20 */ 551, 76, 76, 53, 165, 208, 251, 323, 392, 461, + /* 30 */ 530, 599, 642, 685, 642, 642, 642, 642, 642, 642, + /* 40 */ 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, + /* 50 */ 642, 728, 771, 771, 856, 930, 930, 930, 930, 930, + /* 60 */ 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, + /* 70 */ 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, + /* 80 */ 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, + /* 90 */ 930, 930, 930, -62, -62, -14, 27, 27, -40, 219, + /* 100 */ 463, 560, 540, 540, 540, 540, 540, 540, 540, 551, + /* 110 */ -72, -106, -106, -106, 130, 252, 468, 468, 192, 563, + /* 120 */ 150, 357, 540, 357, 540, 540, 540, 540, 540, 540, + /* 130 */ 540, 540, 540, 540, 540, 540, 540, 214, 376, -105, + /* 140 */ -105, -105, -106, -106, -106, 249, 249, 320, 343, 411, + /* 150 */ 334, 477, 515, 542, 282, 529, 476, 538, 627, 540, + /* 160 */ 540, 578, 540, 540, 397, 540, 540, 404, 540, 540, + /* 170 */ 541, 404, 540, 540, 518, 518, 518, 540, 540, 541, + /* 180 */ 540, 540, 541, 540, 836, 587, 540, 540, 541, 540, + /* 190 */ 540, 540, 541, 540, 540, 540, 541, 541, 540, 540, + /* 200 */ 540, 540, 540, 540, 204, 876, 448, 91, 707, 707, + /* 210 */ 566, 876, 876, 459, 876, 876, 260, 872, 872, 1133, + /* 220 */ 1133, 1133, 1133, 1127, 1052, 1052, 1112, 1052, 1055, 1052, + /* 230 */ -105, 1032, 1037, 1039, 1044, 1043, 1034, 1056, 1071, 1149, + /* 240 */ 1071, 1056, 1076, 1061, 1076, 1061, 1157, 1071, 1071, 1149, + /* 250 */ 1112, 1052, 1052, 1052, 1157, 1163, 1056, 1056, 1056, 1056, + /* 260 */ 1158, 1066, 1163, 1056, 1138, 1138, 1182, 1032, 1056, 1188, + /* 270 */ 1188, 1188, 1032, 1138, 1182, 1056, 1172, 1172, 1056, 1056, + /* 280 */ 1078, -106, -106, -106, -106, -106, -106, 317, 132, 629, + /* 290 */ 590, 794, 905, 851, 796, 955, 936, 980, 984, 896, + /* 300 */ 1015, 1016, 1030, 1026, 1060, 1086, 1087, 1090, 922, 1095, + /* 310 */ 1045, 1213, 1201, 1191, 1181, 1207, 1114, 1116, 1117, 1118, + /* 320 */ 1215, 1212, 1216, 1150, 1135, 1222, 1233, 1226, 1227, 1224, + /* 330 */ 1229, 1132, 1230, 1136, 1231, 1141, 1232, 1237, 1145, 1239, + /* 340 */ 1217, 1241, 1243, 1245, 1246, 1223, 1247, 1173, 1164, 1254, + /* 350 */ 1255, 1250, 1174, 1238, 1234, 1253, 1235, 1142, 1178, 1259, + /* 360 */ 1276, 1281, 1180, 1220, 1221, 1161, 1266, 1177, 1272, 1176, + /* 370 */ 1278, 1179, 1193, 1175, 1280, 1277, 1286, 1244, 1165, 1166, + /* 380 */ 1285, 1302, 1304, }; -#define YY_REDUCE_USE_DFLT (-61) +#define YY_REDUCE_USE_DFLT (-218) +#define YY_REDUCE_MAX 286 static const short yy_reduce_ofst[] = { - /* 0 */ -48, 61, -61, -61, -60, -61, -61, -61, -32, 12, - /* 10 */ -61, 181, -61, -61, -61, -61, -61, -61, -61, 314, - /* 20 */ -61, 386, -61, 622, -61, 654, -61, 51, 798, -61, - /* 30 */ -61, -23, -61, -26, 760, 89, -61, 860, 486, -61, - /* 40 */ 867, -61, -61, 65, -61, -61, -61, -61, -61, -61, - /* 50 */ -61, -61, 909, -61, 910, -61, -61, -61, -61, -61, - /* 60 */ 914, 962, 964, -61, -61, -61, -61, 968, -61, -61, - /* 70 */ 438, -61, 996, -61, -61, 116, -61, -61, -61, 293, - /* 80 */ -61, 1000, 1006, -61, 1011, 569, 1005, 1026, 1034, 1035, - /* 90 */ 1036, 1041, -61, 490, 394, 552, 394, 601, -61, -61, - /* 100 */ 1087, -61, 1093, -61, -61, -61, -61, -61, -61, -61, - /* 110 */ 603, 394, 53, -61, -61, 1082, 110, -61, -61, 229, - /* 120 */ -61, -61, -61, -61, 1019, -61, -61, -61, 1020, -61, - /* 130 */ -61, -61, -61, -61, -61, 640, -61, 394, 651, 394, - /* 140 */ 690, 394, 701, 394, 703, 394, 740, 394, 751, 394, - /* 150 */ 753, 394, 755, 394, 790, 394, 801, 394, 803, 394, - /* 160 */ 818, 394, 829, 394, 831, 394, 835, 394, 841, 394, - /* 170 */ -61, -61, -61, -61, -61, -61, 846, 188, 849, 394, - /* 180 */ -61, -61, -61, -61, -61, -61, -61, 879, 394, 881, - /* 190 */ 394, -61, 1102, -6, 1000, -61, -61, -61, -61, -61, - /* 200 */ 394, 887, 394, 898, 394, 918, 394, 936, 394, -61, - /* 210 */ 662, 1000, -61, 295, 394, 1037, 1039, -61, -61, 946, - /* 220 */ 394, 948, 394, -61, 1073, -61, -61, -61, 1114, -61, - /* 230 */ -61, 950, 394, 956, 394, 974, 394, -61, -61, 303, - /* 240 */ -61, -61, 1118, 1124, -61, -61, -61, 394, 984, 394, - /* 250 */ -61, 183, -61, 190, 1065, 1104, -61, 1119, -61, -61, - /* 260 */ 394, 1070, 1109, -61, 987, 394, -61, 187, -61, 1007, - /* 270 */ 394, -61, 398, 1083, -61, -61, -61, 1136, -61, 1138, - /* 280 */ -61, -61, -61, 1143, 1137, 389, 1144, -61, -61, 1090, - /* 290 */ 1094, -61, -61, 604, -61, -61, 1147, -61, -61, 1015, - /* 300 */ 394, 132, 1000, 1083, -61, 512, 1096, 1097, -61, 1018, - /* 310 */ 241, -61, -61, -61, 1087, -61, -61, 394, -61, -61, - /* 320 */ -61, -61, -61, 394, 1131, -61, 1155, 1132, 1130, 1133, - /* 330 */ -61, 1159, -61, -61, 1134, -61, -61, -61, -61, -61, - /* 340 */ -61, 1135, -61, 1139, -61, 439, -61, -61, 765, 1098, - /* 350 */ 1146, -61, -61, 1099, 1149, -61, -61, 1151, -61, 1145, - /* 360 */ -61, -61, 692, -61, 1022, 394, -61, 1150, -61, -61, - /* 370 */ 1153, -61, -61, -61, -61, 1156, 1158, -61, 1166, -61, - /* 380 */ -61, -61, 899, 1160, -61, 1161, -61, -61, 949, -61, - /* 390 */ 1163, -61, 1030, 375, -61, -61, -61, 979, -61, -61, - /* 400 */ 1180, 1162, 1168, 527, -61, -61, -61, -61, -61, -61, - /* 410 */ 712, 1000, 756, -61, 1181, 1179, -61, 1187, 1186, -61, - /* 420 */ 807, 1000, 1193, 1190, 1115, 1113, -61, 715, 1195, -61, - /* 430 */ 1117, 1120, -61, 1048, 394, -61, -61, -61, -61, -61, - /* 440 */ -61, -61, 709, -61, -61, -61, -61, -61, -61, -61, - /* 450 */ 1209, 1206, -61, 1211, -61, 997, -61, 1192, -61, -61, - /* 460 */ -61, 315, 1000, 1183, 732, -61, -61, -61, -61, -61, - /* 470 */ -61, 382, -61, 1191, 1228, -61, 808, 1185, 1232, -61, - /* 480 */ 1055, 394, -61, -61, 1064, 394, -61, 1236, 1171, 767, - /* 490 */ -61, -61, 854, 1000, -61, -18, -61, 1067, 394, -61, - /* 500 */ 394, -61, 1248, 1196, -61, -61, 815, -61, 891, -61, - /* 510 */ 895, -61, 906, -61, 1000, -61, 942, 1202, -61, 1215, - /* 520 */ 943, -61, 959, 1207, -61, -61, 975, 1194, 985, 1000, - /* 530 */ -61, 434, -61, -61, 1259, -61, 1262, 1257, -61, 435, - /* 540 */ -61, -61, -61, -61, 1267, -61, -61, 1188, 1263, -61, - /* 550 */ 1273, 1197, -61, 1264, -61, -61, -61, 1199, 1279, -61, - /* 560 */ 1284, 1278, -61, 1287, 1286, -61, -61, 522, -61, -61, - /* 570 */ 1291, -61, -61, 1204, -58, -61, -61, -61, -61, -61, - /* 580 */ -61, + /* 0 */ -56, 276, -2, -19, 399, 269, 49, 271, 270, 14, + /* 10 */ -147, -78, 273, 338, 340, 342, 44, 544, 263, -60, + /* 20 */ 32, 144, 349, -217, -217, -217, -217, -217, -217, -217, + /* 30 */ -217, -217, -217, -217, -217, -217, -217, -217, -217, -217, + /* 40 */ -217, -217, -217, -217, -217, -217, -217, -217, -217, -217, + /* 50 */ -217, -217, -217, -217, 405, 482, 485, 525, 568, 654, + /* 60 */ 697, 710, 712, 714, 721, 726, 747, 752, 754, 760, + /* 70 */ 763, 768, 792, 802, 804, 806, 809, 844, 853, 855, + /* 80 */ 857, 859, 873, 883, 892, 897, 900, 903, 918, 924, + /* 90 */ 928, 931, 933, -217, -217, 127, -217, -217, -217, -217, + /* 100 */ 454, 147, 509, 550, 554, 592, 593, 543, 489, -139, + /* 110 */ -217, -217, -217, -217, 45, 21, 67, 120, 110, 110, + /* 120 */ 3, 389, 440, 573, 545, 594, 667, 675, 669, 595, + /* 130 */ 597, 637, 640, 716, 718, 679, 753, 293, 765, 770, + /* 140 */ 803, 843, 628, 576, 588, -112, -83, 18, 154, 287, + /* 150 */ 302, 287, 287, 71, 423, 432, 492, 625, 643, 674, + /* 160 */ 742, 717, 625, 758, 846, 766, 864, 812, 893, 898, + /* 170 */ 287, 812, 901, 913, 885, 890, 904, 927, 942, 287, + /* 180 */ 944, 945, 287, 949, 852, 867, 963, 965, 287, 966, + /* 190 */ 968, 970, 287, 971, 973, 974, 287, 287, 975, 976, + /* 200 */ 977, 978, 979, 981, 982, 957, 939, 934, 906, 907, + /* 210 */ 909, 961, 964, 960, 967, 969, 972, 946, 948, 997, + /* 220 */ 998, 1000, 1001, 995, 983, 986, 987, 988, 989, 990, + /* 230 */ 991, 962, 992, 993, 994, 996, 943, 1017, 959, 1012, + /* 240 */ 999, 1021, 1002, 1003, 1005, 1006, 1004, 1007, 1008, 1019, + /* 250 */ 1009, 1010, 1011, 1013, 1018, 1035, 1031, 1033, 1038, 1041, + /* 260 */ 1014, 1020, 1046, 1047, 1023, 1028, 1022, 1027, 1049, 1029, + /* 270 */ 1036, 1040, 1042, 1048, 1024, 1051, 1025, 1050, 1053, 1062, + /* 280 */ 1054, 1058, 1059, 1063, 1057, 1064, 1065, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 587, 587, 582, 585, 892, 892, 892, 586, 594, 892, - /* 10 */ 892, 892, 892, 614, 615, 616, 595, 596, 597, 892, - /* 20 */ 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, - /* 30 */ 892, 892, 607, 617, 627, 609, 626, 892, 892, 628, - /* 40 */ 672, 635, 892, 892, 673, 676, 677, 678, 872, 873, - /* 50 */ 874, 892, 672, 636, 657, 655, 892, 658, 659, 892, - /* 60 */ 728, 672, 643, 637, 644, 726, 727, 672, 638, 892, - /* 70 */ 892, 758, 692, 690, 691, 824, 764, 759, 755, 892, - /* 80 */ 683, 892, 892, 684, 692, 694, 701, 740, 731, 733, - /* 90 */ 721, 735, 689, 892, 736, 892, 737, 892, 757, 892, - /* 100 */ 892, 760, 892, 761, 762, 763, 765, 766, 767, 892, - /* 110 */ 892, 892, 892, 612, 613, 619, 847, 892, 620, 847, - /* 120 */ 892, 621, 624, 625, 892, 842, 844, 845, 892, 843, - /* 130 */ 846, 623, 622, 892, 768, 892, 771, 773, 892, 774, - /* 140 */ 892, 775, 892, 776, 892, 777, 892, 778, 892, 779, - /* 150 */ 892, 780, 892, 781, 892, 782, 892, 783, 892, 784, - /* 160 */ 892, 785, 892, 786, 892, 787, 892, 788, 892, 789, - /* 170 */ 790, 892, 791, 798, 805, 808, 892, 793, 892, 792, - /* 180 */ 795, 892, 796, 892, 799, 797, 804, 892, 892, 892, - /* 190 */ 806, 807, 892, 824, 892, 892, 892, 892, 892, 811, - /* 200 */ 823, 892, 800, 892, 801, 892, 802, 892, 803, 892, - /* 210 */ 892, 892, 813, 892, 892, 892, 892, 892, 814, 892, - /* 220 */ 892, 892, 815, 892, 892, 892, 870, 892, 892, 892, - /* 230 */ 871, 892, 892, 892, 892, 892, 816, 892, 809, 824, - /* 240 */ 821, 822, 709, 892, 710, 812, 794, 772, 892, 738, - /* 250 */ 892, 892, 722, 892, 729, 728, 723, 892, 611, 730, - /* 260 */ 725, 729, 728, 724, 892, 734, 892, 824, 732, 892, - /* 270 */ 741, 693, 704, 702, 703, 712, 713, 892, 714, 892, - /* 280 */ 715, 892, 716, 892, 709, 700, 892, 698, 699, 718, - /* 290 */ 720, 705, 892, 892, 892, 719, 892, 753, 754, 892, - /* 300 */ 717, 704, 892, 892, 892, 700, 718, 720, 706, 892, - /* 310 */ 700, 695, 696, 892, 892, 697, 810, 892, 756, 892, - /* 320 */ 769, 892, 770, 892, 672, 639, 892, 828, 645, 640, - /* 330 */ 646, 892, 647, 892, 892, 648, 892, 651, 652, 653, - /* 340 */ 654, 892, 649, 892, 650, 892, 892, 829, 892, 729, - /* 350 */ 728, 830, 832, 729, 728, 831, 641, 892, 642, 657, - /* 360 */ 656, 629, 892, 630, 892, 892, 631, 892, 632, 764, - /* 370 */ 892, 633, 634, 618, 610, 892, 892, 662, 892, 665, - /* 380 */ 892, 892, 892, 892, 892, 672, 666, 892, 892, 892, - /* 390 */ 672, 667, 892, 672, 668, 892, 892, 892, 892, 892, - /* 400 */ 892, 828, 645, 670, 892, 669, 671, 663, 664, 608, - /* 410 */ 892, 892, 604, 892, 892, 709, 602, 892, 892, 892, - /* 420 */ 892, 892, 892, 709, 853, 892, 892, 892, 709, 711, - /* 430 */ 858, 892, 892, 892, 892, 892, 892, 859, 860, 892, - /* 440 */ 892, 892, 892, 892, 850, 851, 892, 852, 603, 892, - /* 450 */ 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, - /* 460 */ 892, 892, 892, 892, 892, 675, 892, 892, 892, 892, - /* 470 */ 892, 892, 892, 674, 892, 892, 892, 892, 892, 892, - /* 480 */ 892, 743, 892, 892, 892, 744, 892, 892, 751, 892, - /* 490 */ 892, 752, 892, 892, 892, 892, 892, 892, 749, 892, - /* 500 */ 750, 892, 892, 892, 892, 892, 892, 892, 892, 892, - /* 510 */ 892, 892, 892, 892, 892, 892, 892, 892, 892, 674, - /* 520 */ 892, 892, 892, 892, 892, 892, 892, 751, 892, 892, - /* 530 */ 892, 892, 892, 892, 892, 892, 892, 709, 892, 847, - /* 540 */ 892, 892, 892, 892, 892, 892, 892, 881, 892, 892, - /* 550 */ 892, 892, 892, 892, 892, 892, 880, 881, 892, 892, - /* 560 */ 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, - /* 570 */ 892, 892, 892, 890, 892, 892, 891, 588, 892, 589, + /* 0 */ 587, 813, 890, 702, 890, 813, 890, 813, 890, 706, + /* 10 */ 864, 809, 813, 890, 890, 890, 784, 890, 835, 890, + /* 20 */ 618, 835, 835, 737, 890, 890, 890, 890, 890, 890, + /* 30 */ 890, 890, 738, 890, 812, 808, 804, 806, 805, 739, + /* 40 */ 726, 735, 742, 718, 849, 744, 745, 750, 751, 865, + /* 50 */ 868, 772, 790, 771, 890, 890, 890, 890, 890, 890, + /* 60 */ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, + /* 70 */ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, + /* 80 */ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, + /* 90 */ 890, 890, 890, 774, 795, 611, 773, 783, 775, 776, + /* 100 */ 671, 606, 890, 890, 890, 890, 890, 890, 890, 890, + /* 110 */ 777, 778, 791, 792, 890, 890, 890, 890, 890, 890, + /* 120 */ 587, 702, 890, 702, 890, 890, 890, 890, 890, 890, + /* 130 */ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, + /* 140 */ 890, 890, 696, 706, 883, 890, 890, 662, 890, 890, + /* 150 */ 890, 890, 890, 890, 890, 890, 890, 890, 594, 592, + /* 160 */ 890, 694, 890, 890, 620, 890, 890, 704, 890, 890, + /* 170 */ 709, 710, 890, 890, 890, 890, 890, 890, 890, 608, + /* 180 */ 890, 890, 683, 890, 841, 890, 890, 890, 856, 890, + /* 190 */ 890, 890, 854, 890, 890, 890, 685, 747, 823, 890, + /* 200 */ 890, 869, 871, 890, 890, 729, 694, 703, 890, 890, + /* 210 */ 807, 729, 729, 641, 729, 729, 644, 741, 741, 591, + /* 220 */ 591, 591, 591, 661, 673, 673, 658, 673, 644, 673, + /* 230 */ 890, 741, 732, 734, 722, 736, 890, 711, 730, 890, + /* 240 */ 730, 711, 719, 721, 719, 721, 817, 730, 730, 890, + /* 250 */ 658, 673, 673, 673, 817, 603, 711, 711, 711, 711, + /* 260 */ 845, 848, 603, 711, 675, 675, 752, 741, 711, 682, + /* 270 */ 682, 682, 741, 675, 752, 711, 867, 867, 711, 711, + /* 280 */ 876, 628, 646, 646, 851, 883, 888, 890, 890, 890, + /* 290 */ 890, 890, 890, 759, 890, 890, 890, 890, 890, 890, + /* 300 */ 890, 890, 890, 890, 890, 890, 890, 890, 830, 890, + /* 310 */ 890, 890, 890, 890, 890, 890, 764, 760, 890, 761, + /* 320 */ 890, 890, 890, 890, 688, 890, 890, 890, 890, 890, + /* 330 */ 890, 890, 723, 890, 733, 890, 890, 890, 890, 890, + /* 340 */ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, + /* 350 */ 890, 890, 890, 890, 843, 844, 890, 890, 890, 890, + /* 360 */ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, + /* 370 */ 890, 890, 890, 890, 890, 890, 890, 875, 890, 890, + /* 380 */ 878, 588, 890, 582, 585, 584, 586, 590, 593, 615, + /* 390 */ 616, 617, 595, 596, 597, 598, 599, 600, 601, 607, + /* 400 */ 609, 627, 629, 636, 674, 677, 678, 679, 859, 860, + /* 410 */ 861, 637, 656, 659, 660, 638, 645, 727, 728, 639, + /* 420 */ 692, 693, 756, 686, 687, 691, 758, 762, 763, 765, + /* 430 */ 766, 614, 621, 622, 625, 626, 831, 833, 832, 834, + /* 440 */ 624, 623, 767, 770, 779, 780, 782, 788, 794, 797, + /* 450 */ 781, 786, 787, 789, 793, 796, 689, 690, 800, 802, + /* 460 */ 803, 857, 858, 798, 810, 811, 712, 801, 785, 724, + /* 470 */ 613, 731, 725, 695, 705, 714, 715, 716, 717, 700, + /* 480 */ 701, 707, 720, 754, 755, 708, 697, 698, 699, 799, + /* 490 */ 757, 768, 769, 640, 647, 648, 649, 652, 653, 654, + /* 500 */ 655, 650, 651, 818, 819, 821, 820, 642, 643, 657, + /* 510 */ 630, 631, 632, 633, 764, 634, 635, 619, 612, 663, + /* 520 */ 666, 667, 668, 669, 670, 672, 664, 665, 610, 602, + /* 530 */ 604, 713, 837, 846, 847, 842, 838, 839, 840, 605, + /* 540 */ 814, 815, 676, 748, 749, 836, 850, 852, 753, 853, + /* 550 */ 855, 880, 680, 681, 684, 822, 862, 740, 743, 746, + /* 560 */ 824, 825, 826, 827, 828, 829, 863, 866, 870, 872, + /* 570 */ 873, 874, 877, 879, 884, 885, 886, 889, 887, 589, /* 580 */ 583, }; -#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0])) +#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0])) /* The next table maps tokens into fallback tokens. If a construct ** like the following: @@ -670,75 +595,68 @@ static const YYACTIONTYPE yy_default[] = { #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { 0, /* $ => nothing */ - 0, /* END_OF_FILE => nothing */ - 0, /* ILLEGAL => nothing */ - 0, /* SPACE => nothing */ - 0, /* UNCLOSED_STRING => nothing */ - 0, /* COMMENT => nothing */ - 0, /* FUNCTION => nothing */ - 0, /* COLUMN => nothing */ - 0, /* AGG_FUNCTION => nothing */ - 0, /* AGG_COLUMN => nothing */ - 0, /* CONST_FUNC => nothing */ 0, /* SEMI => nothing */ - 30, /* EXPLAIN => ID */ - 30, /* QUERY => ID */ - 30, /* PLAN => ID */ - 30, /* BEGIN => ID */ + 23, /* EXPLAIN => ID */ + 23, /* QUERY => ID */ + 23, /* PLAN => ID */ + 23, /* BEGIN => ID */ 0, /* TRANSACTION => nothing */ - 30, /* DEFERRED => ID */ - 30, /* IMMEDIATE => ID */ - 30, /* EXCLUSIVE => ID */ + 23, /* DEFERRED => ID */ + 23, /* IMMEDIATE => ID */ + 23, /* EXCLUSIVE => ID */ 0, /* COMMIT => nothing */ - 30, /* END => ID */ + 23, /* END => ID */ 0, /* ROLLBACK => nothing */ 0, /* CREATE => nothing */ 0, /* TABLE => nothing */ - 30, /* TEMP => ID */ + 23, /* IF => ID */ + 0, /* NOT => nothing */ + 0, /* EXISTS => nothing */ + 23, /* TEMP => ID */ 0, /* LP => nothing */ 0, /* RP => nothing */ 0, /* AS => nothing */ 0, /* COMMA => nothing */ 0, /* ID => nothing */ - 30, /* ABORT => ID */ - 30, /* AFTER => ID */ - 30, /* ANALYZE => ID */ - 30, /* ASC => ID */ - 30, /* ATTACH => ID */ - 30, /* BEFORE => ID */ - 30, /* CASCADE => ID */ - 30, /* CAST => ID */ - 30, /* CONFLICT => ID */ - 30, /* DATABASE => ID */ - 30, /* DESC => ID */ - 30, /* DETACH => ID */ - 30, /* EACH => ID */ - 30, /* FAIL => ID */ - 30, /* FOR => ID */ - 30, /* IGNORE => ID */ - 30, /* INITIALLY => ID */ - 30, /* INSTEAD => ID */ - 30, /* LIKE_KW => ID */ - 30, /* MATCH => ID */ - 30, /* KEY => ID */ - 30, /* OF => ID */ - 30, /* OFFSET => ID */ - 30, /* PRAGMA => ID */ - 30, /* RAISE => ID */ - 30, /* REPLACE => ID */ - 30, /* RESTRICT => ID */ - 30, /* ROW => ID */ - 30, /* STATEMENT => ID */ - 30, /* TRIGGER => ID */ - 30, /* VACUUM => ID */ - 30, /* VIEW => ID */ - 30, /* REINDEX => ID */ - 30, /* RENAME => ID */ - 30, /* CTIME_KW => ID */ - 30, /* ALTER => ID */ + 23, /* ABORT => ID */ + 23, /* AFTER => ID */ + 23, /* ANALYZE => ID */ + 23, /* ASC => ID */ + 23, /* ATTACH => ID */ + 23, /* BEFORE => ID */ + 23, /* CASCADE => ID */ + 23, /* CAST => ID */ + 23, /* CONFLICT => ID */ + 23, /* DATABASE => ID */ + 23, /* DESC => ID */ + 23, /* DETACH => ID */ + 23, /* EACH => ID */ + 23, /* FAIL => ID */ + 23, /* FOR => ID */ + 23, /* IGNORE => ID */ + 23, /* INITIALLY => ID */ + 23, /* INSTEAD => ID */ + 23, /* LIKE_KW => ID */ + 23, /* MATCH => ID */ + 23, /* KEY => ID */ + 23, /* OF => ID */ + 23, /* OFFSET => ID */ + 23, /* PRAGMA => ID */ + 23, /* RAISE => ID */ + 23, /* REPLACE => ID */ + 23, /* RESTRICT => ID */ + 23, /* ROW => ID */ + 23, /* STATEMENT => ID */ + 23, /* TRIGGER => ID */ + 23, /* VACUUM => ID */ + 23, /* VIEW => ID */ + 23, /* VIRTUAL => ID */ + 23, /* REINDEX => ID */ + 23, /* RENAME => ID */ + 23, /* CTIME_KW => ID */ + 0, /* ANY => nothing */ 0, /* OR => nothing */ 0, /* AND => nothing */ - 0, /* NOT => nothing */ 0, /* IS => nothing */ 0, /* BETWEEN => nothing */ 0, /* IN => nothing */ @@ -785,8 +703,8 @@ static const YYCODETYPE yyFallback[] = { 0, /* DROP => nothing */ 0, /* UNION => nothing */ 0, /* ALL => nothing */ - 0, /* INTERSECT => nothing */ 0, /* EXCEPT => nothing */ + 0, /* INTERSECT => nothing */ 0, /* SELECT => nothing */ 0, /* DISTINCT => nothing */ 0, /* DOT => nothing */ @@ -806,12 +724,12 @@ static const YYCODETYPE yyFallback[] = { 0, /* BLOB => nothing */ 0, /* REGISTER => nothing */ 0, /* VARIABLE => nothing */ - 0, /* EXISTS => nothing */ 0, /* CASE => nothing */ 0, /* WHEN => nothing */ 0, /* THEN => nothing */ 0, /* ELSE => nothing */ 0, /* INDEX => nothing */ + 0, /* ALTER => nothing */ 0, /* TO => nothing */ 0, /* ADD => nothing */ 0, /* COLUMNKW => nothing */ @@ -885,68 +803,68 @@ void sqlite3ParserTrace(FILE *TraceFILE, char *zTracePrompt){ /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { - "$", "END_OF_FILE", "ILLEGAL", "SPACE", - "UNCLOSED_STRING", "COMMENT", "FUNCTION", "COLUMN", - "AGG_FUNCTION", "AGG_COLUMN", "CONST_FUNC", "SEMI", - "EXPLAIN", "QUERY", "PLAN", "BEGIN", - "TRANSACTION", "DEFERRED", "IMMEDIATE", "EXCLUSIVE", - "COMMIT", "END", "ROLLBACK", "CREATE", - "TABLE", "TEMP", "LP", "RP", - "AS", "COMMA", "ID", "ABORT", - "AFTER", "ANALYZE", "ASC", "ATTACH", - "BEFORE", "CASCADE", "CAST", "CONFLICT", - "DATABASE", "DESC", "DETACH", "EACH", - "FAIL", "FOR", "IGNORE", "INITIALLY", - "INSTEAD", "LIKE_KW", "MATCH", "KEY", - "OF", "OFFSET", "PRAGMA", "RAISE", - "REPLACE", "RESTRICT", "ROW", "STATEMENT", - "TRIGGER", "VACUUM", "VIEW", "REINDEX", - "RENAME", "CTIME_KW", "ALTER", "OR", - "AND", "NOT", "IS", "BETWEEN", - "IN", "ISNULL", "NOTNULL", "NE", - "EQ", "GT", "LE", "LT", - "GE", "ESCAPE", "BITAND", "BITOR", - "LSHIFT", "RSHIFT", "PLUS", "MINUS", - "STAR", "SLASH", "REM", "CONCAT", - "UMINUS", "UPLUS", "BITNOT", "STRING", - "JOIN_KW", "CONSTRAINT", "DEFAULT", "NULL", - "PRIMARY", "UNIQUE", "CHECK", "REFERENCES", - "COLLATE", "AUTOINCR", "ON", "DELETE", - "UPDATE", "INSERT", "SET", "DEFERRABLE", - "FOREIGN", "DROP", "UNION", "ALL", - "INTERSECT", "EXCEPT", "SELECT", "DISTINCT", - "DOT", "FROM", "JOIN", "USING", - "ORDER", "BY", "GROUP", "HAVING", - "LIMIT", "WHERE", "INTO", "VALUES", - "INTEGER", "FLOAT", "BLOB", "REGISTER", - "VARIABLE", "EXISTS", "CASE", "WHEN", - "THEN", "ELSE", "INDEX", "TO", - "ADD", "COLUMNKW", "error", "input", - "cmdlist", "ecmd", "cmdx", "cmd", - "explain", "transtype", "trans_opt", "nm", - "create_table", "create_table_args", "temp", "dbnm", - "columnlist", "conslist_opt", "select", "column", - "columnid", "type", "carglist", "id", - "ids", "typetoken", "typename", "signed", - "plus_num", "minus_num", "carg", "ccons", - "term", "expr", "onconf", "sortorder", - "autoinc", "idxlist_opt", "refargs", "defer_subclause", - "refarg", "refact", "init_deferred_pred_opt", "conslist", - "tcons", "idxlist", "defer_subclause_opt", "orconf", - "resolvetype", "raisetype", "fullname", "oneselect", - "multiselect_op", "distinct", "selcollist", "from", - "where_opt", "groupby_opt", "having_opt", "orderby_opt", - "limit_opt", "sclp", "as", "seltablist", - "stl_prefix", "joinop", "on_opt", "using_opt", - "seltablist_paren", "joinop2", "inscollist", "sortlist", - "sortitem", "collate", "exprlist", "setlist", - "insert_cmd", "inscollist_opt", "itemlist", "likeop", - "escape", "between_op", "in_op", "case_operand", - "case_exprlist", "case_else", "expritem", "uniqueflag", - "idxitem", "plus_opt", "number", "trigger_decl", - "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", - "when_clause", "trigger_cmd", "database_kw_opt", "key_opt", - "add_column_fullname", "kwcolumn_opt", + "$", "SEMI", "EXPLAIN", "QUERY", + "PLAN", "BEGIN", "TRANSACTION", "DEFERRED", + "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END", + "ROLLBACK", "CREATE", "TABLE", "IF", + "NOT", "EXISTS", "TEMP", "LP", + "RP", "AS", "COMMA", "ID", + "ABORT", "AFTER", "ANALYZE", "ASC", + "ATTACH", "BEFORE", "CASCADE", "CAST", + "CONFLICT", "DATABASE", "DESC", "DETACH", + "EACH", "FAIL", "FOR", "IGNORE", + "INITIALLY", "INSTEAD", "LIKE_KW", "MATCH", + "KEY", "OF", "OFFSET", "PRAGMA", + "RAISE", "REPLACE", "RESTRICT", "ROW", + "STATEMENT", "TRIGGER", "VACUUM", "VIEW", + "VIRTUAL", "REINDEX", "RENAME", "CTIME_KW", + "ANY", "OR", "AND", "IS", + "BETWEEN", "IN", "ISNULL", "NOTNULL", + "NE", "EQ", "GT", "LE", + "LT", "GE", "ESCAPE", "BITAND", + "BITOR", "LSHIFT", "RSHIFT", "PLUS", + "MINUS", "STAR", "SLASH", "REM", + "CONCAT", "UMINUS", "UPLUS", "BITNOT", + "STRING", "JOIN_KW", "CONSTRAINT", "DEFAULT", + "NULL", "PRIMARY", "UNIQUE", "CHECK", + "REFERENCES", "COLLATE", "AUTOINCR", "ON", + "DELETE", "UPDATE", "INSERT", "SET", + "DEFERRABLE", "FOREIGN", "DROP", "UNION", + "ALL", "EXCEPT", "INTERSECT", "SELECT", + "DISTINCT", "DOT", "FROM", "JOIN", + "USING", "ORDER", "BY", "GROUP", + "HAVING", "LIMIT", "WHERE", "INTO", + "VALUES", "INTEGER", "FLOAT", "BLOB", + "REGISTER", "VARIABLE", "CASE", "WHEN", + "THEN", "ELSE", "INDEX", "ALTER", + "TO", "ADD", "COLUMNKW", "error", + "input", "cmdlist", "ecmd", "cmdx", + "cmd", "explain", "transtype", "trans_opt", + "nm", "create_table", "create_table_args", "temp", + "ifnotexists", "dbnm", "columnlist", "conslist_opt", + "select", "column", "columnid", "type", + "carglist", "id", "ids", "typetoken", + "typename", "signed", "plus_num", "minus_num", + "carg", "ccons", "term", "expr", + "onconf", "sortorder", "autoinc", "idxlist_opt", + "refargs", "defer_subclause", "refarg", "refact", + "init_deferred_pred_opt", "conslist", "tcons", "idxlist", + "defer_subclause_opt", "orconf", "resolvetype", "raisetype", + "ifexists", "fullname", "oneselect", "multiselect_op", + "distinct", "selcollist", "from", "where_opt", + "groupby_opt", "having_opt", "orderby_opt", "limit_opt", + "sclp", "as", "seltablist", "stl_prefix", + "joinop", "on_opt", "using_opt", "seltablist_paren", + "joinop2", "inscollist", "sortlist", "sortitem", + "collate", "exprlist", "setlist", "insert_cmd", + "inscollist_opt", "itemlist", "likeop", "escape", + "between_op", "in_op", "case_operand", "case_exprlist", + "case_else", "expritem", "uniqueflag", "idxitem", + "plus_opt", "number", "trigger_decl", "trigger_cmd_list", + "trigger_time", "trigger_event", "foreach_clause", "when_clause", + "trigger_cmd", "database_kw_opt", "key_opt", "add_column_fullname", + "kwcolumn_opt", "create_vtab", "vtabarglist", "vtabarg", + "vtabargtoken", "lp", "anylist", }; #endif /* NDEBUG */ @@ -975,296 +893,294 @@ static const char *const yyRuleName[] = { /* 18 */ "cmd ::= END trans_opt", /* 19 */ "cmd ::= ROLLBACK trans_opt", /* 20 */ "cmd ::= create_table create_table_args", - /* 21 */ "create_table ::= CREATE temp TABLE nm dbnm", - /* 22 */ "temp ::= TEMP", - /* 23 */ "temp ::=", - /* 24 */ "create_table_args ::= LP columnlist conslist_opt RP", - /* 25 */ "create_table_args ::= AS select", - /* 26 */ "columnlist ::= columnlist COMMA column", - /* 27 */ "columnlist ::= column", - /* 28 */ "column ::= columnid type carglist", - /* 29 */ "columnid ::= nm", - /* 30 */ "id ::= ID", - /* 31 */ "ids ::= ID", - /* 32 */ "ids ::= STRING", - /* 33 */ "nm ::= ID", - /* 34 */ "nm ::= STRING", - /* 35 */ "nm ::= JOIN_KW", - /* 36 */ "type ::=", - /* 37 */ "type ::= typetoken", - /* 38 */ "typetoken ::= typename", - /* 39 */ "typetoken ::= typename LP signed RP", - /* 40 */ "typetoken ::= typename LP signed COMMA signed RP", - /* 41 */ "typename ::= ids", - /* 42 */ "typename ::= typename ids", - /* 43 */ "signed ::= plus_num", - /* 44 */ "signed ::= minus_num", - /* 45 */ "carglist ::= carglist carg", - /* 46 */ "carglist ::=", - /* 47 */ "carg ::= CONSTRAINT nm ccons", - /* 48 */ "carg ::= ccons", - /* 49 */ "carg ::= DEFAULT term", - /* 50 */ "carg ::= DEFAULT LP expr RP", - /* 51 */ "carg ::= DEFAULT PLUS term", - /* 52 */ "carg ::= DEFAULT MINUS term", - /* 53 */ "carg ::= DEFAULT id", - /* 54 */ "ccons ::= NULL onconf", - /* 55 */ "ccons ::= NOT NULL onconf", - /* 56 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", - /* 57 */ "ccons ::= UNIQUE onconf", - /* 58 */ "ccons ::= CHECK LP expr RP onconf", - /* 59 */ "ccons ::= REFERENCES nm idxlist_opt refargs", - /* 60 */ "ccons ::= defer_subclause", - /* 61 */ "ccons ::= COLLATE id", - /* 62 */ "autoinc ::=", - /* 63 */ "autoinc ::= AUTOINCR", - /* 64 */ "refargs ::=", - /* 65 */ "refargs ::= refargs refarg", - /* 66 */ "refarg ::= MATCH nm", - /* 67 */ "refarg ::= ON DELETE refact", - /* 68 */ "refarg ::= ON UPDATE refact", - /* 69 */ "refarg ::= ON INSERT refact", - /* 70 */ "refact ::= SET NULL", - /* 71 */ "refact ::= SET DEFAULT", - /* 72 */ "refact ::= CASCADE", - /* 73 */ "refact ::= RESTRICT", - /* 74 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", - /* 75 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", - /* 76 */ "init_deferred_pred_opt ::=", - /* 77 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", - /* 78 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", - /* 79 */ "conslist_opt ::=", - /* 80 */ "conslist_opt ::= COMMA conslist", - /* 81 */ "conslist ::= conslist COMMA tcons", - /* 82 */ "conslist ::= conslist tcons", - /* 83 */ "conslist ::= tcons", - /* 84 */ "tcons ::= CONSTRAINT nm", - /* 85 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", - /* 86 */ "tcons ::= UNIQUE LP idxlist RP onconf", - /* 87 */ "tcons ::= CHECK expr onconf", - /* 88 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", - /* 89 */ "defer_subclause_opt ::=", - /* 90 */ "defer_subclause_opt ::= defer_subclause", - /* 91 */ "onconf ::=", - /* 92 */ "onconf ::= ON CONFLICT resolvetype", - /* 93 */ "orconf ::=", - /* 94 */ "orconf ::= OR resolvetype", - /* 95 */ "resolvetype ::= raisetype", - /* 96 */ "resolvetype ::= IGNORE", - /* 97 */ "resolvetype ::= REPLACE", - /* 98 */ "cmd ::= DROP TABLE fullname", - /* 99 */ "cmd ::= CREATE temp VIEW nm dbnm AS select", - /* 100 */ "cmd ::= DROP VIEW fullname", - /* 101 */ "cmd ::= select", - /* 102 */ "select ::= oneselect", - /* 103 */ "select ::= select multiselect_op oneselect", - /* 104 */ "multiselect_op ::= UNION", - /* 105 */ "multiselect_op ::= UNION ALL", - /* 106 */ "multiselect_op ::= INTERSECT", - /* 107 */ "multiselect_op ::= EXCEPT", - /* 108 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", - /* 109 */ "distinct ::= DISTINCT", - /* 110 */ "distinct ::= ALL", - /* 111 */ "distinct ::=", - /* 112 */ "sclp ::= selcollist COMMA", - /* 113 */ "sclp ::=", - /* 114 */ "selcollist ::= sclp expr as", - /* 115 */ "selcollist ::= sclp STAR", - /* 116 */ "selcollist ::= sclp nm DOT STAR", - /* 117 */ "as ::= AS nm", - /* 118 */ "as ::= ids", - /* 119 */ "as ::=", - /* 120 */ "from ::=", - /* 121 */ "from ::= FROM seltablist", - /* 122 */ "stl_prefix ::= seltablist joinop", - /* 123 */ "stl_prefix ::=", - /* 124 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt", - /* 125 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt", - /* 126 */ "seltablist_paren ::= select", - /* 127 */ "seltablist_paren ::= seltablist", - /* 128 */ "dbnm ::=", - /* 129 */ "dbnm ::= DOT nm", - /* 130 */ "fullname ::= nm dbnm", - /* 131 */ "joinop ::= COMMA", - /* 132 */ "joinop ::= JOIN", - /* 133 */ "joinop ::= JOIN_KW JOIN", - /* 134 */ "joinop ::= JOIN_KW nm JOIN", - /* 135 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 136 */ "on_opt ::= ON expr", - /* 137 */ "on_opt ::=", - /* 138 */ "using_opt ::= USING LP inscollist RP", - /* 139 */ "using_opt ::=", - /* 140 */ "orderby_opt ::=", - /* 141 */ "orderby_opt ::= ORDER BY sortlist", - /* 142 */ "sortlist ::= sortlist COMMA sortitem collate sortorder", - /* 143 */ "sortlist ::= sortitem collate sortorder", - /* 144 */ "sortitem ::= expr", - /* 145 */ "sortorder ::= ASC", - /* 146 */ "sortorder ::= DESC", - /* 147 */ "sortorder ::=", - /* 148 */ "collate ::=", - /* 149 */ "collate ::= COLLATE id", - /* 150 */ "groupby_opt ::=", - /* 151 */ "groupby_opt ::= GROUP BY exprlist", - /* 152 */ "having_opt ::=", - /* 153 */ "having_opt ::= HAVING expr", - /* 154 */ "limit_opt ::=", - /* 155 */ "limit_opt ::= LIMIT expr", - /* 156 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 157 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 158 */ "cmd ::= DELETE FROM fullname where_opt", - /* 159 */ "where_opt ::=", - /* 160 */ "where_opt ::= WHERE expr", - /* 161 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt", - /* 162 */ "setlist ::= setlist COMMA nm EQ expr", - /* 163 */ "setlist ::= nm EQ expr", - /* 164 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP", - /* 165 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select", - /* 166 */ "insert_cmd ::= INSERT orconf", - /* 167 */ "insert_cmd ::= REPLACE", - /* 168 */ "itemlist ::= itemlist COMMA expr", - /* 169 */ "itemlist ::= expr", - /* 170 */ "inscollist_opt ::=", - /* 171 */ "inscollist_opt ::= LP inscollist RP", - /* 172 */ "inscollist ::= inscollist COMMA nm", - /* 173 */ "inscollist ::= nm", - /* 174 */ "expr ::= term", - /* 175 */ "expr ::= LP expr RP", - /* 176 */ "term ::= NULL", - /* 177 */ "expr ::= ID", - /* 178 */ "expr ::= JOIN_KW", - /* 179 */ "expr ::= nm DOT nm", - /* 180 */ "expr ::= nm DOT nm DOT nm", - /* 181 */ "term ::= INTEGER", - /* 182 */ "term ::= FLOAT", + /* 21 */ "create_table ::= CREATE temp TABLE ifnotexists nm dbnm", + /* 22 */ "ifnotexists ::=", + /* 23 */ "ifnotexists ::= IF NOT EXISTS", + /* 24 */ "temp ::= TEMP", + /* 25 */ "temp ::=", + /* 26 */ "create_table_args ::= LP columnlist conslist_opt RP", + /* 27 */ "create_table_args ::= AS select", + /* 28 */ "columnlist ::= columnlist COMMA column", + /* 29 */ "columnlist ::= column", + /* 30 */ "column ::= columnid type carglist", + /* 31 */ "columnid ::= nm", + /* 32 */ "id ::= ID", + /* 33 */ "ids ::= ID|STRING", + /* 34 */ "nm ::= ID", + /* 35 */ "nm ::= STRING", + /* 36 */ "nm ::= JOIN_KW", + /* 37 */ "type ::=", + /* 38 */ "type ::= typetoken", + /* 39 */ "typetoken ::= typename", + /* 40 */ "typetoken ::= typename LP signed RP", + /* 41 */ "typetoken ::= typename LP signed COMMA signed RP", + /* 42 */ "typename ::= ids", + /* 43 */ "typename ::= typename ids", + /* 44 */ "signed ::= plus_num", + /* 45 */ "signed ::= minus_num", + /* 46 */ "carglist ::= carglist carg", + /* 47 */ "carglist ::=", + /* 48 */ "carg ::= CONSTRAINT nm ccons", + /* 49 */ "carg ::= ccons", + /* 50 */ "carg ::= DEFAULT term", + /* 51 */ "carg ::= DEFAULT LP expr RP", + /* 52 */ "carg ::= DEFAULT PLUS term", + /* 53 */ "carg ::= DEFAULT MINUS term", + /* 54 */ "carg ::= DEFAULT id", + /* 55 */ "ccons ::= NULL onconf", + /* 56 */ "ccons ::= NOT NULL onconf", + /* 57 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", + /* 58 */ "ccons ::= UNIQUE onconf", + /* 59 */ "ccons ::= CHECK LP expr RP", + /* 60 */ "ccons ::= REFERENCES nm idxlist_opt refargs", + /* 61 */ "ccons ::= defer_subclause", + /* 62 */ "ccons ::= COLLATE id", + /* 63 */ "autoinc ::=", + /* 64 */ "autoinc ::= AUTOINCR", + /* 65 */ "refargs ::=", + /* 66 */ "refargs ::= refargs refarg", + /* 67 */ "refarg ::= MATCH nm", + /* 68 */ "refarg ::= ON DELETE refact", + /* 69 */ "refarg ::= ON UPDATE refact", + /* 70 */ "refarg ::= ON INSERT refact", + /* 71 */ "refact ::= SET NULL", + /* 72 */ "refact ::= SET DEFAULT", + /* 73 */ "refact ::= CASCADE", + /* 74 */ "refact ::= RESTRICT", + /* 75 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", + /* 76 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", + /* 77 */ "init_deferred_pred_opt ::=", + /* 78 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", + /* 79 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", + /* 80 */ "conslist_opt ::=", + /* 81 */ "conslist_opt ::= COMMA conslist", + /* 82 */ "conslist ::= conslist COMMA tcons", + /* 83 */ "conslist ::= conslist tcons", + /* 84 */ "conslist ::= tcons", + /* 85 */ "tcons ::= CONSTRAINT nm", + /* 86 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", + /* 87 */ "tcons ::= UNIQUE LP idxlist RP onconf", + /* 88 */ "tcons ::= CHECK LP expr RP onconf", + /* 89 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", + /* 90 */ "defer_subclause_opt ::=", + /* 91 */ "defer_subclause_opt ::= defer_subclause", + /* 92 */ "onconf ::=", + /* 93 */ "onconf ::= ON CONFLICT resolvetype", + /* 94 */ "orconf ::=", + /* 95 */ "orconf ::= OR resolvetype", + /* 96 */ "resolvetype ::= raisetype", + /* 97 */ "resolvetype ::= IGNORE", + /* 98 */ "resolvetype ::= REPLACE", + /* 99 */ "cmd ::= DROP TABLE ifexists fullname", + /* 100 */ "ifexists ::= IF EXISTS", + /* 101 */ "ifexists ::=", + /* 102 */ "cmd ::= CREATE temp VIEW nm dbnm AS select", + /* 103 */ "cmd ::= DROP VIEW ifexists fullname", + /* 104 */ "cmd ::= select", + /* 105 */ "select ::= oneselect", + /* 106 */ "select ::= select multiselect_op oneselect", + /* 107 */ "multiselect_op ::= UNION", + /* 108 */ "multiselect_op ::= UNION ALL", + /* 109 */ "multiselect_op ::= EXCEPT|INTERSECT", + /* 110 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", + /* 111 */ "distinct ::= DISTINCT", + /* 112 */ "distinct ::= ALL", + /* 113 */ "distinct ::=", + /* 114 */ "sclp ::= selcollist COMMA", + /* 115 */ "sclp ::=", + /* 116 */ "selcollist ::= sclp expr as", + /* 117 */ "selcollist ::= sclp STAR", + /* 118 */ "selcollist ::= sclp nm DOT STAR", + /* 119 */ "as ::= AS nm", + /* 120 */ "as ::= ids", + /* 121 */ "as ::=", + /* 122 */ "from ::=", + /* 123 */ "from ::= FROM seltablist", + /* 124 */ "stl_prefix ::= seltablist joinop", + /* 125 */ "stl_prefix ::=", + /* 126 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt", + /* 127 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt", + /* 128 */ "seltablist_paren ::= select", + /* 129 */ "seltablist_paren ::= seltablist", + /* 130 */ "dbnm ::=", + /* 131 */ "dbnm ::= DOT nm", + /* 132 */ "fullname ::= nm dbnm", + /* 133 */ "joinop ::= COMMA|JOIN", + /* 134 */ "joinop ::= JOIN_KW JOIN", + /* 135 */ "joinop ::= JOIN_KW nm JOIN", + /* 136 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 137 */ "on_opt ::= ON expr", + /* 138 */ "on_opt ::=", + /* 139 */ "using_opt ::= USING LP inscollist RP", + /* 140 */ "using_opt ::=", + /* 141 */ "orderby_opt ::=", + /* 142 */ "orderby_opt ::= ORDER BY sortlist", + /* 143 */ "sortlist ::= sortlist COMMA sortitem collate sortorder", + /* 144 */ "sortlist ::= sortitem collate sortorder", + /* 145 */ "sortitem ::= expr", + /* 146 */ "sortorder ::= ASC", + /* 147 */ "sortorder ::= DESC", + /* 148 */ "sortorder ::=", + /* 149 */ "collate ::=", + /* 150 */ "collate ::= COLLATE id", + /* 151 */ "groupby_opt ::=", + /* 152 */ "groupby_opt ::= GROUP BY exprlist", + /* 153 */ "having_opt ::=", + /* 154 */ "having_opt ::= HAVING expr", + /* 155 */ "limit_opt ::=", + /* 156 */ "limit_opt ::= LIMIT expr", + /* 157 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 158 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 159 */ "cmd ::= DELETE FROM fullname where_opt", + /* 160 */ "where_opt ::=", + /* 161 */ "where_opt ::= WHERE expr", + /* 162 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt", + /* 163 */ "setlist ::= setlist COMMA nm EQ expr", + /* 164 */ "setlist ::= nm EQ expr", + /* 165 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP", + /* 166 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select", + /* 167 */ "insert_cmd ::= INSERT orconf", + /* 168 */ "insert_cmd ::= REPLACE", + /* 169 */ "itemlist ::= itemlist COMMA expr", + /* 170 */ "itemlist ::= expr", + /* 171 */ "inscollist_opt ::=", + /* 172 */ "inscollist_opt ::= LP inscollist RP", + /* 173 */ "inscollist ::= inscollist COMMA nm", + /* 174 */ "inscollist ::= nm", + /* 175 */ "expr ::= term", + /* 176 */ "expr ::= LP expr RP", + /* 177 */ "term ::= NULL", + /* 178 */ "expr ::= ID", + /* 179 */ "expr ::= JOIN_KW", + /* 180 */ "expr ::= nm DOT nm", + /* 181 */ "expr ::= nm DOT nm DOT nm", + /* 182 */ "term ::= INTEGER|FLOAT|BLOB", /* 183 */ "term ::= STRING", - /* 184 */ "term ::= BLOB", - /* 185 */ "expr ::= REGISTER", - /* 186 */ "expr ::= VARIABLE", - /* 187 */ "expr ::= CAST LP expr AS typetoken RP", - /* 188 */ "expr ::= ID LP distinct exprlist RP", - /* 189 */ "expr ::= ID LP STAR RP", - /* 190 */ "term ::= CTIME_KW", - /* 191 */ "expr ::= expr AND expr", - /* 192 */ "expr ::= expr OR expr", - /* 193 */ "expr ::= expr LT expr", - /* 194 */ "expr ::= expr GT expr", - /* 195 */ "expr ::= expr LE expr", - /* 196 */ "expr ::= expr GE expr", - /* 197 */ "expr ::= expr NE expr", - /* 198 */ "expr ::= expr EQ expr", - /* 199 */ "expr ::= expr BITAND expr", - /* 200 */ "expr ::= expr BITOR expr", - /* 201 */ "expr ::= expr LSHIFT expr", - /* 202 */ "expr ::= expr RSHIFT expr", - /* 203 */ "expr ::= expr PLUS expr", - /* 204 */ "expr ::= expr MINUS expr", - /* 205 */ "expr ::= expr STAR expr", - /* 206 */ "expr ::= expr SLASH expr", - /* 207 */ "expr ::= expr REM expr", - /* 208 */ "expr ::= expr CONCAT expr", - /* 209 */ "likeop ::= LIKE_KW", - /* 210 */ "likeop ::= NOT LIKE_KW", - /* 211 */ "escape ::= ESCAPE expr", - /* 212 */ "escape ::=", - /* 213 */ "expr ::= expr likeop expr escape", - /* 214 */ "expr ::= expr ISNULL", - /* 215 */ "expr ::= expr IS NULL", - /* 216 */ "expr ::= expr NOTNULL", - /* 217 */ "expr ::= expr NOT NULL", - /* 218 */ "expr ::= expr IS NOT NULL", - /* 219 */ "expr ::= NOT expr", - /* 220 */ "expr ::= BITNOT expr", - /* 221 */ "expr ::= MINUS expr", - /* 222 */ "expr ::= PLUS expr", - /* 223 */ "between_op ::= BETWEEN", - /* 224 */ "between_op ::= NOT BETWEEN", - /* 225 */ "expr ::= expr between_op expr AND expr", - /* 226 */ "in_op ::= IN", - /* 227 */ "in_op ::= NOT IN", - /* 228 */ "expr ::= expr in_op LP exprlist RP", - /* 229 */ "expr ::= LP select RP", - /* 230 */ "expr ::= expr in_op LP select RP", - /* 231 */ "expr ::= expr in_op nm dbnm", - /* 232 */ "expr ::= EXISTS LP select RP", - /* 233 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 234 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 235 */ "case_exprlist ::= WHEN expr THEN expr", - /* 236 */ "case_else ::= ELSE expr", - /* 237 */ "case_else ::=", - /* 238 */ "case_operand ::= expr", - /* 239 */ "case_operand ::=", - /* 240 */ "exprlist ::= exprlist COMMA expritem", - /* 241 */ "exprlist ::= expritem", - /* 242 */ "expritem ::= expr", - /* 243 */ "expritem ::=", - /* 244 */ "cmd ::= CREATE uniqueflag INDEX nm dbnm ON nm LP idxlist RP onconf", - /* 245 */ "uniqueflag ::= UNIQUE", - /* 246 */ "uniqueflag ::=", - /* 247 */ "idxlist_opt ::=", - /* 248 */ "idxlist_opt ::= LP idxlist RP", - /* 249 */ "idxlist ::= idxlist COMMA idxitem collate sortorder", - /* 250 */ "idxlist ::= idxitem collate sortorder", - /* 251 */ "idxitem ::= nm", - /* 252 */ "cmd ::= DROP INDEX fullname", - /* 253 */ "cmd ::= VACUUM", - /* 254 */ "cmd ::= VACUUM nm", - /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nm", - /* 256 */ "cmd ::= PRAGMA nm dbnm EQ ON", - /* 257 */ "cmd ::= PRAGMA nm dbnm EQ plus_num", - /* 258 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 259 */ "cmd ::= PRAGMA nm dbnm LP nm RP", - /* 260 */ "cmd ::= PRAGMA nm dbnm", - /* 261 */ "plus_num ::= plus_opt number", - /* 262 */ "minus_num ::= MINUS number", - /* 263 */ "number ::= INTEGER", - /* 264 */ "number ::= FLOAT", - /* 265 */ "plus_opt ::= PLUS", - /* 266 */ "plus_opt ::=", - /* 267 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", - /* 268 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 269 */ "trigger_time ::= BEFORE", - /* 270 */ "trigger_time ::= AFTER", - /* 271 */ "trigger_time ::= INSTEAD OF", - /* 272 */ "trigger_time ::=", - /* 273 */ "trigger_event ::= DELETE", - /* 274 */ "trigger_event ::= INSERT", - /* 275 */ "trigger_event ::= UPDATE", - /* 276 */ "trigger_event ::= UPDATE OF inscollist", - /* 277 */ "foreach_clause ::=", - /* 278 */ "foreach_clause ::= FOR EACH ROW", - /* 279 */ "foreach_clause ::= FOR EACH STATEMENT", - /* 280 */ "when_clause ::=", - /* 281 */ "when_clause ::= WHEN expr", - /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list", - /* 283 */ "trigger_cmd_list ::=", - /* 284 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", - /* 285 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", - /* 286 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", - /* 287 */ "trigger_cmd ::= DELETE FROM nm where_opt", - /* 288 */ "trigger_cmd ::= select", - /* 289 */ "expr ::= RAISE LP IGNORE RP", - /* 290 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 291 */ "raisetype ::= ROLLBACK", - /* 292 */ "raisetype ::= ABORT", - /* 293 */ "raisetype ::= FAIL", - /* 294 */ "cmd ::= DROP TRIGGER fullname", - /* 295 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt", - /* 296 */ "key_opt ::=", - /* 297 */ "key_opt ::= KEY ids", - /* 298 */ "key_opt ::= KEY BLOB", - /* 299 */ "database_kw_opt ::= DATABASE", - /* 300 */ "database_kw_opt ::=", - /* 301 */ "cmd ::= DETACH database_kw_opt nm", - /* 302 */ "cmd ::= REINDEX", - /* 303 */ "cmd ::= REINDEX nm dbnm", - /* 304 */ "cmd ::= ANALYZE", - /* 305 */ "cmd ::= ANALYZE nm dbnm", - /* 306 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 307 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", - /* 308 */ "add_column_fullname ::= fullname", - /* 309 */ "kwcolumn_opt ::=", - /* 310 */ "kwcolumn_opt ::= COLUMNKW", + /* 184 */ "expr ::= REGISTER", + /* 185 */ "expr ::= VARIABLE", + /* 186 */ "expr ::= CAST LP expr AS typetoken RP", + /* 187 */ "expr ::= ID LP distinct exprlist RP", + /* 188 */ "expr ::= ID LP STAR RP", + /* 189 */ "term ::= CTIME_KW", + /* 190 */ "expr ::= expr AND expr", + /* 191 */ "expr ::= expr OR expr", + /* 192 */ "expr ::= expr LT|GT|GE|LE expr", + /* 193 */ "expr ::= expr EQ|NE expr", + /* 194 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 195 */ "expr ::= expr PLUS|MINUS expr", + /* 196 */ "expr ::= expr STAR|SLASH|REM expr", + /* 197 */ "expr ::= expr CONCAT expr", + /* 198 */ "likeop ::= LIKE_KW", + /* 199 */ "likeop ::= NOT LIKE_KW", + /* 200 */ "likeop ::= MATCH", + /* 201 */ "likeop ::= NOT MATCH", + /* 202 */ "escape ::= ESCAPE expr", + /* 203 */ "escape ::=", + /* 204 */ "expr ::= expr likeop expr escape", + /* 205 */ "expr ::= expr ISNULL|NOTNULL", + /* 206 */ "expr ::= expr IS NULL", + /* 207 */ "expr ::= expr NOT NULL", + /* 208 */ "expr ::= expr IS NOT NULL", + /* 209 */ "expr ::= NOT|BITNOT expr", + /* 210 */ "expr ::= MINUS expr", + /* 211 */ "expr ::= PLUS expr", + /* 212 */ "between_op ::= BETWEEN", + /* 213 */ "between_op ::= NOT BETWEEN", + /* 214 */ "expr ::= expr between_op expr AND expr", + /* 215 */ "in_op ::= IN", + /* 216 */ "in_op ::= NOT IN", + /* 217 */ "expr ::= expr in_op LP exprlist RP", + /* 218 */ "expr ::= LP select RP", + /* 219 */ "expr ::= expr in_op LP select RP", + /* 220 */ "expr ::= expr in_op nm dbnm", + /* 221 */ "expr ::= EXISTS LP select RP", + /* 222 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 223 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 224 */ "case_exprlist ::= WHEN expr THEN expr", + /* 225 */ "case_else ::= ELSE expr", + /* 226 */ "case_else ::=", + /* 227 */ "case_operand ::= expr", + /* 228 */ "case_operand ::=", + /* 229 */ "exprlist ::= exprlist COMMA expritem", + /* 230 */ "exprlist ::= expritem", + /* 231 */ "expritem ::= expr", + /* 232 */ "expritem ::=", + /* 233 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP", + /* 234 */ "uniqueflag ::= UNIQUE", + /* 235 */ "uniqueflag ::=", + /* 236 */ "idxlist_opt ::=", + /* 237 */ "idxlist_opt ::= LP idxlist RP", + /* 238 */ "idxlist ::= idxlist COMMA idxitem collate sortorder", + /* 239 */ "idxlist ::= idxitem collate sortorder", + /* 240 */ "idxitem ::= nm", + /* 241 */ "cmd ::= DROP INDEX ifexists fullname", + /* 242 */ "cmd ::= VACUUM", + /* 243 */ "cmd ::= VACUUM nm", + /* 244 */ "cmd ::= PRAGMA nm dbnm EQ nm", + /* 245 */ "cmd ::= PRAGMA nm dbnm EQ ON", + /* 246 */ "cmd ::= PRAGMA nm dbnm EQ plus_num", + /* 247 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 248 */ "cmd ::= PRAGMA nm dbnm LP nm RP", + /* 249 */ "cmd ::= PRAGMA nm dbnm", + /* 250 */ "plus_num ::= plus_opt number", + /* 251 */ "minus_num ::= MINUS number", + /* 252 */ "number ::= INTEGER|FLOAT", + /* 253 */ "plus_opt ::= PLUS", + /* 254 */ "plus_opt ::=", + /* 255 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", + /* 256 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 257 */ "trigger_time ::= BEFORE", + /* 258 */ "trigger_time ::= AFTER", + /* 259 */ "trigger_time ::= INSTEAD OF", + /* 260 */ "trigger_time ::=", + /* 261 */ "trigger_event ::= DELETE|INSERT", + /* 262 */ "trigger_event ::= UPDATE", + /* 263 */ "trigger_event ::= UPDATE OF inscollist", + /* 264 */ "foreach_clause ::=", + /* 265 */ "foreach_clause ::= FOR EACH ROW", + /* 266 */ "foreach_clause ::= FOR EACH STATEMENT", + /* 267 */ "when_clause ::=", + /* 268 */ "when_clause ::= WHEN expr", + /* 269 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 270 */ "trigger_cmd_list ::=", + /* 271 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", + /* 272 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", + /* 273 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", + /* 274 */ "trigger_cmd ::= DELETE FROM nm where_opt", + /* 275 */ "trigger_cmd ::= select", + /* 276 */ "expr ::= RAISE LP IGNORE RP", + /* 277 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 278 */ "raisetype ::= ROLLBACK", + /* 279 */ "raisetype ::= ABORT", + /* 280 */ "raisetype ::= FAIL", + /* 281 */ "cmd ::= DROP TRIGGER fullname", + /* 282 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 283 */ "key_opt ::=", + /* 284 */ "key_opt ::= KEY expr", + /* 285 */ "database_kw_opt ::= DATABASE", + /* 286 */ "database_kw_opt ::=", + /* 287 */ "cmd ::= DETACH database_kw_opt expr", + /* 288 */ "cmd ::= REINDEX", + /* 289 */ "cmd ::= REINDEX nm dbnm", + /* 290 */ "cmd ::= ANALYZE", + /* 291 */ "cmd ::= ANALYZE nm dbnm", + /* 292 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 293 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", + /* 294 */ "add_column_fullname ::= fullname", + /* 295 */ "kwcolumn_opt ::=", + /* 296 */ "kwcolumn_opt ::= COLUMNKW", + /* 297 */ "cmd ::= create_vtab", + /* 298 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 299 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm", + /* 300 */ "vtabarglist ::= vtabarg", + /* 301 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 302 */ "vtabarg ::=", + /* 303 */ "vtabarg ::= vtabarg vtabargtoken", + /* 304 */ "vtabargtoken ::= ANY", + /* 305 */ "vtabargtoken ::= lp anylist RP", + /* 306 */ "lp ::= LP", + /* 307 */ "anylist ::=", + /* 308 */ "anylist ::= anylist ANY", }; #endif /* NDEBUG */ @@ -1322,72 +1238,81 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ ** which appear on the RHS of the rule, but which are not used ** inside the C code. */ - case 162: + case 156: + case 190: + case 207: +#line 374 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3SelectDelete((yypminor->yy219));} +#line 1248 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 170: + case 171: case 195: - case 212: -#line 370 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3SelectDelete((yypminor->yy375));} -#line 1332 "ext/pdo_sqlite/sqlite/src/parse.c" + case 197: + case 205: + case 211: + case 219: + case 222: + case 224: + case 225: + case 235: +#line 631 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3ExprDelete((yypminor->yy172));} +#line 1263 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 176: - case 177: + case 175: + case 183: + case 193: + case 196: + case 198: case 200: - case 202: case 210: - case 216: - case 230: -#line 629 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3ExprDelete((yypminor->yy62));} -#line 1343 "ext/pdo_sqlite/sqlite/src/parse.c" + case 213: + case 214: + case 217: + case 223: +#line 865 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3ExprListDelete((yypminor->yy174));} +#line 1278 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 181: case 189: - case 198: - case 201: + case 194: + case 202: case 203: - case 205: - case 215: - case 218: - case 219: - case 222: - case 228: -#line 876 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3ExprListDelete((yypminor->yy418));} -#line 1358 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 502 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3SrcListDelete((yypminor->yy373));} +#line 1286 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 194: case 199: - case 207: - case 208: -#line 499 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3SrcListDelete((yypminor->yy151));} -#line 1366 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 204: -#line 561 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 563 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3ExprDelete((yypminor->yy220).pLimit); - sqlite3ExprDelete((yypminor->yy220).pOffset); + sqlite3ExprDelete((yypminor->yy234).pLimit); + sqlite3ExprDelete((yypminor->yy234).pOffset); } -#line 1374 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1294 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 211: - case 214: - case 221: -#line 517 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3IdListDelete((yypminor->yy240));} -#line 1381 "ext/pdo_sqlite/sqlite/src/parse.c" + case 206: + case 209: + case 216: +#line 519 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3IdListDelete((yypminor->yy432));} +#line 1301 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; + case 231: case 236: - case 241: -#line 969 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3DeleteTriggerStep((yypminor->yy360));} -#line 1387 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 959 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3DeleteTriggerStep((yypminor->yy243));} +#line 1307 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 233: +#line 943 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3IdListDelete((yypminor->yy370).b);} +#line 1312 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 238: -#line 953 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3IdListDelete((yypminor->yy30).b);} -#line 1392 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1027 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3ExprDelete((yypminor->yy386));} +#line 1317 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; default: break; /* If no destructor action specified: do nothing */ } @@ -1451,14 +1376,12 @@ void sqlite3ParserFree( */ static int yy_find_shift_action( yyParser *pParser, /* The parser */ - int iLookAhead /* The look-ahead token */ + YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ - i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ){ + if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){ return yy_default[stateno]; } if( iLookAhead==YYNOCODE ){ @@ -1466,19 +1389,35 @@ static int yy_find_shift_action( } i += iLookAhead; if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ + if( iLookAhead>0 ){ #ifdef YYFALLBACK - int iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + } +#endif + return yy_find_shift_action(pParser, iFallback); } #endif - return yy_find_shift_action(pParser, iFallback); +#ifdef YYWILDCARD + { + int j = i - iLookAhead + YYWILDCARD; + if( j>=0 && j %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); + } +#endif /* NDEBUG */ + return yy_action[j]; + } + } +#endif /* YYWILDCARD */ } -#endif return yy_default[stateno]; }else{ return yy_action[i]; @@ -1495,13 +1434,13 @@ static int yy_find_shift_action( */ static int yy_find_reduce_action( int stateno, /* Current state number */ - int iLookAhead /* The look-ahead token */ + YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; /* int stateno = pParser->yystack[pParser->yyidx].stateno; */ - i = yy_reduce_ofst[stateno]; - if( i==YY_REDUCE_USE_DFLT ){ + if( stateno>YY_REDUCE_MAX || + (i = yy_reduce_ofst[stateno])==YY_REDUCE_USE_DFLT ){ return yy_default[stateno]; } if( iLookAhead==YYNOCODE ){ @@ -1537,6 +1476,11 @@ static void yy_shift( while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ +#line 44 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" + + sqlite3ErrorMsg(pParse, "parser stack overflow"); + pParse->parseError = 1; +#line 1486 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ return; } @@ -1563,317 +1507,315 @@ static const struct { YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ unsigned char nrhs; /* Number of right-hand side symbols in the rule */ } yyRuleInfo[] = { + { 140, 1 }, + { 141, 2 }, + { 141, 1 }, + { 143, 1 }, + { 142, 1 }, + { 142, 3 }, + { 145, 0 }, + { 145, 1 }, + { 145, 3 }, + { 144, 3 }, + { 147, 0 }, { 147, 1 }, - { 148, 2 }, - { 148, 1 }, - { 150, 1 }, - { 149, 1 }, - { 149, 3 }, + { 147, 2 }, + { 146, 0 }, + { 146, 1 }, + { 146, 1 }, + { 146, 1 }, + { 144, 2 }, + { 144, 2 }, + { 144, 2 }, + { 144, 2 }, + { 149, 6 }, { 152, 0 }, - { 152, 1 }, { 152, 3 }, - { 151, 3 }, - { 154, 0 }, + { 151, 1 }, + { 151, 0 }, + { 150, 4 }, + { 150, 2 }, + { 154, 3 }, { 154, 1 }, - { 154, 2 }, - { 153, 0 }, - { 153, 1 }, - { 153, 1 }, - { 153, 1 }, - { 151, 2 }, - { 151, 2 }, - { 151, 2 }, - { 151, 2 }, - { 156, 5 }, + { 157, 3 }, { 158, 1 }, - { 158, 0 }, - { 157, 4 }, - { 157, 2 }, - { 160, 3 }, - { 160, 1 }, - { 163, 3 }, + { 161, 1 }, + { 162, 1 }, + { 148, 1 }, + { 148, 1 }, + { 148, 1 }, + { 159, 0 }, + { 159, 1 }, + { 163, 1 }, + { 163, 4 }, + { 163, 6 }, { 164, 1 }, - { 167, 1 }, - { 168, 1 }, - { 168, 1 }, - { 155, 1 }, - { 155, 1 }, - { 155, 1 }, - { 165, 0 }, + { 164, 2 }, { 165, 1 }, - { 169, 1 }, + { 165, 1 }, + { 160, 2 }, + { 160, 0 }, + { 168, 3 }, + { 168, 1 }, + { 168, 2 }, + { 168, 4 }, + { 168, 3 }, + { 168, 3 }, + { 168, 2 }, + { 169, 2 }, + { 169, 3 }, + { 169, 5 }, + { 169, 2 }, { 169, 4 }, - { 169, 6 }, - { 170, 1 }, - { 170, 2 }, - { 171, 1 }, - { 171, 1 }, - { 166, 2 }, - { 166, 0 }, - { 174, 3 }, + { 169, 4 }, + { 169, 1 }, + { 169, 2 }, + { 174, 0 }, { 174, 1 }, - { 174, 2 }, - { 174, 4 }, - { 174, 3 }, - { 174, 3 }, - { 174, 2 }, - { 175, 2 }, - { 175, 3 }, - { 175, 5 }, - { 175, 2 }, - { 175, 5 }, - { 175, 4 }, - { 175, 1 }, - { 175, 2 }, + { 176, 0 }, + { 176, 2 }, + { 178, 2 }, + { 178, 3 }, + { 178, 3 }, + { 178, 3 }, + { 179, 2 }, + { 179, 2 }, + { 179, 1 }, + { 179, 1 }, + { 177, 3 }, + { 177, 2 }, { 180, 0 }, - { 180, 1 }, - { 182, 0 }, + { 180, 2 }, + { 180, 2 }, + { 155, 0 }, + { 155, 2 }, + { 181, 3 }, + { 181, 2 }, + { 181, 1 }, { 182, 2 }, - { 184, 2 }, - { 184, 3 }, - { 184, 3 }, - { 184, 3 }, - { 185, 2 }, + { 182, 7 }, + { 182, 5 }, + { 182, 5 }, + { 182, 10 }, + { 184, 0 }, + { 184, 1 }, + { 172, 0 }, + { 172, 3 }, + { 185, 0 }, { 185, 2 }, - { 185, 1 }, - { 185, 1 }, - { 183, 3 }, - { 183, 2 }, - { 186, 0 }, - { 186, 2 }, - { 186, 2 }, - { 161, 0 }, - { 161, 2 }, - { 187, 3 }, - { 187, 2 }, - { 187, 1 }, + { 186, 1 }, + { 186, 1 }, + { 186, 1 }, + { 144, 4 }, { 188, 2 }, - { 188, 7 }, - { 188, 5 }, - { 188, 3 }, - { 188, 10 }, - { 190, 0 }, - { 190, 1 }, - { 178, 0 }, - { 178, 3 }, - { 191, 0 }, + { 188, 0 }, + { 144, 7 }, + { 144, 4 }, + { 144, 1 }, + { 156, 1 }, + { 156, 3 }, + { 191, 1 }, { 191, 2 }, + { 191, 1 }, + { 190, 9 }, { 192, 1 }, { 192, 1 }, - { 192, 1 }, - { 151, 3 }, - { 151, 7 }, - { 151, 3 }, - { 151, 1 }, - { 162, 1 }, - { 162, 3 }, - { 196, 1 }, - { 196, 2 }, - { 196, 1 }, - { 196, 1 }, - { 195, 9 }, - { 197, 1 }, - { 197, 1 }, - { 197, 0 }, + { 192, 0 }, + { 200, 2 }, + { 200, 0 }, + { 193, 3 }, + { 193, 2 }, + { 193, 4 }, + { 201, 2 }, + { 201, 1 }, + { 201, 0 }, + { 194, 0 }, + { 194, 2 }, + { 203, 2 }, + { 203, 0 }, + { 202, 6 }, + { 202, 7 }, + { 207, 1 }, + { 207, 1 }, + { 153, 0 }, + { 153, 2 }, + { 189, 2 }, + { 204, 1 }, + { 204, 2 }, + { 204, 3 }, + { 204, 4 }, { 205, 2 }, { 205, 0 }, - { 198, 3 }, - { 198, 2 }, - { 198, 4 }, - { 206, 2 }, - { 206, 1 }, + { 206, 4 }, { 206, 0 }, + { 198, 0 }, + { 198, 3 }, + { 210, 5 }, + { 210, 3 }, + { 211, 1 }, + { 173, 1 }, + { 173, 1 }, + { 173, 0 }, + { 212, 0 }, + { 212, 2 }, + { 196, 0 }, + { 196, 3 }, + { 197, 0 }, + { 197, 2 }, { 199, 0 }, { 199, 2 }, - { 208, 2 }, - { 208, 0 }, - { 207, 6 }, - { 207, 7 }, - { 212, 1 }, - { 212, 1 }, - { 159, 0 }, - { 159, 2 }, - { 194, 2 }, - { 209, 1 }, - { 209, 1 }, - { 209, 2 }, + { 199, 4 }, + { 199, 4 }, + { 144, 4 }, + { 195, 0 }, + { 195, 2 }, + { 144, 6 }, + { 214, 5 }, + { 214, 3 }, + { 144, 8 }, + { 144, 5 }, + { 215, 2 }, + { 215, 1 }, + { 217, 3 }, + { 217, 1 }, + { 216, 0 }, + { 216, 3 }, { 209, 3 }, - { 209, 4 }, - { 210, 2 }, - { 210, 0 }, - { 211, 4 }, - { 211, 0 }, - { 203, 0 }, - { 203, 3 }, - { 215, 5 }, - { 215, 3 }, - { 216, 1 }, - { 179, 1 }, - { 179, 1 }, - { 179, 0 }, - { 217, 0 }, - { 217, 2 }, - { 201, 0 }, - { 201, 3 }, - { 202, 0 }, - { 202, 2 }, - { 204, 0 }, - { 204, 2 }, - { 204, 4 }, - { 204, 4 }, - { 151, 4 }, - { 200, 0 }, - { 200, 2 }, - { 151, 6 }, - { 219, 5 }, - { 219, 3 }, - { 151, 8 }, - { 151, 5 }, - { 220, 2 }, + { 209, 1 }, + { 171, 1 }, + { 171, 3 }, + { 170, 1 }, + { 171, 1 }, + { 171, 1 }, + { 171, 3 }, + { 171, 5 }, + { 170, 1 }, + { 170, 1 }, + { 171, 1 }, + { 171, 1 }, + { 171, 6 }, + { 171, 5 }, + { 171, 4 }, + { 170, 1 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 218, 1 }, + { 218, 2 }, + { 218, 1 }, + { 218, 2 }, + { 219, 2 }, + { 219, 0 }, + { 171, 4 }, + { 171, 2 }, + { 171, 3 }, + { 171, 3 }, + { 171, 4 }, + { 171, 2 }, + { 171, 2 }, + { 171, 2 }, { 220, 1 }, - { 222, 3 }, - { 222, 1 }, - { 221, 0 }, - { 221, 3 }, - { 214, 3 }, - { 214, 1 }, - { 177, 1 }, - { 177, 3 }, - { 176, 1 }, - { 177, 1 }, - { 177, 1 }, - { 177, 3 }, - { 177, 5 }, - { 176, 1 }, - { 176, 1 }, - { 176, 1 }, - { 176, 1 }, - { 177, 1 }, - { 177, 1 }, - { 177, 6 }, - { 177, 5 }, - { 177, 4 }, - { 176, 1 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 223, 1 }, - { 223, 2 }, + { 220, 2 }, + { 171, 5 }, + { 221, 1 }, + { 221, 2 }, + { 171, 5 }, + { 171, 3 }, + { 171, 5 }, + { 171, 4 }, + { 171, 4 }, + { 171, 5 }, + { 223, 5 }, + { 223, 4 }, { 224, 2 }, { 224, 0 }, - { 177, 4 }, - { 177, 2 }, - { 177, 3 }, - { 177, 2 }, - { 177, 3 }, - { 177, 4 }, - { 177, 2 }, - { 177, 2 }, - { 177, 2 }, - { 177, 2 }, + { 222, 1 }, + { 222, 0 }, + { 213, 3 }, + { 213, 1 }, { 225, 1 }, - { 225, 2 }, - { 177, 5 }, + { 225, 0 }, + { 144, 11 }, { 226, 1 }, - { 226, 2 }, - { 177, 5 }, - { 177, 3 }, - { 177, 5 }, - { 177, 4 }, - { 177, 4 }, - { 177, 5 }, - { 228, 5 }, - { 228, 4 }, - { 229, 2 }, - { 229, 0 }, + { 226, 0 }, + { 175, 0 }, + { 175, 3 }, + { 183, 5 }, + { 183, 3 }, { 227, 1 }, - { 227, 0 }, - { 218, 3 }, - { 218, 1 }, - { 230, 1 }, - { 230, 0 }, - { 151, 11 }, - { 231, 1 }, - { 231, 0 }, - { 181, 0 }, - { 181, 3 }, - { 189, 5 }, - { 189, 3 }, + { 144, 4 }, + { 144, 1 }, + { 144, 2 }, + { 144, 5 }, + { 144, 5 }, + { 144, 5 }, + { 144, 5 }, + { 144, 6 }, + { 144, 3 }, + { 166, 2 }, + { 167, 2 }, + { 229, 1 }, + { 228, 1 }, + { 228, 0 }, + { 144, 5 }, + { 230, 10 }, { 232, 1 }, - { 151, 3 }, - { 151, 1 }, - { 151, 2 }, - { 151, 5 }, - { 151, 5 }, - { 151, 5 }, - { 151, 5 }, - { 151, 6 }, - { 151, 3 }, - { 172, 2 }, - { 173, 2 }, - { 234, 1 }, - { 234, 1 }, + { 232, 1 }, + { 232, 2 }, + { 232, 0 }, { 233, 1 }, - { 233, 0 }, - { 151, 5 }, - { 235, 10 }, - { 237, 1 }, + { 233, 1 }, + { 233, 3 }, + { 234, 0 }, + { 234, 3 }, + { 234, 3 }, + { 235, 0 }, + { 235, 2 }, + { 231, 3 }, + { 231, 0 }, + { 236, 6 }, + { 236, 8 }, + { 236, 5 }, + { 236, 4 }, + { 236, 1 }, + { 171, 4 }, + { 171, 6 }, + { 187, 1 }, + { 187, 1 }, + { 187, 1 }, + { 144, 3 }, + { 144, 6 }, + { 238, 0 }, + { 238, 2 }, { 237, 1 }, - { 237, 2 }, { 237, 0 }, - { 238, 1 }, - { 238, 1 }, - { 238, 1 }, - { 238, 3 }, - { 239, 0 }, - { 239, 3 }, - { 239, 3 }, + { 144, 3 }, + { 144, 1 }, + { 144, 3 }, + { 144, 1 }, + { 144, 3 }, + { 144, 6 }, + { 144, 6 }, + { 239, 1 }, { 240, 0 }, - { 240, 2 }, - { 236, 3 }, - { 236, 0 }, - { 241, 6 }, - { 241, 8 }, - { 241, 5 }, - { 241, 4 }, - { 241, 1 }, - { 177, 4 }, - { 177, 6 }, - { 193, 1 }, - { 193, 1 }, - { 193, 1 }, - { 151, 3 }, - { 151, 6 }, + { 240, 1 }, + { 144, 1 }, + { 144, 4 }, + { 241, 7 }, + { 242, 1 }, + { 242, 3 }, { 243, 0 }, { 243, 2 }, - { 243, 2 }, - { 242, 1 }, - { 242, 0 }, - { 151, 3 }, - { 151, 1 }, - { 151, 3 }, - { 151, 1 }, - { 151, 3 }, - { 151, 6 }, - { 151, 6 }, { 244, 1 }, - { 245, 0 }, + { 244, 3 }, { 245, 1 }, + { 246, 0 }, + { 246, 2 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -1895,7 +1837,7 @@ static void yy_reduce( yymsp = &yypParser->yystack[yypParser->yyidx]; #ifndef NDEBUG if( yyTraceFILE && yyruleno>=0 - && yyrulenosLastToken.z-yymsp[-2].minor.yy198.z) + pParse->sLastToken.n; + yygotominor.yy410.z = yymsp[-2].minor.yy410.z; + yygotominor.yy410.n = (pParse->sLastToken.z-yymsp[-2].minor.yy410.z) + pParse->sLastToken.n; } -#line 2029 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1975 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 29: -#line 157 "ext/pdo_sqlite/sqlite/src/parse.y" + case 31: +#line 158 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3AddColumn(pParse,&yymsp[0].minor.yy198); - yygotominor.yy198 = yymsp[0].minor.yy198; + sqlite3AddColumn(pParse,&yymsp[0].minor.yy410); + yygotominor.yy410 = yymsp[0].minor.yy410; } -#line 2037 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1983 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 30: - case 31: case 32: case 33: case 34: case 35: - case 263: - case 264: -#line 167 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy198 = yymsp[0].minor.yy0;} -#line 2049 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 37: -#line 227 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy198);} -#line 2054 "ext/pdo_sqlite/sqlite/src/parse.c" + case 36: + case 252: +#line 168 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy410 = yymsp[0].minor.yy0;} +#line 1993 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 38: - case 41: - case 117: - case 118: - case 129: - case 149: - case 251: - case 261: - case 262: -#line 228 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy198 = yymsp[0].minor.yy198;} -#line 2067 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 228 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy410);} +#line 1998 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 39: -#line 229 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - yygotominor.yy198.z = yymsp[-3].minor.yy198.z; - yygotominor.yy198.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy198.z; -} -#line 2075 "ext/pdo_sqlite/sqlite/src/parse.c" + case 42: + case 119: + case 120: + case 131: + case 150: + case 240: + case 250: + case 251: +#line 229 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy410 = yymsp[0].minor.yy410;} +#line 2011 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 40: -#line 233 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 230 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy198.z = yymsp[-5].minor.yy198.z; - yygotominor.yy198.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy198.z; + yygotominor.yy410.z = yymsp[-3].minor.yy410.z; + yygotominor.yy410.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy410.z; } -#line 2083 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2019 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 42: -#line 239 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy198.z=yymsp[-1].minor.yy198.z; yygotominor.yy198.n=yymsp[0].minor.yy198.n+(yymsp[0].minor.yy198.z-yymsp[-1].minor.yy198.z);} -#line 2088 "ext/pdo_sqlite/sqlite/src/parse.c" + case 41: +#line 234 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + yygotominor.yy410.z = yymsp[-5].minor.yy410.z; + yygotominor.yy410.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy410.z; +} +#line 2027 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 43: -#line 241 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = atoi(yymsp[0].minor.yy198.z); } -#line 2093 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 240 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy410.z=yymsp[-1].minor.yy410.z; yygotominor.yy410.n=yymsp[0].minor.yy410.n+(yymsp[0].minor.yy410.z-yymsp[-1].minor.yy410.z);} +#line 2032 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 44: -#line 242 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = -atoi(yymsp[0].minor.yy198.z); } -#line 2098 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 242 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = atoi((char*)yymsp[0].minor.yy410.z); } +#line 2037 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 49: - case 51: -#line 251 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy62);} -#line 2104 "ext/pdo_sqlite/sqlite/src/parse.c" + case 45: +#line 243 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = -atoi((char*)yymsp[0].minor.yy410.z); } +#line 2042 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 50: -#line 252 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy62);} -#line 2109 "ext/pdo_sqlite/sqlite/src/parse.c" - break; case 52: -#line 254 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 252 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy172);} +#line 2048 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 51: +#line 253 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy172);} +#line 2053 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 53: +#line 255 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy62, 0, 0); + Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy172, 0, 0); sqlite3AddDefaultValue(pParse,p); } -#line 2117 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2061 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 53: -#line 258 "ext/pdo_sqlite/sqlite/src/parse.y" + case 54: +#line 259 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy198); + Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy410); sqlite3AddDefaultValue(pParse,p); } -#line 2125 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 55: -#line 267 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy280);} -#line 2130 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2069 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 56: -#line 269 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy280,yymsp[0].minor.yy280);} -#line 2135 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 268 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy46);} +#line 2074 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 57: -#line 270 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy280,0,0);} -#line 2140 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 270 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy46,yymsp[0].minor.yy46,yymsp[-2].minor.yy46);} +#line 2079 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 58: -#line 271 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3ExprDelete(yymsp[-2].minor.yy62);} -#line 2145 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 271 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy46,0,0,0,0);} +#line 2084 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 59: -#line 273 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy198,yymsp[-1].minor.yy418,yymsp[0].minor.yy280);} -#line 2150 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 272 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy172);} +#line 2089 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 60: -#line 274 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy280);} -#line 2155 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 274 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy410,yymsp[-1].minor.yy174,yymsp[0].minor.yy46);} +#line 2094 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 61: -#line 275 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3AddCollateType(pParse, yymsp[0].minor.yy198.z, yymsp[0].minor.yy198.n);} -#line 2160 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 275 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy46);} +#line 2099 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 64: -#line 288 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = OE_Restrict * 0x010101; } -#line 2165 "ext/pdo_sqlite/sqlite/src/parse.c" + case 62: +#line 276 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddCollateType(pParse, (char*)yymsp[0].minor.yy410.z, yymsp[0].minor.yy410.n);} +#line 2104 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 65: -#line 289 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = (yymsp[-1].minor.yy280 & yymsp[0].minor.yy359.mask) | yymsp[0].minor.yy359.value; } -#line 2170 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 289 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = OE_Restrict * 0x010101; } +#line 2109 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 66: -#line 291 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy359.value = 0; yygotominor.yy359.mask = 0x000000; } -#line 2175 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 290 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = (yymsp[-1].minor.yy46 & yymsp[0].minor.yy405.mask) | yymsp[0].minor.yy405.value; } +#line 2114 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 67: -#line 292 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy359.value = yymsp[0].minor.yy280; yygotominor.yy359.mask = 0x0000ff; } -#line 2180 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 292 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy405.value = 0; yygotominor.yy405.mask = 0x000000; } +#line 2119 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 68: -#line 293 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy359.value = yymsp[0].minor.yy280<<8; yygotominor.yy359.mask = 0x00ff00; } -#line 2185 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 293 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy405.value = yymsp[0].minor.yy46; yygotominor.yy405.mask = 0x0000ff; } +#line 2124 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 69: -#line 294 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy359.value = yymsp[0].minor.yy280<<16; yygotominor.yy359.mask = 0xff0000; } -#line 2190 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 294 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy405.value = yymsp[0].minor.yy46<<8; yygotominor.yy405.mask = 0x00ff00; } +#line 2129 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 70: -#line 296 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = OE_SetNull; } -#line 2195 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 295 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy405.value = yymsp[0].minor.yy46<<16; yygotominor.yy405.mask = 0xff0000; } +#line 2134 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 71: -#line 297 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = OE_SetDflt; } -#line 2200 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 297 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = OE_SetNull; } +#line 2139 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 72: -#line 298 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = OE_Cascade; } -#line 2205 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 298 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = OE_SetDflt; } +#line 2144 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 73: -#line 299 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = OE_Restrict; } -#line 2210 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 299 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = OE_Cascade; } +#line 2149 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 74: +#line 300 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = OE_Restrict; } +#line 2154 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; case 75: - case 90: - case 92: - case 94: + case 76: + case 91: + case 93: case 95: - case 166: -#line 301 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = yymsp[0].minor.yy280;} -#line 2221 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 79: -#line 311 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy198.n = 0; yygotominor.yy198.z = 0;} -#line 2226 "ext/pdo_sqlite/sqlite/src/parse.c" + case 96: + case 167: +#line 302 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = yymsp[0].minor.yy46;} +#line 2165 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 80: -#line 312 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy198 = yymsp[-1].minor.yy0;} -#line 2231 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 312 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy410.n = 0; yygotominor.yy410.z = 0;} +#line 2170 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 85: -#line 318 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy418,yymsp[0].minor.yy280,yymsp[-2].minor.yy280);} -#line 2236 "ext/pdo_sqlite/sqlite/src/parse.c" + case 81: +#line 313 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy410 = yymsp[-1].minor.yy0;} +#line 2175 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 86: -#line 320 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy418,yymsp[0].minor.yy280,0,0);} -#line 2241 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 319 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy174,yymsp[0].minor.yy46,yymsp[-2].minor.yy46,0);} +#line 2180 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 87: +#line 321 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy174,yymsp[0].minor.yy46,0,0,0,0);} +#line 2185 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 88: -#line 323 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 322 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy172);} +#line 2190 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 89: +#line 324 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy418, &yymsp[-3].minor.yy198, yymsp[-2].minor.yy418, yymsp[-1].minor.yy280); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy280); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy174, &yymsp[-3].minor.yy410, yymsp[-2].minor.yy174, yymsp[-1].minor.yy46); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy46); } -#line 2249 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 91: - case 93: -#line 337 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = OE_Default;} -#line 2255 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2198 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 96: -#line 342 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = OE_Ignore;} -#line 2260 "ext/pdo_sqlite/sqlite/src/parse.c" + case 92: + case 94: +#line 338 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = OE_Default;} +#line 2204 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 97: - case 167: -#line 343 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = OE_Replace;} -#line 2266 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 343 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = OE_Ignore;} +#line 2209 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 98: -#line 347 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - sqlite3DropTable(pParse, yymsp[0].minor.yy151, 0); -} -#line 2273 "ext/pdo_sqlite/sqlite/src/parse.c" + case 168: +#line 344 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = OE_Replace;} +#line 2215 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 99: -#line 354 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 348 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy198, &yymsp[-2].minor.yy198, yymsp[0].minor.yy375, yymsp[-5].minor.yy280); + sqlite3DropTable(pParse, yymsp[0].minor.yy373, 0, yymsp[-1].minor.yy46); } -#line 2280 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2222 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 100: -#line 357 "ext/pdo_sqlite/sqlite/src/parse.y" + case 102: +#line 358 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3DropTable(pParse, yymsp[0].minor.yy151, 1); + sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy410, &yymsp[-2].minor.yy410, yymsp[0].minor.yy219, yymsp[-5].minor.yy46); } -#line 2287 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2229 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 101: -#line 364 "ext/pdo_sqlite/sqlite/src/parse.y" + case 103: +#line 361 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3Select(pParse, yymsp[0].minor.yy375, SRT_Callback, 0, 0, 0, 0, 0); - sqlite3SelectDelete(yymsp[0].minor.yy375); + sqlite3DropTable(pParse, yymsp[0].minor.yy373, 1, yymsp[-1].minor.yy46); } -#line 2295 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2236 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 102: - case 126: -#line 374 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy375 = yymsp[0].minor.yy375;} -#line 2301 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 103: -#line 376 "ext/pdo_sqlite/sqlite/src/parse.y" + case 104: +#line 368 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - if( yymsp[0].minor.yy375 ){ - yymsp[0].minor.yy375->op = yymsp[-1].minor.yy280; - yymsp[0].minor.yy375->pPrior = yymsp[-2].minor.yy375; - } - yygotominor.yy375 = yymsp[0].minor.yy375; + sqlite3Select(pParse, yymsp[0].minor.yy219, SRT_Callback, 0, 0, 0, 0, 0); + sqlite3SelectDelete(yymsp[0].minor.yy219); } -#line 2312 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2244 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 105: -#line 385 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = TK_ALL;} -#line 2317 "ext/pdo_sqlite/sqlite/src/parse.c" + case 128: +#line 378 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy219 = yymsp[0].minor.yy219;} +#line 2250 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 108: -#line 390 "ext/pdo_sqlite/sqlite/src/parse.y" + case 106: +#line 380 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy375 = sqlite3SelectNew(yymsp[-6].minor.yy418,yymsp[-5].minor.yy151,yymsp[-4].minor.yy62,yymsp[-3].minor.yy418,yymsp[-2].minor.yy62,yymsp[-1].minor.yy418,yymsp[-7].minor.yy280,yymsp[0].minor.yy220.pLimit,yymsp[0].minor.yy220.pOffset); + if( yymsp[0].minor.yy219 ){ + yymsp[0].minor.yy219->op = yymsp[-1].minor.yy46; + yymsp[0].minor.yy219->pPrior = yymsp[-2].minor.yy219; + } + yygotominor.yy219 = yymsp[0].minor.yy219; } -#line 2324 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2261 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 112: - case 248: -#line 411 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy418 = yymsp[-1].minor.yy418;} -#line 2330 "ext/pdo_sqlite/sqlite/src/parse.c" + case 108: +#line 389 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = TK_ALL;} +#line 2266 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 113: - case 140: - case 150: - case 247: -#line 412 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy418 = 0;} -#line 2338 "ext/pdo_sqlite/sqlite/src/parse.c" + case 110: +#line 393 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + yygotominor.yy219 = sqlite3SelectNew(yymsp[-6].minor.yy174,yymsp[-5].minor.yy373,yymsp[-4].minor.yy172,yymsp[-3].minor.yy174,yymsp[-2].minor.yy172,yymsp[-1].minor.yy174,yymsp[-7].minor.yy46,yymsp[0].minor.yy234.pLimit,yymsp[0].minor.yy234.pOffset); +} +#line 2273 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 114: -#line 413 "ext/pdo_sqlite/sqlite/src/parse.y" + case 237: +#line 414 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy174 = yymsp[-1].minor.yy174;} +#line 2279 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 115: + case 141: + case 151: + case 236: +#line 415 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy174 = 0;} +#line 2287 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 116: +#line 416 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-2].minor.yy418,yymsp[-1].minor.yy62,yymsp[0].minor.yy198.n?&yymsp[0].minor.yy198:0); + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-2].minor.yy174,yymsp[-1].minor.yy172,yymsp[0].minor.yy410.n?&yymsp[0].minor.yy410:0); } -#line 2345 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2294 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 115: -#line 416 "ext/pdo_sqlite/sqlite/src/parse.y" + case 117: +#line 419 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-1].minor.yy418, sqlite3Expr(TK_ALL, 0, 0, 0), 0); + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-1].minor.yy174, sqlite3Expr(TK_ALL, 0, 0, 0), 0); } -#line 2352 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2301 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 116: -#line 419 "ext/pdo_sqlite/sqlite/src/parse.y" + case 118: +#line 422 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0); - Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy198); - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-3].minor.yy418, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0); + Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy410); + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-3].minor.yy174, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0); } -#line 2361 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 119: -#line 431 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy198.n = 0;} -#line 2366 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 120: -#line 443 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy151 = sqliteMalloc(sizeof(*yygotominor.yy151));} -#line 2371 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2310 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 121: -#line 444 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy151 = yymsp[0].minor.yy151;} -#line 2376 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 434 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy410.n = 0;} +#line 2315 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 122: -#line 449 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - yygotominor.yy151 = yymsp[-1].minor.yy151; - if( yygotominor.yy151 && yygotominor.yy151->nSrc>0 ) yygotominor.yy151->a[yygotominor.yy151->nSrc-1].jointype = yymsp[0].minor.yy280; -} -#line 2384 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 446 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy373 = sqliteMalloc(sizeof(*yygotominor.yy373));} +#line 2320 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 123: -#line 453 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy151 = 0;} -#line 2389 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 447 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy373 = yymsp[0].minor.yy373;} +#line 2325 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 124: -#line 454 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 452 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy151 = sqlite3SrcListAppend(yymsp[-5].minor.yy151,&yymsp[-4].minor.yy198,&yymsp[-3].minor.yy198); - if( yymsp[-2].minor.yy198.n ) sqlite3SrcListAddAlias(yygotominor.yy151,&yymsp[-2].minor.yy198); - if( yymsp[-1].minor.yy62 ){ - if( yygotominor.yy151 && yygotominor.yy151->nSrc>1 ){ yygotominor.yy151->a[yygotominor.yy151->nSrc-2].pOn = yymsp[-1].minor.yy62; } - else { sqlite3ExprDelete(yymsp[-1].minor.yy62); } + yygotominor.yy373 = yymsp[-1].minor.yy373; + if( yygotominor.yy373 && yygotominor.yy373->nSrc>0 ) yygotominor.yy373->a[yygotominor.yy373->nSrc-1].jointype = yymsp[0].minor.yy46; +} +#line 2333 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 125: +#line 456 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy373 = 0;} +#line 2338 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 126: +#line 457 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + yygotominor.yy373 = sqlite3SrcListAppend(yymsp[-5].minor.yy373,&yymsp[-4].minor.yy410,&yymsp[-3].minor.yy410); + if( yymsp[-2].minor.yy410.n ) sqlite3SrcListAddAlias(yygotominor.yy373,&yymsp[-2].minor.yy410); + if( yymsp[-1].minor.yy172 ){ + if( yygotominor.yy373 && yygotominor.yy373->nSrc>1 ){ yygotominor.yy373->a[yygotominor.yy373->nSrc-2].pOn = yymsp[-1].minor.yy172; } + else { sqlite3ExprDelete(yymsp[-1].minor.yy172); } } - if( yymsp[0].minor.yy240 ){ - if( yygotominor.yy151 && yygotominor.yy151->nSrc>1 ){ yygotominor.yy151->a[yygotominor.yy151->nSrc-2].pUsing = yymsp[0].minor.yy240; } - else { sqlite3IdListDelete(yymsp[0].minor.yy240); } + if( yymsp[0].minor.yy432 ){ + if( yygotominor.yy373 && yygotominor.yy373->nSrc>1 ){ yygotominor.yy373->a[yygotominor.yy373->nSrc-2].pUsing = yymsp[0].minor.yy432; } + else { sqlite3IdListDelete(yymsp[0].minor.yy432); } } } -#line 2405 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2354 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 125: -#line 468 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - yygotominor.yy151 = sqlite3SrcListAppend(yymsp[-6].minor.yy151,0,0); - yygotominor.yy151->a[yygotominor.yy151->nSrc-1].pSelect = yymsp[-4].minor.yy375; - if( yymsp[-2].minor.yy198.n ) sqlite3SrcListAddAlias(yygotominor.yy151,&yymsp[-2].minor.yy198); - if( yymsp[-1].minor.yy62 ){ - if( yygotominor.yy151 && yygotominor.yy151->nSrc>1 ){ yygotominor.yy151->a[yygotominor.yy151->nSrc-2].pOn = yymsp[-1].minor.yy62; } - else { sqlite3ExprDelete(yymsp[-1].minor.yy62); } + case 127: +#line 471 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + yygotominor.yy373 = sqlite3SrcListAppend(yymsp[-6].minor.yy373,0,0); + if( yygotominor.yy373 && yygotominor.yy373->nSrc>0 ) yygotominor.yy373->a[yygotominor.yy373->nSrc-1].pSelect = yymsp[-4].minor.yy219; + if( yymsp[-2].minor.yy410.n ) sqlite3SrcListAddAlias(yygotominor.yy373,&yymsp[-2].minor.yy410); + if( yymsp[-1].minor.yy172 ){ + if( yygotominor.yy373 && yygotominor.yy373->nSrc>1 ){ yygotominor.yy373->a[yygotominor.yy373->nSrc-2].pOn = yymsp[-1].minor.yy172; } + else { sqlite3ExprDelete(yymsp[-1].minor.yy172); } } - if( yymsp[0].minor.yy240 ){ - if( yygotominor.yy151 && yygotominor.yy151->nSrc>1 ){ yygotominor.yy151->a[yygotominor.yy151->nSrc-2].pUsing = yymsp[0].minor.yy240; } - else { sqlite3IdListDelete(yymsp[0].minor.yy240); } + if( yymsp[0].minor.yy432 ){ + if( yygotominor.yy373 && yygotominor.yy373->nSrc>1 ){ yygotominor.yy373->a[yygotominor.yy373->nSrc-2].pUsing = yymsp[0].minor.yy432; } + else { sqlite3IdListDelete(yymsp[0].minor.yy432); } } } -#line 2422 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2371 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 127: -#line 489 "ext/pdo_sqlite/sqlite/src/parse.y" + case 129: +#line 492 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy375 = sqlite3SelectNew(0,yymsp[0].minor.yy151,0,0,0,0,0,0,0); + yygotominor.yy219 = sqlite3SelectNew(0,yymsp[0].minor.yy373,0,0,0,0,0,0,0); } -#line 2429 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 128: -#line 495 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy198.z=0; yygotominor.yy198.n=0;} -#line 2434 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2378 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 130: -#line 500 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy151 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy198,&yymsp[0].minor.yy198);} -#line 2439 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 498 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy410.z=0; yygotominor.yy410.n=0;} +#line 2383 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 131: case 132: -#line 504 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = JT_INNER; } -#line 2445 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 503 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy373 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410);} +#line 2388 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 133: -#line 506 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } -#line 2450 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 507 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = JT_INNER; } +#line 2393 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 134: -#line 507 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy198,0); } -#line 2455 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 508 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } +#line 2398 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 135: -#line 509 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy198,&yymsp[-1].minor.yy198); } -#line 2460 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 509 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy410,0); } +#line 2403 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 136: - case 144: - case 153: - case 160: - case 174: - case 211: - case 236: - case 238: - case 242: -#line 513 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy62 = yymsp[0].minor.yy62;} -#line 2473 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 511 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy410,&yymsp[-1].minor.yy410); } +#line 2408 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 137: - case 152: - case 159: - case 212: - case 237: - case 239: - case 243: -#line 514 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy62 = 0;} -#line 2484 "ext/pdo_sqlite/sqlite/src/parse.c" + case 145: + case 154: + case 161: + case 175: + case 202: + case 225: + case 227: + case 231: +#line 515 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy172 = yymsp[0].minor.yy172;} +#line 2421 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 138: - case 171: -#line 518 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy240 = yymsp[-1].minor.yy240;} -#line 2490 "ext/pdo_sqlite/sqlite/src/parse.c" + case 153: + case 160: + case 203: + case 226: + case 228: + case 232: +#line 516 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy172 = 0;} +#line 2432 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 139: - case 170: -#line 519 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy240 = 0;} -#line 2496 "ext/pdo_sqlite/sqlite/src/parse.c" + case 172: +#line 520 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy432 = yymsp[-1].minor.yy432;} +#line 2438 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 141: - case 151: -#line 530 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy418 = yymsp[0].minor.yy418;} -#line 2502 "ext/pdo_sqlite/sqlite/src/parse.c" + case 140: + case 171: +#line 521 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy432 = 0;} +#line 2444 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 142: -#line 531 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-4].minor.yy418,yymsp[-2].minor.yy62,yymsp[-1].minor.yy198.n>0?&yymsp[-1].minor.yy198:0); - if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280; -} -#line 2510 "ext/pdo_sqlite/sqlite/src/parse.c" + case 152: +#line 532 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy174 = yymsp[0].minor.yy174;} +#line 2450 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 143: -#line 535 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 533 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy418 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy62,yymsp[-1].minor.yy198.n>0?&yymsp[-1].minor.yy198:0); - if( yygotominor.yy418 && yygotominor.yy418->a ) yygotominor.yy418->a[0].sortOrder = yymsp[0].minor.yy280; + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-4].minor.yy174,yymsp[-2].minor.yy172,yymsp[-1].minor.yy410.n>0?&yymsp[-1].minor.yy410:0); + if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; } -#line 2518 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2458 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 145: - case 147: -#line 544 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = SQLITE_SO_ASC;} -#line 2524 "ext/pdo_sqlite/sqlite/src/parse.c" + case 144: +#line 537 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + yygotominor.yy174 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy172,yymsp[-1].minor.yy410.n>0?&yymsp[-1].minor.yy410:0); + if( yygotominor.yy174 && yygotominor.yy174->a ) yygotominor.yy174->a[0].sortOrder = yymsp[0].minor.yy46; +} +#line 2466 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 146: -#line 545 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = SQLITE_SO_DESC;} -#line 2529 "ext/pdo_sqlite/sqlite/src/parse.c" - break; case 148: -#line 547 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy198.z = 0; yygotominor.yy198.n = 0;} -#line 2534 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 546 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = SQLITE_SO_ASC;} +#line 2472 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 154: -#line 565 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy220.pLimit = 0; yygotominor.yy220.pOffset = 0;} -#line 2539 "ext/pdo_sqlite/sqlite/src/parse.c" + case 147: +#line 547 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = SQLITE_SO_DESC;} +#line 2477 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 149: +#line 549 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy410.z = 0; yygotominor.yy410.n = 0;} +#line 2482 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 155: -#line 566 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy220.pLimit = yymsp[0].minor.yy62; yygotominor.yy220.pOffset = 0;} -#line 2544 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 567 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy234.pLimit = 0; yygotominor.yy234.pOffset = 0;} +#line 2487 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 156: -#line 568 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy220.pLimit = yymsp[-2].minor.yy62; yygotominor.yy220.pOffset = yymsp[0].minor.yy62;} -#line 2549 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 568 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy234.pLimit = yymsp[0].minor.yy172; yygotominor.yy234.pOffset = 0;} +#line 2492 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 157: -#line 570 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy220.pOffset = yymsp[-2].minor.yy62; yygotominor.yy220.pLimit = yymsp[0].minor.yy62;} -#line 2554 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 570 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy234.pLimit = yymsp[-2].minor.yy172; yygotominor.yy234.pOffset = yymsp[0].minor.yy172;} +#line 2497 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 158: -#line 574 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy151,yymsp[0].minor.yy62);} -#line 2559 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 572 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy234.pOffset = yymsp[-2].minor.yy172; yygotominor.yy234.pLimit = yymsp[0].minor.yy172;} +#line 2502 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 161: -#line 585 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Update(pParse,yymsp[-3].minor.yy151,yymsp[-1].minor.yy418,yymsp[0].minor.yy62,yymsp[-4].minor.yy280);} -#line 2564 "ext/pdo_sqlite/sqlite/src/parse.c" + case 159: +#line 576 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy373,yymsp[0].minor.yy172);} +#line 2507 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 162: -#line 591 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-4].minor.yy418,yymsp[0].minor.yy62,&yymsp[-2].minor.yy198);} -#line 2569 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 587 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Update(pParse,yymsp[-3].minor.yy373,yymsp[-1].minor.yy174,yymsp[0].minor.yy172,yymsp[-4].minor.yy46);} +#line 2512 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 163: -#line 592 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy418 = sqlite3ExprListAppend(0,yymsp[0].minor.yy62,&yymsp[-2].minor.yy198);} -#line 2574 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 593 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-4].minor.yy174,yymsp[0].minor.yy172,&yymsp[-2].minor.yy410);} +#line 2517 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 164: -#line 598 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Insert(pParse, yymsp[-5].minor.yy151, yymsp[-1].minor.yy418, 0, yymsp[-4].minor.yy240, yymsp[-7].minor.yy280);} -#line 2579 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 594 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(0,yymsp[0].minor.yy172,&yymsp[-2].minor.yy410);} +#line 2522 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 165: -#line 600 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Insert(pParse, yymsp[-2].minor.yy151, 0, yymsp[0].minor.yy375, yymsp[-1].minor.yy240, yymsp[-4].minor.yy280);} -#line 2584 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 600 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Insert(pParse, yymsp[-5].minor.yy373, yymsp[-1].minor.yy174, 0, yymsp[-4].minor.yy432, yymsp[-7].minor.yy46);} +#line 2527 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 168: - case 240: -#line 610 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-2].minor.yy418,yymsp[0].minor.yy62,0);} -#line 2590 "ext/pdo_sqlite/sqlite/src/parse.c" + case 166: +#line 602 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Insert(pParse, yymsp[-2].minor.yy373, 0, yymsp[0].minor.yy219, yymsp[-1].minor.yy432, yymsp[-4].minor.yy46);} +#line 2532 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 169: - case 241: -#line 611 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy418 = sqlite3ExprListAppend(0,yymsp[0].minor.yy62,0);} -#line 2596 "ext/pdo_sqlite/sqlite/src/parse.c" + case 229: +#line 612 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-2].minor.yy174,yymsp[0].minor.yy172,0);} +#line 2538 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 172: -#line 620 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy240 = sqlite3IdListAppend(yymsp[-2].minor.yy240,&yymsp[0].minor.yy198);} -#line 2601 "ext/pdo_sqlite/sqlite/src/parse.c" + case 170: + case 230: +#line 613 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(0,yymsp[0].minor.yy172,0);} +#line 2544 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 173: -#line 621 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy240 = sqlite3IdListAppend(0,&yymsp[0].minor.yy198);} -#line 2606 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 622 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy432 = sqlite3IdListAppend(yymsp[-2].minor.yy432,&yymsp[0].minor.yy410);} +#line 2549 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 175: -#line 632 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy62 = yymsp[-1].minor.yy62; sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } -#line 2611 "ext/pdo_sqlite/sqlite/src/parse.c" + case 174: +#line 623 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy432 = sqlite3IdListAppend(0,&yymsp[0].minor.yy410);} +#line 2554 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 176: - case 181: +#line 634 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy172 = yymsp[-1].minor.yy172; sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } +#line 2559 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 177: case 182: case 183: - case 184: -#line 633 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy62 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} -#line 2620 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 635 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy172 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} +#line 2566 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 177: case 178: -#line 634 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy62 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} -#line 2626 "ext/pdo_sqlite/sqlite/src/parse.c" - break; case 179: -#line 636 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 636 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy172 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} +#line 2572 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 180: +#line 638 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy198); - Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy198); - yygotominor.yy62 = sqlite3Expr(TK_DOT, temp1, temp2, 0); + Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy410); + Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy410); + yygotominor.yy172 = sqlite3Expr(TK_DOT, temp1, temp2, 0); } -#line 2635 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2581 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 180: -#line 641 "ext/pdo_sqlite/sqlite/src/parse.y" + case 181: +#line 643 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy198); - Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy198); - Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy198); + Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy410); + Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy410); + Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy410); Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0); - yygotominor.yy62 = sqlite3Expr(TK_DOT, temp1, temp4, 0); + yygotominor.yy172 = sqlite3Expr(TK_DOT, temp1, temp4, 0); } -#line 2646 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2592 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 185: -#line 652 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy62 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} -#line 2651 "ext/pdo_sqlite/sqlite/src/parse.c" + case 184: +#line 652 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy172 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} +#line 2597 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 186: -#line 653 "ext/pdo_sqlite/sqlite/src/parse.y" + case 185: +#line 653 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { Token *pToken = &yymsp[0].minor.yy0; - Expr *pExpr = yygotominor.yy62 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); + Expr *pExpr = yygotominor.yy172 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); sqlite3ExprAssignVarNumber(pParse, pExpr); } -#line 2660 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2606 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 187: -#line 659 "ext/pdo_sqlite/sqlite/src/parse.y" + case 186: +#line 659 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy62, 0, &yymsp[-1].minor.yy198); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy172, 0, &yymsp[-1].minor.yy410); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); } -#line 2668 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2614 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 188: -#line 664 "ext/pdo_sqlite/sqlite/src/parse.y" + case 187: +#line 664 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3ExprFunction(yymsp[-1].minor.yy418, &yymsp[-4].minor.yy0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy280 ){ - yygotominor.yy62->flags |= EP_Distinct; + yygotominor.yy172 = sqlite3ExprFunction(yymsp[-1].minor.yy174, &yymsp[-4].minor.yy0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + if( yymsp[-2].minor.yy46 && yygotominor.yy172 ){ + yygotominor.yy172->flags |= EP_Distinct; } } -#line 2679 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2625 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 189: -#line 671 "ext/pdo_sqlite/sqlite/src/parse.y" + case 188: +#line 671 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } -#line 2687 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2633 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 190: -#line 675 "ext/pdo_sqlite/sqlite/src/parse.y" + case 189: +#line 675 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are ** treated as functions that return constants */ - yygotominor.yy62 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0); - if( yygotominor.yy62 ) yygotominor.yy62->op = TK_CONST_FUNC; + yygotominor.yy172 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0); + if( yygotominor.yy172 ) yygotominor.yy172->op = TK_CONST_FUNC; } -#line 2697 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2643 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; + case 190: case 191: case 192: case 193: @@ -2701,516 +2647,534 @@ static void yy_reduce( case 195: case 196: case 197: +#line 681 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy172 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy172, yymsp[0].minor.yy172, 0);} +#line 2655 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; case 198: - case 199: case 200: - case 201: - case 202: - case 203: - case 204: - case 205: - case 206: - case 207: - case 208: -#line 681 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy62 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy62, yymsp[0].minor.yy62, 0);} -#line 2719 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 209: -#line 700 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy222.operator = yymsp[0].minor.yy0; yygotominor.yy222.not = 0;} -#line 2724 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 691 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 0;} +#line 2661 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 210: -#line 701 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy222.operator = yymsp[0].minor.yy0; yygotominor.yy222.not = 1;} -#line 2729 "ext/pdo_sqlite/sqlite/src/parse.c" + case 199: + case 201: +#line 692 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 1;} +#line 2667 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 213: -#line 705 "ext/pdo_sqlite/sqlite/src/parse.y" + case 204: +#line 699 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - ExprList *pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy62, 0); - pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy62, 0); - if( yymsp[0].minor.yy62 ){ - pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy62, 0); + ExprList *pList; + pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy172, 0); + pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy172, 0); + if( yymsp[0].minor.yy172 ){ + pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy172, 0); } - yygotominor.yy62 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy222.operator); - if( yymsp[-2].minor.yy222.not ) yygotominor.yy62 = sqlite3Expr(TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-3].minor.yy62->span, &yymsp[-1].minor.yy62->span); + yygotominor.yy172 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy72.eOperator); + if( yymsp[-2].minor.yy72.not ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy172->span, &yymsp[-1].minor.yy172->span); + if( yygotominor.yy172 ) yygotominor.yy172->flags |= EP_InfixFunc; } -#line 2743 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2683 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 214: -#line 716 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - yygotominor.yy62 = sqlite3Expr(TK_ISNULL, yymsp[-1].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy62->span,&yymsp[0].minor.yy0); -} -#line 2751 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 215: -#line 720 "ext/pdo_sqlite/sqlite/src/parse.y" + case 205: +#line 712 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy62->span,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(yymsp[0].major, yymsp[-1].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2759 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2691 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 216: -#line 724 "ext/pdo_sqlite/sqlite/src/parse.y" + case 206: +#line 716 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_NOTNULL, yymsp[-1].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy62->span,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2767 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2699 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 217: -#line 728 "ext/pdo_sqlite/sqlite/src/parse.y" + case 207: +#line 720 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy62->span,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2775 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2707 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 218: -#line 732 "ext/pdo_sqlite/sqlite/src/parse.y" + case 208: +#line 724 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy62->span,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2783 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2715 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 219: - case 220: -#line 736 "ext/pdo_sqlite/sqlite/src/parse.y" + case 209: +#line 728 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span); + yygotominor.yy172 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span); } -#line 2792 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2723 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 221: -#line 744 "ext/pdo_sqlite/sqlite/src/parse.y" + case 210: +#line 732 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span); + yygotominor.yy172 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span); } -#line 2800 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2731 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 222: -#line 748 "ext/pdo_sqlite/sqlite/src/parse.y" + case 211: +#line 736 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span); + yygotominor.yy172 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span); } -#line 2808 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2739 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 225: -#line 755 "ext/pdo_sqlite/sqlite/src/parse.y" + case 214: +#line 743 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy62, 0); - pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy62, 0); - yygotominor.yy62 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pList = pList; + ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy172, 0); + pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy172, 0); + yygotominor.yy172 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pList = pList; }else{ sqlite3ExprListDelete(pList); } - if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3Expr(TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy62->span); + if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy172->span); } -#line 2824 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2755 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 228: -#line 771 "ext/pdo_sqlite/sqlite/src/parse.y" + case 217: +#line 759 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pList = yymsp[-1].minor.yy418; + yygotominor.yy172 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pList = yymsp[-1].minor.yy174; }else{ - sqlite3ExprListDelete(yymsp[-1].minor.yy418); + sqlite3ExprListDelete(yymsp[-1].minor.yy174); } - if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3Expr(TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy0); + if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2838 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2769 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 229: -#line 781 "ext/pdo_sqlite/sqlite/src/parse.y" + case 218: +#line 769 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_SELECT, 0, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pSelect = yymsp[-1].minor.yy375; + yygotominor.yy172 = sqlite3Expr(TK_SELECT, 0, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pSelect = yymsp[-1].minor.yy219; }else{ - sqlite3SelectDelete(yymsp[-1].minor.yy375); + sqlite3SelectDelete(yymsp[-1].minor.yy219); } - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } -#line 2851 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2782 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 230: -#line 790 "ext/pdo_sqlite/sqlite/src/parse.y" + case 219: +#line 778 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pSelect = yymsp[-1].minor.yy375; + yygotominor.yy172 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pSelect = yymsp[-1].minor.yy219; }else{ - sqlite3SelectDelete(yymsp[-1].minor.yy375); + sqlite3SelectDelete(yymsp[-1].minor.yy219); } - if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3Expr(TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy0); + if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2865 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2796 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 231: -#line 800 "ext/pdo_sqlite/sqlite/src/parse.y" + case 220: +#line 788 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy198,&yymsp[0].minor.yy198); - yygotominor.yy62 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0); + SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410); + yygotominor.yy172 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0); }else{ sqlite3SrcListDelete(pSrc); } - if( yymsp[-2].minor.yy280 ) yygotominor.yy62 = sqlite3Expr(TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy62->span,yymsp[0].minor.yy198.z?&yymsp[0].minor.yy198:&yymsp[-1].minor.yy198); + if( yymsp[-2].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,yymsp[0].minor.yy410.z?&yymsp[0].minor.yy410:&yymsp[-1].minor.yy410); } -#line 2880 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2811 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 232: -#line 811 "ext/pdo_sqlite/sqlite/src/parse.y" + case 221: +#line 799 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - Expr *p = yygotominor.yy62 = sqlite3Expr(TK_EXISTS, 0, 0, 0); + Expr *p = yygotominor.yy172 = sqlite3Expr(TK_EXISTS, 0, 0, 0); if( p ){ - p->pSelect = yymsp[-1].minor.yy375; + p->pSelect = yymsp[-1].minor.yy219; sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); }else{ - sqlite3SelectDelete(yymsp[-1].minor.yy375); + sqlite3SelectDelete(yymsp[-1].minor.yy219); } } -#line 2893 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2824 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 233: -#line 823 "ext/pdo_sqlite/sqlite/src/parse.y" + case 222: +#line 811 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy62, yymsp[-1].minor.yy62, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pList = yymsp[-2].minor.yy418; + yygotominor.yy172 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pList = yymsp[-2].minor.yy174; }else{ - sqlite3ExprListDelete(yymsp[-2].minor.yy418); + sqlite3ExprListDelete(yymsp[-2].minor.yy174); } - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); } -#line 2906 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2837 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 234: -#line 834 "ext/pdo_sqlite/sqlite/src/parse.y" + case 223: +#line 822 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-4].minor.yy418, yymsp[-2].minor.yy62, 0); - yygotominor.yy418 = sqlite3ExprListAppend(yygotominor.yy418, yymsp[0].minor.yy62, 0); + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-4].minor.yy174, yymsp[-2].minor.yy172, 0); + yygotominor.yy174 = sqlite3ExprListAppend(yygotominor.yy174, yymsp[0].minor.yy172, 0); } -#line 2914 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2845 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 235: -#line 838 "ext/pdo_sqlite/sqlite/src/parse.y" + case 224: +#line 826 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yygotominor.yy418 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy62, 0); - yygotominor.yy418 = sqlite3ExprListAppend(yygotominor.yy418, yymsp[0].minor.yy62, 0); + yygotominor.yy174 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy172, 0); + yygotominor.yy174 = sqlite3ExprListAppend(yygotominor.yy174, yymsp[0].minor.yy172, 0); } -#line 2922 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2853 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 244: -#line 863 "ext/pdo_sqlite/sqlite/src/parse.y" + case 233: +#line 853 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - if( yymsp[-9].minor.yy280!=OE_None ) yymsp[-9].minor.yy280 = yymsp[0].minor.yy280; - if( yymsp[-9].minor.yy280==OE_Default) yymsp[-9].minor.yy280 = OE_Abort; - sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy198, &yymsp[-6].minor.yy198, sqlite3SrcListAppend(0,&yymsp[-4].minor.yy198,0),yymsp[-2].minor.yy418,yymsp[-9].minor.yy280, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0); + sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy410, &yymsp[-5].minor.yy410, sqlite3SrcListAppend(0,&yymsp[-3].minor.yy410,0), yymsp[-1].minor.yy174, yymsp[-9].minor.yy46, + &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy46); } -#line 2931 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2861 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 245: - case 292: -#line 870 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = OE_Abort;} -#line 2937 "ext/pdo_sqlite/sqlite/src/parse.c" + case 234: + case 279: +#line 859 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = OE_Abort;} +#line 2867 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 246: -#line 871 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = OE_None;} -#line 2942 "ext/pdo_sqlite/sqlite/src/parse.c" + case 235: +#line 860 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = OE_None;} +#line 2872 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 249: -#line 881 "ext/pdo_sqlite/sqlite/src/parse.y" + case 238: +#line 870 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { Expr *p = 0; - if( yymsp[-1].minor.yy198.n>0 ){ + if( yymsp[-1].minor.yy410.n>0 ){ p = sqlite3Expr(TK_COLUMN, 0, 0, 0); - if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy198.z, yymsp[-1].minor.yy198.n); + if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy410.z, yymsp[-1].minor.yy410.n); } - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-4].minor.yy418, p, &yymsp[-2].minor.yy198); + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-4].minor.yy174, p, &yymsp[-2].minor.yy410); + if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; } -#line 2954 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2885 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 250: -#line 889 "ext/pdo_sqlite/sqlite/src/parse.y" + case 239: +#line 879 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { Expr *p = 0; - if( yymsp[-1].minor.yy198.n>0 ){ + if( yymsp[-1].minor.yy410.n>0 ){ p = sqlite3Expr(TK_COLUMN, 0, 0, 0); - if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy198.z, yymsp[-1].minor.yy198.n); + if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy410.z, yymsp[-1].minor.yy410.n); } - yygotominor.yy418 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy198); + yygotominor.yy174 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy410); + if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; } -#line 2966 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2898 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 252: -#line 902 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3DropIndex(pParse, yymsp[0].minor.yy151);} -#line 2971 "ext/pdo_sqlite/sqlite/src/parse.c" + case 241: +#line 893 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3DropIndex(pParse, yymsp[0].minor.yy373, yymsp[-1].minor.yy46);} +#line 2903 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 253: - case 254: -#line 906 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Vacuum(pParse,0);} -#line 2977 "ext/pdo_sqlite/sqlite/src/parse.c" + case 242: + case 243: +#line 897 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Vacuum(pParse);} +#line 2909 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 255: - case 257: -#line 912 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Pragma(pParse,&yymsp[-3].minor.yy198,&yymsp[-2].minor.yy198,&yymsp[0].minor.yy198,0);} -#line 2983 "ext/pdo_sqlite/sqlite/src/parse.c" + case 244: + case 246: +#line 903 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy410,0);} +#line 2915 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 256: -#line 913 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Pragma(pParse,&yymsp[-3].minor.yy198,&yymsp[-2].minor.yy198,&yymsp[0].minor.yy0,0);} -#line 2988 "ext/pdo_sqlite/sqlite/src/parse.c" + case 245: +#line 904 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy0,0);} +#line 2920 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 258: -#line 915 "ext/pdo_sqlite/sqlite/src/parse.y" + case 247: +#line 906 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3Pragma(pParse,&yymsp[-3].minor.yy198,&yymsp[-2].minor.yy198,&yymsp[0].minor.yy198,1); + sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy410,1); } -#line 2995 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2927 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 259: -#line 918 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Pragma(pParse,&yymsp[-4].minor.yy198,&yymsp[-3].minor.yy198,&yymsp[-1].minor.yy198,0);} -#line 3000 "ext/pdo_sqlite/sqlite/src/parse.c" + case 248: +#line 909 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Pragma(pParse,&yymsp[-4].minor.yy410,&yymsp[-3].minor.yy410,&yymsp[-1].minor.yy410,0);} +#line 2932 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 260: -#line 919 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Pragma(pParse,&yymsp[-1].minor.yy198,&yymsp[0].minor.yy198,0,0);} -#line 3005 "ext/pdo_sqlite/sqlite/src/parse.c" + case 249: +#line 910 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Pragma(pParse,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410,0,0);} +#line 2937 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 267: -#line 932 "ext/pdo_sqlite/sqlite/src/parse.y" + case 255: +#line 922 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { Token all; - all.z = yymsp[-3].minor.yy198.z; - all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy198.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy360, &all); + all.z = yymsp[-3].minor.yy410.z; + all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy410.z) + yymsp[0].minor.yy0.n; + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy243, &all); } -#line 3015 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2947 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 268: -#line 941 "ext/pdo_sqlite/sqlite/src/parse.y" + case 256: +#line 931 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy198, &yymsp[-6].minor.yy198, yymsp[-5].minor.yy280, yymsp[-4].minor.yy30.a, yymsp[-4].minor.yy30.b, yymsp[-2].minor.yy151, yymsp[-1].minor.yy280, yymsp[0].minor.yy62, yymsp[-9].minor.yy280); - yygotominor.yy198 = (yymsp[-6].minor.yy198.n==0?yymsp[-7].minor.yy198:yymsp[-6].minor.yy198); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy410, &yymsp[-6].minor.yy410, yymsp[-5].minor.yy46, yymsp[-4].minor.yy370.a, yymsp[-4].minor.yy370.b, yymsp[-2].minor.yy373, yymsp[-1].minor.yy46, yymsp[0].minor.yy172, yymsp[-9].minor.yy46); + yygotominor.yy410 = (yymsp[-6].minor.yy410.n==0?yymsp[-7].minor.yy410:yymsp[-6].minor.yy410); } -#line 3023 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 2955 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 257: + case 260: +#line 937 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = TK_BEFORE; } +#line 2961 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 258: +#line 938 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = TK_AFTER; } +#line 2966 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 259: +#line 939 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = TK_INSTEAD;} +#line 2971 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 261: + case 262: +#line 944 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy370.a = yymsp[0].major; yygotominor.yy370.b = 0;} +#line 2977 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 263: +#line 946 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy370.a = TK_UPDATE; yygotominor.yy370.b = yymsp[0].minor.yy432;} +#line 2982 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 264: + case 265: +#line 949 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = TK_ROW; } +#line 2988 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 266: +#line 951 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy46 = TK_STATEMENT; } +#line 2993 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 267: +#line 955 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy172 = 0; } +#line 2998 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 268: +#line 956 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy172 = yymsp[0].minor.yy172; } +#line 3003 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 269: - case 272: -#line 947 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = TK_BEFORE; } -#line 3029 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 960 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + if( yymsp[-2].minor.yy243 ){ + yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243; + }else{ + yymsp[-2].minor.yy243 = yymsp[-1].minor.yy243; + } + yymsp[-2].minor.yy243->pLast = yymsp[-1].minor.yy243; + yygotominor.yy243 = yymsp[-2].minor.yy243; +} +#line 3016 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 270: -#line 948 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = TK_AFTER; } -#line 3034 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 969 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy243 = 0; } +#line 3021 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 271: -#line 949 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = TK_INSTEAD;} -#line 3039 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 975 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy243 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy410, yymsp[-1].minor.yy174, yymsp[0].minor.yy172, yymsp[-4].minor.yy46); } +#line 3026 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; + case 272: +#line 980 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy243 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy410, yymsp[-4].minor.yy432, yymsp[-1].minor.yy174, 0, yymsp[-7].minor.yy46);} +#line 3031 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 273: +#line 983 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy243 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy410, yymsp[-1].minor.yy432, 0, yymsp[0].minor.yy219, yymsp[-4].minor.yy46);} +#line 3036 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; case 274: +#line 987 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy243 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy410, yymsp[0].minor.yy172);} +#line 3041 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" + break; case 275: -#line 954 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy30.a = yymsp[0].major; yygotominor.yy30.b = 0;} -#line 3046 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 990 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy243 = sqlite3TriggerSelectStep(yymsp[0].minor.yy219); } +#line 3046 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 276: -#line 957 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy30.a = TK_UPDATE; yygotominor.yy30.b = yymsp[0].minor.yy240;} -#line 3051 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 993 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_RAISE, 0, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->iColumn = OE_Ignore; + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); + } +} +#line 3057 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 277: - case 278: -#line 960 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = TK_ROW; } -#line 3057 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1000 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy410); + if( yygotominor.yy172 ) { + yygotominor.yy172->iColumn = yymsp[-3].minor.yy46; + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); + } +} +#line 3068 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 279: -#line 962 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy280 = TK_STATEMENT; } -#line 3062 "ext/pdo_sqlite/sqlite/src/parse.c" + case 278: +#line 1010 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = OE_Rollback;} +#line 3073 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 280: -#line 965 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy62 = 0; } -#line 3067 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1012 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{yygotominor.yy46 = OE_Fail;} +#line 3078 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 281: -#line 966 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy62 = yymsp[0].minor.yy62; } -#line 3072 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1017 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + sqlite3DropTrigger(pParse,yymsp[0].minor.yy373); +} +#line 3085 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 282: -#line 970 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 1023 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - yymsp[-2].minor.yy360->pNext = yymsp[0].minor.yy360; - yygotominor.yy360 = yymsp[-2].minor.yy360; + sqlite3Attach(pParse, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, yymsp[0].minor.yy386); } -#line 3080 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 3092 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 283: -#line 974 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy360 = 0; } -#line 3085 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1028 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy386 = 0; } +#line 3097 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 284: -#line 980 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy360 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy198, yymsp[-1].minor.yy418, yymsp[0].minor.yy62, yymsp[-4].minor.yy280); } -#line 3090 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 285: -#line 985 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy360 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy198, yymsp[-4].minor.yy240, yymsp[-1].minor.yy418, 0, yymsp[-7].minor.yy280);} -#line 3095 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 286: -#line 988 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy360 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy198, yymsp[-1].minor.yy240, 0, yymsp[0].minor.yy375, yymsp[-4].minor.yy280);} -#line 3100 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1029 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ yygotominor.yy386 = yymsp[0].minor.yy172; } +#line 3102 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 287: -#line 992 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy360 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy198, yymsp[0].minor.yy62);} -#line 3105 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1035 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + sqlite3Detach(pParse, yymsp[0].minor.yy172); +} +#line 3109 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 288: -#line 995 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy360 = sqlite3TriggerSelectStep(yymsp[0].minor.yy375); } -#line 3110 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1041 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Reindex(pParse, 0, 0);} +#line 3114 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 289: -#line 998 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - yygotominor.yy62 = sqlite3Expr(TK_RAISE, 0, 0, 0); - yygotominor.yy62->iColumn = OE_Ignore; - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); -} -#line 3119 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1042 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Reindex(pParse, &yymsp[-1].minor.yy410, &yymsp[0].minor.yy410);} +#line 3119 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 290: -#line 1003 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - yygotominor.yy62 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy198); - yygotominor.yy62->iColumn = yymsp[-3].minor.yy280; - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); -} -#line 3128 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1047 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Analyze(pParse, 0, 0);} +#line 3124 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 291: -#line 1011 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = OE_Rollback;} -#line 3133 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 293: -#line 1013 "ext/pdo_sqlite/sqlite/src/parse.y" -{yygotominor.yy280 = OE_Fail;} -#line 3138 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1048 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3Analyze(pParse, &yymsp[-1].minor.yy410, &yymsp[0].minor.yy410);} +#line 3129 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 294: -#line 1018 "ext/pdo_sqlite/sqlite/src/parse.y" + case 292: +#line 1053 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy151); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy373,&yymsp[0].minor.yy410); } -#line 3145 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 3136 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 295: -#line 1024 "ext/pdo_sqlite/sqlite/src/parse.y" + case 293: +#line 1056 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3Attach(pParse, &yymsp[-3].minor.yy198, &yymsp[-1].minor.yy198, yymsp[0].minor.yy361.type, &yymsp[0].minor.yy361.key); + sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy410); } -#line 3152 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 3143 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 296: -#line 1028 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy361.type = 0; } -#line 3157 "ext/pdo_sqlite/sqlite/src/parse.c" + case 294: +#line 1059 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{ + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy373); +} +#line 3150 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 297: -#line 1029 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy361.type=1; yygotominor.yy361.key = yymsp[0].minor.yy198; } -#line 3162 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1068 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3VtabFinishParse(pParse,0);} +#line 3155 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 298: -#line 1030 "ext/pdo_sqlite/sqlite/src/parse.y" -{ yygotominor.yy361.type=2; yygotominor.yy361.key = yymsp[0].minor.yy0; } -#line 3167 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1069 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} +#line 3160 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; - case 301: -#line 1036 "ext/pdo_sqlite/sqlite/src/parse.y" + case 299: +#line 1070 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" { - sqlite3Detach(pParse, &yymsp[0].minor.yy198); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy410, &yymsp[-2].minor.yy410, &yymsp[0].minor.yy410); } -#line 3174 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 3167 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 302: -#line 1042 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Reindex(pParse, 0, 0);} -#line 3179 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 303: -#line 1043 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Reindex(pParse, &yymsp[-1].minor.yy198, &yymsp[0].minor.yy198);} -#line 3184 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1075 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3VtabArgInit(pParse);} +#line 3172 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; case 304: -#line 1048 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Analyze(pParse, 0, 0);} -#line 3189 "ext/pdo_sqlite/sqlite/src/parse.c" - break; case 305: -#line 1049 "ext/pdo_sqlite/sqlite/src/parse.y" -{sqlite3Analyze(pParse, &yymsp[-1].minor.yy198, &yymsp[0].minor.yy198);} -#line 3194 "ext/pdo_sqlite/sqlite/src/parse.c" - break; case 306: -#line 1054 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy151,&yymsp[0].minor.yy198); -} -#line 3201 "ext/pdo_sqlite/sqlite/src/parse.c" - break; - case 307: -#line 1057 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy198); -} -#line 3208 "ext/pdo_sqlite/sqlite/src/parse.c" - break; case 308: -#line 1060 "ext/pdo_sqlite/sqlite/src/parse.y" -{ - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy151); -} -#line 3215 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 1077 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" +{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} +#line 3180 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" break; }; yygoto = yyRuleInfo[yyruleno].lhs; @@ -3267,16 +3231,17 @@ static void yy_syntax_error( ){ sqlite3ParserARG_FETCH; #define TOKEN (yyminor.yy0) -#line 34 "ext/pdo_sqlite/sqlite/src/parse.y" +#line 34 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.y" - if( pParse->zErrMsg==0 ){ + if( !pParse->parseError ){ if( TOKEN.z[0] ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); }else{ sqlite3ErrorMsg(pParse, "incomplete SQL statement"); } + pParse->parseError = 1; } -#line 3282 "ext/pdo_sqlite/sqlite/src/parse.c" +#line 3248 "/home/rei/php_dev/php52/ext/pdo_sqlite/sqlite/src/parse.c" sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } @@ -3404,7 +3369,9 @@ void sqlite3Parser( while( yypParser->yyidx >= 0 && yymx != YYERRORSYMBOL && - (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE + (yyact = yy_find_reduce_action( + yypParser->yystack[yypParser->yyidx].stateno, + YYERRORSYMBOL)) >= YYNSTATE ){ yy_pop_parser_stack(yypParser); } diff --git a/ext/pdo_sqlite/sqlite/src/parse.h b/ext/pdo_sqlite/sqlite/src/parse.h index fcedda5896..65c9a5ce90 100644 --- a/ext/pdo_sqlite/sqlite/src/parse.h +++ b/ext/pdo_sqlite/sqlite/src/parse.h @@ -1,145 +1,153 @@ -#define TK_END_OF_FILE 1 -#define TK_ILLEGAL 2 -#define TK_SPACE 3 -#define TK_UNCLOSED_STRING 4 -#define TK_COMMENT 5 -#define TK_FUNCTION 6 -#define TK_COLUMN 7 -#define TK_AGG_FUNCTION 8 -#define TK_AGG_COLUMN 9 -#define TK_CONST_FUNC 10 -#define TK_SEMI 11 -#define TK_EXPLAIN 12 -#define TK_QUERY 13 -#define TK_PLAN 14 -#define TK_BEGIN 15 -#define TK_TRANSACTION 16 -#define TK_DEFERRED 17 -#define TK_IMMEDIATE 18 -#define TK_EXCLUSIVE 19 -#define TK_COMMIT 20 -#define TK_END 21 -#define TK_ROLLBACK 22 -#define TK_CREATE 23 -#define TK_TABLE 24 -#define TK_TEMP 25 -#define TK_LP 26 -#define TK_RP 27 -#define TK_AS 28 -#define TK_COMMA 29 -#define TK_ID 30 -#define TK_ABORT 31 -#define TK_AFTER 32 -#define TK_ANALYZE 33 -#define TK_ASC 34 -#define TK_ATTACH 35 -#define TK_BEFORE 36 -#define TK_CASCADE 37 -#define TK_CAST 38 -#define TK_CONFLICT 39 -#define TK_DATABASE 40 -#define TK_DESC 41 -#define TK_DETACH 42 -#define TK_EACH 43 -#define TK_FAIL 44 -#define TK_FOR 45 -#define TK_IGNORE 46 -#define TK_INITIALLY 47 -#define TK_INSTEAD 48 -#define TK_LIKE_KW 49 -#define TK_MATCH 50 -#define TK_KEY 51 -#define TK_OF 52 -#define TK_OFFSET 53 -#define TK_PRAGMA 54 -#define TK_RAISE 55 -#define TK_REPLACE 56 -#define TK_RESTRICT 57 -#define TK_ROW 58 -#define TK_STATEMENT 59 -#define TK_TRIGGER 60 -#define TK_VACUUM 61 -#define TK_VIEW 62 -#define TK_REINDEX 63 -#define TK_RENAME 64 -#define TK_CTIME_KW 65 -#define TK_ALTER 66 -#define TK_OR 67 -#define TK_AND 68 -#define TK_NOT 69 -#define TK_IS 70 -#define TK_BETWEEN 71 -#define TK_IN 72 -#define TK_ISNULL 73 -#define TK_NOTNULL 74 -#define TK_NE 75 -#define TK_EQ 76 -#define TK_GT 77 -#define TK_LE 78 -#define TK_LT 79 -#define TK_GE 80 -#define TK_ESCAPE 81 -#define TK_BITAND 82 -#define TK_BITOR 83 -#define TK_LSHIFT 84 -#define TK_RSHIFT 85 -#define TK_PLUS 86 -#define TK_MINUS 87 -#define TK_STAR 88 -#define TK_SLASH 89 -#define TK_REM 90 -#define TK_CONCAT 91 -#define TK_UMINUS 92 -#define TK_UPLUS 93 -#define TK_BITNOT 94 -#define TK_STRING 95 -#define TK_JOIN_KW 96 -#define TK_CONSTRAINT 97 -#define TK_DEFAULT 98 -#define TK_NULL 99 -#define TK_PRIMARY 100 -#define TK_UNIQUE 101 -#define TK_CHECK 102 -#define TK_REFERENCES 103 -#define TK_COLLATE 104 -#define TK_AUTOINCR 105 -#define TK_ON 106 -#define TK_DELETE 107 -#define TK_UPDATE 108 -#define TK_INSERT 109 -#define TK_SET 110 -#define TK_DEFERRABLE 111 -#define TK_FOREIGN 112 -#define TK_DROP 113 -#define TK_UNION 114 -#define TK_ALL 115 -#define TK_INTERSECT 116 -#define TK_EXCEPT 117 -#define TK_SELECT 118 -#define TK_DISTINCT 119 -#define TK_DOT 120 -#define TK_FROM 121 -#define TK_JOIN 122 -#define TK_USING 123 -#define TK_ORDER 124 -#define TK_BY 125 -#define TK_GROUP 126 -#define TK_HAVING 127 -#define TK_LIMIT 128 -#define TK_WHERE 129 -#define TK_INTO 130 -#define TK_VALUES 131 -#define TK_INTEGER 132 -#define TK_FLOAT 133 -#define TK_BLOB 134 -#define TK_REGISTER 135 -#define TK_VARIABLE 136 -#define TK_EXISTS 137 -#define TK_CASE 138 -#define TK_WHEN 139 -#define TK_THEN 140 -#define TK_ELSE 141 -#define TK_INDEX 142 -#define TK_TO 143 -#define TK_ADD 144 -#define TK_COLUMNKW 145 +#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_CREATE 13 +#define TK_TABLE 14 +#define TK_IF 15 +#define TK_NOT 16 +#define TK_EXISTS 17 +#define TK_TEMP 18 +#define TK_LP 19 +#define TK_RP 20 +#define TK_AS 21 +#define TK_COMMA 22 +#define TK_ID 23 +#define TK_ABORT 24 +#define TK_AFTER 25 +#define TK_ANALYZE 26 +#define TK_ASC 27 +#define TK_ATTACH 28 +#define TK_BEFORE 29 +#define TK_CASCADE 30 +#define TK_CAST 31 +#define TK_CONFLICT 32 +#define TK_DATABASE 33 +#define TK_DESC 34 +#define TK_DETACH 35 +#define TK_EACH 36 +#define TK_FAIL 37 +#define TK_FOR 38 +#define TK_IGNORE 39 +#define TK_INITIALLY 40 +#define TK_INSTEAD 41 +#define TK_LIKE_KW 42 +#define TK_MATCH 43 +#define TK_KEY 44 +#define TK_OF 45 +#define TK_OFFSET 46 +#define TK_PRAGMA 47 +#define TK_RAISE 48 +#define TK_REPLACE 49 +#define TK_RESTRICT 50 +#define TK_ROW 51 +#define TK_STATEMENT 52 +#define TK_TRIGGER 53 +#define TK_VACUUM 54 +#define TK_VIEW 55 +#define TK_VIRTUAL 56 +#define TK_REINDEX 57 +#define TK_RENAME 58 +#define TK_CTIME_KW 59 +#define TK_ANY 60 +#define TK_OR 61 +#define TK_AND 62 +#define TK_IS 63 +#define TK_BETWEEN 64 +#define TK_IN 65 +#define TK_ISNULL 66 +#define TK_NOTNULL 67 +#define TK_NE 68 +#define TK_EQ 69 +#define TK_GT 70 +#define TK_LE 71 +#define TK_LT 72 +#define TK_GE 73 +#define TK_ESCAPE 74 +#define TK_BITAND 75 +#define TK_BITOR 76 +#define TK_LSHIFT 77 +#define TK_RSHIFT 78 +#define TK_PLUS 79 +#define TK_MINUS 80 +#define TK_STAR 81 +#define TK_SLASH 82 +#define TK_REM 83 +#define TK_CONCAT 84 +#define TK_UMINUS 85 +#define TK_UPLUS 86 +#define TK_BITNOT 87 +#define TK_STRING 88 +#define TK_JOIN_KW 89 +#define TK_CONSTRAINT 90 +#define TK_DEFAULT 91 +#define TK_NULL 92 +#define TK_PRIMARY 93 +#define TK_UNIQUE 94 +#define TK_CHECK 95 +#define TK_REFERENCES 96 +#define TK_COLLATE 97 +#define TK_AUTOINCR 98 +#define TK_ON 99 +#define TK_DELETE 100 +#define TK_UPDATE 101 +#define TK_INSERT 102 +#define TK_SET 103 +#define TK_DEFERRABLE 104 +#define TK_FOREIGN 105 +#define TK_DROP 106 +#define TK_UNION 107 +#define TK_ALL 108 +#define TK_EXCEPT 109 +#define TK_INTERSECT 110 +#define TK_SELECT 111 +#define TK_DISTINCT 112 +#define TK_DOT 113 +#define TK_FROM 114 +#define TK_JOIN 115 +#define TK_USING 116 +#define TK_ORDER 117 +#define TK_BY 118 +#define TK_GROUP 119 +#define TK_HAVING 120 +#define TK_LIMIT 121 +#define TK_WHERE 122 +#define TK_INTO 123 +#define TK_VALUES 124 +#define TK_INTEGER 125 +#define TK_FLOAT 126 +#define TK_BLOB 127 +#define TK_REGISTER 128 +#define TK_VARIABLE 129 +#define TK_CASE 130 +#define TK_WHEN 131 +#define TK_THEN 132 +#define TK_ELSE 133 +#define TK_INDEX 134 +#define TK_ALTER 135 +#define TK_TO 136 +#define TK_ADD 137 +#define TK_COLUMNKW 138 +#define TK_TO_TEXT 139 +#define TK_TO_BLOB 140 +#define TK_TO_NUMERIC 141 +#define TK_TO_INT 142 +#define TK_TO_REAL 143 +#define TK_END_OF_FILE 144 +#define TK_ILLEGAL 145 +#define TK_SPACE 146 +#define TK_UNCLOSED_STRING 147 +#define TK_COMMENT 148 +#define TK_FUNCTION 149 +#define TK_COLUMN 150 +#define TK_AGG_FUNCTION 151 +#define TK_AGG_COLUMN 152 +#define TK_CONST_FUNC 153 diff --git a/ext/pdo_sqlite/sqlite/src/parse.y b/ext/pdo_sqlite/sqlite/src/parse.y index 1f16c20a8c..301eb9b8e5 100644 --- a/ext/pdo_sqlite/sqlite/src/parse.y +++ b/ext/pdo_sqlite/sqlite/src/parse.y @@ -32,14 +32,19 @@ // This code runs whenever there is a syntax error // %syntax_error { - if( pParse->zErrMsg==0 ){ + if( !pParse->parseError ){ if( TOKEN.z[0] ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); }else{ sqlite3ErrorMsg(pParse, "incomplete SQL statement"); } + pParse->parseError = 1; } } +%stack_overflow { + sqlite3ErrorMsg(pParse, "parser stack overflow"); + pParse->parseError = 1; +} // The name of the generated procedure that implements the parser // is as follows: @@ -66,7 +71,7 @@ struct LimitVal { ** GLOB, NOT LIKE, and NOT GLOB operators. */ struct LikeOp { - Token operator; /* "like" or "glob" or "regexp" */ + Token eOperator; /* "like" or "glob" or "regexp" */ int not; /* True if the NOT keyword is present */ }; @@ -88,13 +93,6 @@ struct AttachKey { int type; Token key; }; } // end %include -// These are extra tokens used by the lexer but never seen by the -// parser. We put them in a rule so that the parser generator will -// add them to the parse.h output file. -// -%nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION - COLUMN AGG_FUNCTION AGG_COLUMN CONST_FUNC. - // Input is a single SQL command input ::= cmdlist. cmdlist ::= cmdlist ecmd. @@ -127,9 +125,12 @@ cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);} ///////////////////// The CREATE TABLE statement //////////////////////////// // cmd ::= create_table create_table_args. -create_table ::= CREATE(X) temp(T) TABLE nm(Y) dbnm(Z). { - sqlite3StartTable(pParse,&X,&Y,&Z,T,0); +create_table ::= CREATE temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). { + sqlite3StartTable(pParse,&Y,&Z,T,0,0,E); } +%type ifnotexists {int} +ifnotexists(A) ::= . {A = 0;} +ifnotexists(A) ::= IF NOT EXISTS. {A = 1;} %type temp {int} %ifndef SQLITE_OMIT_TEMPDB temp(A) ::= TEMP. {A = 1;} @@ -175,12 +176,13 @@ id(A) ::= ID(X). {A = X;} DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH PLAN QUERY KEY OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT - TEMP TRIGGER VACUUM VIEW + TEMP TRIGGER VACUUM VIEW VIRTUAL %ifdef SQLITE_OMIT_COMPOUND_SELECT EXCEPT INTERSECT UNION %endif - REINDEX RENAME CTIME_KW ALTER + REINDEX RENAME CTIME_KW IF . +%wildcard ANY. // Define operator precedence early so that this is the first occurance // of the operator tokens in the grammer. Keeping the operators together @@ -196,7 +198,7 @@ id(A) ::= ID(X). {A = X;} %left OR. %left AND. %right NOT. -%left IS LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ. +%left IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ. %left GT LE LT GE. %right ESCAPE. %left BITAND BITOR LSHIFT RSHIFT. @@ -208,8 +210,7 @@ id(A) ::= ID(X). {A = X;} // And "ids" is an identifer-or-string. // %type ids {Token} -ids(A) ::= ID(X). {A = X;} -ids(A) ::= STRING(X). {A = X;} +ids(A) ::= ID|STRING(X). {A = X;} // The name of a column or table can be any of the following: // @@ -238,8 +239,8 @@ typetoken(A) ::= typename(X) LP signed COMMA signed RP(Y). { typename(A) ::= ids(X). {A = X;} typename(A) ::= typename(X) ids(Y). {A.z=X.z; A.n=Y.n+(Y.z-X.z);} %type signed {int} -signed(A) ::= plus_num(X). { A = atoi(X.z); } -signed(A) ::= minus_num(X). { A = -atoi(X.z); } +signed(A) ::= plus_num(X). { A = atoi((char*)X.z); } +signed(A) ::= minus_num(X). { A = -atoi((char*)X.z); } // "carglist" is a list of additional constraints that come after the // column name and column type in a CREATE TABLE statement. @@ -265,14 +266,14 @@ carg ::= DEFAULT id(X). { // ccons ::= NULL onconf. ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);} -ccons ::= PRIMARY KEY sortorder onconf(R) autoinc(I). - {sqlite3AddPrimaryKey(pParse,0,R,I);} -ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0);} -ccons ::= CHECK LP expr(X) RP onconf. {sqlite3ExprDelete(X);} +ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I). + {sqlite3AddPrimaryKey(pParse,0,R,I,Z);} +ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);} +ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X);} ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);} -ccons ::= COLLATE id(C). {sqlite3AddCollateType(pParse, C.z, C.n);} +ccons ::= COLLATE id(C). {sqlite3AddCollateType(pParse, (char*)C.z, C.n);} // The optional AUTOINCREMENT keyword %type autoinc {int} @@ -315,10 +316,10 @@ conslist ::= conslist tcons. conslist ::= tcons. tcons ::= CONSTRAINT nm. tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R). - {sqlite3AddPrimaryKey(pParse,X,R,I);} + {sqlite3AddPrimaryKey(pParse,X,R,I,0);} tcons ::= UNIQUE LP idxlist(X) RP onconf(R). - {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0);} -tcons ::= CHECK expr onconf. + {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);} +tcons ::= CHECK LP expr(E) RP onconf. {sqlite3AddCheckConstraint(pParse,E);} tcons ::= FOREIGN KEY LP idxlist(FA) RP REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). { sqlite3CreateForeignKey(pParse, FA, &T, TA, R); @@ -344,9 +345,12 @@ resolvetype(A) ::= REPLACE. {A = OE_Replace;} ////////////////////////// The DROP TABLE ///////////////////////////////////// // -cmd ::= DROP TABLE fullname(X). { - sqlite3DropTable(pParse, X, 0); +cmd ::= DROP TABLE ifexists(E) fullname(X). { + sqlite3DropTable(pParse, X, 0, E); } +%type ifexists {int} +ifexists(A) ::= IF EXISTS. {A = 1;} +ifexists(A) ::= . {A = 0;} ///////////////////// The CREATE VIEW statement ///////////////////////////// // @@ -354,8 +358,8 @@ cmd ::= DROP TABLE fullname(X). { cmd ::= CREATE(X) temp(T) VIEW nm(Y) dbnm(Z) AS select(S). { sqlite3CreateView(pParse, &X, &Y, &Z, S, T); } -cmd ::= DROP VIEW fullname(X). { - sqlite3DropTable(pParse, X, 1); +cmd ::= DROP VIEW ifexists(E) fullname(X). { + sqlite3DropTable(pParse, X, 1, E); } %endif // SQLITE_OMIT_VIEW @@ -381,10 +385,9 @@ select(A) ::= select(X) multiselect_op(Y) oneselect(Z). { A = Z; } %type multiselect_op {int} -multiselect_op(A) ::= UNION(OP). {A = @OP;} -multiselect_op(A) ::= UNION ALL. {A = TK_ALL;} -multiselect_op(A) ::= INTERSECT(OP). {A = @OP;} -multiselect_op(A) ::= EXCEPT(OP). {A = @OP;} +multiselect_op(A) ::= UNION(OP). {A = @OP;} +multiselect_op(A) ::= UNION ALL. {A = TK_ALL;} +multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP;} %endif // SQLITE_OMIT_COMPOUND_SELECT oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). { @@ -467,7 +470,7 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). { seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP as(Z) on_opt(N) using_opt(U). { A = sqlite3SrcListAppend(X,0,0); - A->a[A->nSrc-1].pSelect = S; + if( A && A->nSrc>0 ) A->a[A->nSrc-1].pSelect = S; if( Z.n ) sqlite3SrcListAddAlias(A,&Z); if( N ){ if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; } @@ -479,7 +482,7 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). { } } - // A seltablist_paren nonterminal represents anything in a FROM that + // A seltablist_paren nonterminal represents anything in a FROM that // is contained inside parentheses. This can be either a subquery or // a grouping of table and subqueries. // @@ -501,8 +504,7 @@ fullname(A) ::= nm(X) dbnm(Y). {A = sqlite3SrcListAppend(0,&X,&Y);} %type joinop {int} %type joinop2 {int} -joinop(X) ::= COMMA. { X = JT_INNER; } -joinop(X) ::= JOIN. { X = JT_INNER; } +joinop(X) ::= COMMA|JOIN. { X = JT_INNER; } joinop(X) ::= JOIN_KW(A) JOIN. { X = sqlite3JoinType(pParse,&A,0,0); } joinop(X) ::= JOIN_KW(A) nm(B) JOIN. { X = sqlite3JoinType(pParse,&A,&B,0); } joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN. @@ -645,10 +647,8 @@ expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0); A = sqlite3Expr(TK_DOT, temp1, temp4, 0); } -term(A) ::= INTEGER(X). {A = sqlite3Expr(@X, 0, 0, &X);} -term(A) ::= FLOAT(X). {A = sqlite3Expr(@X, 0, 0, &X);} +term(A) ::= INTEGER|FLOAT|BLOB(X). {A = sqlite3Expr(@X, 0, 0, &X);} term(A) ::= STRING(X). {A = sqlite3Expr(@X, 0, 0, &X);} -term(A) ::= BLOB(X). {A = sqlite3Expr(@X, 0, 0, &X);} expr(A) ::= REGISTER(X). {A = sqlite3RegisterExpr(pParse, &X);} expr(A) ::= VARIABLE(X). { Token *pToken = &X; @@ -664,7 +664,7 @@ expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). { expr(A) ::= ID(X) LP distinct(D) exprlist(Y) RP(E). { A = sqlite3ExprFunction(Y, &X); sqlite3ExprSpan(A,&X,&E); - if( D ){ + if( D && A ){ A->flags |= EP_Distinct; } } @@ -678,53 +678,45 @@ term(A) ::= CTIME_KW(OP). { A = sqlite3ExprFunction(0,&OP); if( A ) A->op = TK_CONST_FUNC; } -expr(A) ::= expr(X) AND(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) OR(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) LT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) GT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) LE(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) GE(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) NE(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) EQ(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) BITAND(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) BITOR(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) LSHIFT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) RSHIFT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) PLUS(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) MINUS(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) STAR(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) SLASH(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) REM(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} -expr(A) ::= expr(X) CONCAT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) AND(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) OR(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) EQ|NE(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y). + {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} +expr(A) ::= expr(X) CONCAT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);} %type likeop {struct LikeOp} -likeop(A) ::= LIKE_KW(X). {A.operator = X; A.not = 0;} -likeop(A) ::= NOT LIKE_KW(X). {A.operator = X; A.not = 1;} +likeop(A) ::= LIKE_KW(X). {A.eOperator = X; A.not = 0;} +likeop(A) ::= NOT LIKE_KW(X). {A.eOperator = X; A.not = 1;} +likeop(A) ::= MATCH(X). {A.eOperator = X; A.not = 0;} +likeop(A) ::= NOT MATCH(X). {A.eOperator = X; A.not = 1;} %type escape {Expr*} +%destructor escape {sqlite3ExprDelete($$);} escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;} escape(X) ::= . [ESCAPE] {X = 0;} expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] { - ExprList *pList = sqlite3ExprListAppend(0, Y, 0); + ExprList *pList; + pList = sqlite3ExprListAppend(0, Y, 0); pList = sqlite3ExprListAppend(pList, X, 0); if( E ){ pList = sqlite3ExprListAppend(pList, E, 0); } - A = sqlite3ExprFunction(pList, &OP.operator); + A = sqlite3ExprFunction(pList, &OP.eOperator); if( OP.not ) A = sqlite3Expr(TK_NOT, A, 0, 0); sqlite3ExprSpan(A, &X->span, &Y->span); + if( A ) A->flags |= EP_InfixFunc; } -expr(A) ::= expr(X) ISNULL(E). { - A = sqlite3Expr(TK_ISNULL, X, 0, 0); +expr(A) ::= expr(X) ISNULL|NOTNULL(E). { + A = sqlite3Expr(@E, X, 0, 0); sqlite3ExprSpan(A,&X->span,&E); } expr(A) ::= expr(X) IS NULL(E). { A = sqlite3Expr(TK_ISNULL, X, 0, 0); sqlite3ExprSpan(A,&X->span,&E); } -expr(A) ::= expr(X) NOTNULL(E). { - A = sqlite3Expr(TK_NOTNULL, X, 0, 0); - sqlite3ExprSpan(A,&X->span,&E); -} expr(A) ::= expr(X) NOT NULL(E). { A = sqlite3Expr(TK_NOTNULL, X, 0, 0); sqlite3ExprSpan(A,&X->span,&E); @@ -733,11 +725,7 @@ expr(A) ::= expr(X) IS NOT NULL(E). { A = sqlite3Expr(TK_NOTNULL, X, 0, 0); sqlite3ExprSpan(A,&X->span,&E); } -expr(A) ::= NOT(B) expr(X). { - A = sqlite3Expr(@B, X, 0, 0); - sqlite3ExprSpan(A,&B,&X->span); -} -expr(A) ::= BITNOT(B) expr(X). { +expr(A) ::= NOT|BITNOT(B) expr(X). { A = sqlite3Expr(@B, X, 0, 0); sqlite3ExprSpan(A,&B,&X->span); } @@ -840,9 +828,11 @@ case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). { A = sqlite3ExprListAppend(A, Z, 0); } %type case_else {Expr*} +%destructor case_else {sqlite3ExprDelete($$);} case_else(A) ::= ELSE expr(X). {A = X;} case_else(A) ::= . {A = 0;} %type case_operand {Expr*} +%destructor case_operand {sqlite3ExprDelete($$);} case_operand(A) ::= expr(X). {A = X;} case_operand(A) ::= . {A = 0;} @@ -859,11 +849,10 @@ expritem(A) ::= . {A = 0;} ///////////////////////////// The CREATE INDEX command /////////////////////// // -cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X) dbnm(D) - ON nm(Y) LP idxlist(Z) RP(E) onconf(R). { - if( U!=OE_None ) U = R; - if( U==OE_Default) U = OE_Abort; - sqlite3CreateIndex(pParse, &X, &D, sqlite3SrcListAppend(0,&Y,0),Z,U, &S, &E); +cmd ::= CREATE(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D) + ON nm(Y) LP idxlist(Z) RP(E). { + sqlite3CreateIndex(pParse, &X, &D, sqlite3SrcListAppend(0,&Y,0), Z, U, + &S, &E, SQLITE_SO_ASC, NE); } %type uniqueflag {int} @@ -878,33 +867,35 @@ uniqueflag(A) ::= . {A = OE_None;} idxlist_opt(A) ::= . {A = 0;} idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} -idxlist(A) ::= idxlist(X) COMMA idxitem(Y) collate(C) sortorder. { +idxlist(A) ::= idxlist(X) COMMA idxitem(Y) collate(C) sortorder(Z). { Expr *p = 0; if( C.n>0 ){ p = sqlite3Expr(TK_COLUMN, 0, 0, 0); - if( p ) p->pColl = sqlite3LocateCollSeq(pParse, C.z, C.n); + if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)C.z, C.n); } A = sqlite3ExprListAppend(X, p, &Y); + if( A ) A->a[A->nExpr-1].sortOrder = Z; } -idxlist(A) ::= idxitem(Y) collate(C) sortorder. { +idxlist(A) ::= idxitem(Y) collate(C) sortorder(Z). { Expr *p = 0; if( C.n>0 ){ p = sqlite3Expr(TK_COLUMN, 0, 0, 0); - if( p ) p->pColl = sqlite3LocateCollSeq(pParse, C.z, C.n); + if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)C.z, C.n); } A = sqlite3ExprListAppend(0, p, &Y); + if( A ) A->a[A->nExpr-1].sortOrder = Z; } idxitem(A) ::= nm(X). {A = X;} ///////////////////////////// The DROP INDEX command ///////////////////////// // -cmd ::= DROP INDEX fullname(X). {sqlite3DropIndex(pParse, X);} +cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);} ///////////////////////////// The VACUUM command ///////////////////////////// // -cmd ::= VACUUM. {sqlite3Vacuum(pParse,0);} -cmd ::= VACUUM nm. {sqlite3Vacuum(pParse,0);} +cmd ::= VACUUM. {sqlite3Vacuum(pParse);} +cmd ::= VACUUM nm. {sqlite3Vacuum(pParse);} ///////////////////////////// The PRAGMA command ///////////////////////////// // @@ -920,8 +911,7 @@ cmd ::= PRAGMA nm(X) dbnm(Z). {sqlite3Pragma(pParse,&X,&Z,0,0);} %endif // SQLITE_OMIT_PRAGMA plus_num(A) ::= plus_opt number(X). {A = X;} minus_num(A) ::= MINUS number(X). {A = X;} -number(A) ::= INTEGER(X). {A = X;} -number(A) ::= FLOAT(X). {A = X;} +number(A) ::= INTEGER|FLOAT(X). {A = X;} plus_opt ::= PLUS. plus_opt ::= . @@ -951,8 +941,7 @@ trigger_time(A) ::= . { A = TK_BEFORE; } %type trigger_event {struct TrigEvent} %destructor trigger_event {sqlite3IdListDelete($$.b);} -trigger_event(A) ::= DELETE(OP). {A.a = @OP; A.b = 0;} -trigger_event(A) ::= INSERT(OP). {A.a = @OP; A.b = 0;} +trigger_event(A) ::= DELETE|INSERT(OP). {A.a = @OP; A.b = 0;} trigger_event(A) ::= UPDATE(OP). {A.a = @OP; A.b = 0;} trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X;} @@ -962,14 +951,20 @@ foreach_clause(A) ::= FOR EACH ROW. { A = TK_ROW; } foreach_clause(A) ::= FOR EACH STATEMENT. { A = TK_STATEMENT; } %type when_clause {Expr*} +%destructor when_clause {sqlite3ExprDelete($$);} when_clause(A) ::= . { A = 0; } when_clause(A) ::= WHEN expr(X). { A = X; } %type trigger_cmd_list {TriggerStep*} %destructor trigger_cmd_list {sqlite3DeleteTriggerStep($$);} -trigger_cmd_list(A) ::= trigger_cmd(X) SEMI trigger_cmd_list(Y). { - X->pNext = Y; - A = X; +trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. { + if( Y ){ + Y->pLast->pNext = X; + }else{ + Y = X; + } + Y->pLast = X; + A = Y; } trigger_cmd_list(A) ::= . { A = 0; } @@ -997,13 +992,17 @@ trigger_cmd(A) ::= select(X). {A = sqlite3TriggerSelectStep(X); } // The special RAISE expression that may occur in trigger programs expr(A) ::= RAISE(X) LP IGNORE RP(Y). { A = sqlite3Expr(TK_RAISE, 0, 0, 0); - A->iColumn = OE_Ignore; - sqlite3ExprSpan(A, &X, &Y); + if( A ){ + A->iColumn = OE_Ignore; + sqlite3ExprSpan(A, &X, &Y); + } } expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). { A = sqlite3Expr(TK_RAISE, 0, 0, &Z); - A->iColumn = T; - sqlite3ExprSpan(A, &X, &Y); + if( A ) { + A->iColumn = T; + sqlite3ExprSpan(A, &X, &Y); + } } %endif // !SQLITE_OMIT_TRIGGER @@ -1021,20 +1020,20 @@ cmd ::= DROP TRIGGER fullname(X). { %endif // !SQLITE_OMIT_TRIGGER //////////////////////// ATTACH DATABASE file AS name ///////////////////////// -cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). { - sqlite3Attach(pParse, &F, &D, K.type, &K.key); +cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). { + sqlite3Attach(pParse, F, D, K); } -%type key_opt {struct AttachKey} -key_opt(A) ::= . { A.type = 0; } -key_opt(A) ::= KEY ids(X). { A.type=1; A.key = X; } -key_opt(A) ::= KEY BLOB(X). { A.type=2; A.key = X; } +%type key_opt {Expr *} +%destructor key_opt {sqlite3ExprDelete($$);} +key_opt(A) ::= . { A = 0; } +key_opt(A) ::= KEY expr(X). { A = X; } database_kw_opt ::= DATABASE. database_kw_opt ::= . //////////////////////// DETACH DATABASE name ///////////////////////////////// -cmd ::= DETACH database_kw_opt nm(D). { - sqlite3Detach(pParse, &D); +cmd ::= DETACH database_kw_opt expr(D). { + sqlite3Detach(pParse, D); } ////////////////////////// REINDEX collation ////////////////////////////////// @@ -1063,3 +1062,21 @@ add_column_fullname ::= fullname(X). { kwcolumn_opt ::= . kwcolumn_opt ::= COLUMNKW. %endif + +//////////////////////// CREATE VIRTUAL TABLE ... ///////////////////////////// +%ifndef SQLITE_OMIT_VIRTUALTABLE +cmd ::= create_vtab. {sqlite3VtabFinishParse(pParse,0);} +cmd ::= create_vtab LP vtabarglist RP(X). {sqlite3VtabFinishParse(pParse,&X);} +create_vtab ::= CREATE VIRTUAL TABLE nm(X) dbnm(Y) USING nm(Z). { + sqlite3VtabBeginParse(pParse, &X, &Y, &Z); +} +vtabarglist ::= vtabarg. +vtabarglist ::= vtabarglist COMMA vtabarg. +vtabarg ::= . {sqlite3VtabArgInit(pParse);} +vtabarg ::= vtabarg vtabargtoken. +vtabargtoken ::= ANY(X). {sqlite3VtabArgExtend(pParse,&X);} +vtabargtoken ::= lp anylist RP(X). {sqlite3VtabArgExtend(pParse,&X);} +lp ::= LP(X). {sqlite3VtabArgExtend(pParse,&X);} +anylist ::= . +anylist ::= anylist ANY(X). {sqlite3VtabArgExtend(pParse,&X);} +%endif diff --git a/ext/pdo_sqlite/sqlite/src/pragma.c b/ext/pdo_sqlite/sqlite/src/pragma.c index e366401d26..fbcc1adc01 100644 --- a/ext/pdo_sqlite/sqlite/src/pragma.c +++ b/ext/pdo_sqlite/sqlite/src/pragma.c @@ -36,7 +36,7 @@ ** to support legacy SQL code. The safety level used to be boolean ** and older scripts may have used numbers 0 for OFF and 1 for ON. */ -static int getSafetyLevel(const u8 *z){ +static int getSafetyLevel(const char *z){ /* 123456789 123456789 */ static const char zText[] = "onoffalseyestruefull"; static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; @@ -58,7 +58,7 @@ static int getSafetyLevel(const u8 *z){ /* ** Interpret the given string as a boolean value. */ -static int getBoolean(const u8 *z){ +static int getBoolean(const char *z){ return getSafetyLevel(z)&1; } @@ -128,7 +128,7 @@ static void returnSingleInt(Parse *pParse, const char *zLabel, int value){ sqlite3VdbeAddOp(v, OP_Integer, value, 0); if( pParse->explain==0 ){ sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, zLabel, P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P3_STATIC); } sqlite3VdbeAddOp(v, OP_Callback, 1, 0); } @@ -151,9 +151,18 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ { "short_column_names", SQLITE_ShortColNames }, { "count_changes", SQLITE_CountRows }, { "empty_result_callbacks", SQLITE_NullCallback }, + { "legacy_file_format", SQLITE_LegacyFileFmt }, + { "fullfsync", SQLITE_FullFSync }, +#ifndef SQLITE_OMIT_CHECK + { "ignore_check_constraints", SQLITE_IgnoreChecks }, +#endif /* The following is VERY experimental */ { "writable_schema", SQLITE_WriteSchema }, { "omit_readlock", SQLITE_NoReadlock }, + + /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted + ** flag if there are any active statements. */ + { "read_uncommitted", SQLITE_ReadUncommitted }, }; int i; const struct sPragmaType *p; @@ -172,10 +181,6 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ db->flags &= ~p->mask; } } - /* If one of these pragmas is executed, any prepared statements - ** need to be recompiled. - */ - sqlite3VdbeAddOp(v, OP_Expire, 0, 0); } return 1; } @@ -222,6 +227,13 @@ void sqlite3Pragma( if( iDb<0 ) return; pDb = &db->aDb[iDb]; + /* If the temp database has been explicitly named as part of the + ** pragma, make sure it is open. + */ + if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){ + return; + } + zLeft = sqlite3NameFromToken(pId); if( !zLeft ) return; if( minusFlag ){ @@ -266,7 +278,7 @@ void sqlite3Pragma( if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( !zRight ){ sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "cache_size", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P3_STATIC); addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+5, MAX_PAGES); @@ -280,8 +292,8 @@ void sqlite3Pragma( sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3); sqlite3VdbeAddOp(v, OP_Negative, 0, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2); - pDb->cache_size = size; - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size); + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } }else @@ -342,12 +354,12 @@ void sqlite3Pragma( if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( !zRight ){ - returnSingleInt(pParse, "cache_size", pDb->cache_size); + returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); }else{ int size = atoi(zRight); if( size<0 ) size = -size; - pDb->cache_size = size; - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size); + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } }else @@ -384,7 +396,8 @@ void sqlite3Pragma( if( !zRight ){ if( sqlite3_temp_directory ){ sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "temp_store_directory", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, + "temp_store_directory", P3_STATIC); sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3_temp_directory, 0); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); } @@ -428,7 +441,6 @@ void sqlite3Pragma( "Safety level may not be changed inside a transaction"); }else{ pDb->safety_level = getSafetyLevel(zRight)+1; - sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level); } } }else @@ -460,22 +472,23 @@ void sqlite3Pragma( pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ int i; + Column *pCol; sqlite3VdbeSetNumCols(v, 6); - sqlite3VdbeSetColName(v, 0, "cid", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); - sqlite3VdbeSetColName(v, 2, "type", P3_STATIC); - sqlite3VdbeSetColName(v, 3, "notnull", P3_STATIC); - sqlite3VdbeSetColName(v, 4, "dflt_value", P3_STATIC); - sqlite3VdbeSetColName(v, 5, "pk", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", P3_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", P3_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", P3_STATIC); + sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P3_STATIC); sqlite3ViewGetColumnNames(pParse, pTab); - for(i=0; inCol; i++){ + for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ sqlite3VdbeAddOp(v, OP_Integer, i, 0); - sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zName, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pCol->zName, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, - pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0); - sqlite3VdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0); - sqlite3ExprCode(pParse, pTab->aCol[i].pDflt); - sqlite3VdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0); + pCol->zType ? pCol->zType : "", 0); + sqlite3VdbeAddOp(v, OP_Integer, pCol->notNull, 0); + sqlite3ExprCode(pParse, pCol->pDflt); + sqlite3VdbeAddOp(v, OP_Integer, pCol->isPrimKey, 0); sqlite3VdbeAddOp(v, OP_Callback, 6, 0); } } @@ -490,9 +503,9 @@ void sqlite3Pragma( int i; pTab = pIdx->pTable; sqlite3VdbeSetNumCols(v, 3); - sqlite3VdbeSetColName(v, 0, "seqno", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "cid", P3_STATIC); - sqlite3VdbeSetColName(v, 2, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", P3_STATIC); for(i=0; inColumn; i++){ int cnum = pIdx->aiColumn[i]; sqlite3VdbeAddOp(v, OP_Integer, i, 0); @@ -515,9 +528,9 @@ void sqlite3Pragma( if( pIdx ){ int i = 0; sqlite3VdbeSetNumCols(v, 3); - sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); - sqlite3VdbeSetColName(v, 2, "unique", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", P3_STATIC); while(pIdx){ sqlite3VdbeAddOp(v, OP_Integer, i, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0); @@ -534,9 +547,9 @@ void sqlite3Pragma( int i; if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 3); - sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); - sqlite3VdbeSetColName(v, 2, "file", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", P3_STATIC); for(i=0; inDb; i++){ if( db->aDb[i].pBt==0 ) continue; assert( db->aDb[i].zName!=0 ); @@ -552,8 +565,8 @@ void sqlite3Pragma( int i = 0; HashElem *p; sqlite3VdbeSetNumCols(v, 2); - sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ CollSeq *pColl = (CollSeq *)sqliteHashData(p); sqlite3VdbeAddOp(v, OP_Integer, i++, 0); @@ -575,11 +588,11 @@ void sqlite3Pragma( if( pFK ){ int i = 0; sqlite3VdbeSetNumCols(v, 5); - sqlite3VdbeSetColName(v, 0, "id", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "seq", P3_STATIC); - sqlite3VdbeSetColName(v, 2, "table", P3_STATIC); - sqlite3VdbeSetColName(v, 3, "from", P3_STATIC); - sqlite3VdbeSetColName(v, 4, "to", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", P3_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", P3_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", P3_STATIC); while(pFK){ int j; for(j=0; jnCol; j++){ @@ -641,12 +654,13 @@ void sqlite3Pragma( /* Initialize the VDBE program */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "integrity_check", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P3_STATIC); sqlite3VdbeAddOp(v, OP_MemInt, 0, 0); /* Initialize error count to 0 */ /* Do an integrity check on each database file */ for(i=0; inDb; i++){ HashElem *x; + Hash *pTbls; int cnt = 0; if( OMIT_TEMPDB && i==1 ) continue; @@ -655,13 +669,13 @@ void sqlite3Pragma( /* Do an integrity check of the B-Tree */ - for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ + pTbls = &db->aDb[i].pSchema->tblHash; + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; sqlite3VdbeAddOp(v, OP_Integer, pTab->tnum, 0); cnt++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) goto pragma_out; sqlite3VdbeAddOp(v, OP_Integer, pIdx->tnum, 0); cnt++; } @@ -670,18 +684,19 @@ void sqlite3Pragma( sqlite3VdbeAddOp(v, OP_IntegrityCk, cnt, i); sqlite3VdbeAddOp(v, OP_Dup, 0, 1); addr = sqlite3VdbeOp3(v, OP_String8, 0, 0, "ok", P3_STATIC); - sqlite3VdbeAddOp(v, OP_Eq, 0, addr+6); + sqlite3VdbeAddOp(v, OP_Eq, 0, addr+7); sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName), P3_DYNAMIC); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeAddOp(v, OP_Concat, 0, 1); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0); /* Make sure all the indices are constructed correctly. */ sqlite3CodeVerifySchema(pParse, i); - for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; int loopTop; @@ -690,11 +705,11 @@ void sqlite3Pragma( sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); sqlite3VdbeAddOp(v, OP_MemInt, 0, 1); loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0); - sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, 1, 1); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int jmp2; static const VdbeOpList idxErr[] = { - { OP_MemIncr, 0, 0, 0}, + { OP_MemIncr, 1, 0, 0}, { OP_String8, 0, 0, "rowid "}, { OP_Rowid, 1, 0, 0}, { OP_String8, 0, 0, " missing from index "}, @@ -714,12 +729,12 @@ void sqlite3Pragma( static const VdbeOpList cntIdx[] = { { OP_MemInt, 0, 2, 0}, { OP_Rewind, 0, 0, 0}, /* 1 */ - { OP_MemIncr, 2, 0, 0}, + { OP_MemIncr, 1, 2, 0}, { OP_Next, 0, 0, 0}, /* 3 */ { OP_MemLoad, 1, 0, 0}, { OP_MemLoad, 2, 0, 0}, { OP_Eq, 0, 0, 0}, /* 6 */ - { OP_MemIncr, 0, 0, 0}, + { OP_MemIncr, 1, 0, 0}, { OP_String8, 0, 0, "wrong # of entries in index "}, { OP_String8, 0, 0, 0}, /* 9 */ { OP_Concat, 0, 0, 0}, @@ -765,7 +780,7 @@ void sqlite3Pragma( ** useful if invoked immediately after the main database i */ if( sqlite3StrICmp(zLeft, "encoding")==0 ){ - static struct EncName { + static const struct EncName { char *zName; u8 enc; } encnames[] = { @@ -775,19 +790,18 @@ void sqlite3Pragma( { "UTF16le", SQLITE_UTF16LE }, { "UTF-16be", SQLITE_UTF16BE }, { "UTF16be", SQLITE_UTF16BE }, - { "UTF-16", 0 /* Filled in at run-time */ }, - { "UTF16", 0 /* Filled in at run-time */ }, + { "UTF-16", 0 }, /* SQLITE_UTF16NATIVE */ + { "UTF16", 0 }, /* SQLITE_UTF16NATIVE */ { 0, 0 } }; - struct EncName *pEnc; - encnames[6].enc = encnames[7].enc = SQLITE_UTF16NATIVE; + const struct EncName *pEnc; if( !zRight ){ /* "PRAGMA encoding" */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "encoding", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", P3_STATIC); sqlite3VdbeAddOp(v, OP_String8, 0, 0); for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ - if( pEnc->enc==pParse->db->enc ){ + if( pEnc->enc==ENC(pParse->db) ){ sqlite3VdbeChangeP3(v, -1, pEnc->zName, P3_STATIC); break; } @@ -799,10 +813,13 @@ void sqlite3Pragma( ** will be overwritten when the schema is next loaded. If it does not ** already exists, it will be created to use the new encoding value. */ - if( !(pParse->db->flags&SQLITE_Initialized) ){ + if( + !(DbHasProperty(db, 0, DB_SchemaLoaded)) || + DbHasProperty(db, 0, DB_Empty) + ){ for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ - pParse->db->enc = pEnc->enc; + ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; break; } } @@ -887,8 +904,8 @@ void sqlite3Pragma( int i; Vdbe *v = sqlite3GetVdbe(pParse); sqlite3VdbeSetNumCols(v, 2); - sqlite3VdbeSetColName(v, 0, "database", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "status", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P3_STATIC); for(i=0; inDb; i++){ Btree *pBt; Pager *pPager; @@ -918,6 +935,12 @@ void sqlite3Pragma( }else #endif +#if SQLITE_HAS_CODEC + if( sqlite3StrICmp(zLeft, "key")==0 ){ + sqlite3_key(db, zRight, strlen(zRight)); + }else +#endif + {} if( v ){ @@ -926,6 +949,17 @@ void sqlite3Pragma( ** are only valid for a single execution. */ sqlite3VdbeAddOp(v, OP_Expire, 1, 0); + + /* + ** Reset the safety level, in case the fullfsync flag or synchronous + ** setting changed. + */ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + if( db->autoCommit ){ + sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level, + (db->flags&SQLITE_FullFSync)!=0); + } +#endif } pragma_out: sqliteFree(zLeft); diff --git a/ext/pdo_sqlite/sqlite/src/prepare.c b/ext/pdo_sqlite/sqlite/src/prepare.c index ad7c712789..0eae259889 100644 --- a/ext/pdo_sqlite/sqlite/src/prepare.c +++ b/ext/pdo_sqlite/sqlite/src/prepare.c @@ -24,10 +24,11 @@ ** that the database is corrupt. */ static void corruptSchema(InitData *pData, const char *zExtra){ - if( !sqlite3_malloc_failed ){ + if( !sqlite3MallocFailed() ){ sqlite3SetString(pData->pzErrMsg, "malformed database schema", zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0); } + pData->rc = SQLITE_CORRUPT; } /* @@ -38,7 +39,7 @@ static void corruptSchema(InitData *pData, const char *zExtra){ ** Each callback contains the following information: ** ** argv[0] = name of thing being created -** argv[1] = root page number for table or index. NULL for trigger or view. +** argv[1] = root page number for table or index. 0 for trigger or view. ** argv[2] = SQL text for the CREATE statement. ** argv[3] = "1" for temporary files, "0" for main database, "2" or more ** for auxiliary database files. @@ -49,6 +50,12 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ sqlite3 *db = pData->db; int iDb; + pData->rc = SQLITE_OK; + if( sqlite3MallocFailed() ){ + corruptSchema(pData, 0); + return SQLITE_NOMEM; + } + assert( argc==4 ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 || argv[3]==0 ){ @@ -70,10 +77,16 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ db->init.newTnum = atoi(argv[1]); rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); db->init.iDb = 0; + assert( rc!=SQLITE_OK || zErr==0 ); if( SQLITE_OK!=rc ){ - corruptSchema(pData, zErr); + pData->rc = rc; + if( rc==SQLITE_NOMEM ){ + sqlite3FailedMalloc(); + }else if( rc!=SQLITE_INTERRUPT ){ + corruptSchema(pData, zErr); + } sqlite3_free(zErr); - return rc; + return 1; } }else{ /* If the SQL column is blank it means this is an index that @@ -111,6 +124,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ BtCursor *curMain; int size; Table *pTab; + Db *pDb; char const *azArg[5]; char zDbNum[30]; int meta[10]; @@ -145,6 +159,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ #endif assert( iDb>=0 && iDbnDb ); + assert( db->aDb[iDb].pSchema ); /* zMasterSchema and zInitScript are set to point at the master schema ** and initialisation script appropriate for the database being @@ -168,9 +183,9 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ initData.db = db; initData.pzErrMsg = pzErrMsg; rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0); - if( rc!=SQLITE_OK ){ + if( rc ){ sqlite3SafetyOn(db); - return rc; + return initData.rc; } pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); if( pTab ){ @@ -180,11 +195,14 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ /* Create a cursor to hold the database open */ - if( db->aDb[iDb].pBt==0 ){ - if( !OMIT_TEMPDB && iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded); + pDb = &db->aDb[iDb]; + if( pDb->pBt==0 ){ + if( !OMIT_TEMPDB && iDb==1 ){ + DbSetProperty(db, 1, DB_SchemaLoaded); + } return SQLITE_OK; } - rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain); + rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain); if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); return rc; @@ -197,20 +215,20 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ ** meta[1] File format of schema layer. ** meta[2] Size of the page cache. ** meta[3] Use freelist if 0. Autovacuum if greater than zero. - ** meta[4] Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE + ** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE ** meta[5] The user cookie. Used by the application. ** meta[6] ** meta[7] ** meta[8] ** meta[9] ** - ** Note: The hash defined SQLITE_UTF* symbols in sqliteInt.h correspond to + ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to ** the possible values of meta[4]. */ if( rc==SQLITE_OK ){ int i; for(i=0; rc==SQLITE_OK && iaDb[iDb].pBt, i+1, (u32 *)&meta[i]); + rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]); } if( rc ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); @@ -220,7 +238,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ }else{ memset(meta, 0, sizeof(meta)); } - db->aDb[iDb].schema_cookie = meta[0]; + pDb->pSchema->schema_cookie = meta[0]; /* If opening a non-empty database, check the text encoding. For the ** main database, set sqlite3.enc to the encoding of the main database. @@ -229,55 +247,44 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ */ if( meta[4] ){ /* text encoding */ if( iDb==0 ){ - /* If opening the main database, set db->enc. */ - db->enc = (u8)meta[4]; - db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0); + /* If opening the main database, set ENC(db). */ + ENC(db) = (u8)meta[4]; + db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0); }else{ - /* If opening an attached database, the encoding much match db->enc */ - if( meta[4]!=db->enc ){ + /* If opening an attached database, the encoding much match ENC(db) */ + if( meta[4]!=ENC(db) ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "attached databases must use the same" " text encoding as main database", (char*)0); return SQLITE_ERROR; } } + }else{ + DbSetProperty(db, iDb, DB_Empty); } + pDb->pSchema->enc = ENC(db); size = meta[2]; if( size==0 ){ size = MAX_PAGES; } - db->aDb[iDb].cache_size = size; - - if( iDb==0 ){ - db->file_format = meta[1]; - if( db->file_format==0 ){ - /* This happens if the database was initially empty */ - db->file_format = 1; - } - - if( db->file_format==2 || db->file_format==3 ){ - /* File format 2 is treated exactly as file format 1. New - ** databases are created with file format 1. - */ - db->file_format = 1; - } - } + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); /* ** file_format==1 Version 3.0.0. - ** file_format==2 Version 3.1.3. - ** file_format==3 Version 3.1.4. - ** - ** Version 3.0 can only use files with file_format==1. Version 3.1.3 - ** can read and write files with file_format==1 or file_format==2. - ** Version 3.1.4 can read and write file formats 1, 2 and 3. + ** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN + ** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults + ** file_format==4 Version 3.3.0. // DESC indices. Boolean constants */ - if( meta[1]>3 ){ + pDb->pSchema->file_format = meta[1]; + if( pDb->pSchema->file_format==0 ){ + pDb->pSchema->file_format = 1; + } + if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); return SQLITE_ERROR; } - sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); /* Read the schema information out of the schema tables */ @@ -292,6 +299,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ zDbNum, db->aDb[iDb].zName, zMasterName); sqlite3SafetyOff(db); rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); + if( rc==SQLITE_ABORT ) rc = initData.rc; sqlite3SafetyOn(db); sqliteFree(zSql); #ifndef SQLITE_OMIT_ANALYZE @@ -301,8 +309,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ #endif sqlite3BtreeCloseCursor(curMain); } - if( sqlite3_malloc_failed ){ - sqlite3SetString(pzErrMsg, "out of memory", (char*)0); + if( sqlite3MallocFailed() ){ + /* sqlite3SetString(pzErrMsg, "out of memory", (char*)0); */ rc = SQLITE_NOMEM; sqlite3ResetInternalSchema(db, 0); } @@ -320,14 +328,15 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ ** created using ATTACH statements. Return a success code. If an ** error occurs, write an error message into *pzErrMsg. ** -** After the database is initialized, the SQLITE_Initialized -** bit is set in the flags field of the sqlite structure. +** After a database is initialized, the DB_SchemaLoaded bit is set +** bit is set in the flags field of the Db structure. If the database +** file was of zero-length, then the DB_Empty flag is also set. */ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; + int called_initone = 0; if( db->init.busy ) return SQLITE_OK; - assert( (db->flags & SQLITE_Initialized)==0 ); rc = SQLITE_OK; db->init.busy = 1; for(i=0; rc==SQLITE_OK && inDb; i++){ @@ -336,6 +345,7 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ if( rc ){ sqlite3ResetInternalSchema(db, i); } + called_initone = 1; } /* Once all the other databases have been initialised, load the schema @@ -348,19 +358,16 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ if( rc ){ sqlite3ResetInternalSchema(db, 1); } + called_initone = 1; } #endif db->init.busy = 0; - if( rc==SQLITE_OK ){ - db->flags |= SQLITE_Initialized; + if( rc==SQLITE_OK && called_initone ){ sqlite3CommitInternalChanges(db); } - if( rc!=SQLITE_OK ){ - db->flags &= ~SQLITE_Initialized; - } - return rc; + return rc; } /* @@ -371,11 +378,8 @@ int sqlite3ReadSchema(Parse *pParse){ int rc = SQLITE_OK; sqlite3 *db = pParse->db; if( !db->init.busy ){ - if( (db->flags & SQLITE_Initialized)==0 ){ - rc = sqlite3Init(db, &pParse->zErrMsg); - } + rc = sqlite3Init(db, &pParse->zErrMsg); } - assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized) || db->init.busy ); if( rc!=SQLITE_OK ){ pParse->rc = rc; pParse->nErr++; @@ -402,7 +406,7 @@ static int schemaIsValid(sqlite3 *db){ rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp); if( rc==SQLITE_OK ){ rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); - if( rc==SQLITE_OK && cookie!=db->aDb[iDb].schema_cookie ){ + if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){ allOk = 0; } sqlite3BtreeCloseCursor(curTemp); @@ -411,6 +415,37 @@ static int schemaIsValid(sqlite3 *db){ return allOk; } +/* +** Convert a schema pointer into the iDb index that indicates +** which database file in db->aDb[] the schema refers to. +** +** If the same database is attached more than once, the first +** attached database is returned. +*/ +int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ + int i = -1000000; + + /* If pSchema is NULL, then return -1000000. This happens when code in + ** expr.c is trying to resolve a reference to a transient table (i.e. one + ** created by a sub-select). In this case the return value of this + ** function should never be used. + ** + ** We return -1000000 instead of the more usual -1 simply because using + ** -1000000 as incorrectly using -1000000 index into db->aDb[] is much + ** more likely to cause a segfault than -1 (of course there are assert() + ** statements too, but it never hurts to play the odds). + */ + if( pSchema ){ + for(i=0; inDb; i++){ + if( db->aDb[i].pSchema==pSchema ){ + break; + } + } + assert( i>=0 &&i>=0 && inDb ); + } + return i; +} + /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ @@ -424,10 +459,10 @@ int sqlite3_prepare( Parse sParse; char *zErrMsg = 0; int rc = SQLITE_OK; + int i; - if( sqlite3_malloc_failed ){ - return SQLITE_NOMEM; - } + /* Assert that malloc() has not failed */ + assert( !sqlite3MallocFailed() ); assert( ppStmt ); *ppStmt = 0; @@ -435,24 +470,43 @@ int sqlite3_prepare( return SQLITE_MISUSE; } + /* If any attached database schemas are locked, do not proceed with + ** compilation. Instead return SQLITE_LOCKED immediately. + */ + for(i=0; inDb; i++) { + Btree *pBt = db->aDb[i].pBt; + if( pBt && sqlite3BtreeSchemaLocked(pBt) ){ + const char *zDb = db->aDb[i].zName; + sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb); + sqlite3SafetyOff(db); + return SQLITE_LOCKED; + } + } + memset(&sParse, 0, sizeof(sParse)); sParse.db = db; - sqlite3RunParser(&sParse, zSql, &zErrMsg); + if( nBytes>=0 && zSql[nBytes]!=0 ){ + char *zSqlCopy = sqlite3StrNDup(zSql, nBytes); + sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sParse.zTail += zSql - zSqlCopy; + sqliteFree(zSqlCopy); + }else{ + sqlite3RunParser(&sParse, zSql, &zErrMsg); + } - if( sqlite3_malloc_failed ){ - rc = SQLITE_NOMEM; - sqlite3RollbackAll(db); - sqlite3ResetInternalSchema(db, 0); - db->flags &= ~SQLITE_InTrans; - goto prepare_out; + if( sqlite3MallocFailed() ){ + sParse.rc = SQLITE_NOMEM; } if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; - if( sParse.rc!=SQLITE_OK && sParse.checkSchema && !schemaIsValid(db) ){ + if( sParse.checkSchema && !schemaIsValid(db) ){ sParse.rc = SQLITE_SCHEMA; } if( sParse.rc==SQLITE_SCHEMA ){ sqlite3ResetInternalSchema(db, 0); } + if( sqlite3MallocFailed() ){ + sParse.rc = SQLITE_NOMEM; + } if( pzTail ) *pzTail = sParse.zTail; rc = sParse.rc; @@ -460,21 +514,20 @@ int sqlite3_prepare( if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ if( sParse.explain==2 ){ sqlite3VdbeSetNumCols(sParse.pVdbe, 3); - sqlite3VdbeSetColName(sParse.pVdbe, 0, "order", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 1, "from", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 2, "detail", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", P3_STATIC); }else{ sqlite3VdbeSetNumCols(sParse.pVdbe, 5); - sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", P3_STATIC); } } #endif -prepare_out: if( sqlite3SafetyOff(db) ){ rc = SQLITE_MISUSE; } @@ -490,6 +543,9 @@ prepare_out: }else{ sqlite3Error(db, rc, 0); } + + rc = sqlite3ApiExit(db, rc); + sqlite3ReleaseThreadData(); return rc; } @@ -508,22 +564,17 @@ int sqlite3_prepare16( ** encoded string to UTF-8, then invoking sqlite3_prepare(). The ** tricky bit is figuring out the pointer to return in *pzTail. */ - char const *zSql8 = 0; - char const *zTail8 = 0; - int rc; - sqlite3_value *pTmp; + char *zSql8; + const char *zTail8 = 0; + int rc = SQLITE_OK; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } - pTmp = sqlite3GetTransientValue(db); - sqlite3ValueSetStr(pTmp, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); - zSql8 = sqlite3ValueText(pTmp, SQLITE_UTF8); - if( !zSql8 ){ - sqlite3Error(db, SQLITE_NOMEM, 0); - return SQLITE_NOMEM; + zSql8 = sqlite3utf16to8(zSql, nBytes); + if( zSql8 ){ + rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8); } - rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8); if( zTail8 && pzTail ){ /* If sqlite3_prepare returns a tail pointer, we calculate the @@ -534,7 +585,7 @@ int sqlite3_prepare16( int chars_parsed = sqlite3utf8CharLen(zSql8, zTail8-zSql8); *pzTail = (u8 *)zSql + sqlite3utf16ByteLen(zSql, chars_parsed); } - - return rc; + sqliteFree(zSql8); + return sqlite3ApiExit(db, rc); } #endif /* SQLITE_OMIT_UTF16 */ diff --git a/ext/pdo_sqlite/sqlite/src/printf.c b/ext/pdo_sqlite/sqlite/src/printf.c index a669eb8d44..b4c37fb61d 100644 --- a/ext/pdo_sqlite/sqlite/src/printf.c +++ b/ext/pdo_sqlite/sqlite/src/printf.c @@ -65,15 +65,14 @@ #define etDYNSTRING 7 /* Dynamically allocated strings. %z */ #define etPERCENT 8 /* Percent symbol. %% */ #define etCHARX 9 /* Characters. %c */ -#define etERROR 10 /* Used to indicate no such conversion type */ /* The rest are extensions, not normally found in printf() */ -#define etCHARLIT 11 /* Literal characters. %' */ -#define etSQLESCAPE 12 /* Strings with '\'' doubled. %q */ -#define etSQLESCAPE2 13 /* Strings with '\'' doubled and enclosed in '', +#define etCHARLIT 10 /* Literal characters. %' */ +#define etSQLESCAPE 11 /* Strings with '\'' doubled. %q */ +#define etSQLESCAPE2 12 /* Strings with '\'' doubled and enclosed in '', NULL pointers replaced by SQL NULL. %Q */ -#define etTOKEN 14 /* a pointer to a Token structure */ -#define etSRCLIST 15 /* a pointer to a SrcList */ -#define etPOINTER 16 /* The %p conversion */ +#define etTOKEN 13 /* a pointer to a Token structure */ +#define etSRCLIST 14 /* a pointer to a SrcList */ +#define etPOINTER 15 /* The %p conversion */ /* @@ -120,10 +119,12 @@ static const et_info fmtinfo[] = { { '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 }, @@ -134,10 +135,10 @@ static const et_info fmtinfo[] = { #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) /* -** If NOFLOATINGPOINT is defined, then none of the floating point +** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point ** conversions will work. */ -#ifndef etNOFLOATINGPOINT +#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 @@ -161,7 +162,7 @@ static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ *val = (*val - d)*10.0; return digit; } -#endif +#endif /* SQLITE_OMIT_FLOATING_POINT */ /* ** On machines with a small stack size, you can redefine the @@ -223,7 +224,7 @@ static int vxprintf( etByte flag_long; /* True if "l" flag is present */ etByte flag_longlong; /* True if the "ll" flag is present */ etByte done; /* Loop termination flag */ - UINT64_TYPE longvalue; /* Value for integer types */ + 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 buf[etBUFSIZE]; /* Conversion buffer */ @@ -234,7 +235,7 @@ static int vxprintf( static const char spaces[] = " "; #define etSPACESIZE (sizeof(spaces)-1) -#ifndef etNOFLOATINGPOINT +#ifndef SQLITE_OMIT_FLOATING_POINT int exp, e2; /* exponent of real numbers */ double rounder; /* Used for rounding floating point values */ etByte flag_dp; /* True if decimal point should be shown */ @@ -327,17 +328,22 @@ static int vxprintf( } /* Fetch the info entry for the field */ infop = 0; - xtype = etERROR; for(idx=0; idxflags & FLAG_INTERN)==0 ){ xtype = infop->type; + }else{ + return -1; } break; } } zExtra = 0; + if( infop==0 ){ + return -1; + } + /* Limit the precision to prevent overflowing buf[] during conversion */ if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){ @@ -425,7 +431,7 @@ static int vxprintf( case etEXP: case etGENERIC: realvalue = va_arg(ap,double); -#ifndef etNOFLOATINGPOINT +#ifndef SQLITE_OMIT_FLOATING_POINT if( precision<0 ) precision = 6; /* Set default precision */ if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10; if( realvalue<0.0 ){ @@ -442,7 +448,7 @@ static int vxprintf( for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1); #else /* It makes more sense to use 0.5 */ - for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1); + for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){} #endif if( xtype==etFLOAT ) realvalue += rounder; /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ @@ -594,13 +600,13 @@ static int vxprintf( break; case etSQLESCAPE: case etSQLESCAPE2: { - int i, j, n, c, isnull; + int i, j, n, ch, isnull; int needQuote; - char *arg = va_arg(ap,char*); - isnull = arg==0; - if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); - for(i=n=0; (c=arg[i])!=0; i++){ - if( c=='\'' ) n++; + char *escarg = va_arg(ap,char*); + isnull = escarg==0; + if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); + for(i=n=0; (ch=escarg[i])!=0; i++){ + if( ch=='\'' ) n++; } needQuote = !isnull && xtype==etSQLESCAPE2; n += i + 1 + needQuote*2; @@ -612,20 +618,21 @@ static int vxprintf( } j = 0; if( needQuote ) bufpt[j++] = '\''; - for(i=0; (c=arg[i])!=0; i++){ - bufpt[j++] = c; - if( c=='\'' ) bufpt[j++] = c; + for(i=0; (ch=escarg[i])!=0; i++){ + bufpt[j++] = ch; + if( ch=='\'' ) bufpt[j++] = ch; } if( needQuote ) bufpt[j++] = '\''; bufpt[j] = 0; length = j; - if( precision>=0 && precision=0 && precisionz ){ - (*func)(arg, pToken->z, pToken->n); + (*func)(arg, (char*)pToken->z, pToken->n); } length = width = 0; break; @@ -643,15 +650,6 @@ static int vxprintf( length = width = 0; break; } - case etERROR: - buf[0] = '%'; - buf[1] = c; - errorflag = 0; - idx = 1+(c!=0); - (*func)(arg,"%",idx); - count += idx; - if( c==0 ) fmt--; - break; }/* End switch over the format type */ /* ** The text of the conversion is pointed to by "bufpt" and is @@ -808,29 +806,28 @@ char *sqlite3MPrintf(const char *zFormat, ...){ } /* -** Print into memory obtained from malloc(). Do not use the internal -** %-conversion extensions. This routine is for use by external users. +** Print into memory obtained from sqlite3_malloc(). Omit the internal +** %-conversion extensions. +*/ +char *sqlite3_vmprintf(const char *zFormat, va_list ap){ + char zBase[SQLITE_PRINT_BUF_SIZE]; + return base_vprintf(sqlite3_realloc, 0, zBase, sizeof(zBase), zFormat, ap); +} + +/* +** Print into memory obtained from sqlite3_malloc()(). Omit the internal +** %-conversion extensions. */ char *sqlite3_mprintf(const char *zFormat, ...){ va_list ap; char *z; - char zBuf[200]; - - va_start(ap,zFormat); - z = base_vprintf((void*(*)(void*,int))realloc, 0, - zBuf, sizeof(zBuf), zFormat, ap); + char zBase[SQLITE_PRINT_BUF_SIZE]; + va_start(ap, zFormat); + z = base_vprintf(sqlite3_realloc, 0, zBase, sizeof(zBase), zFormat, ap); va_end(ap); return z; } -/* This is the varargs version of sqlite3_mprintf. -*/ -char *sqlite3_vmprintf(const char *zFormat, va_list ap){ - char zBuf[200]; - return base_vprintf((void*(*)(void*,int))realloc, 0, - zBuf, sizeof(zBuf), zFormat, ap); -} - /* ** sqlite3_snprintf() works like snprintf() except that it ignores the ** current locale settings. This is important for SQLite because we diff --git a/ext/pdo_sqlite/sqlite/src/select.c b/ext/pdo_sqlite/sqlite/src/select.c index 8a51208d79..57b415bf58 100644 --- a/ext/pdo_sqlite/sqlite/src/select.c +++ b/ext/pdo_sqlite/sqlite/src/select.c @@ -16,6 +16,21 @@ */ #include "sqliteInt.h" +/* +** Delete all the content of a Select structure but do not deallocate +** the select structure itself. +*/ +static void clearSelect(Select *p){ + sqlite3ExprListDelete(p->pEList); + sqlite3SrcListDelete(p->pSrc); + sqlite3ExprDelete(p->pWhere); + sqlite3ExprListDelete(p->pGroupBy); + sqlite3ExprDelete(p->pHaving); + sqlite3ExprListDelete(p->pOrderBy); + sqlite3SelectDelete(p->pPrior); + sqlite3ExprDelete(p->pLimit); + sqlite3ExprDelete(p->pOffset); +} /* ** Allocate a new Select structure and return a pointer to that @@ -33,40 +48,48 @@ Select *sqlite3SelectNew( Expr *pOffset /* OFFSET value. NULL means no offset */ ){ Select *pNew; + Select standin; pNew = sqliteMalloc( sizeof(*pNew) ); assert( !pOffset || pLimit ); /* Can't have OFFSET without LIMIT. */ if( pNew==0 ){ - sqlite3ExprListDelete(pEList); - sqlite3SrcListDelete(pSrc); - sqlite3ExprDelete(pWhere); - sqlite3ExprListDelete(pGroupBy); - sqlite3ExprDelete(pHaving); - sqlite3ExprListDelete(pOrderBy); - sqlite3ExprDelete(pLimit); - sqlite3ExprDelete(pOffset); - }else{ - if( pEList==0 ){ - pEList = sqlite3ExprListAppend(0, sqlite3Expr(TK_ALL,0,0,0), 0); - } - pNew->pEList = pEList; - pNew->pSrc = pSrc; - pNew->pWhere = pWhere; - pNew->pGroupBy = pGroupBy; - pNew->pHaving = pHaving; - pNew->pOrderBy = pOrderBy; - pNew->isDistinct = isDistinct; - pNew->op = TK_SELECT; - pNew->pLimit = pLimit; - pNew->pOffset = pOffset; - pNew->iLimit = -1; - pNew->iOffset = -1; - pNew->addrOpenVirt[0] = -1; - pNew->addrOpenVirt[1] = -1; - pNew->addrOpenVirt[2] = -1; + pNew = &standin; + memset(pNew, 0, sizeof(*pNew)); + } + if( pEList==0 ){ + pEList = sqlite3ExprListAppend(0, sqlite3Expr(TK_ALL,0,0,0), 0); + } + pNew->pEList = pEList; + pNew->pSrc = pSrc; + pNew->pWhere = pWhere; + pNew->pGroupBy = pGroupBy; + pNew->pHaving = pHaving; + pNew->pOrderBy = pOrderBy; + pNew->isDistinct = isDistinct; + pNew->op = TK_SELECT; + pNew->pLimit = pLimit; + pNew->pOffset = pOffset; + pNew->iLimit = -1; + pNew->iOffset = -1; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->addrOpenEphm[2] = -1; + if( pNew==&standin) { + clearSelect(pNew); + pNew = 0; } return pNew; } +/* +** Delete the given Select structure and all of its substructures. +*/ +void sqlite3SelectDelete(Select *p){ + if( p ){ + clearSelect(p); + sqliteFree(p); + } +} + /* ** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the ** type of join. Return an integer constant that expresses that type @@ -109,7 +132,7 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ p = apAll[i]; for(j=0; jn==keywords[j].nChar - && sqlite3StrNICmp(p->z, keywords[j].zKeyword, p->n)==0 ){ + && sqlite3StrNICmp((char*)p->z, keywords[j].zKeyword, p->n)==0 ){ jointype |= keywords[j].code; break; } @@ -154,15 +177,15 @@ static int columnIndex(Table *pTab, const char *zCol){ ** Set the value of a token to a '\000'-terminated string. */ static void setToken(Token *p, const char *z){ - p->z = z; - p->n = strlen(z); + p->z = (u8*)z; + p->n = z ? strlen(z) : 0; p->dyn = 0; } /* ** Create an expression node for an identifier with the name of zName */ -static Expr *createIdExpr(const char *zName){ +Expr *sqlite3CreateIdExpr(const char *zName){ Token dummy; setToken(&dummy, zName); return sqlite3Expr(TK_ID, 0, 0, &dummy); @@ -186,22 +209,27 @@ static void addWhereTerm( Expr *pE2a, *pE2b, *pE2c; Expr *pE; - pE1a = createIdExpr(zCol); - pE2a = createIdExpr(zCol); + pE1a = sqlite3CreateIdExpr(zCol); + pE2a = sqlite3CreateIdExpr(zCol); if( zAlias1==0 ){ zAlias1 = pTab1->zName; } - pE1b = createIdExpr(zAlias1); + pE1b = sqlite3CreateIdExpr(zAlias1); if( zAlias2==0 ){ zAlias2 = pTab2->zName; } - pE2b = createIdExpr(zAlias2); - pE1c = sqlite3Expr(TK_DOT, pE1b, pE1a, 0); - pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0); - pE = sqlite3Expr(TK_EQ, pE1c, pE2c, 0); - ExprSetProperty(pE, EP_FromJoin); - pE->iRightJoinTable = iRightJoinTable; - *ppExpr = sqlite3ExprAnd(*ppExpr, pE); + pE2b = sqlite3CreateIdExpr(zAlias2); + pE1c = sqlite3ExprOrFree(TK_DOT, pE1b, pE1a, 0); + pE2c = sqlite3ExprOrFree(TK_DOT, pE2b, pE2a, 0); + pE = sqlite3ExprOrFree(TK_EQ, pE1c, pE2c, 0); + if( pE ){ + ExprSetProperty(pE, EP_FromJoin); + pE->iRightJoinTable = iRightJoinTable; + } + pE = sqlite3ExprAnd(*ppExpr, pE); + if( pE ){ + *ppExpr = pE; + } } /* @@ -330,59 +358,53 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ return 0; } -/* -** Delete the given Select structure and all of its substructures. -*/ -void sqlite3SelectDelete(Select *p){ - if( p==0 ) return; - sqlite3ExprListDelete(p->pEList); - sqlite3SrcListDelete(p->pSrc); - sqlite3ExprDelete(p->pWhere); - sqlite3ExprListDelete(p->pGroupBy); - sqlite3ExprDelete(p->pHaving); - sqlite3ExprListDelete(p->pOrderBy); - sqlite3SelectDelete(p->pPrior); - sqlite3ExprDelete(p->pLimit); - sqlite3ExprDelete(p->pOffset); - sqliteFree(p); -} - /* ** Insert code into "v" that will push the record on the top of the ** stack into the sorter. */ -static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ +static void pushOntoSorter( + Parse *pParse, /* Parser context */ + ExprList *pOrderBy, /* The ORDER BY clause */ + Select *pSelect /* The whole SELECT statement */ +){ + Vdbe *v = pParse->pVdbe; sqlite3ExprCodeExprList(pParse, pOrderBy); sqlite3VdbeAddOp(v, OP_Sequence, pOrderBy->iECursor, 0); sqlite3VdbeAddOp(v, OP_Pull, pOrderBy->nExpr + 1, 0); sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr + 2, 0); sqlite3VdbeAddOp(v, OP_IdxInsert, pOrderBy->iECursor, 0); + if( pSelect->iLimit>=0 ){ + int addr1, addr2; + addr1 = sqlite3VdbeAddOp(v, OP_IfMemZero, pSelect->iLimit+1, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, -1, pSelect->iLimit+1); + addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp(v, OP_Last, pOrderBy->iECursor, 0); + sqlite3VdbeAddOp(v, OP_Delete, pOrderBy->iECursor, 0); + sqlite3VdbeJumpHere(v, addr2); + pSelect->iLimit = -1; + } } /* -** Add code to implement the OFFSET and LIMIT +** Add code to implement the OFFSET */ -static void codeLimiter( +static void codeOffset( Vdbe *v, /* Generate code into this VM */ Select *p, /* The SELECT statement being coded */ int iContinue, /* Jump here to skip the current record */ - int iBreak, /* Jump here to end the loop */ int nPop /* Number of times to pop stack when jumping */ ){ if( p->iOffset>=0 && iContinue!=0 ){ - int addr = sqlite3VdbeCurrentAddr(v) + 3; - if( nPop>0 ) addr++; - sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, 0); - sqlite3VdbeAddOp(v, OP_IfMemPos, p->iOffset, addr); + int addr; + sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iOffset); + addr = sqlite3VdbeAddOp(v, OP_IfMemNeg, p->iOffset, 0); if( nPop>0 ){ sqlite3VdbeAddOp(v, OP_Pop, nPop, 0); } sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue); VdbeComment((v, "# skip OFFSET records")); - } - if( p->iLimit>=0 && iBreak!=0 ){ - sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak); - VdbeComment((v, "# exit when LIMIT reached")); + sqlite3VdbeJumpHere(v, addr); } } @@ -392,22 +414,18 @@ static void codeLimiter( ** seen combinations of the N values. A new entry is made in iTab ** if the current N values are new. ** -** A jump to addrRepeat is made and the K values are popped from the +** A jump to addrRepeat is made and the N+1 values are popped from the ** stack if the top N elements are not distinct. */ static void codeDistinct( Vdbe *v, /* Generate code into this VM */ int iTab, /* A sorting index used to test for distinctness */ int addrRepeat, /* Jump to here if not distinct */ - int N, /* The top N elements of the stack must be distinct */ - int K /* Pop K elements from the stack if indistinct */ + int N /* The top N elements of the stack must be distinct */ ){ -#if NULL_ALWAYS_DISTINCT - sqlite3VdbeAddOp(v, OP_IsNull, -N, sqlite3VdbeCurrentAddr(v)+6); -#endif sqlite3VdbeAddOp(v, OP_MakeRecord, -N, 0); sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp(v, OP_Pop, K, 0); + sqlite3VdbeAddOp(v, OP_Pop, N+1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat); VdbeComment((v, "# skip indistinct records")); sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0); @@ -447,9 +465,9 @@ static int selectInnerLoop( /* If there was a LIMIT clause on the SELECT statement, then do the check ** to see if this row should be output. */ - hasDistinct = distinct>=0 && pEList && pEList->nExpr>0; + hasDistinct = distinct>=0 && pEList->nExpr>0; if( pOrderBy==0 && !hasDistinct ){ - codeLimiter(v, p, iContinue, iBreak, 0); + codeOffset(v, p, iContinue, 0); } /* Pull the requested columns. @@ -468,10 +486,11 @@ static int selectInnerLoop( ** part of the result. */ if( hasDistinct ){ - int n = pEList->nExpr; - codeDistinct(v, distinct, iContinue, n, n+1); + assert( pEList!=0 ); + assert( pEList->nExpr==nColumn ); + codeDistinct(v, distinct, iContinue, nColumn); if( pOrderBy==0 ){ - codeLimiter(v, p, iContinue, iBreak, nColumn); + codeOffset(v, p, iContinue, nColumn); } } @@ -481,7 +500,7 @@ static int selectInnerLoop( */ #ifndef SQLITE_OMIT_COMPOUND_SELECT case SRT_Union: { - sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); + sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); if( aff ){ sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); } @@ -495,7 +514,7 @@ static int selectInnerLoop( */ case SRT_Except: { int addr; - addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); + addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3); sqlite3VdbeAddOp(v, OP_Delete, iParm, 0); @@ -506,10 +525,10 @@ static int selectInnerLoop( /* Store the result as data using a unique key. */ case SRT_Table: - case SRT_VirtualTab: { + case SRT_EphemTab: { sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); if( pOrderBy ){ - pushOntoSorter(pParse, v, pOrderBy); + pushOntoSorter(pParse, pOrderBy, p); }else{ sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); @@ -536,29 +555,37 @@ static int selectInnerLoop( ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ - pushOntoSorter(pParse, v, pOrderBy); + pushOntoSorter(pParse, pOrderBy, p); }else{ - char aff = (iParm>>16)&0xFF; - aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff); - sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &aff, 1); + char affinity = (iParm>>16)&0xFF; + affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, affinity); + sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0); } sqlite3VdbeJumpHere(v, addr2); break; } + /* If any row exist in the result set, record that fact and abort. + */ + case SRT_Exists: { + sqlite3VdbeAddOp(v, OP_MemInt, 1, iParm); + sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); + /* The LIMIT clause will terminate the loop for us */ + break; + } + /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. */ - case SRT_Exists: case SRT_Mem: { assert( nColumn==1 ); if( pOrderBy ){ - pushOntoSorter(pParse, v, pOrderBy); + pushOntoSorter(pParse, pOrderBy, p); }else{ sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); - sqlite3VdbeAddOp(v, OP_Goto, 0, iBreak); + /* The LIMIT clause will jump out of the loop for us */ } break; } @@ -572,7 +599,7 @@ static int selectInnerLoop( case SRT_Callback: { if( pOrderBy ){ sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); - pushOntoSorter(pParse, v, pOrderBy); + pushOntoSorter(pParse, pOrderBy, p); }else if( eDest==SRT_Subroutine ){ sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm); }else{ @@ -594,6 +621,13 @@ static int selectInnerLoop( } #endif } + + /* Jump to the end of the loop if the LIMIT is reached. + */ + if( p->iLimit>=0 && pOrderBy==0 ){ + sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit); + sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, iBreak); + } return 0; } @@ -622,9 +656,9 @@ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ nExpr = pList->nExpr; pInfo = sqliteMalloc( sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) ); if( pInfo ){ - pInfo->aSortOrder = (char*)&pInfo->aColl[nExpr]; + pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr]; pInfo->nField = nExpr; - pInfo->enc = db->enc; + pInfo->enc = ENC(db); for(i=0, pItem=pList->a; ipExpr); @@ -646,7 +680,7 @@ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ ** routine generates the code needed to do that. */ static void generateSortTail( - Parse *pParse, /* The parsing context */ + Parse *pParse, /* Parsing context */ Select *p, /* The SELECT statement */ Vdbe *v, /* Generate code into this VDBE */ int nColumn, /* Number of columns of data */ @@ -657,15 +691,24 @@ static void generateSortTail( int cont = sqlite3VdbeMakeLabel(v); int addr; int iTab; + int pseudoTab; ExprList *pOrderBy = p->pOrderBy; iTab = pOrderBy->iECursor; + if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ + pseudoTab = pParse->nTab++; + sqlite3VdbeAddOp(v, OP_OpenPseudo, pseudoTab, 0); + sqlite3VdbeAddOp(v, OP_SetNumColumns, pseudoTab, nColumn); + } addr = 1 + sqlite3VdbeAddOp(v, OP_Sort, iTab, brk); - codeLimiter(v, p, cont, brk, 0); + codeOffset(v, p, cont, 0); + if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ + sqlite3VdbeAddOp(v, OP_Integer, 1, 0); + } sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1); switch( eDest ){ case SRT_Table: - case SRT_VirtualTab: { + case SRT_EphemTab: { sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeAddOp(v, OP_Insert, iParm, 0); @@ -677,32 +720,29 @@ static void generateSortTail( sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, "n", P3_STATIC); + sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, "c", P3_STATIC); sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0); break; } - case SRT_Exists: case SRT_Mem: { assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); - sqlite3VdbeAddOp(v, OP_Goto, 0, brk); + /* The LIMIT clause will terminate the loop for us */ break; } #endif case SRT_Callback: case SRT_Subroutine: { int i; - sqlite3VdbeAddOp(v, OP_Integer, p->pEList->nExpr, 0); - sqlite3VdbeAddOp(v, OP_Pull, 1, 0); + sqlite3VdbeAddOp(v, OP_Insert, pseudoTab, 0); for(i=0; iiLimit>=0 ){ + sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit); + sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, brk); + } + + /* The bottom of the loop + */ sqlite3VdbeResolveLabel(v, cont); sqlite3VdbeAddOp(v, OP_Next, iTab, addr); sqlite3VdbeResolveLabel(v, brk); + if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ + sqlite3VdbeAddOp(v, OP_Close, pseudoTab, 0); + } + } /* ** Return a pointer to a string containing the 'declaration type' of the ** expression pExpr. The string may be treated as static by the caller. ** -** If the declaration type is the exact datatype definition extracted from -** the original CREATE TABLE statement if the expression is a column. +** The declaration type is the exact datatype definition extracted from the +** original CREATE TABLE statement if the expression is a column. The +** declaration type for a ROWID field is INTEGER. Exactly when an expression +** is considered a column can be complex in the presence of subqueries. The +** result-set expression in all of the following SELECT statements is +** considered a column by this function. +** +** SELECT col FROM tbl; +** SELECT (SELECT col FROM tbl; +** SELECT (SELECT col FROM tbl); +** SELECT abc FROM (SELECT col AS abc FROM tbl); ** -** The declaration type for an expression is either TEXT, NUMERIC or ANY. -** The declaration type for a ROWID field is INTEGER. +** The declaration type for any expression other than a column is NULL. */ -static const char *columnType(NameContext *pNC, Expr *pExpr){ - char const *zType; +static const char *columnType( + NameContext *pNC, + Expr *pExpr, + const char **pzOriginDb, + const char **pzOriginTab, + const char **pzOriginCol +){ + char const *zType = 0; + char const *zOriginDb = 0; + char const *zOriginTab = 0; + char const *zOriginCol = 0; int j; if( pExpr==0 || pNC->pSrcList==0 ) return 0; @@ -737,18 +808,26 @@ static const char *columnType(NameContext *pNC, Expr *pExpr){ assert( pExpr->op!=TK_AS ); switch( pExpr->op ){ + case TK_AGG_COLUMN: case TK_COLUMN: { - Table *pTab = 0; - int iCol = pExpr->iColumn; + /* The expression is a column. Locate the table the column is being + ** extracted from in NameContext.pSrcList. This table may be real + ** database table or a subquery. + */ + Table *pTab = 0; /* Table structure column is extracted from */ + Select *pS = 0; /* Select the column is extracted from */ + int iCol = pExpr->iColumn; /* Index of column in pTab */ while( pNC && !pTab ){ SrcList *pTabList = pNC->pSrcList; for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); if( jnSrc ){ pTab = pTabList->a[j].pTab; + pS = pTabList->a[j].pSelect; }else{ pNC = pNC->pNext; } } + if( pTab==0 ){ /* FIX ME: ** This can occurs if you have something like "SELECT new.x;" inside @@ -763,30 +842,69 @@ static const char *columnType(NameContext *pNC, Expr *pExpr){ zType = "TEXT"; break; } + assert( pTab ); - if( iCol<0 ) iCol = pTab->iPKey; - assert( iCol==-1 || (iCol>=0 && iColnCol) ); - if( iCol<0 ){ - zType = "INTEGER"; - }else{ - zType = pTab->aCol[iCol].zType; + if( pS ){ + /* The "table" is actually a sub-select or a view in the FROM clause + ** of the SELECT statement. Return the declaration type and origin + ** data for the result-set column of the sub-select. + */ + if( iCol>=0 && iColpEList->nExpr ){ + /* If iCol is less than zero, then the expression requests the + ** rowid of the sub-select or view. This expression is legal (see + ** test case misc2.2.2) - it always evaluates to NULL. + */ + NameContext sNC; + Expr *p = pS->pEList->a[iCol].pExpr; + sNC.pSrcList = pS->pSrc; + sNC.pNext = 0; + sNC.pParse = pNC->pParse; + zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); + } + }else if( pTab->pSchema ){ + /* A real table */ + assert( !pS ); + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==-1 || (iCol>=0 && iColnCol) ); + if( iCol<0 ){ + zType = "INTEGER"; + zOriginCol = "rowid"; + }else{ + zType = pTab->aCol[iCol].zType; + zOriginCol = pTab->aCol[iCol].zName; + } + zOriginTab = pTab->zName; + if( pNC->pParse ){ + int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); + zOriginDb = pNC->pParse->db->aDb[iDb].zName; + } } break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: { + /* The expression is a sub-select. Return the declaration type and + ** origin info for the single column in the result set of the SELECT + ** statement. + */ NameContext sNC; Select *pS = pExpr->pSelect; - sNC.pSrcList = pExpr->pSelect->pSrc; + Expr *p = pS->pEList->a[0].pExpr; + sNC.pSrcList = pS->pSrc; sNC.pNext = pNC; - zType = columnType(&sNC, pS->pEList->a[0].pExpr); + sNC.pParse = pNC->pParse; + zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); break; } #endif - default: - zType = 0; } + if( pzOriginDb ){ + assert( pzOriginTab && pzOriginCol ); + *pzOriginDb = zOriginDb; + *pzOriginTab = zOriginTab; + *pzOriginCol = zOriginCol; + } return zType; } @@ -803,14 +921,22 @@ static void generateColumnTypes( int i; NameContext sNC; sNC.pSrcList = pTabList; + sNC.pParse = pParse; for(i=0; inExpr; i++){ Expr *p = pEList->a[i].pExpr; - const char *zType = columnType(&sNC, p); - if( zType==0 ) continue; - /* The vdbe must make it's own copy of the column-type, in case the - ** schema is reset before this virtual machine is deleted. + const char *zOrigDb = 0; + const char *zOrigTab = 0; + const char *zOrigCol = 0; + const char *zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); + + /* The vdbe must make it's own copy of the column-type and other + ** column specific strings, in case the schema is reset before this + ** virtual machine is deleted. */ - sqlite3VdbeSetColName(v, i+pEList->nExpr, zType, strlen(zType)); + sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P3_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P3_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P3_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P3_TRANSIENT); } } @@ -837,7 +963,7 @@ static void generateColumnNames( #endif assert( v!=0 ); - if( pParse->colNamesSet || v==0 || sqlite3_malloc_failed ) return; + if( pParse->colNamesSet || v==0 || sqlite3MallocFailed() ) return; pParse->colNamesSet = 1; fullNames = (db->flags & SQLITE_FullColNames)!=0; shortNames = (db->flags & SQLITE_ShortColNames)!=0; @@ -848,7 +974,7 @@ static void generateColumnNames( if( p==0 ) continue; if( pEList->a[i].zName ){ char *zName = pEList->a[i].zName; - sqlite3VdbeSetColName(v, i, zName, strlen(zName)); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName)); continue; } if( p->op==TK_COLUMN && pTabList ){ @@ -866,26 +992,26 @@ static void generateColumnNames( zCol = pTab->aCol[iCol].zName; } if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ - sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){ char *zName = 0; char *zTab; zTab = pTabList->a[j].zAlias; if( fullNames || zTab==0 ) zTab = pTab->zName; - sqlite3SetString(&zName, zTab, ".", zCol, 0); - sqlite3VdbeSetColName(v, i, zName, P3_DYNAMIC); + sqlite3SetString(&zName, zTab, ".", zCol, (char*)0); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, P3_DYNAMIC); }else{ - sqlite3VdbeSetColName(v, i, zCol, strlen(zCol)); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol)); } }else if( p->span.z && p->span.z[0] ){ - sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); /* sqlite3VdbeCompressSpace(v, addr); */ }else{ char zName[30]; assert( p->op!=TK_COLUMN || pTabList==0 ); sprintf(zName, "column%d", i+1); - sqlite3VdbeSetColName(v, i, zName, 0); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, 0); } } generateColumnTypes(pParse, pTabList, pEList); @@ -922,6 +1048,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ ExprList *pEList; Column *aCol, *pCol; + while( pSelect->pPrior ) pSelect = pSelect->pPrior; if( prepSelectStmt(pParse, pSelect) ){ return 0; } @@ -943,6 +1070,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ char *zType; char *zName; char *zBasename; + CollSeq *pColl; int cnt; NameContext sNC; @@ -965,7 +1093,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ zName = sqlite3MPrintf("column%d", i+1); } sqlite3Dequote(zName); - if( sqlite3_malloc_failed ){ + if( sqlite3MallocFailed() ){ sqliteFree(zName); sqlite3DeleteTable(0, pTab); return 0; @@ -992,12 +1120,12 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ */ memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; - zType = sqliteStrDup(columnType(&sNC, p)); + zType = sqliteStrDup(columnType(&sNC, p, 0, 0, 0)); pCol->zType = zType; pCol->affinity = sqlite3ExprAffinity(p); - pCol->pColl = sqlite3ExprCollSeq(pParse, p); - if( !pCol->pColl ){ - pCol->pColl = pParse->db->pDfltColl; + pColl = sqlite3ExprCollSeq(pParse, p); + if( pColl ){ + pCol->zColl = sqliteStrDup(pColl->zName); } } pTab->iPKey = -1; @@ -1034,10 +1162,11 @@ static int prepSelectStmt(Parse *pParse, Select *p){ int i, j, k, rc; SrcList *pTabList; ExprList *pEList; - Table *pTab; struct SrcList_item *pFrom; - if( p==0 || p->pSrc==0 || sqlite3_malloc_failed ) return 1; + if( p==0 || p->pSrc==0 || sqlite3MallocFailed() ){ + return 1; + } pTabList = p->pSrc; pEList = p->pEList; @@ -1051,6 +1180,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){ ** then create a transient table structure to describe the subquery. */ for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + Table *pTab; if( pFrom->pTab!=0 ){ /* This statement has already been prepared. There is no need ** to go further. */ @@ -1071,11 +1201,11 @@ static int prepSelectStmt(Parse *pParse, Select *p){ if( pTab==0 ){ return 1; } - /* The isTransient flag indicates that the Table structure has been + /* The isEphem flag indicates that the Table structure has been ** dynamically allocated and may be freed at any time. In other words, ** pTab is not pointing to a persistent table structure that defines ** part of the schema. */ - pTab->isTransient = 1; + pTab->isEphem = 1; #endif }else{ /* An ordinary table or view name in the FROM clause */ @@ -1086,8 +1216,8 @@ static int prepSelectStmt(Parse *pParse, Select *p){ return 1; } pTab->nRef++; -#ifndef SQLITE_OMIT_VIEW - if( pTab->pSelect ){ +#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) + if( pTab->pSelect || IsVirtual(pTab) ){ /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ return 1; @@ -1145,7 +1275,11 @@ static int prepSelectStmt(Parse *pParse, Select *p){ /* This particular expression does not need to be expanded. */ pNew = sqlite3ExprListAppend(pNew, a[k].pExpr, 0); - pNew->a[pNew->nExpr-1].zName = a[k].zName; + if( pNew ){ + pNew->a[pNew->nExpr-1].zName = a[k].zName; + }else{ + rc = 1; + } a[k].pExpr = 0; a[k].zName = 0; }else{ @@ -1170,7 +1304,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){ } tableSeen = 1; for(j=0; jnCol; j++){ - Expr *pExpr, *pLeft, *pRight; + Expr *pExpr, *pRight; char *zName = pTab->aCol[j].zName; if( i>0 ){ @@ -1191,7 +1325,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){ if( pRight==0 ) break; setToken(&pRight->token, zName); if( zTabName && (longNames || pTabList->nSrc>1) ){ - pLeft = sqlite3Expr(TK_ID, 0, 0, 0); + Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, 0); pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0); if( pExpr==0 ) break; setToken(&pLeft->token, zTabName); @@ -1326,25 +1460,31 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){ return v; } + /* ** Compute the iLimit and iOffset fields of the SELECT based on the -** pLimit and pOffset expressions. nLimit and nOffset hold the expressions +** pLimit and pOffset expressions. pLimit and pOffset hold the expressions ** that appear in the original SQL statement after the LIMIT and OFFSET ** keywords. Or NULL if those keywords are omitted. iLimit and iOffset ** are the integer memory register numbers for counters used to compute ** the limit and offset. If there is no limit and/or offset, then ** iLimit and iOffset are negative. ** -** This routine changes the values if iLimit and iOffset only if -** a limit or offset is defined by nLimit and nOffset. iLimit and +** This routine changes the values of iLimit and iOffset only if +** a limit or offset is defined by pLimit and pOffset. iLimit and ** iOffset should have been preset to appropriate default values ** (usually but not always -1) prior to calling this routine. -** Only if nLimit>=0 or nOffset>0 do the limit registers get +** Only if pLimit!=0 or pOffset!=0 do the limit registers get ** redefined. The UNION ALL operator uses this property to force ** the reuse of the same limit and offset registers across multiple ** SELECT statements. */ -static void computeLimitRegisters(Parse *pParse, Select *p){ +static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ + Vdbe *v = 0; + int iLimit = 0; + int iOffset; + int addr1, addr2; + /* ** "LIMIT -1" always shows all rows. There is some ** contraversy about what the correct behavior should be. @@ -1352,26 +1492,41 @@ static void computeLimitRegisters(Parse *pParse, Select *p){ ** no rows. */ if( p->pLimit ){ - int iMem = pParse->nMem++; - Vdbe *v = sqlite3GetVdbe(pParse); + p->iLimit = iLimit = pParse->nMem; + pParse->nMem += 2; + v = sqlite3GetVdbe(pParse); if( v==0 ) return; sqlite3ExprCode(pParse, p->pLimit); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); - sqlite3VdbeAddOp(v, OP_Negative, 0, 0); - sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1); + sqlite3VdbeAddOp(v, OP_MemStore, iLimit, 0); VdbeComment((v, "# LIMIT counter")); - p->iLimit = iMem; + sqlite3VdbeAddOp(v, OP_IfMemZero, iLimit, iBreak); } if( p->pOffset ){ - int iMem = pParse->nMem++; - Vdbe *v = sqlite3GetVdbe(pParse); + p->iOffset = iOffset = pParse->nMem++; + v = sqlite3GetVdbe(pParse); if( v==0 ) return; sqlite3ExprCode(pParse, p->pOffset); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); - sqlite3VdbeAddOp(v, OP_Negative, 0, 0); - sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1); + sqlite3VdbeAddOp(v, OP_MemStore, iOffset, p->pLimit==0); VdbeComment((v, "# OFFSET counter")); - p->iOffset = iMem; + addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iOffset, 0); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_Integer, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + if( p->pLimit ){ + sqlite3VdbeAddOp(v, OP_Add, 0, 0); + } + } + if( p->pLimit ){ + addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iLimit, 0); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_MemInt, -1, iLimit+1); + addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp(v, OP_MemStore, iLimit+1, 1); + VdbeComment((v, "# LIMIT+OFFSET")); + sqlite3VdbeJumpHere(v, addr2); } } @@ -1383,27 +1538,13 @@ static void createSortingIndex(Parse *pParse, Select *p, ExprList *pOrderBy){ int addr; assert( pOrderBy->iECursor==0 ); pOrderBy->iECursor = pParse->nTab++; - addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenVirtual, + addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenEphemeral, pOrderBy->iECursor, pOrderBy->nExpr+1); - assert( p->addrOpenVirt[2] == -1 ); - p->addrOpenVirt[2] = addr; + assert( p->addrOpenEphm[2] == -1 ); + p->addrOpenEphm[2] = addr; } } -/* -** The opcode at addr is an OP_OpenVirtual that created a sorting -** index tha we ended up not needing. This routine changes that -** opcode to OP_Noop. -*/ -static void uncreateSortingIndex(Parse *pParse, int addr){ - Vdbe *v = pParse->pVdbe; - VdbeOp *pOp = sqlite3VdbeGetOp(v, addr); - sqlite3VdbeChangeP3(v, addr, 0, 0); - pOp->opcode = OP_Noop; - pOp->p1 = 0; - pOp->p2 = 0; -} - #ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** Return the appropriate collating sequence for the iCol-th column of @@ -1506,10 +1647,10 @@ static int multiSelect( /* Create the destination temporary table if necessary */ - if( eDest==SRT_VirtualTab ){ + if( eDest==SRT_EphemTab ){ assert( p->pEList ); assert( nSetP2op ){ case TK_ALL: { if( pOrderBy==0 ){ + int addr = 0; assert( !pPrior->pLimit ); pPrior->pLimit = p->pLimit; pPrior->pOffset = p->pOffset; rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff); + p->pLimit = 0; + p->pOffset = 0; if( rc ){ goto multi_select_end; } p->pPrior = 0; p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; - p->pLimit = 0; - p->pOffset = 0; + if( p->iLimit>=0 ){ + addr = sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, 0); + VdbeComment((v, "# Jump ahead if LIMIT reached")); + } rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff); p->pPrior = pPrior; if( rc ){ goto multi_select_end; } + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + } break; } /* For UNION ALL ... ORDER BY fall through to the next case */ @@ -1563,14 +1712,14 @@ static int multiSelect( rc = 1; goto multi_select_end; } - addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, unionTab, 0); + addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, unionTab, 0); if( priorOp==SRT_Table ){ assert( nSetP2addrOpenVirt[0] == -1 ); - p->addrOpenVirt[0] = addr; - p->pRightmost->usesVirt = 1; + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + p->pRightmost->usesEphm = 1; } createSortingIndex(pParse, p, pOrderBy); assert( p->pEList ); @@ -1618,12 +1767,14 @@ static int multiSelect( int iCont, iBreak, iStart; assert( p->pEList ); if( eDest==SRT_Callback ){ - generateColumnNames(pParse, 0, p->pEList); + Select *pFirst = p; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, 0, pFirst->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak); - computeLimitRegisters(pParse, p); iStart = sqlite3VdbeCurrentAddr(v); rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, pOrderBy, -1, eDest, iParm, @@ -1657,10 +1808,10 @@ static int multiSelect( } createSortingIndex(pParse, p, pOrderBy); - addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab1, 0); - assert( p->addrOpenVirt[0] == -1 ); - p->addrOpenVirt[0] = addr; - p->pRightmost->usesVirt = 1; + addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab1, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + p->pRightmost->usesEphm = 1; assert( p->pEList ); /* Code the SELECTs to our left into temporary table "tab1". @@ -1672,9 +1823,9 @@ static int multiSelect( /* Code the current SELECT into temporary table "tab2" */ - addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab2, 0); - assert( p->addrOpenVirt[1] == -1 ); - p->addrOpenVirt[1] = addr; + addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab2, 0); + assert( p->addrOpenEphm[1] == -1 ); + p->addrOpenEphm[1] = addr; p->pPrior = 0; pLimit = p->pLimit; p->pLimit = 0; @@ -1694,12 +1845,14 @@ static int multiSelect( */ assert( p->pEList ); if( eDest==SRT_Callback ){ - generateColumnNames(pParse, 0, p->pEList); + Select *pFirst = p; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, 0, pFirst->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak); - computeLimitRegisters(pParse, p); iStart = sqlite3VdbeAddOp(v, OP_RowKey, tab1, 0); sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont); rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, @@ -1746,21 +1899,23 @@ static int multiSelect( ** SELECT might also skip this part if it has no ORDER BY clause and ** no temp tables are required. */ - if( pOrderBy || p->usesVirt ){ + if( pOrderBy || p->usesEphm ){ int i; /* Loop counter */ KeyInfo *pKeyInfo; /* Collating sequence for the result set */ Select *pLoop; /* For looping through SELECT statements */ + int nKeyCol; /* Number of entries in pKeyInfo->aCol[] */ CollSeq **apColl; CollSeq **aCopy; assert( p->pRightmost==p ); - pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*2*sizeof(CollSeq*) + nCol); + nKeyCol = nCol + (pOrderBy ? pOrderBy->nExpr : 0); + pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nKeyCol*(sizeof(CollSeq*) + 1)); if( !pKeyInfo ){ rc = SQLITE_NOMEM; goto multi_select_end; } - pKeyInfo->enc = pParse->db->enc; + pKeyInfo->enc = ENC(pParse->db); pKeyInfo->nField = nCol; for(i=0, apColl=pKeyInfo->aColl; ipPrior){ for(i=0; i<2; i++){ - int addr = pLoop->addrOpenVirt[i]; + int addr = pLoop->addrOpenEphm[i]; if( addr<0 ){ /* If [0] is unused then [1] is also unused. So we can ** always safely abort as soon as the first unused slot is found */ - assert( pLoop->addrOpenVirt[1]<0 ); + assert( pLoop->addrOpenEphm[1]<0 ); break; } sqlite3VdbeChangeP2(v, addr, nCol); @@ -1786,15 +1941,15 @@ static int multiSelect( if( pOrderBy ){ struct ExprList_item *pOTerm = pOrderBy->a; - int nExpr = pOrderBy->nExpr; + int nOrderByExpr = pOrderBy->nExpr; int addr; u8 *pSortOrder; - aCopy = (CollSeq**)&pKeyInfo[1]; - pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nExpr]; + aCopy = &pKeyInfo->aColl[nOrderByExpr]; + pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nCol]; memcpy(aCopy, pKeyInfo->aColl, nCol*sizeof(CollSeq*)); apColl = pKeyInfo->aColl; - for(i=0; inExpr; i++, pOTerm++, apColl++, pSortOrder++){ + for(i=0; ipExpr; char *zName = pOTerm->zName; assert( pExpr->op==TK_COLUMN && pExpr->iColumnsortOrder; } assert( p->pRightmost==p ); - assert( p->addrOpenVirt[2]>=0 ); - addr = p->addrOpenVirt[2]; + assert( p->addrOpenEphm[2]>=0 ); + addr = p->addrOpenEphm[2]; sqlite3VdbeChangeP2(v, addr, p->pEList->nExpr+2); - pKeyInfo->nField = pOrderBy->nExpr; + pKeyInfo->nField = nOrderByExpr; sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); pKeyInfo = 0; generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm); @@ -1858,6 +2013,7 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){ assert( pExpr->pList==0 ); pExpr->pList = sqlite3ExprListDup(pNew->pList); pExpr->iTable = pNew->iTable; + pExpr->pTab = pNew->pTab; pExpr->iColumn = pNew->iColumn; pExpr->iAgg = pNew->iAgg; sqlite3TokenCopy(&pExpr->token, &pNew->token); @@ -1949,6 +2105,10 @@ static void substSelect(Select *p, int iTable, ExprList *pEList){ ** (12) The subquery is not the right term of a LEFT OUTER JOIN or the ** subquery has no WHERE clause. (added by ticket #350) ** +** (13) The subquery and outer query do not both use LIMIT +** +** (14) The subquery does not use OFFSET +** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query ** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. @@ -1960,7 +2120,6 @@ static void substSelect(Select *p, int iTable, ExprList *pEList){ ** the subquery before this routine runs. */ static int flattenSubquery( - Parse *pParse, /* The parsing context */ Select *p, /* The parent or outer SELECT statement */ int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ int isAgg, /* True if outer SELECT uses aggregate functions */ @@ -1983,18 +2142,26 @@ static int flattenSubquery( pSubitem = &pSrc->a[iFrom]; pSub = pSubitem->pSelect; assert( pSub!=0 ); - if( isAgg && subqueryIsAgg ) return 0; - if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; + if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ + if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ pSubSrc = pSub->pSrc; assert( pSubSrc ); - if( (pSub->pLimit && p->pLimit) || pSub->pOffset || - (pSub->pLimit && isAgg) ) return 0; - if( pSubSrc->nSrc==0 ) return 0; - if( pSub->isDistinct && (pSrc->nSrc>1 || isAgg) ){ - return 0; + /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, + ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET + ** because they could be computed at compile-time. But when LIMIT and OFFSET + ** became arbitrary expressions, we were forced to add restrictions (13) + ** and (14). */ + if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ + if( pSub->pOffset ) return 0; /* Restriction (14) */ + if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ + if( (pSub->isDistinct || pSub->pLimit) + && (pSrc->nSrc>1 || isAgg) ){ /* Restrictions (4)(5)(8)(9) */ + return 0; + } + if( p->isDistinct && subqueryIsAgg ) return 0; /* Restriction (6) */ + if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){ + return 0; /* Restriction (11) */ } - if( p->isDistinct && subqueryIsAgg ) return 0; - if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ) return 0; /* Restriction 3: If the subquery is a join, make sure the subquery is ** not used as the right operand of an outer join. Examples of why this @@ -2080,14 +2247,14 @@ static int flattenSubquery( ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ - substExprList(p->pEList, iParent, pSub->pEList); pList = p->pEList; for(i=0; inExpr; i++){ Expr *pExpr; if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){ - pList->a[i].zName = sqliteStrNDup(pExpr->span.z, pExpr->span.n); + pList->a[i].zName = sqliteStrNDup((char*)pExpr->span.z, pExpr->span.n); } } + substExprList(p->pEList, iParent, pSub->pEList); if( isAgg ){ substExprList(p->pGroupBy, iParent, pSub->pEList); substExpr(p->pHaving, iParent, pSub->pEList); @@ -2124,6 +2291,9 @@ static int flattenSubquery( /* ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y; + ** + ** One is tempted to try to add a and b to combine the limits. But this + ** does not work if either limit is negative. */ if( pSub->pLimit ){ p->pLimit = pSub->pLimit; @@ -2166,10 +2336,11 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ int base; Vdbe *v; int seekOp; - int cont; ExprList *pEList, *pList, eList; struct ExprList_item eListItem; SrcList *pSrc; + int brk; + int iDb; /* Check to see if this query is a simple min() or max() query. Return ** zero if it is not. @@ -2184,9 +2355,9 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ pList = pExpr->pList; if( pList==0 || pList->nExpr!=1 ) return 0; if( pExpr->token.n!=3 ) return 0; - if( sqlite3StrNICmp(pExpr->token.z,"min",3)==0 ){ + if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){ seekOp = OP_Rewind; - }else if( sqlite3StrNICmp(pExpr->token.z,"max",3)==0 ){ + }else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){ seekOp = OP_Last; }else{ return 0; @@ -2196,6 +2367,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ iCol = pExpr->iColumn; pTab = pSrc->a[0].pTab; + /* If we get to here, it means the query is of the correct form. ** Check to make sure we have an index and make pIdx point to the ** appropriate index. If the min() or max() is on an INTEGER PRIMARY @@ -2206,9 +2378,13 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ pIdx = 0; }else{ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); + if( pColl==0 ) return 0; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->nColumn>=1 ); - if( pIdx->aiColumn[0]==iCol && pIdx->keyInfo.aColl[0]==pColl ) break; + if( pIdx->aiColumn[0]==iCol && + 0==sqlite3StrICmp(pIdx->azColl[0], pColl->zName) ){ + break; + } } if( pIdx==0 ) return 0; } @@ -2222,8 +2398,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ /* If the output is destined for a temporary table, open that table. */ - if( eDest==SRT_VirtualTab ){ - sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 1); + if( eDest==SRT_EphemTab ){ + sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 1); } /* Generating code to find the min or the max. Basically all we have @@ -2231,13 +2407,16 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first ** or last entry in the main table. */ - sqlite3CodeVerifySchema(pParse, pTab->iDb); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 || pTab->isEphem ); + sqlite3CodeVerifySchema(pParse, iDb); + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); base = pSrc->a[0].iCursor; - computeLimitRegisters(pParse, p); + brk = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, brk); if( pSrc->a[0].pSelect==0 ){ - sqlite3OpenTableForReading(v, base, pTab); + sqlite3OpenTable(pParse, base, iDb, pTab, OP_OpenRead); } - cont = sqlite3VdbeMakeLabel(v); if( pIdx==0 ){ sqlite3VdbeAddOp(v, seekOp, base, 0); }else{ @@ -2248,10 +2427,12 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ ** "INSERT INTO x SELECT max() FROM x". */ int iIdx; + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); iIdx = pParse->nTab++; - sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); - sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum, - (char*)&pIdx->keyInfo, P3_KEYINFO); + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); + sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum, + (char*)pKey, P3_KEYINFO_HANDOFF); if( seekOp==OP_Rewind ){ sqlite3VdbeAddOp(v, OP_Null, 0, 0); sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0); @@ -2266,8 +2447,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ memset(&eListItem, 0, sizeof(eListItem)); eList.a = &eListItem; eList.a[0].pExpr = pExpr; - selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont, 0); - sqlite3VdbeResolveLabel(v, cont); + selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, brk, brk, 0); + sqlite3VdbeResolveLabel(v, brk); sqlite3VdbeAddOp(v, OP_Close, base, 0); return 1; @@ -2309,11 +2490,6 @@ static int processOrderGroupBy( if( sqlite3ExprResolveNames(pNC, pE) ){ return 1; } - if( sqlite3ExprIsConstant(pE) ){ - sqlite3ErrorMsg(pParse, - "%s BY terms must not be non-integer constants", zType); - return 1; - } } return 0; } @@ -2356,14 +2532,8 @@ int sqlite3SelectResolve( /* 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; - sNC.hasAgg = 0; - sNC.nErr = 0; - sNC.nRef = 0; - sNC.pEList = 0; - sNC.allowAgg = 0; - sNC.pSrcList = 0; - sNC.pNext = 0; if( sqlite3ExprResolveNames(&sNC, p->pLimit) || sqlite3ExprResolveNames(&sNC, p->pOffset) ){ return SQLITE_ERROR; @@ -2465,7 +2635,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ pFunc->iDistinct = -1; }else{ KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->pList); - sqlite3VdbeOp3(v, OP_OpenVirtual, pFunc->iDistinct, 0, + sqlite3VdbeOp3(v, OP_OpenEphemeral, pFunc->iDistinct, 0, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); } } @@ -2511,13 +2681,14 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ if( pF->iDistinct>=0 ){ addrNext = sqlite3VdbeMakeLabel(v); assert( nArg==1 ); - codeDistinct(v, pF->iDistinct, addrNext, 1, 2); + codeDistinct(v, pF->iDistinct, addrNext, 1); } if( pF->pFunc->needCollSeq ){ CollSeq *pColl = 0; struct ExprList_item *pItem; int j; - for(j=0, pItem=pList->a; !pColl && jnExpr; j++, pItem++){ + assert( pList!=0 ); /* pList!=0 if pF->pFunc->needCollSeq is true */ + for(j=0, pItem=pList->a; !pColl && jpExpr); } if( !pColl ){ @@ -2613,10 +2784,13 @@ int sqlite3Select( int isDistinct; /* True if the DISTINCT keyword is present */ int distinct; /* Table to use for the distinct set */ int rc = 1; /* Value to return from this function */ - int addrSortIndex; /* Address of an OP_OpenVirtual instruction */ + int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */ AggInfo sAggInfo; /* Information used by aggregate queries */ + int iEnd; /* Address of the end of the query */ - if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1; + if( p==0 || sqlite3MallocFailed() || pParse->nErr ){ + return 1; + } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); @@ -2663,7 +2837,6 @@ int sqlite3Select( /* If writing to memory or generating a set ** only a single column may be output. */ - assert( eDest!=SRT_Exists || pEList->nExpr==1 ); #ifndef SQLITE_OMIT_SUBQUERY if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){ sqlite3ErrorMsg(pParse, "only a single result allowed for " @@ -2683,13 +2856,6 @@ int sqlite3Select( v = sqlite3GetVdbe(pParse); if( v==0 ) goto select_end; - /* Identify column names if we will be using them in a callback. This - ** step is skipped if the output is going to some other destination. - */ - if( eDest==SRT_Callback ){ - generateColumnNames(pParse, pTabList, pEList); - } - /* Generate code for all sub-queries in the FROM clause */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) @@ -2698,7 +2864,7 @@ int sqlite3Select( int needRestoreContext; struct SrcList_item *pItem = &pTabList->a[i]; - if( pItem->pSelect==0 ) continue; + if( pItem->pSelect==0 || pItem->isPopulated ) continue; if( pItem->zName!=0 ){ zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pItem->zName; @@ -2706,7 +2872,7 @@ int sqlite3Select( }else{ needRestoreContext = 0; } - sqlite3Select(pParse, pItem->pSelect, SRT_VirtualTab, + sqlite3Select(pParse, pItem->pSelect, SRT_EphemTab, pItem->iCursor, p, i, &isAgg, 0); if( needRestoreContext ){ pParse->zAuthContext = zSavedAuthContext; @@ -2735,7 +2901,7 @@ int sqlite3Select( */ #ifndef SQLITE_OMIT_VIEW if( pParent && pParentAgg && - flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){ + flattenSubquery(pParent, parentTab, *pParentAgg, isAgg) ){ if( isAgg ) *pParentAgg = 1; goto select_end; } @@ -2746,7 +2912,7 @@ int sqlite3Select( ** ** This sorting index might end up being unused if the data can be ** extracted in pre-sorted order. If that is the case, then the - ** OP_OpenVirtual instruction will be changed to an OP_Noop once + ** OP_OpenEphemeral instruction will be changed to an OP_Noop once ** we figure out that the sorting index is not needed. The addrSortIndex ** variable is used to facilitate that change. */ @@ -2763,31 +2929,22 @@ int sqlite3Select( } pKeyInfo = keyInfoFromExprList(pParse, pOrderBy); pOrderBy->iECursor = pParse->nTab++; - p->addrOpenVirt[2] = addrSortIndex = - sqlite3VdbeOp3(v, OP_OpenVirtual, pOrderBy->iECursor, pOrderBy->nExpr+2, - (char*)pKeyInfo, P3_KEYINFO_HANDOFF); + p->addrOpenEphm[2] = addrSortIndex = + sqlite3VdbeOp3(v, OP_OpenEphemeral, pOrderBy->iECursor, pOrderBy->nExpr+2, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); }else{ addrSortIndex = -1; } - /* Set the limiter. - */ - computeLimitRegisters(pParse, p); - /* If the output is destined for a temporary table, open that table. */ - if( eDest==SRT_VirtualTab ){ - sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, pEList->nExpr); + if( eDest==SRT_EphemTab ){ + sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, pEList->nExpr); } - - /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists + /* Set the limiter. */ - if( eDest==SRT_Mem ){ - sqlite3VdbeAddOp(v, OP_MemNull, iParm, 0); - }else if( eDest==SRT_Exists ){ - sqlite3VdbeAddOp(v, OP_MemInt, 0, iParm); - } + iEnd = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iEnd); /* Open a virtual index to use for the distinct set. */ @@ -2795,7 +2952,7 @@ int sqlite3Select( KeyInfo *pKeyInfo; distinct = pParse->nTab++; pKeyInfo = keyInfoFromExprList(pParse, p->pEList); - sqlite3VdbeOp3(v, OP_OpenVirtual, distinct, 0, + sqlite3VdbeOp3(v, OP_OpenEphemeral, distinct, 0, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); }else{ distinct = -1; @@ -2809,13 +2966,13 @@ int sqlite3Select( pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy); if( pWInfo==0 ) goto select_end; - /* If sorting index that was created by a prior OP_OpenVirtual - ** instruction ended up not being needed, then change the OP_OpenVirtual + /* If sorting index that was created by a prior OP_OpenEphemeral + ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ if( addrSortIndex>=0 && pOrderBy==0 ){ - uncreateSortingIndex(pParse, addrSortIndex); - p->addrOpenVirt[2] = -1; + sqlite3VdbeChangeToNoop(v, addrSortIndex, 1); + p->addrOpenEphm[2] = -1; } /* Use the standard inner loop @@ -2849,7 +3006,7 @@ int sqlite3Select( int addrGroupByChange; /* Code that runs when any GROUP BY term changes */ int addrProcessRow; /* Code to process a single input row */ int addrEnd; /* End of all processing */ - int addrSortingIdx; /* The OP_OpenVirtual for the sorting index */ + int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */ int addrReset; /* Subroutine for resetting the accumulator */ addrEnd = sqlite3VdbeMakeLabel(v); @@ -2879,7 +3036,7 @@ int sqlite3Select( goto select_end; } } - if( sqlite3_malloc_failed ) goto select_end; + if( sqlite3MallocFailed() ) goto select_end; /* Processing for aggregates with GROUP BY is very different and ** much more complex tha aggregates without a GROUP BY. @@ -2896,13 +3053,13 @@ int sqlite3Select( /* If there is a GROUP BY clause we might need a sorting index to ** implement it. Allocate that sorting index now. If it turns out - ** that we do not need it after all, the OpenVirtual instruction + ** that we do not need it after all, the OpenEphemeral instruction ** will be converted into a Noop. */ sAggInfo.sortingIdx = pParse->nTab++; pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); addrSortingIdx = - sqlite3VdbeOp3(v, OP_OpenVirtual, sAggInfo.sortingIdx, + sqlite3VdbeOp3(v, OP_OpenEphemeral, sAggInfo.sortingIdx, sAggInfo.nSortingColumn, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); @@ -2965,7 +3122,7 @@ int sqlite3Select( if( pWInfo==0 ) goto select_end; if( pGroupBy==0 ){ /* The optimizer is able to deliver rows in group by order so - ** we do not have to sort. The OP_OpenVirtual table will be + ** we do not have to sort. The OP_OpenEphemeral table will be ** cancelled later because we still need to use the pKeyInfo */ pGroupBy = p->pGroupBy; @@ -3060,7 +3217,7 @@ int sqlite3Select( sqlite3VdbeAddOp(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop); }else{ sqlite3WhereEnd(pWInfo); - uncreateSortingIndex(pParse, addrSortingIdx); + sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1); } /* Output the final row of result @@ -3100,18 +3257,21 @@ int sqlite3Select( #ifndef SQLITE_OMIT_SUBQUERY /* If this was a subquery, we have now converted the subquery into a - ** temporary table. So delete the subquery structure from the parent - ** to prevent this subquery from being evaluated again and to force the - ** the use of the temporary table. + ** temporary table. So set the SrcList_item.isPopulated flag to prevent + ** this subquery from being evaluated again and to force the use of + ** the temporary table. */ if( pParent ){ assert( pParent->pSrc->nSrc>parentTab ); assert( pParent->pSrc->a[parentTab].pSelect==p ); - sqlite3SelectDelete(p); - pParent->pSrc->a[parentTab].pSelect = 0; + pParent->pSrc->a[parentTab].isPopulated = 1; } #endif + /* Jump here to skip this query + */ + sqlite3VdbeResolveLabel(v, iEnd); + /* The SELECT was successfully coded. Set the return code to 0 ** to indicate no errors. */ @@ -3121,6 +3281,14 @@ int sqlite3Select( ** successful coding of the SELECT. */ select_end: + + /* Identify column names if we will be using them in a callback. This + ** step is skipped if the output is going to some other destination. + */ + if( rc==SQLITE_OK && eDest==SRT_Callback ){ + generateColumnNames(pParse, pTabList, pEList); + } + sqliteFree(sAggInfo.aCol); sqliteFree(sAggInfo.aFunc); return rc; diff --git a/ext/pdo_sqlite/sqlite/src/shell.c b/ext/pdo_sqlite/sqlite/src/shell.c index 61ff2482d5..6058bc195e 100644 --- a/ext/pdo_sqlite/sqlite/src/shell.c +++ b/ext/pdo_sqlite/sqlite/src/shell.c @@ -21,7 +21,7 @@ #include "sqlite3.h" #include -#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) +#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__) # include # include # include @@ -37,6 +37,10 @@ # include #endif +#ifdef __OS2__ +# include +#endif + #if defined(HAVE_READLINE) && HAVE_READLINE==1 # include # include @@ -62,7 +66,7 @@ static sqlite3 *db = 0; /* ** True if an interrupt (Control-C) has been received. */ -static int seenInterrupt = 0; +static volatile int seenInterrupt = 0; /* ** This is the name of our program. It is set in main(), used @@ -81,7 +85,7 @@ static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ /* ** Determines if a string is a number of not. */ -static int isNumber(const unsigned char *z, int *realnum){ +static int isNumber(const char *z, int *realnum){ if( *z=='-' || *z=='+' ) z++; if( !isdigit(*z) ){ return 0; @@ -197,7 +201,7 @@ static char *one_input_line(const char *zPrior, FILE *in){ } zResult = readline(zPrompt); #if defined(HAVE_READLINE) && HAVE_READLINE==1 - if( zResult ) add_history(zResult); + if( zResult && *zResult ) add_history(zResult); #endif return zResult; } @@ -247,7 +251,7 @@ struct callback_data { #define MODE_Csv 7 /* Quote strings, numbers are plain */ #define MODE_NUM_OF 8 /* The number of modes (not a mode itself) */ -char *modeDescr[MODE_NUM_OF] = { +static const char *modeDescr[MODE_NUM_OF] = { "line", "column", "list", @@ -384,12 +388,12 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){ int w = 5; if( azArg==0 ) break; for(i=0; iw ) w = len; } if( p->cnt++>0 ) fprintf(p->out,"\n"); for(i=0; iout,"%*s = %s\n", w, azCol[i], + fprintf(p->out,"%*s = %s\n", w, azCol[i], azArg[i] ? azArg[i] : p->nullvalue); } break; @@ -486,7 +490,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){ case MODE_Tcl: { if( p->cnt++==0 && p->showHeader ){ for(i=0; iout,azCol[i]); + output_c_string(p->out,azCol[i] ? azCol[i] : ""); fprintf(p->out, "%s", p->separator); } fprintf(p->out,"\n"); @@ -502,7 +506,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){ case MODE_Csv: { if( p->cnt++==0 && p->showHeader ){ for(i=0; iout,"\n"); } @@ -690,8 +694,9 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ 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, sqlite3_column_text(pTableInfo, 1), '"'); + zSelect = appendText(zSelect, zText, '"'); rc = sqlite3_step(pTableInfo); if( rc==SQLITE_ROW ){ zSelect = appendText(zSelect, ") || ', ' || ", 0); @@ -758,6 +763,9 @@ static char zHelp[] = ".help Show this message\n" ".import FILE TABLE Import data from FILE into TABLE\n" ".indices TABLE Show names of all indices on TABLE\n" +#ifndef SQLITE_OMIT_LOAD_EXTENSION + ".load FILE ?ENTRY? Load an extension library\n" +#endif ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" " csv Comma-separated values\n" " column Left-aligned columns. (See .width)\n" @@ -773,9 +781,6 @@ static char zHelp[] = ".prompt MAIN CONTINUE Replace the standard prompts\n" ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" -#ifdef SQLITE_HAS_CODEC - ".rekey OLD NEW NEW Change the encryption key\n" -#endif ".schema ?TABLE? Show the CREATE statements\n" ".separator STRING Change separator used by output mode and .import\n" ".show Show the current values for various settings\n" @@ -795,9 +800,6 @@ static void open_db(struct callback_data *p){ if( p->db==0 ){ sqlite3_open(p->zDbFilename, &p->db); db = p->db; -#ifdef SQLITE_HAS_CODEC - sqlite3_key(p->db, p->zKey, p->zKey ? strlen(p->zKey) : 0); -#endif sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, shellstaticFunc, 0, 0); if( SQLITE_OK!=sqlite3_errcode(db) ){ @@ -805,6 +807,9 @@ static void open_db(struct callback_data *p){ p->zDbFilename, sqlite3_errmsg(db)); exit(1); } +#ifndef SQLITE_OMIT_LOAD_EXTENSION + sqlite3_enable_load_extension(p->db, 1); +#endif } } @@ -829,7 +834,7 @@ static void resolve_backslashes(char *z){ }else if( c=='r' ){ c = '\r'; }else if( c>='0' && c<='7' ){ - c =- '0'; + c -= '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ i++; c = (c<<3) + z[i] - '0'; @@ -1037,6 +1042,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ FILE *in; /* The input file */ int lineno = 0; /* Line number of input file */ + open_db(p); nSep = strlen(p->separator); if( nSep==0 ){ fprintf(stderr, "non-null separator required for import\n"); @@ -1045,7 +1051,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable); if( zSql==0 ) return 0; nByte = strlen(zSql); - rc = sqlite3_prepare(p->db, zSql, 0, &pStmt, 0); + rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ){ fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); @@ -1065,7 +1071,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ } zSql[j++] = ')'; zSql[j] = 0; - rc = sqlite3_prepare(p->db, zSql, 0, &pStmt, 0); + rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); free(zSql); if( rc ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); @@ -1079,7 +1085,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){ return 0; } azCol = malloc( sizeof(azCol[0])*(nCol+1) ); - if( azCol==0 ) return 0; + if( azCol==0 ){ + fclose(in); + return 0; + } sqlite3_exec(p->db, "BEGIN", 0, 0, 0); zCommit = "COMMIT"; while( (zLine = local_getline(0, in))!=0 ){ @@ -1146,6 +1155,22 @@ static int do_meta_command(char *zLine, struct callback_data *p){ } }else +#ifndef SQLITE_OMIT_LOAD_EXTENSION + if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){ + const char *zFile, *zProc; + char *zErrMsg = 0; + int rc; + zFile = azArg[1]; + zProc = nArg>=3 ? azArg[2] : 0; + open_db(p); + rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "%s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + }else +#endif + if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){ int n2 = strlen(azArg[1]); if( strncmp(azArg[1],"line",n2)==0 @@ -1226,22 +1251,6 @@ static int do_meta_command(char *zLine, struct callback_data *p){ } }else -#ifdef SQLITE_HAS_CODEC - if( c=='r' && strncmp(azArg[0],"rekey", n)==0 && nArg==4 ){ - char *zOld = p->zKey; - if( zOld==0 ) zOld = ""; - if( strcmp(azArg[1],zOld) ){ - fprintf(stderr,"old key is incorrect\n"); - }else if( strcmp(azArg[2], azArg[3]) ){ - fprintf(stderr,"2nd copy of new key does not match the 1st\n"); - }else{ - sqlite3_free(p->zKey); - p->zKey = sqlite3_mprintf("%s", azArg[2]); - sqlite3_rekey(p->db, p->zKey, strlen(p->zKey)); - } - }else -#endif - if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ struct callback_data data; char *zErrMsg = 0; @@ -1392,6 +1401,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ int j; + assert( nArg<=ArraySize(azArg) ); for(j=1; jcolWidth); j++){ p->colWidth[j-1] = atoi(azArg[j]); } @@ -1488,6 +1498,10 @@ static void process_input(struct callback_data *p, FILE *in){ if( zLine[i]!=0 ){ nSql = strlen(zLine); zSql = malloc( nSql+1 ); + if( zSql==0 ){ + fprintf(stderr, "out of memory\n"); + exit(1); + } strcpy(zSql, zLine); } }else{ @@ -1507,7 +1521,7 @@ static void process_input(struct callback_data *p, FILE *in){ open_db(p); rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg); if( rc || zErrMsg ){ - if( in!=0 && !p->echoOn ) printf("%s\n",zSql); + /* if( in!=0 && !p->echoOn ) printf("%s\n",zSql); */ if( zErrMsg!=0 ){ printf("SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); @@ -1536,7 +1550,7 @@ static void process_input(struct callback_data *p, FILE *in){ static char *find_home_dir(void){ char *home_dir = NULL; -#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) +#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__) struct passwd *pwent; uid_t uid = getuid(); if( (pwent=getpwuid(uid)) != NULL) { @@ -1556,7 +1570,7 @@ static char *find_home_dir(void){ } } -#if defined(_WIN32) || defined(WIN32) +#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) if (!home_dir) { home_dir = "c:"; } @@ -1581,7 +1595,7 @@ static void process_sqliterc( ){ char *home_dir = NULL; const char *sqliterc = sqliterc_override; - char *zBuf; + char *zBuf = 0; FILE *in = NULL; if (sqliterc == NULL) { @@ -1607,6 +1621,7 @@ static void process_sqliterc( process_input(p,in); fclose(in); } + free(zBuf); return; } @@ -1619,9 +1634,6 @@ static const char zOptions[] = " -[no]header turn headers on or off\n" " -column set output mode to 'column'\n" " -html set output mode to HTML\n" -#ifdef SQLITE_HAS_CODEC - " -key KEY encryption key\n" -#endif " -line set output mode to 'line'\n" " -list set output mode to 'list'\n" " -separator 'x' set output field separator (|)\n" @@ -1642,7 +1654,7 @@ static void usage(int showDetail){ /* ** Initialize the state information in data */ -void main_init(struct callback_data *data) { +static void main_init(struct callback_data *data) { memset(data, 0, sizeof(*data)); data->mode = MODE_List; strcpy(data->separator,"|"); @@ -1755,7 +1767,7 @@ int main(int argc, char **argv){ data.echoOn = 1; }else if( strcmp(z,"-version")==0 ){ printf("%s\n", sqlite3_libversion()); - return 1; + return 0; }else if( strcmp(z,"-help")==0 ){ usage(1); }else{ @@ -1802,12 +1814,18 @@ int main(int argc, char **argv){ if( zHistory ){ stifle_history(100); write_history(zHistory); + free(zHistory); } + free(zHome); }else{ process_input(&data, stdin); } } set_table_name(&data, 0); - if( db ) sqlite3_close(db); + if( db ){ + if( sqlite3_close(db)!=SQLITE_OK ){ + fprintf(stderr,"error closing database: %s\n", sqlite3_errmsg(db)); + } + } return 0; } diff --git a/ext/pdo_sqlite/sqlite/src/sqlite.h.in b/ext/pdo_sqlite/sqlite/src/sqlite.h.in index 6b2dd551d6..a1b4759f84 100644 --- a/ext/pdo_sqlite/sqlite/src/sqlite.h.in +++ b/ext/pdo_sqlite/sqlite/src/sqlite.h.in @@ -78,7 +78,10 @@ typedef struct sqlite3 sqlite3; ** to do a typedef that for 64-bit integers that depends on what compiler ** is being used. */ -#if defined(_MSC_VER) || defined(__BORLANDC__) +#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 @@ -86,6 +89,13 @@ typedef struct sqlite3 sqlite3; typedef unsigned long long int sqlite_uint64; #endif +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite_int64 +#endif /* ** A function to close the database. @@ -157,6 +167,7 @@ int sqlite3_exec( ** Return values for sqlite3_exec() and sqlite3_step() */ #define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ #define SQLITE_ERROR 1 /* SQL error or missing database */ #define SQLITE_INTERNAL 2 /* NOT USED. Internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ @@ -185,6 +196,7 @@ int sqlite3_exec( #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-error-codes */ /* ** Each entry in an SQLite table has a unique integer key. (The key is @@ -393,9 +405,19 @@ void sqlite3_free_table(char **result); */ char *sqlite3_mprintf(const char*,...); char *sqlite3_vmprintf(const char*, va_list); -void sqlite3_free(char *z); char *sqlite3_snprintf(int,char*,const char*, ...); +/* +** SQLite uses its own memory allocator. On many installations, this +** memory allocator is identical to the standard malloc()/realloc()/free() +** and can be used interchangable. On others, the implementations are +** different. For maximum portability, it is best not to mix calls +** to the standard malloc/realloc/free with the sqlite versions. +*/ +void *sqlite3_malloc(int); +void *sqlite3_realloc(void*, int); +void sqlite3_free(void*); + #ifndef SQLITE_OMIT_AUTHORIZATION /* ** This routine registers a callback with the SQLite library. The @@ -454,7 +476,8 @@ int sqlite3_set_authorizer( #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 */ /* ** The return value of the authorization function should be one of the @@ -716,6 +739,30 @@ int sqlite3_column_count(sqlite3_stmt *pStmt); const char *sqlite3_column_name(sqlite3_stmt*,int); const void *sqlite3_column_name16(sqlite3_stmt*,int); +/* +** The first parameter to the following calls is a compiled SQL statement. +** These functions return information about the Nth column returned by +** the statement, where N is the second function argument. +** +** If the Nth column returned by the statement is not a column value, +** then all of the functions return NULL. Otherwise, the return the +** name of the attached database, table and column that the expression +** extracts a value from. +** +** As with all other SQLite APIs, those postfixed with "16" return UTF-16 +** encoded strings, the other functions return UTF-8. The memory containing +** the returned strings is valid until the statement handle is finalized(). +** +** These APIs are only available if the library was compiled with the +** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +*/ +const char *sqlite3_column_database_name(sqlite3_stmt*,int); +const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +const char *sqlite3_column_table_name(sqlite3_stmt*,int); +const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); + /* ** The first parameter is a compiled SQL statement. If this statement ** is a SELECT statement, the Nth column of the returned result set @@ -728,7 +775,7 @@ const void *sqlite3_column_name16(sqlite3_stmt*,int); ** ** And the following statement compiled: ** -** SELECT c1 + 1, 0 FROM t1; +** SELECT c1 + 1, c1 FROM t1; ** ** Then this routine would return the string "VARIANT" for the second ** result column (i==1), and a NULL pointer for the first result column @@ -748,7 +795,7 @@ const char *sqlite3_column_decltype(sqlite3_stmt *, int i); ** ** And the following statement compiled: ** -** SELECT c1 + 1, 0 FROM t1; +** SELECT c1 + 1, c1 FROM t1; ** ** Then this routine would return the string "INTEGER" for the second ** result column (i==1), and a NULL pointer for the first result column @@ -889,6 +936,8 @@ sqlite_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); int sqlite3_column_type(sqlite3_stmt*, int iCol); +int sqlite3_column_numeric_type(sqlite3_stmt*, int iCol); +sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); /* ** The sqlite3_finalize() function is called to delete a compiled @@ -972,9 +1021,8 @@ int sqlite3_create_function16( ); /* -** The next routine returns the number of calls to xStep for a particular -** aggregate function instance. The current call to xStep counts so this -** routine always returns at least 1. +** This function is deprecated. Do not use it. It continues to exist +** so as not to break legacy code. But new code should avoid using it. */ int sqlite3_aggregate_count(sqlite3_context*); @@ -997,6 +1045,7 @@ const void *sqlite3_value_text16(sqlite3_value*); const void *sqlite3_value_text16le(sqlite3_value*); const void *sqlite3_value_text16be(sqlite3_value*); int sqlite3_value_type(sqlite3_value*); +int sqlite3_value_numeric_type(sqlite3_value*); /* ** Aggregate functions use the following routine to allocate @@ -1080,11 +1129,12 @@ void sqlite3_result_value(sqlite3_context*, sqlite3_value*); ** These are the allowed values for the eTextRep argument to ** sqlite3_create_collation and sqlite3_create_function. */ -#define SQLITE_UTF8 1 -#define SQLITE_UTF16LE 2 -#define SQLITE_UTF16BE 3 -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_UTF8 1 +#define SQLITE_UTF16LE 2 +#define SQLITE_UTF16BE 3 +#define SQLITE_UTF16 4 /* Use native byte order */ +#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ /* ** These two functions are used to add new collation sequences to the @@ -1251,7 +1301,7 @@ extern char *sqlite3_temp_directory; ** This functionality can be omitted from a build by defining the ** SQLITE_OMIT_GLOBALRECOVER at compile time. */ -int sqlite3_global_recover(); +int sqlite3_global_recover(void); /* ** Test to see whether or not the database connection is in autocommit @@ -1269,6 +1319,403 @@ int sqlite3_get_autocommit(sqlite3*); */ sqlite3 *sqlite3_db_handle(sqlite3_stmt*); +/* +** Register a callback function with the database connection identified by the +** first argument to be invoked whenever a row is updated, inserted or deleted. +** 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. 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). +** +** If another function was previously registered, its pArg value is returned. +** Otherwise NULL is returned. +*/ +void *sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite_int64), + void* +); + +/* +** Register a callback to be invoked whenever a transaction is rolled +** back. +** +** The new callback function overrides any existing rollback-hook +** callback. If there was an existing callback, then it's pArg value +** (the third argument to sqlite3_rollback_hook() when it was registered) +** is returned. Otherwise, NULL is returned. +** +** 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 +** callback is not invoked if a transaction is automatically rolled +** back because the database connection is closed. +*/ +void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** This function is only available if the library is compiled without +** the SQLITE_OMIT_SHARED_CACHE macro defined. It is used to enable or +** disable (if the argument is true or false, respectively) the +** "shared pager" feature. +*/ +int sqlite3_enable_shared_cache(int); + +/* +** Attempt to free N bytes of heap memory by deallocating non-essential +** memory allocations held by the database library (example: memory +** used to cache database pages to improve performance). +** +** This function is not a part of standard builds. It is only created +** if SQLite is compiled with the SQLITE_ENABLE_MEMORY_MANAGEMENT macro. +*/ +int sqlite3_release_memory(int); + +/* +** Place a "soft" limit on the amount of heap memory that may be allocated by +** SQLite within the current thread. If an internal allocation is requested +** that would exceed the specified limit, sqlite3_release_memory() is invoked +** one or more times to free up some space before the allocation is made. +** +** The limit is called "soft", because if sqlite3_release_memory() cannot free +** sufficient memory to prevent the limit from being exceeded, the memory is +** allocated anyway and the current operation proceeds. +** +** This function is only available if the library was compiled with the +** SQLITE_ENABLE_MEMORY_MANAGEMENT option set. +** memory-management has been enabled. +*/ +void sqlite3_soft_heap_limit(int); + +/* +** This routine makes sure that all thread-local storage has been +** deallocated for the current thread. +** +** This routine is not technically necessary. All thread-local storage +** will be automatically deallocated once memory-management and +** shared-cache are disabled and the soft heap limit has been set +** to zero. This routine is provided as a convenience for users who +** want to make absolutely sure they have not forgotten something +** prior to killing off a thread. +*/ +void sqlite3_thread_cleanup(void); + +/* +** Return meta information about a specific column of a specific database +** table accessible using the connection handle passed as the first function +** argument. +** +** 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 as the database engine uses to +** resolve unqualified table references. +** +** The third and fourth parameters to this function are the table and column +** name of the desired column, respectively. Neither of these parameters +** may be NULL. +** +** Meta information 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 meta +** information is ommitted. +** +** Parameter Output Type Description +** ----------------------------------- +** +** 5th const char* Data type +** 6th const char* Name of the default collation sequence +** 7th int True if the column has a NOT NULL constraint +** 8th int True if the column is part of the PRIMARY KEY +** 9th int True if the column is AUTOINCREMENT +** +** +** The memory pointed to by the character pointers returned for the +** declaration type and collation sequence is valid only until the next +** call to any sqlite API function. +** +** If the specified table is actually a view, then an error is returned. +** +** If the specified column is "rowid", "oid" or "_rowid_" 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 +** explicitly declared IPK column, then the output parameters are set as +** follows: +** +** data type: "INTEGER" +** collation sequence: "BINARY" +** not null: 0 +** primary key: 1 +** auto increment: 0 +** +** This function may load one or more schemas from database files. If an +** error occurs during this process, or if the requested table or column +** cannot be found, an SQLITE error code is returned and an error message +** left in the database handle (to be retrieved using sqlite3_errmsg()). +** +** This API is only available if the library was compiled with the +** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +*/ +int 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 colums is auto-increment */ +); + +/* +****** EXPERIMENTAL - subject to change without notice ************** +** +** Attempt to load an SQLite extension library contained in the file +** zFile. The entry point is zProc. zProc may be 0 in which case the +** name of the entry point defaults to "sqlite3_extension_init". +** +** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong. +** +** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with +** error message text. 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 or an error will be returned. +** +****** EXPERIMENTAL - subject to change without notice ************** +*/ +int 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 */ +); + +/* +** So as not to open security holes in older applications that are +** unprepared to deal with extension load, and as a means of disabling +** extension loading while executing user-entered SQL, the following +** API is provided to turn the extension loading mechanism on and +** off. It is off by default. See ticket #1863. +** +** Call this routine with onoff==1 to turn extension loading on +** and call it with onoff==0 to turn it back off again. +*/ +int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + +/* +****** EXPERIMENTAL - subject to change without notice ************** +** +** 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 stablizes, 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; + +/* +** A module is a class of virtual tables. Each module is defined +** by an instance of the following structure. This structure consists +** mostly of methods for the module. +*/ +struct sqlite3_module { + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, char **argv, + sqlite3_vtab **ppVTab); + int (*xConnect)(sqlite3*, void *pAux, + int argc, char **argv, + sqlite3_vtab **ppVTab); + 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*, sqlite_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite_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); +}; + +/* +** The sqlite3_index_info structure and its substructures is used to +** pass information into and receive the reply from the xBestIndex +** method of an sqlite3_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. 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 simplificatinos 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 in the correct +** form that refer 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 xFilter. +** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. +** +** The orderByConsumed means that output from xFilter 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 doing the +** particular lookup. A full scan of a table with N entries should have +** a cost of N. A binary search of a table of N entries should have a +** cost of approximately log(N). +*/ +struct sqlite3_index_info { + /* Inputs */ + const int nConstraint; /* Number of entries in aConstraint */ + const 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 */ + } *const aConstraint; /* Table of WHERE clause constraints */ + const int nOrderBy; /* Number of terms in the ORDER BY clause */ + const struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *const 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 */ + } *const 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 */ +}; +#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 + +/* +** This routine is used to register a new module name with an SQLite +** connection. Module names must be registered before creating new +** virtual tables on the module, or before using preexisting virtual +** tables of the module. +*/ +int sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *, /* Methods for the module */ + void * /* Client data for xCreate/xConnect */ +); + +/* +** Every module implementation uses a subclass of the following structure +** to describe a particular instance of the module. Each subclass will +** be taylored 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. +*/ +struct sqlite3_vtab { + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Used internally */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* Every 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 +** xOpen method 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 */ +}; + +/* +** The xCreate and xConnect methods of a module use the following API +** to declare the format (the names and datatypes of the columns) of +** the virtual tables they implement. +*/ +int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); + +/* +** 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 stablizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +** +****** EXPERIMENTAL - subject to change without notice ************** +*/ + +/* +** 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 + #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif diff --git a/ext/pdo_sqlite/sqlite/src/sqlite3ext.h b/ext/pdo_sqlite/sqlite/src/sqlite3ext.h new file mode 100644 index 0000000000..9b3dae7407 --- /dev/null +++ b/ext/pdo_sqlite/sqlite/src/sqlite3ext.h @@ -0,0 +1,280 @@ +/* +** 2006 June 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 header file defines the SQLite interface for use by +** shared libraries that want to be imported as extensions into +** an SQLite instance. Shared libraries that intend to be loaded +** as extensions by SQLite should #include this file instead of +** sqlite3.h. +** +** @(#) $Id$ +*/ +#ifndef _SQLITE3EXT_H_ +#define _SQLITE3EXT_H_ +#include + +typedef struct sqlite3_api_routines sqlite3_api_routines; + +/* +** The following structure hold pointers to all of the SQLite API +** routines. +*/ +struct sqlite3_api_routines { + void * (*aggregate_context)(sqlite3_context*,int nBytes); + int (*aggregate_count)(sqlite3_context*); + int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); + int (*bind_double)(sqlite3_stmt*,int,double); + int (*bind_int)(sqlite3_stmt*,int,int); + int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); + int (*bind_null)(sqlite3_stmt*,int); + int (*bind_parameter_count)(sqlite3_stmt*); + int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); + const char * (*bind_parameter_name)(sqlite3_stmt*,int); + int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); + int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); + int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); + int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); + int (*busy_timeout)(sqlite3*,int ms); + int (*changes)(sqlite3*); + int (*close)(sqlite3*); + int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*)); + int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*)); + const void * (*column_blob)(sqlite3_stmt*,int iCol); + int (*column_bytes)(sqlite3_stmt*,int iCol); + int (*column_bytes16)(sqlite3_stmt*,int iCol); + int (*column_count)(sqlite3_stmt*pStmt); + const char * (*column_database_name)(sqlite3_stmt*,int); + const void * (*column_database_name16)(sqlite3_stmt*,int); + const char * (*column_decltype)(sqlite3_stmt*,int i); + const void * (*column_decltype16)(sqlite3_stmt*,int); + double (*column_double)(sqlite3_stmt*,int iCol); + int (*column_int)(sqlite3_stmt*,int iCol); + sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); + const char * (*column_name)(sqlite3_stmt*,int); + const void * (*column_name16)(sqlite3_stmt*,int); + const char * (*column_origin_name)(sqlite3_stmt*,int); + const void * (*column_origin_name16)(sqlite3_stmt*,int); + const char * (*column_table_name)(sqlite3_stmt*,int); + const void * (*column_table_name16)(sqlite3_stmt*,int); + const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); + const void * (*column_text16)(sqlite3_stmt*,int iCol); + int (*column_type)(sqlite3_stmt*,int iCol); + sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); + void * (*commit_hook)(sqlite3*,int(*)(void*),void*); + int (*complete)(const char*sql); + int (*complete16)(const void*sql); + int (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*)); + int (*create_collation16)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*)); + int (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*)); + int (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*)); + int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); + int (*data_count)(sqlite3_stmt*pStmt); + sqlite3 * (*db_handle)(sqlite3_stmt*); + int (*declare_vtab)(sqlite3*,const char*); + int (*enable_shared_cache)(int); + int (*errcode)(sqlite3*db); + const char * (*errmsg)(sqlite3*); + const void * (*errmsg16)(sqlite3*); + int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); + int (*expired)(sqlite3_stmt*); + int (*finalize)(sqlite3_stmt*pStmt); + void (*free)(void*); + void (*free_table)(char**result); + int (*get_autocommit)(sqlite3*); + void * (*get_auxdata)(sqlite3_context*,int); + int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); + int (*global_recover)(void); + void (*interrupt)(sqlite3*); + sqlite_int64 (*last_insert_rowid)(sqlite3*); + const char * (*libversion)(void); + int (*libversion_number)(void); + void *(*malloc)(int); + char * (*mprintf)(const char*,...); + int (*open)(const char*,sqlite3**); + int (*open16)(const void*,sqlite3**); + int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); + int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); + void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); + void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); + void *(*realloc)(void*,int); + int (*reset)(sqlite3_stmt*pStmt); + void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_double)(sqlite3_context*,double); + void (*result_error)(sqlite3_context*,const char*,int); + void (*result_error16)(sqlite3_context*,const void*,int); + void (*result_int)(sqlite3_context*,int); + void (*result_int64)(sqlite3_context*,sqlite_int64); + void (*result_null)(sqlite3_context*); + void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); + void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_value)(sqlite3_context*,sqlite3_value*); + void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); + int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*); + void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); + char * (*snprintf)(int,char*,const char*,...); + int (*step)(sqlite3_stmt*); + int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*); + void (*thread_cleanup)(void); + int (*total_changes)(sqlite3*); + void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); + int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); + void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*); + void * (*user_data)(sqlite3_context*); + const void * (*value_blob)(sqlite3_value*); + int (*value_bytes)(sqlite3_value*); + int (*value_bytes16)(sqlite3_value*); + double (*value_double)(sqlite3_value*); + int (*value_int)(sqlite3_value*); + sqlite_int64 (*value_int64)(sqlite3_value*); + int (*value_numeric_type)(sqlite3_value*); + const unsigned char * (*value_text)(sqlite3_value*); + const void * (*value_text16)(sqlite3_value*); + const void * (*value_text16be)(sqlite3_value*); + const void * (*value_text16le)(sqlite3_value*); + int (*value_type)(sqlite3_value*); + char * (*vmprintf)(const char*,va_list); +}; + +/* +** The following macros redefine the API routines so that they are +** redirected throught the global sqlite3_api structure. +** +** This header file is also used by the loadext.c source file +** (part of the main SQLite library - not an extension) so that +** it can get access to the sqlite3_api_routines structure +** definition. But the main library does not want to redefine +** the API. So the redefinition macros are only valid if the +** SQLITE_CORE macros is undefined. +*/ +#ifndef SQLITE_CORE +#define sqlite3_aggregate_context sqlite3_api->aggregate_context +#define sqlite3_aggregate_count sqlite3_api->aggregate_count +#define sqlite3_bind_blob sqlite3_api->bind_blob +#define sqlite3_bind_double sqlite3_api->bind_double +#define sqlite3_bind_int sqlite3_api->bind_int +#define sqlite3_bind_int64 sqlite3_api->bind_int64 +#define sqlite3_bind_null sqlite3_api->bind_null +#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count +#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index +#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name +#define sqlite3_bind_text sqlite3_api->bind_text +#define sqlite3_bind_text16 sqlite3_api->bind_text16 +#define sqlite3_bind_value sqlite3_api->bind_value +#define sqlite3_busy_handler sqlite3_api->busy_handler +#define sqlite3_busy_timeout sqlite3_api->busy_timeout +#define sqlite3_changes sqlite3_api->changes +#define sqlite3_close sqlite3_api->close +#define sqlite3_collation_needed sqlite3_api->collation_needed +#define sqlite3_collation_needed16 sqlite3_api->collation_needed16 +#define sqlite3_column_blob sqlite3_api->column_blob +#define sqlite3_column_bytes sqlite3_api->column_bytes +#define sqlite3_column_bytes16 sqlite3_api->column_bytes16 +#define sqlite3_column_count sqlite3_api->column_count +#define sqlite3_column_database_name sqlite3_api->column_database_name +#define sqlite3_column_database_name16 sqlite3_api->column_database_name16 +#define sqlite3_column_decltype sqlite3_api->column_decltype +#define sqlite3_column_decltype16 sqlite3_api->column_decltype16 +#define sqlite3_column_double sqlite3_api->column_double +#define sqlite3_column_int sqlite3_api->column_int +#define sqlite3_column_int64 sqlite3_api->column_int64 +#define sqlite3_column_name sqlite3_api->column_name +#define sqlite3_column_name16 sqlite3_api->column_name16 +#define sqlite3_column_origin_name sqlite3_api->column_origin_name +#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16 +#define sqlite3_column_table_name sqlite3_api->column_table_name +#define sqlite3_column_table_name16 sqlite3_api->column_table_name16 +#define sqlite3_column_text sqlite3_api->column_text +#define sqlite3_column_text16 sqlite3_api->column_text16 +#define sqlite3_column_type sqlite3_api->column_type +#define sqlite3_column_value sqlite3_api->column_value +#define sqlite3_commit_hook sqlite3_api->commit_hook +#define sqlite3_complete sqlite3_api->complete +#define sqlite3_complete16 sqlite3_api->complete16 +#define sqlite3_create_collation sqlite3_api->create_collation +#define sqlite3_create_collation16 sqlite3_api->create_collation16 +#define sqlite3_create_function sqlite3_api->create_function +#define sqlite3_create_function16 sqlite3_api->create_function16 +#define sqlite3_create_module sqlite3_api->create_module +#define sqlite3_data_count sqlite3_api->data_count +#define sqlite3_db_handle sqlite3_api->db_handle +#define sqlite3_declare_vtab sqlite3_api->declare_vtab +#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache +#define sqlite3_errcode sqlite3_api->errcode +#define sqlite3_errmsg sqlite3_api->errmsg +#define sqlite3_errmsg16 sqlite3_api->errmsg16 +#define sqlite3_exec sqlite3_api->exec +#define sqlite3_expired sqlite3_api->expired +#define sqlite3_finalize sqlite3_api->finalize +#define sqlite3_free sqlite3_api->free +#define sqlite3_free_table sqlite3_api->free_table +#define sqlite3_get_autocommit sqlite3_api->get_autocommit +#define sqlite3_get_auxdata sqlite3_api->get_auxdata +#define sqlite3_get_table sqlite3_api->get_table +#define sqlite3_global_recover sqlite3_api->global_recover +#define sqlite3_interrupt sqlite3_api->interrupt +#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid +#define sqlite3_libversion sqlite3_api->libversion +#define sqlite3_libversion_number sqlite3_api->libversion_number +#define sqlite3_malloc sqlite3_api->malloc +#define sqlite3_mprintf sqlite3_api->mprintf +#define sqlite3_open sqlite3_api->open +#define sqlite3_open16 sqlite3_api->open16 +#define sqlite3_prepare sqlite3_api->prepare +#define sqlite3_prepare16 sqlite3_api->prepare16 +#define sqlite3_profile sqlite3_api->profile +#define sqlite3_progress_handler sqlite3_api->progress_handler +#define sqlite3_realloc sqlite3_api->realloc +#define sqlite3_reset sqlite3_api->reset +#define sqlite3_result_blob sqlite3_api->result_blob +#define sqlite3_result_double sqlite3_api->result_double +#define sqlite3_result_error sqlite3_api->result_error +#define sqlite3_result_error16 sqlite3_api->result_error16 +#define sqlite3_result_int sqlite3_api->result_int +#define sqlite3_result_int64 sqlite3_api->result_int64 +#define sqlite3_result_null sqlite3_api->result_null +#define sqlite3_result_text sqlite3_api->result_text +#define sqlite3_result_text16 sqlite3_api->result_text16 +#define sqlite3_result_text16be sqlite3_api->result_text16be +#define sqlite3_result_text16le sqlite3_api->result_text16le +#define sqlite3_result_value sqlite3_api->result_value +#define sqlite3_rollback_hook sqlite3_api->rollback_hook +#define sqlite3_set_authorizer sqlite3_api->set_authorizer +#define sqlite3_set_auxdata sqlite3_api->set_auxdata +#define sqlite3_snprintf sqlite3_api->snprintf +#define sqlite3_step sqlite3_api->step +#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata +#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup +#define sqlite3_total_changes sqlite3_api->total_changes +#define sqlite3_trace sqlite3_api->trace +#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings +#define sqlite3_update_hook sqlite3_api->update_hook +#define sqlite3_user_data sqlite3_api->user_data +#define sqlite3_value_blob sqlite3_api->value_blob +#define sqlite3_value_bytes sqlite3_api->value_bytes +#define sqlite3_value_bytes16 sqlite3_api->value_bytes16 +#define sqlite3_value_double sqlite3_api->value_double +#define sqlite3_value_int sqlite3_api->value_int +#define sqlite3_value_int64 sqlite3_api->value_int64 +#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type +#define sqlite3_value_text sqlite3_api->value_text +#define sqlite3_value_text16 sqlite3_api->value_text16 +#define sqlite3_value_text16be sqlite3_api->value_text16be +#define sqlite3_value_text16le sqlite3_api->value_text16le +#define sqlite3_value_type sqlite3_api->value_type +#define sqlite3_vmprintf sqlite3_api->vmprintf +#endif /* SQLITE_CORE */ + +#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api; +#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; + +#endif /* _SQLITE3EXT_H_ */ diff --git a/ext/pdo_sqlite/sqlite/src/sqliteInt.h b/ext/pdo_sqlite/sqlite/src/sqliteInt.h index 1635369c4a..58e21c4f3c 100644 --- a/ext/pdo_sqlite/sqlite/src/sqliteInt.h +++ b/ext/pdo_sqlite/sqlite/src/sqliteInt.h @@ -16,6 +16,13 @@ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ +/* +** Extra interface definitions for those who need them +*/ +#ifdef SQLITE_EXTRA +# include "sqliteExtra.h" +#endif + /* ** Many people are failing to set -DNDEBUG=1 when compiling SQLite. ** Setting NDEBUG makes the code smaller and run faster. So the following @@ -59,6 +66,23 @@ #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 LONGDOUBLE_TYPE sqlite_int64 +# ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (0x7fffffffffffffff) +# endif +# define SQLITE_OMIT_DATETIME_FUNCS 1 +# define SQLITE_OMIT_TRACE 1 +#endif +#ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (1e99) +#endif + /* ** The maximum number of in-memory pages to use for the main database ** table and for temporary tables. Internally, the MAX_PAGES and @@ -88,18 +112,6 @@ #define OMIT_TEMPDB 0 #endif -/* -** If the following macro is set to 1, then NULL values are considered -** distinct for the SELECT DISTINCT statement and for UNION or EXCEPT -** compound queries. No other SQL database engine (among those tested) -** works this way except for OCELOT. But the SQL92 spec implies that -** this is how things should work. -** -** If the following macro is set to 0, then NULLs are indistinct for -** SELECT DISTINCT and for UNION. -*/ -#define NULL_ALWAYS_DISTINCT 0 - /* ** If the following macro is set to 1, then NULL values are considered ** distinct when determining whether or not two entries are the same @@ -129,18 +141,15 @@ #define SQLITE_MAX_VARIABLE_NUMBER 999 /* -** When building SQLite for embedded systems where memory is scarce, -** you can define one or more of the following macros to omit extra -** features of the library and thus keep the size of the library to -** a minimum. +** 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_OMIT_AUTHORIZATION 1 */ -/* #define SQLITE_OMIT_MEMORYDB 1 */ -/* #define SQLITE_OMIT_VACUUM 1 */ -/* #define SQLITE_OMIT_DATETIME_FUNCS 1 */ -/* #define SQLITE_OMIT_PROGRESS_CALLBACK 1 */ -/* #define SQLITE_OMIT_AUTOVACUUM */ -/* #define SQLITE_OMIT_ALTERTABLE */ +#define SQLITE_MAX_FILE_FORMAT 4 +#ifndef SQLITE_DEFAULT_FILE_FORMAT +# define SQLITE_DEFAULT_FILE_FORMAT 1 +#endif /* ** Provide a default value for TEMP_STORE in case it is not specified @@ -158,6 +167,16 @@ #define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) #endif +/* +** 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 @@ -165,13 +184,6 @@ ** ** cc '-DUINTPTR_TYPE=long long int' ... */ -#ifndef UINT64_TYPE -# if defined(_MSC_VER) || defined(__BORLANDC__) -# define UINT64_TYPE unsigned __int64 -# else -# define UINT64_TYPE unsigned long long int -# endif -#endif #ifndef UINT32_TYPE # define UINT32_TYPE unsigned int #endif @@ -191,7 +203,7 @@ # define LONGDOUBLE_TYPE long double #endif typedef sqlite_int64 i64; /* 8-byte signed integer */ -typedef UINT64_TYPE u64; /* 8-byte unsigned 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 */ @@ -228,59 +240,67 @@ struct BusyHandler { */ #include "vdbe.h" #include "btree.h" +#include "pager.h" +#ifdef SQLITE_MEMDEBUG /* -** This macro casts a pointer to an integer. Useful for doing -** pointer arithmetic. +** The following global variables are used for testing and debugging +** only. They only work if SQLITE_MEMDEBUG is defined. */ -#define Addr(X) ((uptr)X) +extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ +extern int sqlite3_nFree; /* Number of sqliteFree() calls */ +extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ +extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */ + +extern void *sqlite3_pFirst; /* Pointer to linked list of allocations */ +extern int sqlite3_nMaxAlloc; /* High water mark of ThreadData.nAlloc */ +extern int sqlite3_mallocDisallowed; /* assert() in sqlite3Malloc() if set */ +extern int sqlite3_isFail; /* True if all malloc calls should fail */ +extern const char *sqlite3_zFile; /* Filename to associate debug info with */ +extern int sqlite3_iLine; /* Line number for debug info */ + +#define ENTER_MALLOC (sqlite3_zFile = __FILE__, sqlite3_iLine = __LINE__) +#define sqliteMalloc(x) (ENTER_MALLOC, sqlite3Malloc(x,1)) +#define sqliteMallocRaw(x) (ENTER_MALLOC, sqlite3MallocRaw(x,1)) +#define sqliteRealloc(x,y) (ENTER_MALLOC, sqlite3Realloc(x,y)) +#define sqliteStrDup(x) (ENTER_MALLOC, sqlite3StrDup(x)) +#define sqliteStrNDup(x,y) (ENTER_MALLOC, sqlite3StrNDup(x,y)) +#define sqliteReallocOrFree(x,y) (ENTER_MALLOC, sqlite3ReallocOrFree(x,y)) -/* -** If memory allocation problems are found, recompile with -** -** -DSQLITE_DEBUG=1 -** -** to enable some sanity checking on malloc() and free(). To -** check for memory leaks, recompile with -** -** -DSQLITE_DEBUG=2 -** -** and a line of text will be written to standard error for -** each malloc() and free(). This output can be analyzed -** by an AWK script to determine if there are any leaks. -*/ -#ifdef SQLITE_MEMDEBUG -# define sqliteMalloc(X) sqlite3Malloc_(X,1,__FILE__,__LINE__) -# define sqliteMallocRaw(X) sqlite3Malloc_(X,0,__FILE__,__LINE__) -# define sqliteFree(X) sqlite3Free_(X,__FILE__,__LINE__) -# define sqliteRealloc(X,Y) sqlite3Realloc_(X,Y,__FILE__,__LINE__) -# define sqliteStrDup(X) sqlite3StrDup_(X,__FILE__,__LINE__) -# define sqliteStrNDup(X,Y) sqlite3StrNDup_(X,Y,__FILE__,__LINE__) #else -# define sqliteFree sqlite3FreeX -# define sqliteMalloc sqlite3Malloc -# define sqliteMallocRaw sqlite3MallocRaw -# define sqliteRealloc sqlite3Realloc -# define sqliteStrDup sqlite3StrDup -# define sqliteStrNDup sqlite3StrNDup + +#define ENTER_MALLOC 0 +#define sqliteMalloc(x) sqlite3Malloc(x,1) +#define sqliteMallocRaw(x) sqlite3MallocRaw(x,1) +#define sqliteRealloc(x,y) sqlite3Realloc(x,y) +#define sqliteStrDup(x) sqlite3StrDup(x) +#define sqliteStrNDup(x,y) sqlite3StrNDup(x,y) +#define sqliteReallocOrFree(x,y) sqlite3ReallocOrFree(x,y) + #endif -/* -** This variable gets set if malloc() ever fails. After it gets set, -** the SQLite library shuts down permanently. -*/ -extern int sqlite3_malloc_failed; +#define sqliteFree(x) sqlite3FreeX(x) +#define sqliteAllocSize(x) sqlite3AllocSize(x) + /* -** The following global variables are used for testing and debugging -** only. They only work if SQLITE_DEBUG is defined. +** An instance of this structure might be allocated to store information +** specific to a single thread. */ -#ifdef SQLITE_MEMDEBUG -extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ -extern int sqlite3_nFree; /* Number of sqliteFree() calls */ -extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ -extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */ +struct ThreadData { + int dummy; /* So that this structure is never empty */ + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + int nSoftHeapLimit; /* Suggested max mem allocation. No limit if <0 */ + int nAlloc; /* Number of bytes currently allocated */ + Pager *pPager; /* Linked list of all pagers in this thread */ +#endif + +#ifndef SQLITE_OMIT_SHARED_CACHE + u8 useSharedData; /* True if shared pagers and schemas are enabled */ + BtShared *pBtree; /* Linked list of all currently open BTrees */ #endif +}; /* ** Name of the master database table. The master database table @@ -314,6 +334,7 @@ typedef struct AuthContext AuthContext; 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 FKey FKey; @@ -322,11 +343,14 @@ typedef struct IdList IdList; typedef struct Index Index; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; +typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; typedef struct Select Select; typedef struct SrcList SrcList; +typedef struct ThreadData ThreadData; typedef struct Table Table; +typedef struct TableLock TableLock; typedef struct Token Token; typedef struct TriggerStack TriggerStack; typedef struct TriggerStep TriggerStep; @@ -344,28 +368,37 @@ typedef struct WhereLevel WhereLevel; struct Db { char *zName; /* Name of this database */ Btree *pBt; /* The B*Tree structure for this database file */ + u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ + u8 safety_level; /* How aggressive at synching data to disk */ + void *pAux; /* Auxiliary data. Usually NULL */ + void (*xFreeAux)(void*); /* Routine to free pAux */ + Schema *pSchema; /* Pointer to database schema (possibly shared) */ +}; + +/* +** An instance of the following structure stores a database schema. +*/ +struct Schema { int schema_cookie; /* Database schema version number for this file */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ Hash trigHash; /* All triggers indexed by name */ Hash aFKey; /* Foreign keys indexed by to-table */ - u16 flags; /* Flags associated with this database */ - u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ - u8 safety_level; /* How aggressive at synching data to disk */ - int cache_size; /* Number of pages to use in the cache */ Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ - void *pAux; /* Auxiliary data. Usually NULL */ - void (*xFreeAux)(void*); /* Routine to free pAux */ + u8 file_format; /* Schema format version for this file */ + u8 enc; /* Text encoding used by this database */ + u16 flags; /* 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.flags field. */ -#define DbHasProperty(D,I,P) (((D)->aDb[I].flags&(P))==(P)) -#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].flags&(P))!=0) -#define DbSetProperty(D,I,P) (D)->aDb[I].flags|=(P) -#define DbClearProperty(D,I,P) (D)->aDb[I].flags&=~(P) +#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) +#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) +#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) +#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) /* ** Allowed values for the DB.flags field. @@ -379,6 +412,7 @@ struct Db { */ #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) */ #define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) @@ -413,9 +447,7 @@ struct sqlite3 { Db *aDb; /* All backends */ int flags; /* Miscellanous flags. See below */ int errCode; /* Most recent error code (SQLITE_*) */ - u8 enc; /* Text encoding for this database. */ u8 autoCommit; /* The auto-commit flag. */ - u8 file_format; /* What file format version is this database? */ u8 temp_store; /* 1: file 2: memory 0: default */ int nTable; /* Number of tables in the database */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ @@ -429,21 +461,30 @@ struct sqlite3 { int newTnum; /* Rootpage of table being initialized */ u8 busy; /* TRUE if currently initializing */ } init; + int nExtension; /* Number of loaded extensions */ + void *aExtension; /* Array of shared libraray handles */ struct Vdbe *pVdbe; /* List of active virtual machines */ int activeVdbeCnt; /* Number of vdbes currently executing */ 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 *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); void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); void *pCollNeededArg; - sqlite3_value *pValue; /* Value used for transient conversions */ sqlite3_value *pErr; /* Most recent error message */ char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ + union { + int isInterrupted; /* True if sqlite3_interrupt has been called */ + double notUsed1; /* Spacer */ + } u1; #ifndef SQLITE_OMIT_AUTHORIZATION int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); /* Access authorization function */ @@ -454,19 +495,27 @@ struct sqlite3 { void *pProgressArg; /* Argument to the progress callback */ int nProgressOps; /* Number of opcodes for progress callback */ #endif -#ifndef SQLITE_OMIT_GLOBALRECOVER - sqlite3 *pNext; /* Linked list of open db handles. */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + Hash aModule; /* populated by sqlite3_create_module() */ + Table *pVTab; /* vtab with active Connect/Create method */ + sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */ + int nVTrans; /* Allocated size of aVTrans */ #endif Hash aFunc; /* All functions that can be in SQL exprs */ Hash aCollSeq; /* All collating sequences */ BusyHandler busyHandler; /* Busy callback */ - int busyTimeout; /* Busy handler timeout, in msec */ + int busyTimeout; /* Busy handler timeout, in msec */ Db aDbStatic[2]; /* Static space for the 2 default backends */ #ifdef SQLITE_SSE sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */ #endif }; +/* +** A macro to discover the encoding of a database. +*/ +#define ENC(db) ((db)->aDb[0].pSchema->enc) + /* ** Possible values for the sqlite.flags and or Db.flags fields. ** @@ -475,8 +524,6 @@ struct sqlite3 { ** transaction is active on that particular database file. */ #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ -#define SQLITE_Initialized 0x00000002 /* True after initialization */ -#define SQLITE_Interrupt 0x00000004 /* Cancel current operation */ #define SQLITE_InTrans 0x00000008 /* True if in a transaction */ #define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ #define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ @@ -491,6 +538,11 @@ struct sqlite3 { #define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ #define SQLITE_NoReadlock 0x00001000 /* Readlocks are omitted when ** accessing read-only databases */ +#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommitted 0x00004000 /* For shared-cache mode */ +#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ +#define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */ +#define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */ /* ** Possible values for the sqlite.magic field. @@ -521,11 +573,23 @@ struct FuncDef { char zName[1]; /* SQL name of the function. MUST BE LAST */ }; +/* +** 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() */ +}; + /* ** Possible values for FuncDef.flags */ #define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ #define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */ /* ** information about each column of an SQL table is held in an instance @@ -535,7 +599,7 @@ struct Column { char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ char *zType; /* Data type for this column */ - CollSeq *pColl; /* Collating sequence. If NULL, use the default */ + char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* True if there is a NOT NULL constraint */ u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ char affinity; /* One of the SQLITE_AFF_... values */ @@ -551,7 +615,7 @@ struct Column { ** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine ** native byte order. When a collation sequence is invoked, SQLite selects ** the version that will require the least expensive encoding -** transalations, if any. +** translations, if any. ** ** The CollSeq.pUser member variable is an extra parameter that passed in ** as the first argument to the UTF-8 comparison function, xCmp. @@ -586,12 +650,25 @@ struct CollSeq { /* ** 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 number 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 P3 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. */ -#define SQLITE_AFF_INTEGER 'i' -#define SQLITE_AFF_NUMERIC 'n' -#define SQLITE_AFF_TEXT 't' -#define SQLITE_AFF_NONE 'o' +#define SQLITE_AFF_TEXT 'a' +#define SQLITE_AFF_NONE 'b' +#define SQLITE_AFF_NUMERIC 'c' +#define SQLITE_AFF_INTEGER 'd' +#define SQLITE_AFF_REAL 'e' +#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) /* ** Each SQL table is represented in memory by an instance of the @@ -615,7 +692,7 @@ struct CollSeq { ** Table.tnum is the page number for the root BTree page of the table in the ** database file. If Table.iDb is the index of the database table backend ** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that -** holds temporary tables and indices. If Table.isTransient +** holds temporary tables and indices. If Table.isEphem ** is true, then the table is stored in a file that is automatically deleted ** when the VDBE cursor to the table is closed. In this case Table.tnum ** refers VDBE cursor number that holds the table open, not to the root @@ -631,21 +708,43 @@ struct Table { Index *pIndex; /* List of SQL indexes on this table. */ int tnum; /* Root BTree node for this table (see note above) */ Select *pSelect; /* NULL for tables. Points to definition if a view. */ - u8 readOnly; /* True if this table should not be written by the user */ - u8 iDb; /* Index into sqlite.aDb[] of the backend for this table */ - u8 isTransient; /* True if automatically deleted when VDBE finishes */ - u8 hasPrimKey; /* True if there exists a primary key */ - u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ - u8 autoInc; /* True if the integer primary key is autoincrement */ int nRef; /* Number of pointers to this Table */ Trigger *pTrigger; /* List of SQL triggers on this table */ FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ +#ifndef SQLITE_OMIT_CHECK + Expr *pCheck; /* The AND of all CHECK constraints */ +#endif #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE statement to add a new column */ #endif + u8 readOnly; /* True if this table should not be written by the user */ + u8 isEphem; /* True if created using OP_OpenEphermeral */ + u8 hasPrimKey; /* True if there exists a primary key */ + u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ + u8 autoInc; /* True if the integer primary key is autoincrement */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 isVirtual; /* True if this is a virtual table */ + u8 isCommit; /* True once the CREATE TABLE has been committed */ + Module *pMod; /* Pointer to the implementation of the module */ + sqlite3_vtab *pVtab; /* Pointer to the module instance */ + int nModuleArg; /* Number of arguments to the module */ + char **azModuleArg; /* Text of all module args. [0] is module name */ +#endif + Schema *pSchema; }; +/* +** 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)->isVirtual) +#else +# define IsVirtual(X) 0 +#endif + /* ** Each foreign key constraint is an instance of the following structure. ** @@ -779,10 +878,11 @@ struct Index { int tnum; /* Page containing root of this index in database file */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ - u8 iDb; /* Index in sqlite.aDb[] of where this index is stored */ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ - KeyInfo keyInfo; /* Info on how to order keys. MUST BE LAST */ + Schema *pSchema; /* Schema containing this index */ + u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ + char **azColl; /* Array of collation sequence names for index */ }; /* @@ -836,7 +936,7 @@ struct AggInfo { Expr *pExpr; /* Expression encoding the function */ FuncDef *pFunc; /* The aggregate function implementation */ int iMem; /* Memory location that acts as accumulator */ - int iDistinct; /* Virtual table used to enforce DISTINCT */ + int iDistinct; /* Ephermeral table used to enforce DISTINCT */ } *aFunc; int nFunc; /* Number of entries in aFunc[] */ int nFuncAlloc; /* Number of slots allocated for aFunc[] */ @@ -891,8 +991,7 @@ struct AggInfo { struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ - u8 iDb; /* Database referenced by this expression */ - u8 flags; /* Various flags. See below */ + u16 flags; /* Various flags. See below */ CollSeq *pColl; /* The collation type of the column or 0 */ Expr *pLeft, *pRight; /* Left and right subnodes */ ExprList *pList; /* A list of expressions used as function arguments @@ -907,6 +1006,7 @@ struct Expr { Select *pSelect; /* When the expression is a sub-select. Also the ** right side of " IN (