]> granicus.if.org Git - php/commitdiff
upgrade bundled sqlite to sqlite 3.1.3
authorWez Furlong <wez@php.net>
Sun, 27 Feb 2005 05:20:19 +0000 (05:20 +0000)
committerWez Furlong <wez@php.net>
Sun, 27 Feb 2005 05:20:19 +0000 (05:20 +0000)
62 files changed:
ext/pdo_sqlite/config.m4
ext/pdo_sqlite/package.xml
ext/pdo_sqlite/sqlite/Makefile.in
ext/pdo_sqlite/sqlite/VERSION
ext/pdo_sqlite/sqlite/configure
ext/pdo_sqlite/sqlite/configure.ac
ext/pdo_sqlite/sqlite/main.mk
ext/pdo_sqlite/sqlite/mkopcodec.awk
ext/pdo_sqlite/sqlite/mkopcodeh.awk
ext/pdo_sqlite/sqlite/mkso.sh
ext/pdo_sqlite/sqlite/publish.sh
ext/pdo_sqlite/sqlite/src/alter.c [new file with mode: 0644]
ext/pdo_sqlite/sqlite/src/attach.c
ext/pdo_sqlite/sqlite/src/auth.c
ext/pdo_sqlite/sqlite/src/btree.c
ext/pdo_sqlite/sqlite/src/btree.h
ext/pdo_sqlite/sqlite/src/build.c
ext/pdo_sqlite/sqlite/src/date.c
ext/pdo_sqlite/sqlite/src/delete.c
ext/pdo_sqlite/sqlite/src/experimental.c [new file with mode: 0644]
ext/pdo_sqlite/sqlite/src/expr.c
ext/pdo_sqlite/sqlite/src/func.c
ext/pdo_sqlite/sqlite/src/hash.c
ext/pdo_sqlite/sqlite/src/insert.c
ext/pdo_sqlite/sqlite/src/main.c
ext/pdo_sqlite/sqlite/src/opcodes.c
ext/pdo_sqlite/sqlite/src/opcodes.h
ext/pdo_sqlite/sqlite/src/os.h
ext/pdo_sqlite/sqlite/src/os_test.c
ext/pdo_sqlite/sqlite/src/os_unix.c
ext/pdo_sqlite/sqlite/src/os_win.c
ext/pdo_sqlite/sqlite/src/pager.c
ext/pdo_sqlite/sqlite/src/pager.h
ext/pdo_sqlite/sqlite/src/parse.c
ext/pdo_sqlite/sqlite/src/parse.h
ext/pdo_sqlite/sqlite/src/parse.y
ext/pdo_sqlite/sqlite/src/pragma.c
ext/pdo_sqlite/sqlite/src/printf.c
ext/pdo_sqlite/sqlite/src/select.c
ext/pdo_sqlite/sqlite/src/shell.c
ext/pdo_sqlite/sqlite/src/sqlite.h.in
ext/pdo_sqlite/sqlite/src/sqliteInt.h
ext/pdo_sqlite/sqlite/src/tclsqlite.c
ext/pdo_sqlite/sqlite/src/test1.c
ext/pdo_sqlite/sqlite/src/test2.c
ext/pdo_sqlite/sqlite/src/test3.c
ext/pdo_sqlite/sqlite/src/test5.c
ext/pdo_sqlite/sqlite/src/tokenize.c
ext/pdo_sqlite/sqlite/src/trigger.c
ext/pdo_sqlite/sqlite/src/update.c
ext/pdo_sqlite/sqlite/src/utf.c
ext/pdo_sqlite/sqlite/src/util.c
ext/pdo_sqlite/sqlite/src/vacuum.c
ext/pdo_sqlite/sqlite/src/vdbe.c
ext/pdo_sqlite/sqlite/src/vdbe.h
ext/pdo_sqlite/sqlite/src/vdbeInt.h
ext/pdo_sqlite/sqlite/src/vdbeapi.c
ext/pdo_sqlite/sqlite/src/vdbeaux.c
ext/pdo_sqlite/sqlite/src/vdbemem.c
ext/pdo_sqlite/sqlite/src/where.c
ext/pdo_sqlite/sqlite/tool/mkkeywordhash.c
ext/pdo_sqlite/sqlite_statement.c

index 90e986c0a63627faef085abd31ed8ba97507a8f1..ea319006a47ec3018a6e456333b60e8c02d636ab 100644 (file)
@@ -72,23 +72,27 @@ if test "$PHP_PDO_SQLITE" != "no"; then
       sqlite/src/table.c sqlite/src/tokenize.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/vdbemem.c sqlite/src/where.c sqlite/src/parse.c sqlite/src/opcodes.c \
+      sqlite/src/alter.c sqlite/src/experimental.c"
 
       PHP_NEW_EXTENSION(pdo_sqlite,
         $php_pdo_sqlite_sources_core $pdo_sqlite_sources,
-        $ext_shared,,-I@ext_srcdir@/sqlite/src -DPDO_SQLITE_BUNDLED=1 -I$pdo_inc_path)
+        $ext_shared,,-I@ext_srcdir@/sqlite/src -DPDO_SQLITE_BUNDLED=1 -DSQLITE_OMIT_CURSOR -I$pdo_inc_path)
 
       PHP_ADD_BUILD_DIR($ext_builddir/sqlite)
       PHP_ADD_BUILD_DIR($ext_builddir/sqlite/src)
       AC_CHECK_SIZEOF(char *,4)
       AC_DEFINE(SQLITE_PTR_SZ, SIZEOF_CHAR_P, [Size of a pointer])
       PDO_SQLITE_VERSION=`cat $ext_srcdir/sqlite/VERSION`
-      sed -e s/--VERS--/$PDO_SQLITE_VERSION/ $ext_srcdir/sqlite/src/sqlite.h.in > $ext_srcdir/sqlite3.h
+      PDO_SQLITE_VERSION_NUMBER=`echo $PDO_SQLITE_VERSION | awk -F. '{printf("%d%03d%03d", $1, $2, $3)}'`
+      sed -e s/--VERS--/$PDO_SQLITE_VERSION/ -e s/--VERSION-NUMBER--/$PDO_SQLITE_VERSION_NUMBER/ $ext_srcdir/sqlite/src/sqlite.h.in > $ext_srcdir/sqlite3.h
       if ! test -f $ext_srcdir/sqlite/src/parse.h ; then
         $CC -o $ext_srcdir/sqlite/tool/lemon $ext_srcdir/sqlite/tool/lemon.c
         $ext_srcdir/sqlite/tool/lemon $ext_srcdir/sqlite/src/parse.y
              cat $ext_srcdir/sqlite/src/parse.h $ext_srcdir/sqlite/src/vdbe.c | awk -f $ext_srcdir/sqlite/mkopcodeh.awk > $ext_srcdir/sqlite/src/opcodes.h
         sort -n +2 $ext_srcdir/sqlite/src/opcodes.h | awk -f $ext_srcdir/sqlite/mkopcodec.awk > $ext_srcdir/sqlite/src/opcodes.c
+        $CC -o $ext_srcdir/sqlite/tool/mkkeywordhash $ext_srcdir/sqlite/tool/mkkeywordhash.c
+        $ext_srcdir/sqlite/tool/mkkeywordhash > $ext_srcdir/keywordhash.h
       fi
 
       if test "$ext_shared" = "no" -o "$ext_srcdir" != "$abs_srcdir"; then
index 97bf1c8415f1cd5119b6ecbd1f49a6f9cee69775..9f86503d934268bf38cb477ab27f234bca02dcd1 100755 (executable)
 <file role="src" name="sqlite3.pc.in"/>\r
 <file role="src" name="sqlite.pc.in"/>\r
 <file role="src" name="VERSION"/>\r
+<file role="src" name="keywordhash.h"/>\r
 <dir name="src">\r
 <file role="src" name="attach.c"/>\r
+<file role="src" name="alter.c"/>\r
 <file role="src" name="auth.c"/>\r
 <file role="src" name="btree.c"/>\r
 <file role="src" name="btree.h"/>\r
@@ -81,6 +83,7 @@
 <file role="src" name="date.c"/>\r
 <file role="src" name="delete.c"/>\r
 <file role="src" name="expr.c"/>\r
+<file role="src" name="experimental.c"/>\r
 <file role="src" name="func.c"/>\r
 <file role="src" name="hash.c"/>\r
 <file role="src" name="hash.h"/>\r
index 3136476bcfa340247f24c282ec1c87807125ad99..198a7877c1319a39558e7b41b2179f0bf822b882 100644 (file)
@@ -26,29 +26,21 @@ BCC = @BUILD_CC@ @BUILD_CFLAGS@
 # will run on the target platform.  (BCC and TCC are usually the
 # same unless your are cross-compiling.)
 #
-TCC = @TARGET_CC@ @TARGET_CFLAGS@ -I. -I${TOP}/src -DNDEBUG
+TCC = @TARGET_CC@ @TARGET_CFLAGS@ -I. -I${TOP}/src
 
-# Some standard variables and programs
+# Define -DNDEBUG to compile without debugging (i.e., for production usage)
+# Omitting the define will cause extra debugging code to be inserted and
+# includes extra comments when "EXPLAIN stmt" is used.
 #
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-libdir = @libdir@
-INSTALL = @INSTALL@
-LIBTOOL = ./libtool
-RELEASE = @ALLOWRELEASE@
-
-# libtool compile/link/install
-LTCOMPILE = $(LIBTOOL) --mode=compile $(TCC)
-LTLINK = $(LIBTOOL) --mode=link $(TCC)
-LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL)
+TCC += @TARGET_DEBUG@
 
 # Compiler options needed for programs that use the TCL library.
 #
-TCL_FLAGS = @TARGET_TCL_INC@
+TCC += @TCL_INCLUDE_SPEC@
 
 # The library that programs using TCL must link against.
 #
-LIBTCL = @TARGET_TCL_LIBS@
+LIBTCL = @TCL_LIB_SPEC@ @TCL_LIBS@
 
 # Compiler options needed for programs that use the readline() library.
 #
@@ -74,22 +66,64 @@ LIBPTHREAD=@TARGET_THREAD_LIB@
 #
 TEMP_STORE = -DTEMP_STORE=@TEMP_STORE@
 
+# Version numbers and release number for the SQLite being compiled.
+#
+VERSION = @VERSION@
+VERSION_NUMBER = @VERSION_NUMBER@
+RELEASE = @RELEASE@
+
+# Filename extensions
+#
+BEXE = @BUILD_EXEEXT@
+TEXE = @TARGET_EXEEXT@
+
+# The following variable is "1" if the configure script was able to locate
+# the tclConfig.sh file.  It is an empty string otherwise.  When this
+# variable is "1", the TCL extension library (libtclsqlite3.so) is built
+# and installed.
+#
+HAVE_TCL = @HAVE_TCL@
+
+# The suffix used on shared libraries.  Ex:  ".dll", ".so", ".dylib"
+#
+SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@
+
+# The directory into which to store package information for
+
+# Some standard variables and programs
+#
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+INSTALL = @INSTALL@
+LIBTOOL = ./libtool
+ALLOWRELEASE = @ALLOWRELEASE@
+
+# libtool compile/link/install
+LTCOMPILE = $(LIBTOOL) --mode=compile $(TCC)
+LTLINK = $(LIBTOOL) --mode=link $(TCC)
+LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL)
+
 # You should not have to change anything below this line
 ###############################################################################
 
+OPTS += -DSQLITE_OMIT_CURSOR          # Cursors do not work at this time
+TCC += -DSQLITE_OMIT_CURSOR
+
 # Object files for the SQLite library.
 #
-LIBOBJ = attach.lo auth.lo btree.lo build.lo date.lo delete.lo \
-         expr.lo func.lo hash.lo insert.lo \
-         main.lo opcodes.lo os_mac.lo os_unix.lo os_win.lo \
+LIBOBJ = alter.lo attach.lo auth.lo btree.lo build.lo date.lo \
+         delete.lo expr.lo func.lo hash.lo insert.lo \
+         main.lo opcodes.lo os_unix.lo os_win.lo \
          pager.lo parse.lo pragma.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 vdbemem.lo \
+         select.lo table.lo tokenize.lo trigger.lo update.lo \
+         util.lo vacuum.lo vdbe.lo vdbeapi.lo vdbeaux.lo vdbemem.lo \
          where.lo utf.lo legacy.lo
 
 # All of the source code files.
 #
 SRC = \
+  $(TOP)/src/alter.c \
   $(TOP)/src/attach.c \
   $(TOP)/src/auth.c \
   $(TOP)/src/btree.c \
@@ -104,7 +138,6 @@ SRC = \
   $(TOP)/src/insert.c \
   $(TOP)/src/legacy.c \
   $(TOP)/src/main.c \
-  $(TOP)/src/os_mac.c \
   $(TOP)/src/os_unix.c \
   $(TOP)/src/os_win.c \
   $(TOP)/src/pager.c \
@@ -137,8 +170,8 @@ SRC = \
 #
 TESTSRC = \
   $(TOP)/src/btree.c \
+  $(TOP)/src/date.c \
   $(TOP)/src/func.c \
-  $(TOP)/src/os_mac.c \
   $(TOP)/src/os_unix.c \
   $(TOP)/src/os_win.c \
   $(TOP)/src/pager.c \
@@ -164,7 +197,6 @@ HDR = \
    opcodes.h \
    $(TOP)/src/os.h \
    $(TOP)/src/os_common.h \
-   $(TOP)/src/os_mac.h \
    $(TOP)/src/os_unix.h \
    $(TOP)/src/os_win.h \
    $(TOP)/src/sqliteInt.h  \
@@ -180,7 +212,7 @@ VDBEHDR = \
 # This is the default Makefile target.  The objects listed here
 # are what get build when you type just "make" with no arguments.
 #
-all:   sqlite3.h libsqlite3.la sqlite3@TARGET_EXEEXT@
+all:   sqlite3.h libsqlite3.la sqlite3$(TEXE) $(HAVE_TCL:1=libtclsqlite3.la)
 
 Makefile: $(TOP)/Makefile.in
        ./config.status
@@ -194,14 +226,15 @@ last_change:      $(SRC)
 
 libsqlite3.la: $(LIBOBJ)
        $(LTLINK) -o libsqlite3.la $(LIBOBJ) $(LIBPTHREAD) \
-               ${RELEASE} -rpath $(libdir) -version-info "8:6:8"
+               ${ALLOWRELEASE} -rpath $(libdir) -version-info "8:6:8"
 
 libtclsqlite3.la:      tclsqlite.lo libsqlite3.la
        $(LTLINK) -o libtclsqlite3.la tclsqlite.lo \
-               libsqlite3.la $(LIBTCL) $(LIBPTHREAD) -rpath $(libdir)/sqlite \
+               $(LIBOBJ) @TCL_STUB_LIB_SPEC@ $(LIBPTHREAD) \
+                -rpath $(libdir)/sqlite \
                -version-info "8:6:8"
 
-sqlite3@TARGET_EXEEXT@:        $(TOP)/src/shell.c libsqlite3.la sqlite3.h
+sqlite3$(TEXE):        $(TOP)/src/shell.c libsqlite3.la sqlite3.h
        $(LTLINK) $(READLINE_FLAGS) $(LIBPTHREAD) \
                -o sqlite3 $(TOP)/src/shell.c libsqlite3.la $(LIBREADLINE)
 
@@ -211,23 +244,26 @@ sqlite3@TARGET_EXEEXT@:   $(TOP)/src/shell.c libsqlite3.la sqlite3.h
 # files are automatically generated.  This target takes care of
 # all that automatic generation.
 #
-target_source: $(SRC) $(VDBEHDR) 
+target_source: $(SRC) parse.c opcodes.c keywordhash.h $(VDBEHDR) 
        rm -rf tsrc
        mkdir -p tsrc
        cp $(SRC) $(VDBEHDR) tsrc
        rm tsrc/sqlite.h.in tsrc/parse.y
-       cp parse.c opcodes.c tsrc
+       cp parse.c opcodes.c keywordhash.h tsrc
        cp $(TOP)/sqlite3.def tsrc
 
 # Rules to build the LEMON compiler generator
 #
-lemon@BUILD_EXEEXT@:   $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
+lemon$(BEXE):  $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
        $(BCC) -o lemon $(TOP)/tool/lemon.c
        cp $(TOP)/tool/lempar.c .
 
 
 # Rules to build individual files
 #
+alter.lo:      $(TOP)/src/alter.c $(HDR)
+       $(LTCOMPILE) -c $(TOP)/src/alter.c
+
 attach.lo:     $(TOP)/src/attach.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/attach.c
 
@@ -287,14 +323,11 @@ opcodes.lo:       opcodes.c
        $(LTCOMPILE) -c opcodes.c
 
 opcodes.c:     opcodes.h $(TOP)/mkopcodec.awk
-       sort -n +2 opcodes.h | awk -f $(TOP)/mkopcodec.awk >opcodes.c
+       sort -n -b +2 opcodes.h | awk -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
 
-os_mac.lo:     $(TOP)/src/os_mac.c $(HDR)
-       $(LTCOMPILE) $(THREADSAFE) -c $(TOP)/src/os_mac.c
-
 os_unix.lo:    $(TOP)/src/os_unix.c $(HDR)
        $(LTCOMPILE) $(THREADSAFE) -c $(TOP)/src/os_unix.c
 
@@ -306,15 +339,15 @@ parse.lo: parse.c $(HDR)
 
 parse.h:       parse.c
 
-parse.c:       $(TOP)/src/parse.y lemon@BUILD_EXEEXT@
+parse.c:       $(TOP)/src/parse.y lemon$(BEXE)
        cp $(TOP)/src/parse.y .
-       ./lemon parse.y
+       ./lemon $(OPTS) parse.y
 
 pragma.lo:     $(TOP)/src/pragma.c $(HDR)
-       $(LTCOMPILE) $(TCL_FLAGS) -c $(TOP)/src/pragma.c
+       $(LTCOMPILE) -c $(TOP)/src/pragma.c
 
 printf.lo:     $(TOP)/src/printf.c $(HDR)
-       $(LTCOMPILE) $(TCL_FLAGS) -c $(TOP)/src/printf.c
+       $(LTCOMPILE) -c $(TOP)/src/printf.c
 
 random.lo:     $(TOP)/src/random.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/random.c
@@ -323,18 +356,22 @@ select.lo:        $(TOP)/src/select.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/select.c
 
 sqlite3.h:     $(TOP)/src/sqlite.h.in 
-       sed -e s/--VERS--/`cat ${TOP}/VERSION`/ \
-                 $(TOP)/src/sqlite.h.in >sqlite3.h
+       sed -e s/--VERS--/$(RELEASE)/ $(TOP)/src/sqlite.h.in | \
+       sed -e s/--VERSION-NUMBER--/$(VERSION_NUMBER)/ >sqlite3.h
 
 table.lo:      $(TOP)/src/table.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/table.c
 
 tclsqlite.lo:  $(TOP)/src/tclsqlite.c $(HDR)
-       $(LTCOMPILE) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c
+       $(LTCOMPILE) -c $(TOP)/src/tclsqlite.c
 
-tokenize.lo:   $(TOP)/src/tokenize.c $(HDR)
+tokenize.lo:   $(TOP)/src/tokenize.c keywordhash.h $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/tokenize.c
 
+keywordhash.h: $(TOP)/tool/mkkeywordhash.c
+       $(BCC) -o mkkeywordhash$(BEXE) $(OPTS) $(TOP)/tool/mkkeywordhash.c
+       ./mkkeywordhash$(BEXE) >keywordhash.h
+
 trigger.lo:    $(TOP)/src/trigger.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/trigger.c
 
@@ -365,33 +402,49 @@ vdbemem.lo:       $(TOP)/src/vdbemem.c $(VDBEHDR)
 where.lo:      $(TOP)/src/where.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/where.c
 
-tclsqlite-sh.lo:       $(TOP)/src/tclsqlite.c $(HDR)
-       $(LTCOMPILE) $(TCL_FLAGS) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c
+tclsqlite-shell.lo:    $(TOP)/src/tclsqlite.c $(HDR)
+       $(LTCOMPILE) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c
+
+tclsqlite-stubs.lo:    $(TOP)/src/tclsqlite.c $(HDR)
+       $(LTCOMPILE) -DTCL_USE_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c
 
-tclsqlite3:    tclsqlite-sh.lo libsqlite3.la
-       $(LTLINK) $(TCL_FLAGS) -o tclsqlite3 tclsqlite-sh.lo \
+tclsqlite3:    tclsqlite-shell.lo libsqlite3.la
+       $(LTLINK) -o tclsqlite3 tclsqlite-shell.lo \
                 libsqlite3.la $(LIBTCL)
 
-testfixture@TARGET_EXEEXT@:    $(TOP)/src/tclsqlite.c libtclsqlite3.la libsqlite3.la $(TESTSRC)
-       $(LTLINK) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1\
+testfixture$(TEXE):    $(TOP)/src/tclsqlite.c libtclsqlite3.la libsqlite3.la $(TESTSRC)
+       $(LTLINK) -DTCLSH=1 -DSQLITE_TEST=1\
                 $(THREADSAFE) $(TEMP_STORE)\
                 -o testfixture $(TESTSRC) $(TOP)/src/tclsqlite.c \
-               libtclsqlite3.la libsqlite3.la $(LIBTCL)
+               libtclsqlite3.la $(LIBTCL)
 
-crashtest@TARGET_EXEEXT@:      $(TOP)/src/tclsqlite.c libsqlite3.la $(TESTSRC) $(TOP)/src/os_test.c
-       $(LTLINK) $(TCL_FLAGS) -DOS_TEST=1 -DTCLSH=1 -DSQLITE_TEST=1 \
+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) $(THREADLIB)
 
 
 
-fulltest:      testfixture@TARGET_EXEEXT@ sqlite3@TARGET_EXEEXT@ crashtest@TARGET_EXEEXT@
+fulltest:      testfixture$(TEXE) sqlite3$(TEXE) crashtest$(TEXE)
        ./testfixture $(TOP)/test/all.test
 
-test:  testfixture@TARGET_EXEEXT@ sqlite3@TARGET_EXEEXT@
+test:  testfixture$(TEXE) sqlite3$(TEXE)
        ./testfixture $(TOP)/test/quick.test
 
+sqlite3_analyzer$(TEXE):       $(TOP)/src/tclsqlite.c libtclsqlite3.la \
+                               $(TESTSRC) $(TOP)/tool/spaceanal.tcl
+       sed \
+         -e '/^#/d' \
+         -e 's,\\,\\\\,g' \
+         -e 's,",\\",g' \
+         -e 's,^,",' \
+         -e 's,$$,\\n",' \
+         $(TOP)/tool/spaceanal.tcl >spaceanal_tcl.h
+       $(LTLINK) -DTCLSH=2 -DSQLITE_TEST=1\
+                $(THREADSAFE) $(TEMP_STORE)\
+                -o sqlite3_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \
+               libtclsqlite3.la $(LIBTCL)
 
 # Rules used to build documentation
 #
@@ -401,6 +454,9 @@ arch.html:  $(TOP)/www/arch.tcl
 arch2.gif:     $(TOP)/www/arch2.gif
        cp $(TOP)/www/arch2.gif .
 
+autoinc.html:  $(TOP)/www/autoinc.tcl
+       tclsh $(TOP)/www/autoinc.tcl >autoinc.html
+
 c_interface.html:      $(TOP)/www/c_interface.tcl
        tclsh $(TOP)/www/c_interface.tcl >c_interface.html
 
@@ -413,6 +469,9 @@ capi3ref.html:      $(TOP)/www/capi3ref.tcl
 changes.html:  $(TOP)/www/changes.tcl
        tclsh $(TOP)/www/changes.tcl >changes.html
 
+compile.html:  $(TOP)/www/compile.tcl
+       tclsh $(TOP)/www/compile.tcl >compile.html
+
 copyright.html:        $(TOP)/www/copyright.tcl
        tclsh $(TOP)/www/copyright.tcl >copyright.html
 
@@ -456,6 +515,9 @@ index.html: $(TOP)/www/index.tcl last_change
 lang.html:     $(TOP)/www/lang.tcl
        tclsh $(TOP)/www/lang.tcl >lang.html
 
+pragma.html:   $(TOP)/www/pragma.tcl
+       tclsh $(TOP)/www/pragma.tcl >pragma.html
+
 lockingv3.html:        $(TOP)/www/lockingv3.tcl
        tclsh $(TOP)/www/lockingv3.tcl >lockingv3.html
 
@@ -503,11 +565,13 @@ version3.html:    $(TOP)/www/version3.tcl
 #
 DOC = \
   arch.html \
-  arch2.gif \
+  arch.png \
+  autoinc.html \
   c_interface.html \
   capi3.html \
   capi3ref.html \
   changes.html \
+  compile.html \
   copyright.html \
   copyright-release.html \
   copyright-release.pdf \
@@ -527,6 +591,7 @@ DOC = \
   oldnews.html \
   omitted.html \
   opcode.html \
+  pragma.html \
   quickstart.html \
   speed.html \
   sqlite.gif \
@@ -534,13 +599,13 @@ DOC = \
   support.html \
   tclsqlite.html \
   vdbe.html \
-  version3.html
+  version3.html 
 
 doc:   common.tcl $(DOC)
        mkdir -p doc
        mv $(DOC) doc
 
-install:       sqlite3 libsqlite3.la sqlite3.h
+install:       sqlite3 libsqlite3.la sqlite3.h ${HAVE_TCL:1=tcl_install}
        $(INSTALL) -d $(DESTDIR)$(libdir)
        $(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)
        $(INSTALL) -d $(DESTDIR)$(exec_prefix)/bin
@@ -550,14 +615,18 @@ install:  sqlite3 libsqlite3.la sqlite3.h
        $(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig; 
        $(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(libdir)/pkgconfig; 
 
+tcl_install:   libtclsqlite3.la
+       tclsh $(TOP)/tclinstaller.tcl $(VERSION)
+
 clean: 
-       rm -f *.lo *.la *.o sqlite3@TARGET_EXEEXT@ libsqlite3.la
+       rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la
        rm -f sqlite3.h opcodes.*
        rm -rf .libs .deps 
-       rm -f lemon@BUILD_EXEEXT@ lempar.c parse.* sqlite*.tar.gz
+       rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz
+       rm -f mkkeywordhash$(BEXE) keywordhash.h
        rm -f $(PUBLISH)
        rm -f *.da *.bb *.bbg gmon.out
-       rm -f testfixture@TARGET_EXEEXT@ test.db
+       rm -f testfixture$(TEXE) test.db
        rm -rf doc
        rm -f common.tcl
        rm -f sqlite3.dll sqlite3.lib
index 67786e246ef5cbdf27c91c78d679e000b3d31cbf..ff365e06b9577c96dfeadddb8c4cccb09b85665c 100644 (file)
@@ -1 +1 @@
-3.0.8
+3.1.3
index 183977d168c92c4b0c5602a085bbba1a1ba30240..779a859463860cc2459e683a95ec60f9bc2afda3 100755 (executable)
@@ -463,7 +463,7 @@ ac_includes_default="\
 # include <unistd.h>
 #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 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 TARGET_TCL_LIBS TARGET_TCL_INC TARGET_READLINE_LIBS TARGET_READLINE_INC TARGET_HAVE_READLINE 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 program_prefix VERSION VERSION_NUMBER RELEASE 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_files=''
 
 # Initialize some variables set by options.
@@ -1028,6 +1028,8 @@ Optional Features:
   --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
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1038,6 +1040,7 @@ 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)
 
 Some influential environment variables:
   CC          C compiler command
@@ -3052,7 +3055,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 3055 "configure"' > conftest.$ac_ext
+  echo '#line 3058 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -4515,7 +4518,7 @@ fi
 
 
 # Provide some information about the compiler.
-echo "$as_me:4518:" \
+echo "$as_me:4521:" \
      "checking for Fortran 77 compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
 { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
@@ -5549,11 +5552,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:5552: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:5555: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:5556: \$? = $ac_status" >&5
+   echo "$as_me:5559: \$? = $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
@@ -5782,11 +5785,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:5785: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:5788: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:5789: \$? = $ac_status" >&5
+   echo "$as_me:5792: \$? = $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
@@ -5842,11 +5845,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:5845: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:5848: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:5849: \$? = $ac_status" >&5
+   echo "$as_me:5852: \$? = $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
@@ -8026,7 +8029,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 8029 "configure"
+#line 8032 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -8124,7 +8127,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 8127 "configure"
+#line 8130 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10303,11 +10306,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:10306: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:10309: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:10310: \$? = $ac_status" >&5
+   echo "$as_me:10313: \$? = $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
@@ -10363,11 +10366,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:10366: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:10369: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:10370: \$? = $ac_status" >&5
+   echo "$as_me:10373: \$? = $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
@@ -11724,7 +11727,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 11727 "configure"
+#line 11730 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11822,7 +11825,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 11825 "configure"
+#line 11828 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12649,11 +12652,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:12652: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:12655: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:12656: \$? = $ac_status" >&5
+   echo "$as_me:12659: \$? = $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
@@ -12709,11 +12712,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:12712: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:12715: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:12716: \$? = $ac_status" >&5
+   echo "$as_me:12719: \$? = $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
@@ -14743,11 +14746,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:14746: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14749: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:14750: \$? = $ac_status" >&5
+   echo "$as_me:14753: \$? = $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
@@ -14976,11 +14979,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:14979: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14982: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:14983: \$? = $ac_status" >&5
+   echo "$as_me:14986: \$? = $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
@@ -15036,11 +15039,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:15039: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15042: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:15043: \$? = $ac_status" >&5
+   echo "$as_me:15046: \$? = $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
@@ -17220,7 +17223,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 17223 "configure"
+#line 17226 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -17318,7 +17321,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 17321 "configure"
+#line 17324 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -18420,11 +18423,17 @@ if test "$program_prefix" = "NONE"; then
 fi
 
 
-if test -f VERSION; then
-  VERSION=`cat VERSION`
-  echo "Version set to $VERSION"
-fi
+VERSION=`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'`
+echo "Version set to $VERSION"
+
+RELEASE=`cat $srcdir/VERSION`
+echo "Release set to $RELEASE"
 
+VERSION_NUMBER=`cat $srcdir/VERSION  \
+               | sed 's/[^0-9]/ /g' \
+                | awk '{printf "%d%03d%03d",$1,$2,$3}'`
+
+echo "Version number set to $VERSION_NUMBER"
 
 #########
 # Check to see if the --with-hints=FILE option is used.  If there is none,
 
 
 ##########
-# Figure out what C libraries are required to compile Tcl programs.
+# Figure out all the parameters needed to compile against Tcl.
+#
+# This code is derived from the SC_PATH_TCLCONFIG and SC_LOAD_TCLCONFIG
+# macros in the in the tcl.m4 file of the standard TCL distribution.
+# Those macros could not be used directly since we have to make some
+# minor changes to accomodate systems that do not have TCL installed.
 #
-if test "$config_TARGET_TCL_LIBS" != ""; then
-  TARGET_TCL_LIBS="$config_TARGET_TCL_LIBS"
+# Check whether --enable-tcl or --disable-tcl was given.
+if test "${enable_tcl+set}" = set; then
+  enableval="$enable_tcl"
+  use_tcl=$enableval
 else
-  if test "$with_tcl" != ""; then
-    extra=`echo $with_tcl/$tclsubdir/libtcl8*.a`
-  fi
-  CC=$TARGET_CC
-  echo "$as_me:$LINENO: checking for sin" >&5
-echo $ECHO_N "checking for sin... $ECHO_C" >&6
-if test "${ac_cv_func_sin+set}" = set; then
+  use_tcl=yes
+fi;
+if test "${use_tcl}" = "yes" ; then
+
+# Check whether --with-tcl or --without-tcl was given.
+if test "${with_tcl+set}" = set; then
+  withval="$with_tcl"
+  with_tclconfig=${withval}
+fi;
+  echo "$as_me:$LINENO: checking for Tcl configuration" >&5
+echo $ECHO_N "checking for Tcl configuration... $ECHO_C" >&6
+  if test "${ac_cv_c_tclconfig+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 sin to an innocuous variant, in case <limits.h> declares sin.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define sin innocuous_sin
 
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char sin (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef sin
+    # First check to see if --with-tcl was specified.
+    if test x"${with_tclconfig}" != x ; then
+      if test -f "${with_tclconfig}/tclConfig.sh" ; then
+        ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
+      else
+        { { echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5
+echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;}
+   { (exit 1); exit 1; }; }
+      fi
+    fi
+    # then check for a private Tcl installation
+    if test x"${ac_cv_c_tclconfig}" = x ; then
+      for i in \
+            ../tcl \
+            `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+            `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \
+            `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \
+            ../../tcl \
+            `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+            `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \
+            `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \
+            ../../../tcl \
+            `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+            `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \
+            `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null`
+      do
+        if test -f "$i/unix/tclConfig.sh" ; then
+          ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
+          break
+        fi
+      done
+    fi
 
-/* 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 sin ();
-/* 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_sin) || defined (__stub___sin)
-choke me
-#else
-char (*f) () = sin;
-#endif
-#ifdef __cplusplus
-}
-#endif
+    # check in a few common install locations
+    if test x"${ac_cv_c_tclconfig}" = x ; then
+      for i in \
+            `ls -d ${libdir} 2>/dev/null` \
+            `ls -d /usr/local/lib 2>/dev/null` \
+            `ls -d /usr/contrib/lib 2>/dev/null` \
+            `ls -d /usr/lib 2>/dev/null`
+      do
+        if test -f "$i/tclConfig.sh" ; then
+           ac_cv_c_tclconfig=`(cd $i; pwd)`
+           break
+        fi
+      done
+    fi
 
-int
-main ()
-{
-return f != sin;
-  ;
-  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_sin=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+    # check in a few other private locations
+    if test x"${ac_cv_c_tclconfig}" = x ; then
+      for i in \
+         ${srcdir}/../tcl \
+         `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+         `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \
+         `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null`
+      do
+        if test -f "$i/unix/tclConfig.sh" ; then
+          ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
+          break
+        fi
+      done
+    fi
 
-ac_cv_func_sin=no
-fi
-rm -f conftest.err conftest.$ac_objext \
-      conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_func_sin" >&5
-echo "${ECHO_T}$ac_cv_func_sin" >&6
-if test $ac_cv_func_sin = yes; then
-  LIBS=""
-else
-  LIBS="-lm"
 fi
 
 
-echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
-echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
-if test "${ac_cv_lib_dl_dlopen+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
+  if test x"${ac_cv_c_tclconfig}" = x ; then
+    use_tcl=no
+    { echo "$as_me:$LINENO: WARNING: Can't find Tcl configuration definitions" >&5
+echo "$as_me: WARNING: Can't find Tcl configuration definitions" >&2;}
+    { echo "$as_me:$LINENO: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&5
+echo "$as_me: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&2;}
+    { echo "$as_me:$LINENO: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&5
+echo "$as_me: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&2;}
+  else
+    TCL_BIN_DIR=${ac_cv_c_tclconfig}
+    echo "$as_me:$LINENO: result: found $TCL_BIN_DIR/tclConfig.sh" >&5
+echo "${ECHO_T}found $TCL_BIN_DIR/tclConfig.sh" >&6
+
+    echo "$as_me:$LINENO: checking for existence of $TCL_BIN_DIR/tclConfig.sh" >&5
+echo $ECHO_N "checking for existence of $TCL_BIN_DIR/tclConfig.sh... $ECHO_C" >&6
+    if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
+      echo "$as_me:$LINENO: result: loading" >&5
+echo "${ECHO_T}loading" >&6
+      . $TCL_BIN_DIR/tclConfig.sh
+    else
+      echo "$as_me:$LINENO: result: file not found" >&5
+echo "${ECHO_T}file not found" >&6
+    fi
 
-/* 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 dlopen ();
-int
-main ()
-{
-dlopen ();
-  ;
-  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_lib_dl_dlopen=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+    #
+    # If the TCL_BIN_DIR is the build directory (not the install directory),
+    # then set the common variable name to the value of the build variables.
+    # For example, the variable TCL_LIB_SPEC will be set to the value
+    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
+    # instead of TCL_BUILD_LIB_SPEC since it will work with both an
+    # installed and uninstalled version of Tcl.
+    #
+
+   if test -f $TCL_BIN_DIR/Makefile ; then
+      TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
+      TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
+      TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
+    fi
 
-ac_cv_lib_dl_dlopen=no
-fi
-rm -f conftest.err conftest.$ac_objext \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
-echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
-if test $ac_cv_lib_dl_dlopen = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBDL 1
-_ACEOF
+    #
+    # eval is required to do the TCL_DBGX substitution
+    #
 
-  LIBS="-ldl $LIBS"
+    eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
+    eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
+    eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
 
-fi
+    eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
+    eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
+    eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
 
-  otherlibs=$LIBS
-  if test "$extra" != ""; then
-    LIBS=$extra
-  else
-    LIBS=""
-    echo "$as_me:$LINENO: checking for library containing Tcl_Init" >&5
-echo $ECHO_N "checking for library containing Tcl_Init... $ECHO_C" >&6
-if test "${ac_cv_search_Tcl_Init+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-ac_cv_search_Tcl_Init=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 Tcl_Init ();
-int
-main ()
-{
-Tcl_Init ();
-  ;
-  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_Tcl_Init="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_Tcl_Init" = no; then
-  for ac_lib in         tcl8.4 tcl8.3 tcl84 tcl83 tcl; do
-    LIBS="-l$ac_lib $otherlibs $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 Tcl_Init ();
-int
-main ()
-{
-Tcl_Init ();
-  ;
-  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_Tcl_Init="-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_Tcl_Init" >&5
-echo "${ECHO_T}$ac_cv_search_Tcl_Init" >&6
-if test "$ac_cv_search_Tcl_Init" != no; then
-  test "$ac_cv_search_Tcl_Init" = "none required" || LIBS="$ac_cv_search_Tcl_Init $LIBS"
 
-fi
 
-  fi
-  TARGET_TCL_LIBS="$LIBS $otherlibs"
-fi
 
 
-##########
-# Figure out where to get the TCL header files.
-#
-echo "$as_me:$LINENO: checking TCL header files" >&5
-echo $ECHO_N "checking TCL header files... $ECHO_C" >&6
-found=no
-if test "$config_TARGET_TCL_INC" != ""; then
-  TARGET_TCL_INC=$config_TARGET_TCL_INC
-  found=yes
-else
-  if test "$with_tcl" != ""; then
-    TARGET_TCL_INC="-I$with_tcl/generic -I$with_tcl/$tclsubdir"
-    found=yes
-  else
-    TARGET_TCL_INC=""
-    found=no
-  fi
-fi
-if test "$found" = "yes"; then
-  echo "$as_me:$LINENO: result: $TARGET_TCL_INC" >&5
-echo "${ECHO_T}$TARGET_TCL_INC" >&6
-else
-  echo "$as_me:$LINENO: result: not specified: still searching..." >&5
-echo "${ECHO_T}not specified: still searching..." >&6
-  if test "${ac_cv_header_tcl_h+set}" = set; then
-  echo "$as_me:$LINENO: checking for tcl.h" >&5
-echo $ECHO_N "checking for tcl.h... $ECHO_C" >&6
-if test "${ac_cv_header_tcl_h+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: $ac_cv_header_tcl_h" >&5
-echo "${ECHO_T}$ac_cv_header_tcl_h" >&6
-else
-  # Is the header compilable?
-echo "$as_me:$LINENO: checking tcl.h usability" >&5
-echo $ECHO_N "checking tcl.h usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-#include <tcl.h>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 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_objext'
-  { (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_header_compiler=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
 
-# Is the header present?
-echo "$as_me:$LINENO: checking tcl.h presence" >&5
-echo $ECHO_N "checking tcl.h presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <tcl.h>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 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); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  ac_header_preproc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
 
-  ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
 
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { echo "$as_me:$LINENO: WARNING: tcl.h: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: tcl.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: tcl.h: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: tcl.h: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: tcl.h: present but cannot be compiled" >&5
-echo "$as_me: WARNING: tcl.h: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: tcl.h:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: tcl.h:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: tcl.h: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: tcl.h: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: tcl.h:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: tcl.h:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: tcl.h: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: tcl.h: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: tcl.h: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: tcl.h: in the future, the compiler will take precedence" >&2;}
-    (
-      cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists.  ##
-## ------------------------------------------ ##
-_ASBOX
-    ) |
-      sed "s/^/$as_me: WARNING:     /" >&2
-    ;;
-esac
-echo "$as_me:$LINENO: checking for tcl.h" >&5
-echo $ECHO_N "checking for tcl.h... $ECHO_C" >&6
-if test "${ac_cv_header_tcl_h+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_header_tcl_h=$ac_header_preproc
-fi
-echo "$as_me:$LINENO: result: $ac_cv_header_tcl_h" >&5
-echo "${ECHO_T}$ac_cv_header_tcl_h" >&6
 
-fi
-if test $ac_cv_header_tcl_h = yes; then
-  found=yes
-fi
 
 
+  fi
 fi
-if test "$found" = "no"; then
-  for dir in /usr/local /usr/X11 /usr/X11R6 /usr/pkg /usr/contrib /usr; do
-    as_ac_File=`echo "ac_cv_file_$dir/include/tcl.h" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $dir/include/tcl.h" >&5
-echo $ECHO_N "checking for $dir/include/tcl.h... $ECHO_C" >&6
-if eval "test \"\${$as_ac_File+set}\" = set"; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  test "$cross_compiling" = yes &&
-  { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
-echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
-   { (exit 1); exit 1; }; }
-if test -r "$dir/include/tcl.h"; then
-  eval "$as_ac_File=yes"
+if test "${use_tcl}" = "no" ; then
+  HAVE_TCL=""
 else
-  eval "$as_ac_File=no"
-fi
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_File'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_File'}'`" >&6
-if test `eval echo '${'$as_ac_File'}'` = yes; then
-  found=yes
-fi
-
-    if test "$found" = "yes"; then
-      TARGET_TCL_INC="-I$dir/include"
-      break
-    fi
-  done
-fi
-if test "$found" = "no"; then
-  TARGET_TCL_INC="-DNO_TCL=1"
+  HAVE_TCL=1
 fi
 
 
 
 
 
+#########
+# check for debug enabled
+# Check whether --enable-debug or --disable-debug was given.
+if test "${enable_debug+set}" = set; then
+  enableval="$enable_debug"
+  use_debug=$enableval
+else
+  use_debug=no
+fi;
+if test "${use_debug}" = "yes" ; then
+  TARGET_DEBUG=""
+else
+  TARGET_DEBUG="-DNDEBUG"
+fi
+
+
 #########
 # Figure out whether or not we have a "usleep()" function.
 #
@@ -21344,6 +21018,8 @@ s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
 s,@INSTALL_DATA@,$INSTALL_DATA,;t t
 s,@program_prefix@,$program_prefix,;t t
 s,@VERSION@,$VERSION,;t t
+s,@VERSION_NUMBER@,$VERSION_NUMBER,;t t
+s,@RELEASE@,$RELEASE,;t t
 s,@BUILD_CC@,$BUILD_CC,;t t
 s,@BUILD_CFLAGS@,$BUILD_CFLAGS,;t t
 s,@BUILD_LIBS@,$BUILD_LIBS,;t t
@@ -21362,11 +21038,22 @@ s,@OS_UNIX@,$OS_UNIX,;t t
 s,@OS_WIN@,$OS_WIN,;t t
 s,@TARGET_EXEEXT@,$TARGET_EXEEXT,;t t
 s,@TARGET_LIBS@,$TARGET_LIBS,;t t
-s,@TARGET_TCL_LIBS@,$TARGET_TCL_LIBS,;t t
-s,@TARGET_TCL_INC@,$TARGET_TCL_INC,;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
+s,@TCL_LIBS@,$TCL_LIBS,;t t
+s,@TCL_INCLUDE_SPEC@,$TCL_INCLUDE_SPEC,;t t
+s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t
+s,@TCL_LIB_FLAG@,$TCL_LIB_FLAG,;t t
+s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t
+s,@TCL_STUB_LIB_FILE@,$TCL_STUB_LIB_FILE,;t t
+s,@TCL_STUB_LIB_FLAG@,$TCL_STUB_LIB_FLAG,;t t
+s,@TCL_STUB_LIB_SPEC@,$TCL_STUB_LIB_SPEC,;t t
+s,@HAVE_TCL@,$HAVE_TCL,;t t
 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,@LIBOBJS@,$LIBOBJS,;t t
 s,@LTLIBOBJS@,$LTLIBOBJS,;t t
 CEOF
index 20cd5a8ccde84faba3c20417cb48fd25d067ff6d..6137f39d20a83952bfee3ab487e62d9bdf3a8020 100644 (file)
@@ -1,9 +1,4 @@
 #
-# This file describes a "configure" script that is used to build
-# makefiles for a particular platform.  Process this file using 
-# Autoconf version 1.13 in order to generate that script.  All 
-# lines of this file up to the AC_INIT macro are ignored.
-#
 # The build process allows for using a cross-compiler.  But the default
 # action is to target the same platform that we are running on.  The
 # configure script needs to discover the following properties of the 
 #        into *.o files.  Do not include TARGET_TCL_INC in this list.
 #        Makefiles might add additional switches such as "-I.".
 #
-#    TARGET_TCL_LIBS
-#
-#        This is the library directives passed to the target linker
-#        that cause the executable to link against Tcl.  This might
-#        be a switch like "-ltcl8.0" or pathnames of library file
-#        like "../../src/libtcl8.0.a".
-#
-#    TARGET_TCL_INC
+#    TCL_*
 #
-#        This variables define the directory that contain header
-#        files for Tcl.  If the compiler is able to find <tcl.h>
-#        on its own, then this can be blank.
+#        Lots of values are read in from the tclConfig.sh script,
+#        if that script is available.  This values are used for
+#        constructing and installing the TCL extension.
 #
 #    TARGET_READLINE_LIBS
 #
 # where FILE is the name of the file that sets the environment
 # variables.  FILE should be an absolute pathname.
 #
-# If you have a Tcl/Tk/BLT source distribution available, then the
-# files in that distribution will be used instead of any other
-# Tcl/Tk/BLT files the script might discover if you tell the configure
-# script about the source tree.  Use commandline options:
-#
-#         --with-tcl=PATH  --with-tk=PATH  --with-blt=PATH
-#
-# Or set environment variables config_WITH_TCL, config_WITH_TK, or
-# config_WITH_BLT.
-#
 # This configure.in file is easy to reuse on other projects.  Just
 # change the argument to AC_INIT().  And disable any features that
 # you don't need (for example BLT) by erasing or commenting out
@@ -154,11 +132,17 @@ if test "$program_prefix" = "NONE"; then
 fi
 AC_SUBST(program_prefix)
 
-if test -f VERSION; then
-  VERSION=`cat VERSION`
-  echo "Version set to $VERSION"
-fi
+VERSION=[`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'`]
+echo "Version set to $VERSION"
 AC_SUBST(VERSION)
+RELEASE=`cat $srcdir/VERSION`
+echo "Release set to $RELEASE"
+AC_SUBST(RELEASE)
+VERSION_NUMBER=`cat $srcdir/VERSION  \
+                           | sed 's/[^0-9]/ /g' \
+                | awk '{printf "%d%03d%03d",$1,$2,$3}'`
+echo "Version number set to $VERSION_NUMBER"
+AC_SUBST(VERSION_NUMBER)
 
 #########
 # Check to see if the --with-hints=FILE option is used.  If there is none,
@@ -410,65 +394,146 @@ fi
 AC_SUBST(TARGET_LIBS)
 
 ##########
-# Figure out what C libraries are required to compile Tcl programs.
-#
-if test "$config_TARGET_TCL_LIBS" != ""; then
-  TARGET_TCL_LIBS="$config_TARGET_TCL_LIBS"
-else
-  if test "$with_tcl" != ""; then
-    extra=`echo $with_tcl/$tclsubdir/libtcl8*.a`
-  fi
-  CC=$TARGET_CC
-  AC_CHECK_FUNC(sin, LIBS="", LIBS="-lm")
-  AC_CHECK_LIB(dl, dlopen)
-  otherlibs=$LIBS
-  if test "$extra" != ""; then
-    LIBS=$extra
-  else 
-    LIBS=""
-    AC_SEARCH_LIBS(Tcl_Init, dnl
-        tcl8.4 tcl8.3 tcl84 tcl83 tcl,,,$otherlibs)
-  fi
-  TARGET_TCL_LIBS="$LIBS $otherlibs"
-fi
-AC_SUBST(TARGET_TCL_LIBS)
+# Figure out all the parameters needed to compile against Tcl.
+#
+# This code is derived from the SC_PATH_TCLCONFIG and SC_LOAD_TCLCONFIG
+# macros in the in the tcl.m4 file of the standard TCL distribution.
+# 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],
+      [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_MSG_CHECKING([for Tcl configuration])
+  AC_CACHE_VAL(ac_cv_c_tclconfig,[
+    # First check to see if --with-tcl was specified.
+    if test x"${with_tclconfig}" != x ; then
+      if test -f "${with_tclconfig}/tclConfig.sh" ; then
+        ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
+      else
+        AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
+      fi
+    fi
+    # then check for a private Tcl installation
+    if test x"${ac_cv_c_tclconfig}" = x ; then
+      for i in \
+            ../tcl \
+            `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+            `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+            `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
+            ../../tcl \
+            `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+            `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+            `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
+            ../../../tcl \
+            `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+            `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+            `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null`
+      do
+        if test -f "$i/unix/tclConfig.sh" ; then
+          ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
+          break
+        fi
+      done
+    fi
 
-##########
-# Figure out where to get the TCL header files.
-#
-AC_MSG_CHECKING([TCL header files])
-found=no
-if test "$config_TARGET_TCL_INC" != ""; then
-  TARGET_TCL_INC=$config_TARGET_TCL_INC
-  found=yes
-else
-  if test "$with_tcl" != ""; then
-    TARGET_TCL_INC="-I$with_tcl/generic -I$with_tcl/$tclsubdir"
-    found=yes
+    # check in a few common install locations
+    if test x"${ac_cv_c_tclconfig}" = x ; then
+      for i in \
+            `ls -d ${libdir} 2>/dev/null` \
+            `ls -d /usr/local/lib 2>/dev/null` \
+            `ls -d /usr/contrib/lib 2>/dev/null` \
+            `ls -d /usr/lib 2>/dev/null`
+      do
+        if test -f "$i/tclConfig.sh" ; then
+           ac_cv_c_tclconfig=`(cd $i; pwd)`
+           break
+        fi
+      done
+    fi
+
+    # check in a few other private locations
+    if test x"${ac_cv_c_tclconfig}" = x ; then
+      for i in \
+         ${srcdir}/../tcl \
+         `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+         `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+         `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null`
+      do
+        if test -f "$i/unix/tclConfig.sh" ; then
+          ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
+          break
+        fi
+      done
+    fi
+  ])
+
+  if test x"${ac_cv_c_tclconfig}" = x ; then
+    use_tcl=no
+    AC_MSG_WARN(Can't find Tcl configuration definitions)
+    AC_MSG_WARN(*** Without Tcl the regression tests cannot be executed ***)
+    AC_MSG_WARN(*** Consider using --with-tcl=... to define location of Tcl ***)
   else
-    TARGET_TCL_INC=""
-    found=no
+    TCL_BIN_DIR=${ac_cv_c_tclconfig}
+    AC_MSG_RESULT(found $TCL_BIN_DIR/tclConfig.sh)
+
+    AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh])
+    if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
+      AC_MSG_RESULT([loading])
+      . $TCL_BIN_DIR/tclConfig.sh
+    else
+      AC_MSG_RESULT([file not found])
+    fi
+    
+    #
+    # If the TCL_BIN_DIR is the build directory (not the install directory),
+    # then set the common variable name to the value of the build variables.
+    # For example, the variable TCL_LIB_SPEC will be set to the value
+    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
+    # instead of TCL_BUILD_LIB_SPEC since it will work with both an
+    # installed and uninstalled version of Tcl.
+    #
+    
+   if test -f $TCL_BIN_DIR/Makefile ; then
+      TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
+      TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
+      TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
+    fi
+    
+    #
+    # eval is required to do the TCL_DBGX substitution
+    #
+    
+    eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
+    eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
+    eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
+    
+    eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
+    eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
+    eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
+    
+    AC_SUBST(TCL_VERSION)
+    AC_SUBST(TCL_BIN_DIR)
+    AC_SUBST(TCL_SRC_DIR)
+    AC_SUBST(TCL_LIBS)
+    AC_SUBST(TCL_INCLUDE_SPEC)
+    
+    AC_SUBST(TCL_LIB_FILE)
+    AC_SUBST(TCL_LIB_FLAG)
+    AC_SUBST(TCL_LIB_SPEC)
+    
+    AC_SUBST(TCL_STUB_LIB_FILE)
+    AC_SUBST(TCL_STUB_LIB_FLAG)
+    AC_SUBST(TCL_STUB_LIB_SPEC)
   fi
 fi
-if test "$found" = "yes"; then
-  AC_MSG_RESULT($TARGET_TCL_INC)
+if test "${use_tcl}" = "no" ; then
+  HAVE_TCL=""
 else
-  AC_MSG_RESULT(not specified: still searching...)
-  AC_CHECK_HEADER(tcl.h, [found=yes])
+  HAVE_TCL=1
 fi
-if test "$found" = "no"; then
-  for dir in /usr/local /usr/X11 /usr/X11R6 /usr/pkg /usr/contrib /usr; do
-    AC_CHECK_FILE($dir/include/tcl.h, found=yes)
-    if test "$found" = "yes"; then
-      TARGET_TCL_INC="-I$dir/include"
-      break
-    fi
-  done
-fi
-if test "$found" = "no"; then
-  TARGET_TCL_INC="-DNO_TCL=1"
-fi
-AC_SUBST(TARGET_TCL_INC)
+AC_SUBST(HAVE_TCL)
 
 ##########
 # Figure out what C libraries are required to compile programs
@@ -526,6 +591,17 @@ fi
 AC_SUBST(TARGET_READLINE_INC)
 AC_SUBST(TARGET_HAVE_READLINE)
 
+#########
+# check for debug enabled
+AC_ARG_ENABLE(debug, [  --enable-debug         enable debugging & verbose explain],
+      [use_debug=$enableval],[use_debug=no])
+if test "${use_debug}" = "yes" ; then
+  TARGET_DEBUG=""
+else
+  TARGET_DEBUG="-DNDEBUG"
+fi
+AC_SUBST(TARGET_DEBUG)
+
 #########
 # Figure out whether or not we have a "usleep()" function.
 #
index e79e0926ba70078e73ae0587669db8739b48c04a..f6fc40c136567e9ec833de292485cba0203a8a60 100644 (file)
@@ -54,9 +54,9 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src
 
 # Object files for the SQLite library.
 #
-LIBOBJ+= attach.o auth.o btree.o build.o date.o delete.o \
+LIBOBJ+= alter.o attach.o auth.o btree.o build.o date.o delete.o \
          expr.o func.o hash.o insert.o \
-         main.o opcodes.o os_mac.o os_unix.o os_win.o \
+         main.o opcodes.o os_unix.o os_win.o \
          pager.o parse.o pragma.o printf.o random.o \
          select.o table.o tclsqlite.o tokenize.o trigger.o \
          update.o util.o vacuum.o \
@@ -66,6 +66,7 @@ LIBOBJ+= attach.o auth.o btree.o build.o date.o delete.o \
 # All of the source code files.
 #
 SRC = \
+  $(TOP)/src/alter.c \
   $(TOP)/src/attach.c \
   $(TOP)/src/auth.c \
   $(TOP)/src/btree.c \
@@ -80,7 +81,6 @@ SRC = \
   $(TOP)/src/insert.c \
   $(TOP)/src/legacy.c \
   $(TOP)/src/main.c \
-  $(TOP)/src/os_mac.c \
   $(TOP)/src/os_unix.c \
   $(TOP)/src/os_win.c \
   $(TOP)/src/pager.c \
@@ -113,8 +113,8 @@ SRC = \
 #
 TESTSRC = \
   $(TOP)/src/btree.c \
+  $(TOP)/src/date.c \
   $(TOP)/src/func.c \
-  $(TOP)/src/os_mac.c \
   $(TOP)/src/os_unix.c \
   $(TOP)/src/os_win.c \
   $(TOP)/src/pager.c \
@@ -140,7 +140,6 @@ HDR = \
    opcodes.h \
    $(TOP)/src/os.h \
    $(TOP)/src/os_common.h \
-   $(TOP)/src/os_mac.h \
    $(TOP)/src/os_unix.h \
    $(TOP)/src/os_win.h \
    $(TOP)/src/sqliteInt.h  \
@@ -181,12 +180,12 @@ objects: $(LIBOBJ_ORIG)
 # files are automatically generated.  This target takes care of
 # all that automatic generation.
 #
-target_source: $(SRC) $(VDBEHDR) opcodes.c
+target_source: $(SRC) $(VDBEHDR) opcodes.c keywordhash.h
        rm -rf tsrc
        mkdir tsrc
        cp $(SRC) $(VDBEHDR) tsrc
        rm tsrc/sqlite.h.in tsrc/parse.y
-       cp parse.c opcodes.c tsrc
+       cp parse.c opcodes.c keywordhash.h tsrc
        cp $(TOP)/sqlite3.def tsrc
 
 # Rules to build the LEMON compiler generator
@@ -197,6 +196,9 @@ lemon:      $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
 
 # Rules to build individual files
 #
+alter.o:       $(TOP)/src/alter.c $(HDR)
+       $(TCCX) -c $(TOP)/src/alter.c
+
 attach.o:      $(TOP)/src/attach.c $(HDR)
        $(TCCX) -c $(TOP)/src/attach.c
 
@@ -256,14 +258,11 @@ opcodes.o:        opcodes.c
        $(TCCX) -c opcodes.c
 
 opcodes.c:     opcodes.h $(TOP)/mkopcodec.awk
-       sort -n +2 opcodes.h | awk -f $(TOP)/mkopcodec.awk >opcodes.c
+       sort -n -b +2 opcodes.h | awk -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
 
-os_mac.o:      $(TOP)/src/os_mac.c $(HDR)
-       $(TCCX) -c $(TOP)/src/os_mac.c
-
 os_unix.o:     $(TOP)/src/os_unix.c $(HDR)
        $(TCCX) -c $(TOP)/src/os_unix.c
 
@@ -277,7 +276,7 @@ parse.h:    parse.c
 
 parse.c:       $(TOP)/src/parse.y lemon
        cp $(TOP)/src/parse.y .
-       ./lemon parse.y
+       ./lemon $(OPTS) parse.y
 
 pragma.o:      $(TOP)/src/pragma.c $(HDR)
        $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/pragma.c
@@ -293,7 +292,7 @@ select.o:   $(TOP)/src/select.c $(HDR)
 
 sqlite3.h:     $(TOP)/src/sqlite.h.in 
        sed -e s/--VERS--/`cat ${TOP}/VERSION`/ \
-            -e s/--ENCODING--/$(ENCODING)/ \
+           -e s/--VERSION-NUMBER--/`cat ${TOP}/VERSION | sed 's/[^0-9]/ /g' | awk '{printf "%d%03d%03d",$$1,$$2,$$3}'`/ \
                  $(TOP)/src/sqlite.h.in >sqlite3.h
 
 table.o:       $(TOP)/src/table.c $(HDR)
@@ -302,9 +301,13 @@ table.o:   $(TOP)/src/table.c $(HDR)
 tclsqlite.o:   $(TOP)/src/tclsqlite.c $(HDR)
        $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c
 
-tokenize.o:    $(TOP)/src/tokenize.c $(HDR)
+tokenize.o:    $(TOP)/src/tokenize.c keywordhash.h $(HDR)
        $(TCCX) -c $(TOP)/src/tokenize.c
 
+keywordhash.h: $(TOP)/tool/mkkeywordhash.c
+       $(BCC) -o mkkeywordhash $(OPTS) $(TOP)/tool/mkkeywordhash.c
+       ./mkkeywordhash >keywordhash.h
+
 trigger.o:     $(TOP)/src/trigger.c $(HDR)
        $(TCCX) -c $(TOP)/src/trigger.c
 
@@ -367,7 +370,7 @@ 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 -static -o \
+       $(TCCX) $(TCL_FLAGS) -DTCLSH=2 -DSQLITE_TEST=1 -o \
                sqlite3_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \
                libsqlite3.a $(LIBTCL) $(THREADLIB)
 
@@ -379,6 +382,9 @@ arch.html:  $(TOP)/www/arch.tcl
 arch.png:      $(TOP)/www/arch.png
        cp $(TOP)/www/arch.png .
 
+autoinc.html:  $(TOP)/www/autoinc.tcl
+       tclsh $(TOP)/www/autoinc.tcl >autoinc.html
+
 c_interface.html:      $(TOP)/www/c_interface.tcl
        tclsh $(TOP)/www/c_interface.tcl >c_interface.html
 
@@ -391,6 +397,9 @@ capi3ref.html:      $(TOP)/www/capi3ref.tcl
 changes.html:  $(TOP)/www/changes.tcl
        tclsh $(TOP)/www/changes.tcl >changes.html
 
+compile.html:  $(TOP)/www/compile.tcl
+       tclsh $(TOP)/www/compile.tcl >compile.html
+
 copyright.html:        $(TOP)/www/copyright.tcl
        tclsh $(TOP)/www/copyright.tcl >copyright.html
 
@@ -432,7 +441,10 @@ index.html:        $(TOP)/www/index.tcl last_change
        tclsh $(TOP)/www/index.tcl >index.html
 
 lang.html:     $(TOP)/www/lang.tcl
-       tclsh $(TOP)/www/lang.tcl >lang.html
+       tclsh $(TOP)/www/lang.tcl doc >lang.html
+
+pragma.html:   $(TOP)/www/pragma.tcl
+       tclsh $(TOP)/www/pragma.tcl >pragma.html
 
 lockingv3.html:        $(TOP)/www/lockingv3.tcl
        tclsh $(TOP)/www/lockingv3.tcl >lockingv3.html
@@ -476,16 +488,21 @@ vdbe.html:        $(TOP)/www/vdbe.tcl
 version3.html: $(TOP)/www/version3.tcl
        tclsh $(TOP)/www/version3.tcl >version3.html
 
+whentouse.html:        $(TOP)/www/whentouse.tcl
+       tclsh $(TOP)/www/whentouse.tcl >whentouse.html
+
 
 # Files to be published on the website.
 #
 DOC = \
   arch.html \
   arch.png \
+  autoinc.html \
   c_interface.html \
   capi3.html \
   capi3ref.html \
   changes.html \
+  compile.html \
   copyright.html \
   copyright-release.html \
   copyright-release.pdf \
@@ -505,6 +522,7 @@ DOC = \
   oldnews.html \
   omitted.html \
   opcode.html \
+  pragma.html \
   quickstart.html \
   speed.html \
   sqlite.gif \
@@ -512,7 +530,8 @@ DOC = \
   support.html \
   tclsqlite.html \
   vdbe.html \
-  version3.html
+  version3.html \
+  whentouse.html
 
 doc:   common.tcl $(DOC)
        mkdir -p doc
@@ -527,7 +546,7 @@ install:    sqlite3 libsqlite3.a sqlite3.h
 
 clean: 
        rm -f *.o sqlite3 libsqlite3.a sqlite3.h opcodes.*
-       rm -f lemon lempar.c parse.* sqlite*.tar.gz
+       rm -f lemon lempar.c parse.* sqlite*.tar.gz mkkeywordhash keywordhash.h
        rm -f $(PUBLISH)
        rm -f *.da *.bb *.bbg gmon.out
        rm -rf tsrc
index 6119272bd7326466ceb79b854b04c38632e662a6..bf6bfbeb3706470c3f8c5bc968f6c2030cdb7d4f 100644 (file)
 #
 BEGIN {
   print "/* Automatically generated.  Do not edit */"
-  print "/* See the mkopcodec.h script for details. */"
+  print "/* See the mkopcodec.awk script for details. */"
+  printf "#if !defined(SQLITE_OMIT_EXPLAIN)"
+  printf    " || !defined(NDEBUG)"
+  printf    " || defined(VDBE_PROFILE)"
+  print     " || defined(SQLITE_DEBUG)"
   print "const char *const sqlite3OpcodeNames[] = { \"?\","
 }
-/^#define OP_/ {
+/define OP_/ {
   sub("OP_","",$2)
-  print "  \"" $2 "\","
+  i++
+  printf " /* %3d */ \"%s\",\n", $3, $2
 }
 END {
   print "};"
+  print "#endif"
 }
index ead07d5ff9811a69ed574a170e9701b723034484..641b987a81e63764e8c9c84839d0f7049e68698a 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/awk -f
 #
+# Generate the file opcodes.h.
+#
 # This AWK script scans a concatenation of the parse.h output file from the
 # parser and the vdbe.c source file in order to generate the opcodes numbers
 # for all opcodes.  
 # 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
+# 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 generator run (infinitesimally) faster and more importantly it makes
+# the total library smaller.
+#
 
 # Remember the TK_ values from the parse.h file
 /^#define TK_/ {
@@ -28,6 +39,7 @@
     if($i=="same" && $(i+1)=="as"){
       op[name] = tk[$(i+2)]
       used[op[name]] = 1
+      sameas[op[name]] = $(i+2)
     }
   }
 }
@@ -35,6 +47,7 @@
 # Assign numbers to all opcodes and output the result.
 END {
   cnt = 0
+  max = 0
   print "/* Automatically generated.  Do not edit */"
   print "/* See the mkopcodeh.awk script for details */"
   for(name in op){
@@ -43,6 +56,23 @@ END {
       while( used[cnt] ) cnt++
       op[name] = cnt
     }
-    printf "#define %-30s %d\n", name, op[name]
+    used[op[name]] = 1;
+    if( op[name]>max ) max = op[name]
+    printf "#define %-25s %15d", name, op[name]
+    if( sameas[op[name]] ) {
+      printf "   /* same as %-12s*/", sameas[op[name]]
+    } 
+    printf "\n"
+
+  }
+  seenUnused = 0;
+  for(i=1; i<max; i++){
+    if( !used[i] ){
+      if( !seenUnused ){
+        printf "\n/* The following opcode values are never used */\n"
+        seenUnused = 1
+      }
+      printf "#define %-25s %15d\n", sprintf( "OP_NotUsed_%-3d", i ), i
+    }
   }
 }
index 9da593bfb645dd595af6cc6bf4ff384a33a61006..b26382c99a6b06c1f32b3c0a4e90abff5cc99471 100644 (file)
@@ -13,9 +13,11 @@ TCLDIR=/home/drh/tcltk/846/linux/846linux
 TCLSTUBLIB=$TCLDIR/libtclstub8.4g.a
 OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1'
 for i in *.c; do
-  CMD="cc -fPIC $OPTS -O2 -I. -I$TCLDIR -c $i"
-  echo $CMD
-  $CMD
+  if test $i != 'keywordhash.c'; then
+    CMD="cc -fPIC $OPTS -O2 -I. -I$TCLDIR -c $i"
+    echo $CMD
+    $CMD
+  fi
 done
 echo gcc -shared *.o $TCLSTUBLIB -o tclsqlite3.so
 gcc -shared *.o $TCLSTUBLIB -o tclsqlite3.so
index 7c45550bbaa15ae1b1797ab480da999a29735e1f..0a61d90ed2fdfc390f98d855a9f3fc8a0a8c0185 100644 (file)
@@ -75,8 +75,10 @@ cd ..
 ORIGIN=`pwd`
 cd $srcdir
 cd ..
-EXCLUDE=`find sqlite -print | grep CVS | sed 's,^, --exclude ,'`
-tar czf $ORIGIN/doc/sqlite-$VERS.tar.gz $EXCLUDE sqlite
+mv sqlite sqlite-$VERS
+EXCLUDE=`find sqlite-$VERS -print | grep CVS | sed 's,^, --exclude ,'`
+tar czf $ORIGIN/doc/sqlite-$VERS.tar.gz $EXCLUDE sqlite-$VERS
+mv sqlite-$VERS sqlite
 cd $ORIGIN
 
 #
diff --git a/ext/pdo_sqlite/sqlite/src/alter.c b/ext/pdo_sqlite/sqlite/src/alter.c
new file mode 100644 (file)
index 0000000..199cdca
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+** 2005 February 15
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains C code routines that used to generate VDBE code
+** that implements the ALTER TABLE command.
+**
+** $Id$
+*/
+#include "sqliteInt.h"
+
+/*
+** The code in this file only exists if we are not omitting the
+** ALTER TABLE logic from the build.
+*/
+#ifndef SQLITE_OMIT_ALTERTABLE
+
+
+/*
+** This function is used by SQL generated to implement the 
+** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
+** CREATE INDEX command. The second is a table name. The table name in 
+** the CREATE TABLE or CREATE INDEX statement is replaced with the second
+** argument and the result returned. Examples:
+**
+** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
+**     -> 'CREATE TABLE def(a, b, c)'
+**
+** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
+**     -> 'CREATE INDEX i ON def(a, b, c)'
+*/
+static void renameTableFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  unsigned char const *zSql = sqlite3_value_text(argv[0]);
+  unsigned char const *zTableName = sqlite3_value_text(argv[1]);
+
+  int token;
+  Token tname;
+  char const *zCsr = zSql;
+  int len = 0;
+  char *zRet;
+
+  /* The principle used to locate the table name in the CREATE TABLE 
+  ** statement is that the table name is the first token that is immediatedly
+  ** followed by a left parenthesis - TK_LP.
+  */
+  if( zSql ){
+    do {
+      /* Store the token that zCsr points to in tname. */
+      tname.z = zCsr;
+      tname.n = len;
+
+      /* Advance zCsr to the next token. Store that token type in 'token',
+      ** and it's length in 'len' (to be used next iteration of this loop).
+      */
+      do {
+        zCsr += len;
+        len = sqlite3GetToken(zCsr, &token);
+      } while( token==TK_SPACE );
+      assert( len>0 );
+    } while( token!=TK_LP );
+
+    zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql, 
+       zTableName, tname.z+tname.n);
+    sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
+  }
+}
+
+#ifndef SQLITE_OMIT_TRIGGER
+/* This function is used by SQL generated to implement the ALTER TABLE
+** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER 
+** statement. The second is a table name. The table name in the CREATE 
+** TRIGGER statement is replaced with the second argument and the result 
+** returned. This is analagous to renameTableFunc() above, except for CREATE
+** TRIGGER, not CREATE INDEX and CREATE TABLE.
+*/
+static void renameTriggerFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  unsigned char const *zSql = sqlite3_value_text(argv[0]);
+  unsigned char const *zTableName = sqlite3_value_text(argv[1]);
+
+  int token;
+  Token tname;
+  int dist = 3;
+  char const *zCsr = zSql;
+  int len = 0;
+  char *zRet;
+
+  /* The principle used to locate the table name in the CREATE TRIGGER 
+  ** statement is that the table name is the first token that is immediatedly
+  ** preceded by either TK_ON or TK_DOT and immediatedly followed by one
+  ** of TK_WHEN, TK_BEGIN or TK_FOR.
+  */
+  if( zSql ){
+    do {
+      /* Store the token that zCsr points to in tname. */
+      tname.z = zCsr;
+      tname.n = len;
+
+      /* Advance zCsr to the next token. Store that token type in 'token',
+      ** and it's length in 'len' (to be used next iteration of this loop).
+      */
+      do {
+        zCsr += len;
+        len = sqlite3GetToken(zCsr, &token);
+      }while( token==TK_SPACE );
+      assert( len>0 );
+
+      /* Variable 'dist' stores the number of tokens read since the most
+      ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN 
+      ** token is read and 'dist' equals 2, the condition stated above
+      ** to be met.
+      **
+      ** Note that ON cannot be a database, table or column name, so
+      ** there is no need to worry about syntax like 
+      ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
+      */
+      dist++;
+      if( token==TK_DOT || token==TK_ON ){
+        dist = 0;
+      }
+    } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
+
+    /* Variable tname now contains the token that is the old table-name
+    ** in the CREATE TRIGGER statement.
+    */
+    zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql, 
+       zTableName, tname.z+tname.n);
+    sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
+  }
+}
+#endif   /* !SQLITE_OMIT_TRIGGER */
+
+/*
+** Register built-in functions used to help implement ALTER TABLE
+*/
+void sqlite3AlterFunctions(sqlite3 *db){
+  static const struct {
+     char *zName;
+     signed char nArg;
+     void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
+  } aFuncs[] = {
+    { "sqlite_rename_table",    2, renameTableFunc},
+#ifndef SQLITE_OMIT_TRIGGER
+    { "sqlite_rename_trigger",  2, renameTriggerFunc},
+#endif
+  };
+  int i;
+
+  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
+    sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
+        SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
+  }
+}
+
+/*
+** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" 
+** command. 
+*/
+void sqlite3AlterRenameTable(
+  Parse *pParse,            /* Parser context. */
+  SrcList *pSrc,            /* The table to rename. */
+  Token *pName              /* The new table name. */
+){
+  int iDb;                  /* Database that contains the table */
+  char *zDb;                /* Name of database iDb */
+  Table *pTab;              /* Table being renamed */
+  char *zName = 0;          /* NULL-terminated version of pName */ 
+  char *zWhere = 0;         /* Where clause of schema elements to reparse */
+  sqlite3 *db = pParse->db; /* Database connection */
+  Vdbe *v;
+#ifndef SQLITE_OMIT_TRIGGER
+  char *zTempTrig = 0;      /* Where clause to locate temp triggers */
+#endif
+  
+  assert( pSrc->nSrc==1 );
+
+  pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+  if( !pTab ) goto exit_rename_table;
+  iDb = pTab->iDb;
+  zDb = db->aDb[iDb].zName;
+
+  /* Get a NULL terminated version of the new table name. */
+  zName = sqlite3NameFromToken(pName);
+  if( !zName ) goto exit_rename_table;
+
+  /* Check that a table or index named 'zName' does not already exist
+  ** in database iDb. If so, this is an error.
+  */
+  if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
+    sqlite3ErrorMsg(pParse, 
+        "there is already another table or index with this name: %s", zName);
+    goto exit_rename_table;
+  }
+
+  /* Make sure it is not a system table being altered, or a reserved name
+  ** that the table is being renamed to.
+  */
+  if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){
+    sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
+    goto exit_rename_table;
+  }
+  if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+    goto exit_rename_table;
+  }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+  /* Invoke the authorization callback. */
+  if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
+    goto exit_rename_table;
+  }
+#endif
+
+  /* Begin a transaction and code the VerifyCookie for database iDb. 
+  ** Then modify the schema cookie (since the ALTER TABLE modifies the
+  ** schema).
+  */
+  v = sqlite3GetVdbe(pParse);
+  if( v==0 ){
+    goto exit_rename_table;
+  }
+  sqlite3BeginWriteOperation(pParse, 0, iDb);
+  sqlite3ChangeCookie(db, v, iDb);
+
+  /* Modify the sqlite_master table to use the new table name. */
+  sqlite3NestedParse(pParse,
+      "UPDATE %Q.%s SET "
+#ifdef SQLITE_OMIT_TRIGGER
+          "sql = sqlite_rename_table(sql, %Q), "
+#else
+          "sql = CASE "
+            "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
+            "ELSE sqlite_rename_table(sql, %Q) END, "
+#endif
+          "tbl_name = %Q, "
+          "name = CASE "
+            "WHEN type='table' THEN %Q "
+            "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
+              "'sqlite_autoindex_' || %Q || substr(name, %d+18,10) "
+            "ELSE name END "
+      "WHERE tbl_name=%Q AND "
+          "(type='table' OR type='index' OR type='trigger');", 
+      zDb, SCHEMA_TABLE(iDb), zName, zName, zName, 
+#ifndef SQLITE_OMIT_TRIGGER
+zName,
+#endif
+      zName, strlen(pTab->zName), pTab->zName
+  );
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+  /* If the sqlite_sequence table exists in this database, then update 
+  ** it with the new table name.
+  */
+  if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
+    sqlite3NestedParse(pParse,
+        "UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q",
+        zDb, zName, pTab->zName);
+  }
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
+  /* If there are TEMP triggers on this table, modify the sqlite_temp_master
+  ** table. Don't do this if the table being ALTERed is itself located in
+  ** the temp database.
+  */
+  if( iDb!=1 ){
+    Trigger *pTrig;
+    char *tmp = 0;
+    for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
+      if( pTrig->iDb==1 ){
+        if( !zTempTrig ){
+          zTempTrig = 
+              sqlite3MPrintf("type = 'trigger' AND (name=%Q", pTrig->name);
+        }else{
+          tmp = zTempTrig;
+          zTempTrig = sqlite3MPrintf("%s OR name=%Q", zTempTrig, pTrig->name);
+          sqliteFree(tmp);
+        }
+      }
+    }
+    if( zTempTrig ){
+      tmp = zTempTrig;
+      zTempTrig = sqlite3MPrintf("%s)", zTempTrig);
+      sqliteFree(tmp);
+      sqlite3NestedParse(pParse, 
+          "UPDATE sqlite_temp_master SET "
+              "sql = sqlite_rename_trigger(sql, %Q), "
+              "tbl_name = %Q "
+              "WHERE %s;", zName, zName, zTempTrig);
+    }
+  }
+#endif
+
+  /* Drop the elements of the in-memory schema that refered to the table
+  ** renamed and load the new versions from the database.
+  */
+  if( pParse->nErr==0 ){
+#ifndef SQLITE_OMIT_TRIGGER
+    Trigger *pTrig;
+    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);
+    }
+#endif
+    sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
+    zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
+    sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
+#ifndef SQLITE_OMIT_TRIGGER
+    if( zTempTrig ){
+      sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zTempTrig, P3_DYNAMIC);
+    }
+  }else{
+    sqliteFree(zTempTrig);
+#endif
+  }
+
+exit_rename_table:
+  sqlite3SrcListDelete(pSrc);
+  sqliteFree(zName);
+}
+#endif  /* SQLITE_ALTER_TABLE */
index 2f0899865cc04fd79054d880255e9e8a1ce8b00a..79c325f4c194c9b7f498ac64d19d83cbf0d24030 100644 (file)
@@ -38,6 +38,7 @@ void sqlite3Attach(
 
   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;
@@ -160,6 +161,7 @@ void sqlite3Detach(Parse *pParse, Token *pDbname){
 
   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;
@@ -251,11 +253,14 @@ int sqlite3FixSrcList(
          pFix->zType, pFix->pName, pItem->zDatabase);
       return 1;
     }
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
     if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
     if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
+#endif
   }
   return 0;
 }
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
 int sqlite3FixSelect(
   DbFixer *pFix,       /* Context of the fixation */
   Select *pSelect      /* The SELECT statement to be fixed to one database */
@@ -309,6 +314,9 @@ int sqlite3FixExprList(
   }
   return 0;
 }
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
 int sqlite3FixTriggerStep(
   DbFixer *pFix,     /* Context of the fixation */
   TriggerStep *pStep /* The trigger step be fixed to one database */
@@ -327,3 +335,4 @@ int sqlite3FixTriggerStep(
   }
   return 0;
 }
+#endif
index b251eacfdf4f2f3f25285cf9991076e1bd1d8829..d4b7a61bd38d035348731a135e094264a235dcec 100644 (file)
@@ -76,6 +76,7 @@ int sqlite3_set_authorizer(
 ){
   db->xAuth = xAuth;
   db->pAuthArg = pArg;
+  sqlite3ExpirePreparedStatements(db);
   return SQLITE_OK;
 }
 
@@ -114,10 +115,10 @@ void sqlite3AuthRead(
 
   if( db->xAuth==0 ) return;
   assert( pExpr->op==TK_COLUMN );
-  for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
+  for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){
     if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
   }
-  if( iSrc>=0 && iSrc<pTabList->nSrc ){
+  if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){
     pTab = pTabList->a[iSrc].pTab;
   }else if( (pStack = pParse->trigStack)!=0 ){
     /* This must be an attempt to read the NEW or OLD pseudo-tables
index fe8754e01df46c6c6937ddda3a4a90ae85a08d39..b4ea019b6eb8efb8c55f221ccecede8698fbff8a 100644 (file)
 #include "os.h"
 #include <assert.h>
 
+/*
+** This macro rounds values up so that if the value is an address it
+** is guaranteed to be an address that is aligned to an 8-byte boundary.
+*/
+#define FORCE_ALIGNMENT(X)   (((X)+7)&~7)
 
 /* The following value is the maximum cell size assuming a maximum page
 ** size give above.
@@ -299,7 +304,11 @@ struct Btree {
   u8 minEmbedFrac;      /* Minimum payload as % of total page size */
   u8 minLeafFrac;       /* Minimum leaf payload as % of total page size */
   u8 pageSizeFixed;     /* True if the page size can no longer be changed */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  u8 autoVacuum;        /* True if database supports auto-vacuum */
+#endif
   u16 pageSize;         /* Total number of bytes on a page */
+  u16 psAligned;        /* pageSize rounded up to a multiple of 8 */
   u16 usableSize;       /* Number of usable bytes on each page */
   int maxLocal;         /* Maximum local payload in non-LEAFDATA tables */
   int minLocal;         /* Minimum local payload in non-LEAFDATA tables */
@@ -347,15 +356,26 @@ struct BtCursor {
   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 status;                /* Set to SQLITE_ABORT if cursors is invalidated */
 };
 
+/*
+** The TRACE macro will print high-level status information about the
+** btree operation when the global variable sqlite3_btree_trace is
+** enabled.
+*/
+#if SQLITE_TEST
+# define TRACE(X)   if( sqlite3_btree_trace )\
+                        { sqlite3DebugPrintf X; fflush(stdout); }
+#else
+# define TRACE(X)
+#endif
+int sqlite3_btree_trace=0;  /* True to enable tracing */
+
 /*
 ** Forward declaration
 */
 static int checkReadLocks(Btree*,Pgno,BtCursor*);
 
-
 /*
 ** Read or write a two- and four-byte big-endian integer values.
 */
@@ -385,6 +405,136 @@ static void put4byte(unsigned char *p, u32 v){
 #define getVarint32  sqlite3GetVarint32
 #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).
+*/
+#define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1)
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** These macros define the location of the pointer-map entry for a 
+** database page. The first argument to each is the number of usable
+** bytes on each page of the database (often 1024). The second is the
+** page number to look up in the pointer map.
+**
+** PTRMAP_PAGENO returns the database page number of the pointer-map
+** page that stores the required pointer. PTRMAP_PTROFFSET returns
+** the offset of the requested map entry.
+**
+** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page,
+** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be
+** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
+** this test.
+*/
+#define PTRMAP_PAGENO(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)
+
+/*
+** The pointer map is a lookup table that identifies the parent page for
+** each child page in the database file.  The parent page is the page that
+** contains a pointer to the child.  Every page in the database contains
+** 0 or 1 parent pages.  (In this context 'database page' refers
+** to any page that is not part of the pointer map itself.)  Each pointer map
+** entry consists of a single byte 'type' and a 4 byte parent page number.
+** The PTRMAP_XXX identifiers below are the valid types.
+**
+** The purpose of the pointer map is to facility moving pages from one
+** position in the file to another as part of autovacuum.  When a page
+** is moved, the pointer in its parent must be updated to point to the
+** new location.  The pointer map is used to locate the parent page quickly.
+**
+** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
+**                  used in this case.
+**
+** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number 
+**                  is not used in this case.
+**
+** PTRMAP_OVERFLOW1: The database page is the first page in a list of 
+**                   overflow pages. The page number identifies the page that
+**                   contains the cell with a pointer to this overflow page.
+**
+** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of
+**                   overflow pages. The page-number identifies the previous
+**                   page in the overflow page list.
+**
+** PTRMAP_BTREE: The database page is a non-root btree page. The page number
+**               identifies the parent page in the btree.
+*/
+#define PTRMAP_ROOTPAGE 1
+#define PTRMAP_FREEPAGE 2
+#define PTRMAP_OVERFLOW1 3
+#define PTRMAP_OVERFLOW2 4
+#define PTRMAP_BTREE 5
+
+/*
+** Write an entry into the pointer map.
+**
+** This routine updates the pointer map entry for page number 'key'
+** so that it maps to type 'eType' and parent page number 'pgno'.
+** An error code is returned if something goes wrong, otherwise SQLITE_OK.
+*/
+static int ptrmapPut(Btree *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;
+
+  assert( pBt->autoVacuum );
+  if( key==0 ){
+    return SQLITE_CORRUPT;
+  }
+  iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key);
+  rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap);
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+  offset = PTRMAP_PTROFFSET(pBt->usableSize, key);
+
+  if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){
+    TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent));
+    rc = sqlite3pager_write(pPtrmap);
+    if( rc==SQLITE_OK ){
+      pPtrmap[offset] = eType;
+      put4byte(&pPtrmap[offset+1], parent);
+    }
+  }
+
+  sqlite3pager_unref(pPtrmap);
+  return rc;
+}
+
+/*
+** Read an entry from the pointer map.
+**
+** This routine retrieves the pointer map entry for page 'key', writing
+** the type and parent page number to *pEType and *pPgno respectively.
+** An error code is returned if something goes wrong, otherwise SQLITE_OK.
+*/
+static int ptrmapGet(Btree *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);
+  rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap);
+  if( rc!=0 ){
+    return rc;
+  }
+
+  offset = PTRMAP_PTROFFSET(pBt->usableSize, key);
+  if( pEType ) *pEType = pPtrmap[offset];
+  if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
+
+  sqlite3pager_unref(pPtrmap);
+  if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT;
+  return SQLITE_OK;
+}
+
+#endif /* SQLITE_OMIT_AUTOVACUUM */
+
 /*
 ** Given a btree page and a cell index (0 means the first cell on
 ** the page, 1 means the second cell, and so forth) return a pointer
@@ -514,6 +664,36 @@ static int cellSizePtr(MemPage *pPage, u8 *pCell){
   return info.nSize;
 }
 
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** If the cell pCell, part of page pPage contains a pointer
+** to an overflow page, insert an entry into the pointer-map
+** for the overflow page.
+*/
+static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){
+  if( pCell ){
+    CellInfo info;
+    parseCellPtr(pPage, pCell, &info);
+    if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){
+      Pgno ovfl = get4byte(&pCell[info.iOverflow]);
+      return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno);
+    }
+  }
+  return SQLITE_OK;
+}
+/*
+** If the cell with index iCell on page pPage contains a pointer
+** to an overflow page, insert an entry into the pointer-map
+** for the overflow page.
+*/
+static int ptrmapPutOvfl(MemPage *pPage, int iCell){
+  u8 *pCell;
+  pCell = findOverflowCell(pPage, iCell);
+  return ptrmapPutOvflPtr(pPage, pCell);
+}
+#endif
+
+
 /*
 ** Do sanity checking on a page.  Throw an exception if anything is
 ** not right.
@@ -533,7 +713,7 @@ static void _pageIntegrity(MemPage *pPage){
   used = sqliteMallocRaw( pPage->pBt->pageSize );
   if( used==0 ) return;
   usableSize = pPage->pBt->usableSize;
-  assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] );
+  assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->psAligned] );
   hdr = pPage->hdrOffset;
   assert( hdr==(pPage->pgno==1 ? 100 : 0) );
   assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
@@ -824,7 +1004,6 @@ static int initPage(
   MemPage *pParent       /* The parent.  Might be NULL */
 ){
   int pc;            /* Address of a freeblock within pPage->aData[] */
-  int i;             /* Loop counter */
   int hdr;           /* Offset to beginning of page header */
   u8 *data;          /* Equal to pPage->aData */
   Btree *pBt;        /* The main btree structure */
@@ -837,7 +1016,7 @@ static int initPage(
   assert( pBt!=0 );
   assert( pParent==0 || pParent->pBt==pBt );
   assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
-  assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] );
+  assert( pPage->aData == &((unsigned char*)pPage)[-pBt->psAligned] );
   if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
     /* The parent page should never change unless the file is corrupt */
     return SQLITE_CORRUPT; /* bkpt-CORRUPT */
@@ -868,17 +1047,12 @@ static int initPage(
   /* Compute the total free space on the page */
   pc = get2byte(&data[hdr+1]);
   nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);
-  i = 0;
   while( pc>0 ){
     int next, size;
     if( pc>usableSize-4 ){
       /* Free block is off the page */
       return SQLITE_CORRUPT;  /* bkpt-CORRUPT */
     }
-    if( i++>SQLITE_MAX_PAGE_SIZE/4 ){
-      /* The free block list forms an infinite loop */
-      return SQLITE_CORRUPT;  /* bkpt-CORRUPT */
-    }
     next = get2byte(&data[pc]);
     size = get2byte(&data[pc+2]);
     if( next>0 && next<=pc+size+3 ){
@@ -910,7 +1084,7 @@ static void zeroPage(MemPage *pPage, int flags){
   int first;
 
   assert( sqlite3pager_pagenumber(data)==pPage->pgno );
-  assert( &data[pBt->pageSize] == (unsigned char*)pPage );
+  assert( &data[pBt->psAligned] == (unsigned char*)pPage );
   assert( sqlite3pager_iswriteable(data) );
   memset(&data[hdr], 0, pBt->usableSize - hdr);
   data[hdr] = flags;
@@ -939,7 +1113,7 @@ static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){
   MemPage *pPage;
   rc = sqlite3pager_get(pBt->pPager, pgno, (void**)&aData);
   if( rc ) return rc;
-  pPage = (MemPage*)&aData[pBt->pageSize];
+  pPage = (MemPage*)&aData[pBt->psAligned];
   pPage->aData = aData;
   pPage->pBt = pBt;
   pPage->pgno = pgno;
@@ -978,7 +1152,7 @@ static void releasePage(MemPage *pPage){
   if( pPage ){
     assert( pPage->aData );
     assert( pPage->pBt );
-    assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage );
+    assert( &pPage->aData[pPage->pBt->psAligned]==(unsigned char*)pPage );
     sqlite3pager_unref(pPage->aData);
   }
 }
@@ -989,7 +1163,7 @@ static void releasePage(MemPage *pPage){
 ** happens.
 */
 static void pageDestructor(void *pData, int pageSize){
-  MemPage *pPage = (MemPage*)&((char*)pData)[pageSize];
+  MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)];
   if( pPage->pParent ){
     MemPage *pParent = pPage->pParent;
     pPage->pParent = 0;
@@ -1007,7 +1181,7 @@ static void pageDestructor(void *pData, int pageSize){
 ** page to agree with the restored data.
 */
 static void pageReinit(void *pData, int pageSize){
-  MemPage *pPage = (MemPage*)&((char*)pData)[pageSize];
+  MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)];
   if( pPage->isInit ){
     pPage->isInit = 0;
     initPage(pPage, pPage->pParent);
@@ -1049,8 +1223,7 @@ int sqlite3BtreeOpen(
     *ppBtree = 0;
     return SQLITE_NOMEM;
   }
-  rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE,
-                        (flags & BTREE_OMIT_JOURNAL)==0);
+  rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, flags);
   if( rc!=SQLITE_OK ){
     if( pBt->pPager ) sqlite3pager_close(pBt->pPager);
     sqliteFree(pBt);
@@ -1069,6 +1242,21 @@ int sqlite3BtreeOpen(
     pBt->maxEmbedFrac = 64;   /* 25% */
     pBt->minEmbedFrac = 32;   /* 12.5% */
     pBt->minLeafFrac = 32;    /* 12.5% */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    /* If the magic name ":memory:" will create an in-memory database, then
+    ** do not set the auto-vacuum flag, even if SQLITE_DEFAULT_AUTOVACUUM
+    ** is true. On the other hand, if SQLITE_OMIT_MEMORYDB has been defined,
+    ** then ":memory:" is just a regular file-name. Respect the auto-vacuum
+    ** default in this case.
+    */
+#ifndef SQLITE_OMIT_MEMORYDB
+    if( zFilename && strcmp(zFilename,":memory:") ){
+#else
+    if( zFilename ){
+#endif
+      pBt->autoVacuum = SQLITE_DEFAULT_AUTOVACUUM;
+    }
+#endif
     nReserve = 0;
   }else{
     nReserve = zDbHeader[20];
@@ -1076,8 +1264,12 @@ int sqlite3BtreeOpen(
     pBt->minEmbedFrac = zDbHeader[22];
     pBt->minLeafFrac = zDbHeader[23];
     pBt->pageSizeFixed = 1;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);
+#endif
   }
   pBt->usableSize = pBt->pageSize - nReserve;
+  pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize);
   sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize);
   *ppBtree = pBt;
   return SQLITE_OK;
@@ -1131,13 +1323,28 @@ int sqlite3BtreeSetCacheSize(Btree *pBt, int mxPage){
 ** is a very low but non-zero probability of damage.  Level 3 reduces the
 ** probability of damage to near zero but with a write performance reduction.
 */
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
 int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){
   sqlite3pager_set_safety_level(pBt->pPager, level);
   return SQLITE_OK;
 }
+#endif
 
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
 /*
 ** Change the default pages size and the number of reserved bytes per page.
+**
+** The page size must be a power of 2 between 512 and 65536.  If the page
+** size supplied does not meet this constraint then the page size is not
+** changed.
+**
+** Page sizes are constrained to be a power of two so that the region
+** of the database file used for locking (beginning at PENDING_BYTE,
+** the first byte past the 1GB boundary, 0x40000000) needs to occur
+** at the beginning of a page.
+**
+** If parameter nReserve is less than zero, then the number of reserved
+** bytes per page is left unchanged.
 */
 int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){
   if( pBt->pageSizeFixed ){
@@ -1146,8 +1353,10 @@ int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){
   if( nReserve<0 ){
     nReserve = pBt->pageSize - pBt->usableSize;
   }
-  if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ){
+  if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
+        ((pageSize-1)&pageSize)==0 ){
     pBt->pageSize = pageSize;
+    pBt->psAligned = FORCE_ALIGNMENT(pageSize);
     sqlite3pager_set_pagesize(pBt->pPager, pageSize);
   }
   pBt->usableSize = pBt->pageSize - nReserve;
@@ -1163,6 +1372,38 @@ int sqlite3BtreeGetPageSize(Btree *pBt){
 int sqlite3BtreeGetReserve(Btree *pBt){
   return pBt->pageSize - pBt->usableSize;
 }
+#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */
+
+/*
+** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
+** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it
+** is disabled. The default value for the auto-vacuum property is 
+** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.
+*/
+int sqlite3BtreeSetAutoVacuum(Btree *pBt, int autoVacuum){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+  return SQLITE_READONLY;
+#else
+  if( pBt->pageSizeFixed ){
+    return SQLITE_READONLY;
+  }
+  pBt->autoVacuum = (autoVacuum?1:0);
+  return SQLITE_OK;
+#endif
+}
+
+/*
+** Return the value of the 'auto-vacuum' property. If auto-vacuum is 
+** enabled 1 is returned. Otherwise 0.
+*/
+int sqlite3BtreeGetAutoVacuum(Btree *pBt){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+  return 0;
+#else
+  return pBt->autoVacuum;
+#endif
+}
+
 
 /*
 ** Get a reference to pPage1 of the database file.  This will
@@ -1199,9 +1440,13 @@ static int lockBtree(Btree *pBt){
     if( pBt->usableSize<500 ){
       goto page1_init_failed;
     }
+    pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize);
     pBt->maxEmbedFrac = page1[21];
     pBt->minEmbedFrac = page1[22];
     pBt->minLeafFrac = page1[23];
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0);
+#endif
   }
 
   /* maxLocal is the maximum amount of payload to store locally for
@@ -1248,7 +1493,7 @@ static void unlockBtreeIfUnused(Btree *pBt){
   if( pBt->inTrans==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 = &((char*)pPage)[-pBt->psAligned];
       pPage->pBt = pBt;
       pPage->pgno = 1;
     }
@@ -1284,6 +1529,11 @@ static int newDatabase(Btree *pBt){
   memset(&data[24], 0, 100-24);
   zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );
   pBt->pageSizeFixed = 1;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  if( pBt->autoVacuum ){
+    put4byte(&data[36 + 4*4], 1);
+  }
+#endif
   return SQLITE_OK;
 }
 
@@ -1348,6 +1598,304 @@ int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){
   return rc;
 }
 
+#ifndef SQLITE_OMIT_AUTOVACUUM
+
+/*
+** Set the pointer-map entries for all children of page pPage. Also, if
+** pPage contains cells that point to overflow pages, set the pointer
+** map entries for the overflow pages as well.
+*/
+static int setChildPtrmaps(MemPage *pPage){
+  int i;                             /* Counter variable */
+  int nCell;                         /* Number of cells in page pPage */
+  int rc = SQLITE_OK;                /* Return code */
+  Btree *pBt = pPage->pBt;
+  int isInitOrig = pPage->isInit;
+  Pgno pgno = pPage->pgno;
+
+  initPage(pPage, 0);
+  nCell = pPage->nCell;
+
+  for(i=0; i<nCell; i++){
+    u8 *pCell = findCell(pPage, i);
+
+    rc = ptrmapPutOvflPtr(pPage, pCell);
+    if( rc!=SQLITE_OK ){
+      goto set_child_ptrmaps_out;
+    }
+
+    if( !pPage->leaf ){
+      Pgno childPgno = get4byte(pCell);
+      rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno);
+      if( rc!=SQLITE_OK ) goto set_child_ptrmaps_out;
+    }
+  }
+
+  if( !pPage->leaf ){
+    Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+    rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno);
+  }
+
+set_child_ptrmaps_out:
+  pPage->isInit = isInitOrig;
+  return rc;
+}
+
+/*
+** Somewhere on pPage, which is guarenteed to be a btree page, not an overflow
+** page, is a pointer to page iFrom. Modify this pointer so that it points to
+** iTo. Parameter eType describes the type of pointer to be modified, as 
+** follows:
+**
+** PTRMAP_BTREE:     pPage is a btree-page. The pointer points at a child 
+**                   page of pPage.
+**
+** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow
+**                   page pointed to by one of the cells on pPage.
+**
+** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next
+**                   overflow page in the list.
+*/
+static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
+  if( eType==PTRMAP_OVERFLOW2 ){
+    /* The pointer is always the first 4 bytes of the page in this case.  */
+    if( get4byte(pPage->aData)!=iFrom ){
+      return SQLITE_CORRUPT;
+    }
+    put4byte(pPage->aData, iTo);
+  }else{
+    int isInitOrig = pPage->isInit;
+    int i;
+    int nCell;
+
+    initPage(pPage, 0);
+    nCell = pPage->nCell;
+
+    for(i=0; i<nCell; i++){
+      u8 *pCell = findCell(pPage, i);
+      if( eType==PTRMAP_OVERFLOW1 ){
+        CellInfo info;
+        parseCellPtr(pPage, pCell, &info);
+        if( info.iOverflow ){
+          if( iFrom==get4byte(&pCell[info.iOverflow]) ){
+            put4byte(&pCell[info.iOverflow], iTo);
+            break;
+          }
+        }
+      }else{
+        if( get4byte(pCell)==iFrom ){
+          put4byte(pCell, iTo);
+          break;
+        }
+      }
+    }
+  
+    if( i==nCell ){
+      if( eType!=PTRMAP_BTREE || 
+          get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
+        return SQLITE_CORRUPT;
+      }
+      put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
+    }
+
+    pPage->isInit = isInitOrig;
+  }
+  return SQLITE_OK;
+}
+
+
+/*
+** Move the open database page pDbPage to location iFreePage in the 
+** database. The pDbPage reference remains valid.
+*/
+static int relocatePage(
+  Btree *pBt,              /* Btree */
+  MemPage *pDbPage,        /* Open page to move */
+  u8 eType,                /* Pointer map 'type' entry for pDbPage */
+  Pgno iPtrPage,           /* Pointer map 'page-no' entry for pDbPage */
+  Pgno iFreePage           /* The location to move pDbPage to */
+){
+  MemPage *pPtrPage;   /* The page that contains a pointer to pDbPage */
+  Pgno iDbPage = pDbPage->pgno;
+  Pager *pPager = pBt->pPager;
+  int rc;
+
+  assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || 
+      eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
+
+  /* Move page iDbPage from it's current location to page number iFreePage */
+  TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", 
+      iDbPage, iFreePage, iPtrPage, eType));
+  rc = sqlite3pager_movepage(pPager, pDbPage->aData, iFreePage);
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+  pDbPage->pgno = iFreePage;
+
+  /* If pDbPage was a btree-page, then it may have child pages and/or cells
+  ** that point to overflow pages. The pointer map entries for all these
+  ** pages need to be changed.
+  **
+  ** If pDbPage is an overflow page, then the first 4 bytes may store a
+  ** pointer to a subsequent overflow page. If this is the case, then
+  ** the pointer map needs to be updated for the subsequent overflow page.
+  */
+  if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){
+    rc = setChildPtrmaps(pDbPage);
+    if( rc!=SQLITE_OK ){
+      return rc;
+    }
+  }else{
+    Pgno nextOvfl = get4byte(pDbPage->aData);
+    if( nextOvfl!=0 ){
+      rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage);
+      if( rc!=SQLITE_OK ){
+        return rc;
+      }
+    }
+  }
+
+  /* Fix the database pointer on page iPtrPage that pointed at iDbPage so
+  ** that it points at iFreePage. Also fix the pointer map entry for
+  ** iPtrPage.
+  */
+  if( eType!=PTRMAP_ROOTPAGE ){
+    rc = getPage(pBt, iPtrPage, &pPtrPage);
+    if( rc!=SQLITE_OK ){
+      return rc;
+    }
+    rc = sqlite3pager_write(pPtrPage->aData);
+    if( rc!=SQLITE_OK ){
+      releasePage(pPtrPage);
+      return rc;
+    }
+    rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);
+    releasePage(pPtrPage);
+    if( rc==SQLITE_OK ){
+      rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage);
+    }
+  }
+  return rc;
+}
+
+/* Forward declaration required by autoVacuumCommit(). */
+static int allocatePage(Btree *, 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){
+  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 */
+  u8 eType;
+  int pgsz = pBt->pageSize;  /* Page size for this database */
+  Pgno iDbPage;              /* The database page to move */
+  MemPage *pDbMemPage = 0;   /* "" */
+  Pgno iPtrPage;             /* The page that contains a pointer to iDbPage */
+  Pgno iFreePage;            /* The free-list page to move iDbPage to */
+  MemPage *pFreeMemPage = 0; /* "" */
+
+#ifndef NDEBUG
+  int nRef = *sqlite3pager_stats(pPager);
+#endif
+
+  assert( pBt->autoVacuum );
+  if( PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) ){
+    return SQLITE_CORRUPT;
+  }
+
+  /* Figure out how many free-pages are in the database. If there are no
+  ** free pages, then auto-vacuum is a no-op.
+  */
+  nFreeList = get4byte(&pBt->pPage1->aData[36]);
+  if( nFreeList==0 ){
+    *nTrunc = 0;
+    return SQLITE_OK;
+  }
+
+  origSize = sqlite3pager_pagecount(pPager);
+  nPtrMap = (nFreeList-origSize+PTRMAP_PAGENO(pgsz, origSize)+pgsz/5)/(pgsz/5);
+  finSize = origSize - nFreeList - nPtrMap;
+  if( origSize>PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){
+    finSize--;
+    if( PTRMAP_ISPAGE(pBt->usableSize, finSize) ){
+      finSize--;
+    }
+  }
+  TRACE(("AUTOVACUUM: Begin (db size %d->%d)\n", origSize, finSize));
+
+  /* Variable 'finSize' will be the size of the file in pages after
+  ** the auto-vacuum has completed (the current file size minus the number
+  ** of pages on the free list). Loop through the pages that lie beyond
+  ** this mark, and if they are not already on the free list, move them
+  ** to a free page earlier in the file (somewhere before finSize).
+  */
+  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) ){
+      continue;
+    }
+
+    rc = ptrmapGet(pBt, iDbPage, &eType, &iPtrPage);
+    if( rc!=SQLITE_OK ) goto autovacuum_out;
+    assert( eType!=PTRMAP_ROOTPAGE );
+
+    /* If iDbPage is free, do not swap it.  */
+    if( eType==PTRMAP_FREEPAGE ){
+      continue;
+    }
+    rc = getPage(pBt, iDbPage, &pDbMemPage);
+    if( rc!=SQLITE_OK ) goto autovacuum_out;
+
+    /* Find the next page in the free-list that is not already at the end 
+    ** of the file. A page can be pulled off the free list using the 
+    ** allocatePage() routine.
+    */
+    do{
+      if( pFreeMemPage ){
+        releasePage(pFreeMemPage);
+        pFreeMemPage = 0;
+      }
+      rc = allocatePage(pBt, &pFreeMemPage, &iFreePage, 0, 0);
+      if( rc!=SQLITE_OK ){
+        releasePage(pDbMemPage);
+        goto autovacuum_out;
+      }
+      assert( iFreePage<=origSize );
+    }while( iFreePage>finSize );
+    releasePage(pFreeMemPage);
+    pFreeMemPage = 0;
+
+    rc = relocatePage(pBt, pDbMemPage, eType, iPtrPage, iFreePage);
+    releasePage(pDbMemPage);
+    if( rc!=SQLITE_OK ) goto autovacuum_out;
+  }
+
+  /* The entire free-list has been swapped to the end of the file. So
+  ** truncate the database file to finSize pages and consider the
+  ** free-list empty.
+  */
+  rc = sqlite3pager_write(pBt->pPage1->aData);
+  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;
+
+autovacuum_out:
+  assert( nRef==*sqlite3pager_stats(pPager) );
+  if( rc!=SQLITE_OK ){
+    sqlite3pager_rollback(pPager);
+  }
+  return rc;
+}
+#endif
+
 /*
 ** Commit the transaction currently in progress.
 **
@@ -1381,25 +1929,6 @@ static int countWriteCursors(Btree *pBt){
 }
 #endif
 
-#if 0
-/*
-** Invalidate all cursors
-*/
-static void invalidateCursors(Btree *pBt){
-  BtCursor *pCur;
-  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-    MemPage *pPage = pCur->pPage;
-    if( pPage /* && !pPage->isInit */ ){
-      pageIntegrity(pPage);
-      releasePage(pPage);
-      pCur->pPage = 0;
-      pCur->isValid = 0;
-      pCur->status = SQLITE_ABORT;
-    }
-  }
-}
-#endif
-
 #ifdef SQLITE_TEST
 /*
 ** Print debugging information about all cursors to standard output.
@@ -1618,7 +2147,6 @@ int sqlite3BtreeCursor(
   pCur->pPrev = 0;
   pBt->pCursor = pCur;
   pCur->isValid = 0;
-  pCur->status = SQLITE_OK;
   *ppCur = pCur;
   return SQLITE_OK;
 
@@ -1845,9 +2373,7 @@ static int getPayload(
 ** the available payload.
 */
 int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
-  if( pCur->isValid==0 ){
-    return pCur->status;
-  }
+  assert( pCur->isValid );
   assert( pCur->pPage!=0 );
   assert( pCur->pPage->intKey==0 );
   assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
@@ -1864,9 +2390,7 @@ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
 ** the available payload.
 */
 int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
-  if( !pCur->isValid ){
-    return pCur->status ? pCur->status : SQLITE_INTERNAL;
-  }
+  assert( pCur->isValid );
   assert( pCur->pPage!=0 );
   assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
   return getPayload(pCur, offset, amt, pBuf, 1);
@@ -2104,9 +2628,6 @@ static int moveToRightmost(BtCursor *pCur){
 */
 int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
   int rc;
-  if( pCur->status ){
-    return pCur->status;
-  }
   rc = moveToRoot(pCur);
   if( rc ) return rc;
   if( pCur->isValid==0 ){
@@ -2126,9 +2647,6 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
 */
 int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
   int rc;
-  if( pCur->status ){
-    return pCur->status;
-  }
   rc = moveToRoot(pCur);
   if( rc ) return rc;
   if( pCur->isValid==0 ){
@@ -2171,10 +2689,6 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
 */
 int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){
   int rc;
-
-  if( pCur->status ){
-    return pCur->status;
-  }
   rc = moveToRoot(pCur);
   if( rc ) return rc;
   assert( pCur->pPage );
@@ -2184,13 +2698,16 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){
     assert( pCur->pPage->nCell==0 );
     return SQLITE_OK;
   }
-  for(;;){
+   for(;;){
     int lwr, upr;
     Pgno chldPg;
     MemPage *pPage = pCur->pPage;
     int c = -1;  /* pRes return if table is empty must be -1 */
     lwr = 0;
     upr = pPage->nCell-1;
+    if( !pPage->intKey && pKey==0 ){
+      return SQLITE_CORRUPT;
+    }
     pageIntegrity(pPage);
     while( lwr<=upr ){
       void *pCellKey;
@@ -2288,6 +2805,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
   }
   assert( pPage->isInit );
   assert( pCur->idx<pPage->nCell );
+
   pCur->idx++;
   pCur->info.nSize = 0;
   if( pCur->idx>=pPage->nCell ){
@@ -2337,6 +2855,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
     *pRes = 1;
     return SQLITE_OK;
   }
+
   pPage = pCur->pPage;
   assert( pPage->isInit );
   assert( pCur->idx>=0 );
@@ -2357,7 +2876,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
     }
     pCur->idx--;
     pCur->info.nSize = 0;
-    if( pPage->leafData ){
+    if( pPage->leafData && !pPage->leaf ){
       rc = sqlite3BtreePrevious(pCur, pRes);
     }else{
       rc = SQLITE_OK;
@@ -2367,19 +2886,6 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
   return rc;
 }
 
-/*
-** The TRACE macro will print high-level status information about the
-** btree operation when the global variable sqlite3_btree_trace is
-** enabled.
-*/
-#if SQLITE_TEST
-# define TRACE(X)   if( sqlite3_btree_trace )\
-                        { sqlite3DebugPrintf X; fflush(stdout); }
-#else
-# define TRACE(X)
-#endif
-int sqlite3_btree_trace=0;  /* True to enable tracing */
-
 /*
 ** Allocate a new page from the database file.
 **
@@ -2396,8 +2902,18 @@ int sqlite3_btree_trace=0;  /* True to enable tracing */
 ** locate a page close to the page number "nearby".  This can be used in an
 ** attempt to keep related pages close to each other in the database file,
 ** which in turn can make database access faster.
+**
+** If the "exact" parameter is not 0, and the page-number nearby exists 
+** anywhere on the free-list, then it is guarenteed to be returned. This
+** is only used by auto-vacuum databases when allocating a new table.
 */
-static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
+static int allocatePage(
+  Btree *pBt, 
+  MemPage **ppPage, 
+  Pgno *pPgno, 
+  Pgno nearby,
+  u8 exact
+){
   MemPage *pPage1;
   int rc;
   int n;     /* Number of pages on the freelist */
@@ -2407,72 +2923,200 @@ static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
   n = get4byte(&pPage1->aData[36]);
   if( n>0 ){
     /* There are pages on the freelist.  Reuse one of those pages. */
-    MemPage *pTrunk;
+    MemPage *pTrunk = 0;
+    Pgno iTrunk;
+    MemPage *pPrevTrunk = 0;
+    u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
+    
+    /* If the 'exact' parameter was true and a query of the pointer-map
+    ** shows that the page 'nearby' is somewhere on the free-list, then
+    ** the entire-list will be searched for that page.
+    */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    if( exact ){
+      u8 eType;
+      assert( nearby>0 );
+      assert( pBt->autoVacuum );
+      rc = ptrmapGet(pBt, nearby, &eType, 0);
+      if( rc ) return rc;
+      if( eType==PTRMAP_FREEPAGE ){
+        searchList = 1;
+      }
+      *pPgno = nearby;
+    }
+#endif
+
+    /* Decrement the free-list count by 1. Set iTrunk to the index of the
+    ** first free-list trunk page. iPrevTrunk is initially 1.
+    */
     rc = sqlite3pager_write(pPage1->aData);
     if( rc ) return rc;
     put4byte(&pPage1->aData[36], n-1);
-    rc = getPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk);
-    if( rc ) return rc;
-    rc = sqlite3pager_write(pTrunk->aData);
-    if( rc ){
-      releasePage(pTrunk);
-      return rc;
-    }
-    k = get4byte(&pTrunk->aData[4]);
-    if( k==0 ){
-      /* The trunk has no leaves.  So extract the trunk page itself and
-      ** use it as the newly allocated page */
-      *pPgno = get4byte(&pPage1->aData[32]);
-      memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
-      *ppPage = pTrunk;
-      TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
-    }else if( k>pBt->usableSize/4 - 8 ){
-      /* Value of k is out of range.  Database corruption */
-      return SQLITE_CORRUPT; /* bkpt-CORRUPT */
-    }else{
-      /* Extract a leaf from the trunk */
-      int closest;
-      unsigned char *aData = pTrunk->aData;
-      if( nearby>0 ){
-        int i, dist;
-        closest = 0;
-        dist = get4byte(&aData[8]) - nearby;
-        if( dist<0 ) dist = -dist;
-        for(i=1; i<k; i++){
-          int d2 = get4byte(&aData[8+i*4]) - nearby;
-          if( d2<0 ) d2 = -d2;
-          if( d2<dist ) closest = i;
-        }
+
+    /* The code within this loop is run only once if the 'searchList' variable
+    ** is not true. Otherwise, it runs once for each trunk-page on the
+    ** free-list until the page 'nearby' is located.
+    */
+    do {
+      pPrevTrunk = pTrunk;
+      if( pPrevTrunk ){
+        iTrunk = get4byte(&pPrevTrunk->aData[0]);
       }else{
-        closest = 0;
+        iTrunk = get4byte(&pPage1->aData[32]);
       }
-      *pPgno = get4byte(&aData[8+closest*4]);
-      if( *pPgno>sqlite3pager_pagecount(pBt->pPager) ){
-        /* Free page off the end of the file */
-        return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+      rc = getPage(pBt, iTrunk, &pTrunk);
+      if( rc ){
+        releasePage(pPrevTrunk);
+        return rc;
       }
-      TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d: %d more free pages\n",
-             *pPgno, closest+1, k, pTrunk->pgno, n-1));
-      if( closest<k-1 ){
-        memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
+
+      /* TODO: This should move to after the loop? */
+      rc = sqlite3pager_write(pTrunk->aData);
+      if( rc ){
+        releasePage(pTrunk);
+        releasePage(pPrevTrunk);
+        return rc;
       }
-      put4byte(&aData[4], k-1);
-      rc = getPage(pBt, *pPgno, ppPage);
-      releasePage(pTrunk);
-      if( rc==SQLITE_OK ){
-        sqlite3pager_dont_rollback((*ppPage)->aData);
-        rc = sqlite3pager_write((*ppPage)->aData);
+
+      k = get4byte(&pTrunk->aData[4]);
+      if( k==0 && !searchList ){
+        /* The trunk has no leaves and the list is not being searched. 
+        ** So extract the trunk page itself and use it as the newly 
+        ** allocated page */
+        assert( pPrevTrunk==0 );
+        *pPgno = iTrunk;
+        memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
+        *ppPage = pTrunk;
+        pTrunk = 0;
+        TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
+      }else if( k>pBt->usableSize/4 - 8 ){
+        /* Value of k is out of range.  Database corruption */
+        return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+      }else if( searchList && nearby==iTrunk ){
+        /* The list is being searched and this trunk page is the page
+        ** to allocate, regardless of whether it has leaves.
+        */
+        assert( *pPgno==iTrunk );
+        *ppPage = pTrunk;
+        searchList = 0;
+        if( k==0 ){
+          if( !pPrevTrunk ){
+            memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
+          }else{
+            memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
+          }
+        }else{
+          /* The trunk page is required by the caller but it contains 
+          ** pointers to free-list leaves. The first leaf becomes a trunk
+          ** page in this case.
+          */
+          MemPage *pNewTrunk;
+          Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
+          rc = getPage(pBt, iNewTrunk, &pNewTrunk);
+          if( rc!=SQLITE_OK ){
+            releasePage(pTrunk);
+            releasePage(pPrevTrunk);
+            return rc;
+          }
+          rc = sqlite3pager_write(pNewTrunk->aData);
+          if( rc!=SQLITE_OK ){
+            releasePage(pNewTrunk);
+            releasePage(pTrunk);
+            releasePage(pPrevTrunk);
+            return rc;
+          }
+          memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4);
+          put4byte(&pNewTrunk->aData[4], k-1);
+          memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4);
+          if( !pPrevTrunk ){
+            put4byte(&pPage1->aData[32], iNewTrunk);
+          }else{
+            put4byte(&pPrevTrunk->aData[0], iNewTrunk);
+          }
+          releasePage(pNewTrunk);
+        }
+        pTrunk = 0;
+        TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
+#endif
+      }else{
+        /* Extract a leaf from the trunk */
+        int closest;
+        Pgno iPage;
+        unsigned char *aData = pTrunk->aData;
+        if( nearby>0 ){
+          int i, dist;
+          closest = 0;
+          dist = get4byte(&aData[8]) - nearby;
+          if( dist<0 ) dist = -dist;
+          for(i=1; i<k; i++){
+            int d2 = get4byte(&aData[8+i*4]) - nearby;
+            if( d2<0 ) d2 = -d2;
+            if( d2<dist ){
+              closest = i;
+              dist = d2;
+            }
+          }
+        }else{
+          closest = 0;
+        }
+
+        iPage = get4byte(&aData[8+closest*4]);
+        if( !searchList || iPage==nearby ){
+          *pPgno = iPage;
+          if( *pPgno>sqlite3pager_pagecount(pBt->pPager) ){
+            /* Free page off the end of the file */
+            return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+          }
+          TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
+                 ": %d more free pages\n",
+                 *pPgno, closest+1, k, pTrunk->pgno, n-1));
+          if( closest<k-1 ){
+            memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
+          }
+          put4byte(&aData[4], k-1);
+          rc = getPage(pBt, *pPgno, ppPage);
+          if( rc==SQLITE_OK ){
+            sqlite3pager_dont_rollback((*ppPage)->aData);
+            rc = sqlite3pager_write((*ppPage)->aData);
+            if( rc!=SQLITE_OK ){
+              releasePage(*ppPage);
+            }
+          }
+          searchList = 0;
+        }
       }
-    }
+      releasePage(pPrevTrunk);
+    }while( searchList );
+    releasePage(pTrunk);
   }else{
     /* There are no pages on the freelist, so create a new page at the
     ** end of the file */
     *pPgno = sqlite3pager_pagecount(pBt->pPager) + 1;
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt->usableSize, *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.
+      */
+      TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno));
+      assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
+      (*pPgno)++;
+    }
+#endif
+
+    assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
     rc = getPage(pBt, *pPgno, ppPage);
     if( rc ) return rc;
     rc = sqlite3pager_write((*ppPage)->aData);
+    if( rc!=SQLITE_OK ){
+      releasePage(*ppPage);
+    }
     TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
   }
+
+  assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
   return rc;
 }
 
@@ -2498,6 +3142,16 @@ static int freePage(MemPage *pPage){
   n = get4byte(&pPage1->aData[36]);
   put4byte(&pPage1->aData[36], n+1);
 
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  /* If the database supports auto-vacuum, write an entry in the pointer-map
+  ** to indicate that the page is free.
+  */
+  if( pBt->autoVacuum ){
+    rc = ptrmapPut(pBt, pPage->pgno, PTRMAP_FREEPAGE, 0);
+    if( rc ) return rc;
+  }
+#endif
+
   if( n==0 ){
     /* This is the first free page */
     rc = sqlite3pager_write(pPage->aData);
@@ -2552,6 +3206,9 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
   ovflPgno = get4byte(&pCell[info.iOverflow]);
   while( ovflPgno!=0 ){
     MemPage *pOvfl;
+    if( ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){
+      return SQLITE_CORRUPT;
+    }
     rc = getPage(pBt, ovflPgno, &pOvfl);
     if( rc ) return rc;
     ovflPgno = get4byte(pOvfl->aData);
@@ -2628,10 +3285,23 @@ static int fillInCell(
 
   while( nPayload>0 ){
     if( spaceLeft==0 ){
-      rc =  allocatePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+      Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */
+#endif
+      rc = allocatePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+      /* If the database supports auto-vacuum, and the second or subsequent
+      ** overflow page is being allocated, add an entry to the pointer-map
+      ** for that page now. The entry for the first overflow page will be
+      ** added later, by the insertCell() routine.
+      */
+      if( pBt->autoVacuum && pgnoPtrmap!=0 && rc==SQLITE_OK ){
+        rc = ptrmapPut(pBt, pgnoOvfl, PTRMAP_OVERFLOW2, pgnoPtrmap);
+      }
+#endif
       if( rc ){
         releasePage(pToRelease);
-        clearCell(pPage, pCell);
+        /* clearCell(pPage, pCell); */
         return rc;
       }
       put4byte(pPrior, pgnoOvfl);
@@ -2665,15 +3335,15 @@ static int fillInCell(
 ** given in the second argument so that MemPage.pParent holds the
 ** pointer in the third argument.
 */
-static void reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){
+static int reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){
   MemPage *pThis;
   unsigned char *aData;
 
-  if( pgno==0 ) return;
+  if( pgno==0 ) return SQLITE_OK;
   assert( pBt->pPager!=0 );
   aData = sqlite3pager_lookup(pBt->pPager, pgno);
   if( aData ){
-    pThis = (MemPage*)&aData[pBt->pageSize];
+    pThis = (MemPage*)&aData[pBt->psAligned];
     assert( pThis->aData==aData );
     if( pThis->isInit ){
       if( pThis->pParent!=pNewParent ){
@@ -2685,8 +3355,17 @@ static void reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){
     }
     sqlite3pager_unref(aData);
   }
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  if( pBt->autoVacuum ){
+    return ptrmapPut(pBt, pgno, PTRMAP_BTREE, pNewParent->pgno);
+  }
+#endif
+  return SQLITE_OK;
 }
 
+
+
 /*
 ** Change the pParent pointer of all children of pPage to point back
 ** to pPage.
@@ -2697,17 +3376,26 @@ static void reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){
 ** This routine gets called after you memcpy() one page into
 ** another.
 */
-static void reparentChildPages(MemPage *pPage){
+static int reparentChildPages(MemPage *pPage){
   int i;
-  Btree *pBt;
+  Btree *pBt = pPage->pBt;
+  int rc = SQLITE_OK;
+
+  if( pPage->leaf ) return SQLITE_OK;
 
-  if( pPage->leaf ) return;
-  pBt = pPage->pBt;
   for(i=0; i<pPage->nCell; i++){
-    reparentPage(pBt, get4byte(findCell(pPage,i)), pPage, i);
+    u8 *pCell = findCell(pPage, i);
+    if( !pPage->leaf ){
+      rc = reparentPage(pBt, get4byte(pCell), pPage, i);
+      if( rc!=SQLITE_OK ) return rc;
+    }
   }
-  reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]), pPage, i);
-  pPage->idxShift = 0;
+  if( !pPage->leaf ){
+    rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]), 
+       pPage, i);
+    pPage->idxShift = 0;
+  }
+  return rc;
 }
 
 /*
@@ -2753,13 +3441,19 @@ static void dropCell(MemPage *pPage, int idx, int sz){
 ** in pTemp or the original pCell) and also record its index. 
 ** Allocating a new entry in pPage->aCell[] implies that 
 ** pPage->nOverflow is incremented.
+**
+** If nSkip is non-zero, then do not copy the first nSkip bytes of the
+** cell. The caller will overwrite them after this function returns. If
+** nSkip is non-zero, then pCell may not point to an invalid memory location 
+** (but pCell+nSkip is always valid).
 */
-static void insertCell(
+static int insertCell(
   MemPage *pPage,   /* Page into which we are copying */
   int i,            /* New cell becomes the i-th cell of the page */
   u8 *pCell,        /* Content of the new cell */
   int sz,           /* Bytes of content in pCell */
-  u8 *pTemp         /* Temp storage space for pCell, if needed */
+  u8 *pTemp,        /* Temp storage space for pCell, if needed */
+  u8 nSkip          /* Do not write the first nSkip bytes of the cell */
 ){
   int idx;          /* Where to write new cell content in data[] */
   int j;            /* Loop counter */
@@ -2776,7 +3470,7 @@ static void insertCell(
   assert( sqlite3pager_iswriteable(pPage->aData) );
   if( pPage->nOverflow || sz+2>pPage->nFree ){
     if( pTemp ){
-      memcpy(pTemp, pCell, sz);
+      memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip);
       pCell = pTemp;
     }
     j = pPage->nOverflow++;
@@ -2801,7 +3495,7 @@ static void insertCell(
     assert( end <= get2byte(&data[hdr+5]) );
     pPage->nCell++;
     pPage->nFree -= 2;
-    memcpy(&data[idx], pCell, sz);
+    memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
     for(j=end-2, ptr=&data[j]; j>ins; j-=2, ptr-=2){
       ptr[0] = ptr[-2];
       ptr[1] = ptr[-1];
@@ -2810,7 +3504,23 @@ static void insertCell(
     put2byte(&data[hdr+3], pPage->nCell);
     pPage->idxShift = 1;
     pageIntegrity(pPage);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    if( pPage->pBt->autoVacuum ){
+      /* The cell may contain a pointer to an overflow page. If so, write
+      ** the entry for the overflow page into the pointer map.
+      */
+      CellInfo info;
+      parseCellPtr(pPage, pCell, &info);
+      if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){
+        Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
+        int rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno);
+        if( rc!=SQLITE_OK ) return rc;
+      }
+    }
+#endif
   }
+
+  return SQLITE_OK;
 }
 
 /*
@@ -2855,14 +3565,6 @@ static void assemblePage(
   pPage->nCell = nCell;
 }
 
-/*
-** GCC does not define the offsetof() macro so we'll have to do it
-** ourselves.
-*/
-#ifndef offsetof
-#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
-#endif
-
 /*
 ** The following parameters determine how many adjacent pages get involved
 ** in a balancing operation.  NN is the number of neighbors on either side
@@ -2879,7 +3581,110 @@ static void assemblePage(
 #define NB (NN*2+1)      /* Total pages involved in the balance */
 
 /* Forward reference */
-static int balance(MemPage*);
+static int balance(MemPage*, int);
+
+#ifndef SQLITE_OMIT_QUICKBALANCE
+/*
+** This version of balance() handles the common special case where
+** a new entry is being inserted on the extreme right-end of the
+** tree, in other words, when the new entry will become the largest
+** entry in the tree.
+**
+** Instead of trying balance the 3 right-most leaf pages, just add
+** a new page to the right-hand side and put the one new entry in
+** that page.  This leaves the right side of the tree somewhat
+** unbalanced.  But odds are that we will be inserting new entries
+** at the end soon afterwards so the nearly empty page will quickly
+** fill up.  On average.
+**
+** pPage is the leaf page which is the right-most page in the tree.
+** pParent is its parent.  pPage must have a single overflow entry
+** which is also the right-most entry on the page.
+*/
+static int balance_quick(MemPage *pPage, MemPage *pParent){
+  int rc;
+  MemPage *pNew;
+  Pgno pgnoNew;
+  u8 *pCell;
+  int szCell;
+  CellInfo info;
+  Btree *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 */
+
+  /* Allocate a new page. Insert the overflow cell from pPage
+  ** into it. Then remove the overflow cell from pPage.
+  */
+  rc = allocatePage(pBt, &pNew, &pgnoNew, 0, 0);
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+  pCell = pPage->aOvfl[0].pCell;
+  szCell = cellSizePtr(pPage, pCell);
+  zeroPage(pNew, pPage->aData[0]);
+  assemblePage(pNew, 1, &pCell, &szCell);
+  pPage->nOverflow = 0;
+
+  /* Set the parent of the newly allocated page to pParent. */
+  pNew->pParent = pParent;
+  sqlite3pager_ref(pParent->aData);
+
+  /* pPage is currently the right-child of pParent. Change this
+  ** so that the right-child is the new page allocated above and
+  ** pPage is the next-to-right child. 
+  */
+  assert( pPage->nCell>0 );
+  parseCellPtr(pPage, findCell(pPage, pPage->nCell-1), &info);
+  rc = fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, &parentSize);
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+  assert( parentSize<64 );
+  rc = insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4);
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+  put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno);
+  put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  /* If this is an auto-vacuum database, update the pointer map
+  ** with entries for the new page, and any pointer from the 
+  ** cell on the page to an overflow page.
+  */
+  if( pBt->autoVacuum ){
+    rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
+    if( rc!=SQLITE_OK ){
+      return rc;
+    }
+    rc = ptrmapPutOvfl(pNew, 0);
+    if( rc!=SQLITE_OK ){
+      return rc;
+    }
+  }
+#endif
+
+  /* Release the reference to the new page and balance the parent page,
+  ** in case the divider cell inserted caused it to become overfull.
+  */
+  releasePage(pNew);
+  return balance(pParent, 0);
+}
+#endif /* SQLITE_OMIT_QUICKBALANCE */
+
+/*
+** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
+** if the database supports auto-vacuum or not. Because it is used
+** within an expression that is an argument to another macro 
+** (sqliteMallocRaw), it is not possible to use conditional compilation.
+** So, this macro is defined instead.
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+#define ISAUTOVACUUM (pBt->autoVacuum)
+#else
+#define ISAUTOVACUUM 0
+#endif
 
 /*
 ** This routine redistributes Cells on pPage and up to NN*2 siblings
@@ -2941,6 +3746,9 @@ static int balance_nonroot(MemPage *pPage){
   int *szCell;                 /* Local size of all cells in apCell[] */
   u8 *aCopy[NB];               /* Space for holding data of apCopy[] */
   u8 *aSpace;                  /* Space to hold copies of dividers cells */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  u8 *aFrom = 0;
+#endif
 
   /* 
   ** Find the parent page.
@@ -2953,6 +3761,31 @@ static int balance_nonroot(MemPage *pPage){
   assert( pParent );
   TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
 
+#ifndef SQLITE_OMIT_QUICKBALANCE
+  /*
+  ** A special case:  If a new entry has just been inserted into a
+  ** table (that is, a btree with integer keys and all data at the leaves)
+  ** an the new entry is the right-most entry in the tree (it has the
+  ** largest key) then use the special balance_quick() routine for
+  ** balancing.  balance_quick() is much faster and results in a tighter
+  ** packing of data in the common case.
+  */
+  if( pPage->leaf &&
+      pPage->intKey &&
+      pPage->leafData &&
+      pPage->nOverflow==1 &&
+      pPage->aOvfl[0].idx==pPage->nCell &&
+      pPage->pParent->pgno!=1 &&
+      get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno
+  ){
+    /*
+    ** TODO: Check the siblings to the left of pPage. It may be that
+    ** they are not full and no new page is required.
+    */
+    return balance_quick(pPage, pParent);
+  }
+#endif
+
   /*
   ** Allocate space for memory structures
   */
@@ -2960,7 +3793,8 @@ static int balance_nonroot(MemPage *pPage){
   apCell = sqliteMallocRaw( 
        (mxCellPerPage+2)*NB*(sizeof(u8*)+sizeof(int))
      + sizeof(MemPage)*NB
-     + pBt->pageSize*(5+NB)
+     + pBt->psAligned*(5+NB)
+     + (ISAUTOVACUUM ? (mxCellPerPage+2)*NN*2 : 0)
   );
   if( apCell==0 ){
     return SQLITE_NOMEM;
@@ -2968,9 +3802,14 @@ static int balance_nonroot(MemPage *pPage){
   szCell = (int*)&apCell[(mxCellPerPage+2)*NB];
   aCopy[0] = (u8*)&szCell[(mxCellPerPage+2)*NB];
   for(i=1; i<NB; i++){
-    aCopy[i] = &aCopy[i-1][pBt->pageSize+sizeof(MemPage)];
+    aCopy[i] = &aCopy[i-1][pBt->psAligned+sizeof(MemPage)];
+  }
+  aSpace = &aCopy[NB-1][pBt->psAligned+sizeof(MemPage)];
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  if( pBt->autoVacuum ){
+    aFrom = &aSpace[5*pBt->psAligned];
   }
-  aSpace = &aCopy[NB-1][pBt->pageSize+sizeof(MemPage)];
+#endif
   
   /*
   ** Find the cell in the parent page whose left child points back
@@ -3041,10 +3880,10 @@ static int balance_nonroot(MemPage *pPage){
   ** process of being overwritten.
   */
   for(i=0; i<nOld; i++){
-    MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->pageSize];
-    p->aData = &((u8*)p)[-pBt->pageSize];
-    memcpy(p->aData, apOld[i]->aData, pBt->pageSize + sizeof(MemPage));
-    p->aData = &((u8*)p)[-pBt->pageSize];
+    MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->psAligned];
+    p->aData = &((u8*)p)[-pBt->psAligned];
+    memcpy(p->aData, apOld[i]->aData, pBt->psAligned + sizeof(MemPage));
+    p->aData = &((u8*)p)[-pBt->psAligned];
   }
 
   /*
@@ -3072,6 +3911,18 @@ static int balance_nonroot(MemPage *pPage){
     for(j=0; j<limit; j++){
       apCell[nCell] = findOverflowCell(pOld, j);
       szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+      if( pBt->autoVacuum ){
+        int a;
+        aFrom[nCell] = i;
+        for(a=0; a<pOld->nOverflow; a++){
+          if( pOld->aOvfl[a].pCell==apCell[nCell] ){
+            aFrom[nCell] = 0xFF;
+            break;
+          }
+        }
+      }
+#endif
       nCell++;
     }
     if( i<nOld-1 ){
@@ -3088,9 +3939,14 @@ static int balance_nonroot(MemPage *pPage){
         szCell[nCell] = sz;
         pTemp = &aSpace[iSpace];
         iSpace += sz;
-        assert( iSpace<=pBt->pageSize*5 );
+        assert( iSpace<=pBt->psAligned*5 );
         memcpy(pTemp, apDiv[i], sz);
         apCell[nCell] = pTemp+leafCorrection;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+        if( pBt->autoVacuum ){
+          aFrom[nCell] = 0xFF;
+        }
+#endif
         dropCell(pParent, nxDiv, sz);
         szCell[nCell] -= leafCorrection;
         assert( get4byte(pTemp)==pgnoOld[i] );
@@ -3179,9 +4035,10 @@ static int balance_nonroot(MemPage *pPage){
       pNew = apNew[i] = apOld[i];
       pgnoNew[i] = pgnoOld[i];
       apOld[i] = 0;
-      sqlite3pager_write(pNew->aData);
+      rc = sqlite3pager_write(pNew->aData);
+      if( rc ) goto balance_cleanup;
     }else{
-      rc = allocatePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1]);
+      rc = allocatePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0);
       if( rc ) goto balance_cleanup;
       apNew[i] = pNew;
     }
@@ -3243,19 +4100,42 @@ static int balance_nonroot(MemPage *pPage){
     nNew>=4 ? pgnoNew[3] : 0, nNew>=4 ? szNew[3] : 0,
     nNew>=5 ? pgnoNew[4] : 0, nNew>=5 ? szNew[4] : 0));
 
-
   /*
   ** Evenly distribute the data in apCell[] across the new pages.
   ** Insert divider cells into pParent as necessary.
   */
   j = 0;
   for(i=0; i<nNew; i++){
+    /* Assemble the new sibling page. */
     MemPage *pNew = apNew[i];
     assert( pNew->pgno==pgnoNew[i] );
     assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]);
-    j = cntNew[i];
     assert( pNew->nCell>0 );
     assert( pNew->nOverflow==0 );
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    /* If this is an auto-vacuum database, update the pointer map entries
+    ** that point to the siblings that were rearranged. These can be: left
+    ** children of cells, the right-child of the page, or overflow pages
+    ** pointed to by cells.
+    */
+    if( pBt->autoVacuum ){
+      for(k=j; k<cntNew[i]; k++){
+        if( aFrom[k]==0xFF || apCopy[aFrom[k]]->pgno!=pNew->pgno ){
+          rc = ptrmapPutOvfl(pNew, k-j);
+          if( rc!=SQLITE_OK ){
+            goto balance_cleanup;
+          }
+        }
+      }
+    }
+#endif
+
+    j = cntNew[i];
+
+    /* If the sibling page assembled above was not the right-most sibling,
+    ** insert a divider cell into the parent page.
+    */
     if( i<nNew-1 && j<nCell ){
       u8 *pCell;
       u8 *pTemp;
@@ -3266,22 +4146,40 @@ static int balance_nonroot(MemPage *pPage){
         memcpy(&pNew->aData[8], pCell, 4);
         pTemp = 0;
       }else if( leafData ){
+       /* If the tree is a leaf-data tree, and the siblings are leaves, 
+        ** then there is no divider cell in apCell[]. Instead, the divider 
+        ** cell consists of the integer key for the right-most cell of 
+        ** the sibling-page assembled above only.
+        */
         CellInfo info;
         j--;
         parseCellPtr(pNew, apCell[j], &info);
         pCell = &aSpace[iSpace];
         fillInCell(pParent, pCell, 0, info.nKey, 0, 0, &sz);
         iSpace += sz;
-        assert( iSpace<=pBt->pageSize*5 );
+        assert( iSpace<=pBt->psAligned*5 );
         pTemp = 0;
       }else{
         pCell -= 4;
         pTemp = &aSpace[iSpace];
         iSpace += sz;
-        assert( iSpace<=pBt->pageSize*5 );
+        assert( iSpace<=pBt->psAligned*5 );
       }
-      insertCell(pParent, nxDiv, pCell, sz, pTemp);
+      rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4);
+      if( rc!=SQLITE_OK ) goto balance_cleanup;
       put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+      /* If this is an auto-vacuum database, and not a leaf-data tree,
+      ** then update the pointer map with an entry for the overflow page
+      ** that the cell just inserted points to (if any).
+      */
+      if( pBt->autoVacuum && !leafData ){
+        rc = ptrmapPutOvfl(pParent, nxDiv);
+        if( rc!=SQLITE_OK ){
+          goto balance_cleanup;
+        }
+      }
+#endif
       j++;
       nxDiv++;
     }
@@ -3303,19 +4201,21 @@ static int balance_nonroot(MemPage *pPage){
   ** Reparent children of all cells.
   */
   for(i=0; i<nNew; i++){
-    reparentChildPages(apNew[i]);
+    rc = reparentChildPages(apNew[i]);
+    if( rc!=SQLITE_OK ) goto balance_cleanup;
   }
-  reparentChildPages(pParent);
+  rc = reparentChildPages(pParent);
+  if( rc!=SQLITE_OK ) goto balance_cleanup;
 
   /*
   ** Balance the parent page.  Note that the current page (pPage) might
-  ** have been added to the freelist is it might no longer be initialized.
+  ** have been added to the freelist so it might no longer be initialized.
   ** But the parent page will always be initialized.
   */
   assert( pParent->isInit );
   /* assert( pPage->isInit ); // No! pPage might have been added to freelist */
   /* pageIntegrity(pPage);    // No! pPage might have been added to freelist */ 
-  rc = balance(pParent);
+  rc = balance(pParent, 0);
   
   /*
   ** Cleanup before returning.
@@ -3390,6 +4290,9 @@ static int balance_shallower(MemPage *pPage){
           szCell[i] = cellSizePtr(pChild, apCell[i]);
         }
         assemblePage(pPage, pChild->nCell, apCell, szCell);
+        /* Copy the right-pointer of the child to the parent. */
+        put4byte(&pPage->aData[pPage->hdrOffset+8], 
+            get4byte(&pChild->aData[pChild->hdrOffset+8]));
         freePage(pChild);
         TRACE(("BALANCE: child %d transfer to page 1\n", pChild->pgno));
       }else{
@@ -3407,7 +4310,20 @@ static int balance_shallower(MemPage *pPage){
       TRACE(("BALANCE: transfer child %d into root %d\n",
               pChild->pgno, pPage->pgno));
     }
-    reparentChildPages(pPage);
+    rc = reparentChildPages(pPage);
+    assert( pPage->nOverflow==0 );
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    if( pBt->autoVacuum ){
+      int i;
+      for(i=0; i<pPage->nCell; i++){ 
+        rc = ptrmapPutOvfl(pPage, i);
+        if( rc!=SQLITE_OK ){
+          goto end_shallow_balance;
+        }
+      }
+    }
+#endif
+    if( rc!=SQLITE_OK ) goto end_shallow_balance;
     releasePage(pChild);
   }
 end_shallow_balance:
@@ -3439,7 +4355,7 @@ static int balance_deeper(MemPage *pPage){
   assert( pPage->pParent==0 );
   assert( pPage->nOverflow>0 );
   pBt = pPage->pBt;
-  rc = allocatePage(pBt, &pChild, &pgnoChild, pPage->pgno);
+  rc = allocatePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0);
   if( rc ) return rc;
   assert( sqlite3pager_iswriteable(pChild->aData) );
   usableSize = pBt->usableSize;
@@ -3449,6 +4365,7 @@ static int balance_deeper(MemPage *pPage){
   cdata = pChild->aData;
   memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr);
   memcpy(&cdata[brk], &data[brk], usableSize-brk);
+  assert( pChild->isInit==0 );
   rc = initPage(pChild, pPage);
   if( rc ) return rc;
   memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0]));
@@ -3460,6 +4377,19 @@ static int balance_deeper(MemPage *pPage){
   zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF);
   put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild);
   TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno));
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  if( pBt->autoVacuum ){
+    int i;
+    rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno);
+    if( rc ) return rc;
+    for(i=0; i<pChild->nCell; i++){
+      rc = ptrmapPutOvfl(pChild, i);
+      if( rc!=SQLITE_OK ){
+        return rc;
+      }
+    }
+  }
+#endif
   rc = balance_nonroot(pChild);
   releasePage(pChild);
   return rc;
@@ -3469,17 +4399,18 @@ static int balance_deeper(MemPage *pPage){
 ** Decide if the page pPage needs to be balanced.  If balancing is
 ** required, call the appropriate balancing routine.
 */
-static int balance(MemPage *pPage){
+static int balance(MemPage *pPage, int insert){
   int rc = SQLITE_OK;
   if( pPage->pParent==0 ){
     if( pPage->nOverflow>0 ){
       rc = balance_deeper(pPage);
     }
-    if( pPage->nCell==0 ){
+    if( rc==SQLITE_OK && pPage->nCell==0 ){
       rc = balance_shallower(pPage);
     }
   }else{
-    if( pPage->nOverflow>0 || pPage->nFree>pPage->pBt->usableSize*2/3 ){
+    if( pPage->nOverflow>0 || 
+        (!insert && pPage->nFree>pPage->pBt->usableSize*2/3) ){
       rc = balance_nonroot(pPage);
     }
   }
@@ -3535,9 +4466,6 @@ int sqlite3BtreeInsert(
   unsigned char *oldCell;
   unsigned char *newCell = 0;
 
-  if( pCur->status ){
-    return pCur->status;  /* A rollback destroyed this cursor */
-  }
   if( pBt->inTrans!=TRANS_WRITE ){
     /* Must start a transaction before doing an insert */
     return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
@@ -3584,11 +4512,14 @@ int sqlite3BtreeInsert(
   }else{
     assert( pPage->leaf );
   }
-  insertCell(pPage, pCur->idx, newCell, szNew, 0);
-  rc = balance(pPage);
+  rc = insertCell(pPage, pCur->idx, newCell, szNew, 0, 0);
+  if( rc!=SQLITE_OK ) goto end_insert;
+  rc = balance(pPage, 1);
   /* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */
   /* fflush(stdout); */
-  moveToRoot(pCur);
+  if( rc==SQLITE_OK ){
+    moveToRoot(pCur);
+  }
 end_insert:
   sqliteFree(newCell);
   return rc;
@@ -3606,9 +4537,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){
   Btree *pBt = pCur->pBt;
 
   assert( pPage->isInit );
-  if( pCur->status ){
-    return pCur->status;  /* A rollback destroyed this cursor */
-  }
   if( pBt->inTrans!=TRANS_WRITE ){
     /* Must start a transaction before doing a delete */
     return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
@@ -3625,11 +4553,18 @@ int sqlite3BtreeDelete(BtCursor *pCur){
   }
   rc = sqlite3pager_write(pPage->aData);
   if( rc ) 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
+  ** cell. The cell itself is still intact.
+  */
   pCell = findCell(pPage, pCur->idx);
   if( !pPage->leaf ){
     pgnoChild = get4byte(pCell);
   }
-  clearCell(pPage, pCell);
+  rc = clearCell(pPage, pCell);
+  if( rc ) return rc;
+
   if( !pPage->leaf ){
     /*
     ** The entry we are about to delete is not a leaf so if we do not
@@ -3662,19 +4597,20 @@ int sqlite3BtreeDelete(BtCursor *pCur){
     assert( MX_CELL_SIZE(pBt)>=szNext+4 );
     tempCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) );
     if( tempCell==0 ) return SQLITE_NOMEM;
-    insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell);
+    rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0);
+    if( rc!=SQLITE_OK ) return rc;
     put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild);
-    rc = balance(pPage);
+    rc = balance(pPage, 0);
     sqliteFree(tempCell);
     if( rc ) return rc;
     dropCell(leafCur.pPage, leafCur.idx, szNext);
-    rc = balance(leafCur.pPage);
+    rc = balance(leafCur.pPage, 0);
     releaseTempCursor(&leafCur);
   }else{
     TRACE(("DELETE: table=%d delete from leaf %d\n",
        pCur->pgnoRoot, pPage->pgno));
     dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell));
-    rc = balance(pPage);
+    rc = balance(pPage, 0);
   }
   moveToRoot(pCur);
   return rc;
@@ -3699,11 +4635,102 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){
     /* Must start a transaction first */
     return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
   }
-  if( pBt->readOnly ){
-    return SQLITE_READONLY;
+  assert( !pBt->readOnly );
+
+  /* It is illegal to create a table if any cursors are open on the
+  ** database. This is because in auto-vacuum mode the backend may
+  ** need to move a database page to make room for the new root-page.
+  ** If an open cursor was using the page a problem would occur.
+  */
+  if( pBt->pCursor ){
+    return SQLITE_LOCKED;
   }
-  rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1);
+
+#ifdef SQLITE_OMIT_AUTOVACUUM
+  rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1, 0);
   if( rc ) return rc;
+#else
+  if( pBt->autoVacuum ){
+    Pgno pgnoMove;      /* Move a page here to make room for the root-page */
+    MemPage *pPageMove; /* The page to move to. */
+
+    /* Read the value of meta[3] from the database to determine where the
+    ** root page of the new table should go. meta[3] is the largest root-page
+    ** created so far, so the new root-page is (meta[3]+1).
+    */
+    rc = sqlite3BtreeGetMeta(pBt, 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) ||
+        pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
+      pgnoRoot++;
+    }
+    assert( pgnoRoot>=3 );
+
+    /* Allocate a page. The page that currently resides at pgnoRoot will
+    ** be moved to the allocated page (unless the allocated page happens
+    ** to reside at pgnoRoot).
+    */
+    rc = allocatePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1);
+    if( rc!=SQLITE_OK ){
+      return rc;
+    }
+
+    if( pgnoMove!=pgnoRoot ){
+      u8 eType;
+      Pgno iPtrPage;
+
+      releasePage(pPageMove);
+      rc = getPage(pBt, pgnoRoot, &pRoot);
+      if( rc!=SQLITE_OK ){
+        return rc;
+      }
+      rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
+      assert( eType!=PTRMAP_ROOTPAGE );
+      assert( eType!=PTRMAP_FREEPAGE );
+      if( rc!=SQLITE_OK ){
+        releasePage(pRoot);
+        return rc;
+      }
+      rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove);
+      releasePage(pRoot);
+      if( rc!=SQLITE_OK ){
+        return rc;
+      }
+      rc = getPage(pBt, pgnoRoot, &pRoot);
+      if( rc!=SQLITE_OK ){
+        return rc;
+      }
+      rc = sqlite3pager_write(pRoot->aData);
+      if( rc!=SQLITE_OK ){
+        releasePage(pRoot);
+        return rc;
+      }
+    }else{
+      pRoot = pPageMove;
+    } 
+
+    /* Update the pointer-map and meta-data with the new root-page number. */
+    rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0);
+    if( rc ){
+      releasePage(pRoot);
+      return rc;
+    }
+    rc = sqlite3BtreeUpdateMeta(pBt, 4, pgnoRoot);
+    if( rc ){
+      releasePage(pRoot);
+      return rc;
+    }
+
+  }else{
+    rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1, 0);
+    if( rc ) return rc;
+  }
+#endif
   assert( sqlite3pager_iswriteable(pRoot->aData) );
   zeroPage(pRoot, flags | PTF_LEAF);
   sqlite3pager_unref(pRoot->aData);
@@ -3726,6 +4753,10 @@ static int clearDatabasePage(
   unsigned char *pCell;
   int i;
 
+  if( pgno>sqlite3pager_pagecount(pBt->pPager) ){
+    return SQLITE_CORRUPT;
+  }
+
   rc = getAndInitPage(pBt, pgno, &pPage, pParent);
   if( rc ) return rc;
   rc = sqlite3pager_write(pPage->aData);
@@ -3787,29 +4818,119 @@ int sqlite3BtreeClearTable(Btree *pBt, int iTable){
 **
 ** This routine will fail with SQLITE_LOCKED if there are any open
 ** cursors on the table.
+**
+** If AUTOVACUUM is enabled and the page at iTable is not the last
+** root page in the database file, then the last root page 
+** in the database file is moved into the slot formerly occupied by
+** iTable and that last slot formerly occupied by the last root page
+** is added to the freelist instead of iTable.  In this say, all
+** root pages are kept at the beginning of the database file, which
+** is necessary for AUTOVACUUM to work right.  *piMoved is set to the 
+** page number that used to be the last root page in the file before
+** the move.  If no page gets moved, *piMoved is set to 0.
+** The last root page is recorded in meta[3] and the value of
+** meta[3] is updated by this procedure.
 */
-int sqlite3BtreeDropTable(Btree *pBt, int iTable){
+int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){
   int rc;
-  MemPage *pPage;
-  BtCursor *pCur;
+  MemPage *pPage = 0;
+
   if( pBt->inTrans!=TRANS_WRITE ){
     return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
   }
-  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-    if( pCur->pgnoRoot==(Pgno)iTable ){
-      return SQLITE_LOCKED;  /* Cannot drop a table that has a cursor */
-    }
+
+  /* It is illegal to drop a table if any cursors are open on the
+  ** database. This is because in auto-vacuum mode the backend may
+  ** need to move another root-page to fill a gap left by the deleted
+  ** root page. If an open cursor was using this page a problem would 
+  ** occur.
+  */
+  if( pBt->pCursor ){
+    return SQLITE_LOCKED;
   }
+
   rc = getPage(pBt, (Pgno)iTable, &pPage);
   if( rc ) return rc;
   rc = sqlite3BtreeClearTable(pBt, iTable);
   if( rc ) return rc;
+
+  *piMoved = 0;
+
   if( iTable>1 ){
+#ifdef SQLITE_OMIT_AUTOVACUUM
     rc = freePage(pPage);
+    releasePage(pPage);
+#else
+    if( pBt->autoVacuum ){
+      Pgno maxRootPgno;
+      rc = sqlite3BtreeGetMeta(pBt, 4, &maxRootPgno);
+      if( rc!=SQLITE_OK ){
+        releasePage(pPage);
+        return rc;
+      }
+
+      if( iTable==maxRootPgno ){
+        /* If the table being dropped is the table with the largest root-page
+        ** number in the database, put the root page on the free list. 
+        */
+        rc = freePage(pPage);
+        releasePage(pPage);
+        if( rc!=SQLITE_OK ){
+          return rc;
+        }
+      }else{
+        /* The table being dropped does not have the largest root-page
+        ** number in the database. So move the page that does into the 
+        ** gap left by the deleted root-page.
+        */
+        MemPage *pMove;
+        releasePage(pPage);
+        rc = getPage(pBt, maxRootPgno, &pMove);
+        if( rc!=SQLITE_OK ){
+          return rc;
+        }
+        rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable);
+        releasePage(pMove);
+        if( rc!=SQLITE_OK ){
+          return rc;
+        }
+        rc = getPage(pBt, maxRootPgno, &pMove);
+        if( rc!=SQLITE_OK ){
+          return rc;
+        }
+        rc = freePage(pMove);
+        releasePage(pMove);
+        if( rc!=SQLITE_OK ){
+          return rc;
+        }
+        *piMoved = maxRootPgno;
+      }
+
+      /* Set the new 'max-root-page' value in the database header. This
+      ** is the old value less one, less one more if that happens to
+      ** be a root-page number, less one again if that is the
+      ** PENDING_BYTE_PAGE.
+      */
+      maxRootPgno--;
+      if( maxRootPgno==PENDING_BYTE_PAGE(pBt) ){
+        maxRootPgno--;
+      }
+      if( maxRootPgno==PTRMAP_PAGENO(pBt->usableSize, maxRootPgno) ){
+        maxRootPgno--;
+      }
+      assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) );
+
+      rc = sqlite3BtreeUpdateMeta(pBt, 4, maxRootPgno);
+    }else{
+      rc = freePage(pPage);
+      releasePage(pPage);
+    }
+#endif
   }else{
+    /* If sqlite3BtreeDropTable was called on page 1. */
     zeroPage(pPage, PTF_INTKEY|PTF_LEAF );
+    releasePage(pPage);
   }
-  releasePage(pPage);
   return rc;  
 }
 
@@ -3834,9 +4955,12 @@ int sqlite3BtreeGetMeta(Btree *pBt, int idx, u32 *pMeta){
   *pMeta = get4byte(&pP1[36 + idx*4]);
   sqlite3pager_unref(pP1);
 
-  /* The current implementation is unable to handle writes to an autovacuumed
-  ** database.  So make such a database readonly. */
+  /* If autovacuumed is disabled in this build but we are trying to 
+  ** access an autovacuumed database, then make the database readonly. 
+  */
+#ifdef SQLITE_OMIT_AUTOVACUUM
   if( idx==4 && *pMeta>0 ) pBt->readOnly = 1;
+#endif
 
   return SQLITE_OK;
 }
@@ -3869,12 +4993,12 @@ int sqlite3BtreeFlags(BtCursor *pCur){
   return pPage ? pPage->aData[pPage->hdrOffset] : 0;
 }
 
+#ifdef SQLITE_DEBUG
 /*
 ** Print a disassembly of the given page on standard output.  This routine
 ** is used for debugging and testing only.
 */
-#ifdef SQLITE_TEST
-int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
+static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){
   int rc;
   MemPage *pPage;
   int i, j, c;
@@ -3890,7 +5014,7 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
   rc = getPage(pBt, (Pgno)pgno, &pPage);
   isInit = pPage->isInit;
   if( pPage->isInit==0 ){
-    initPage(pPage, 0);
+    initPage(pPage, pParent);
   }
   if( rc ){
     return rc;
@@ -3960,16 +5084,19 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
   if( recursive && !pPage->leaf ){
     for(i=0; i<nCell; i++){
       unsigned char *pCell = findCell(pPage, i);
-      sqlite3BtreePageDump(pBt, get4byte(pCell), 1);
+      btreePageDump(pBt, get4byte(pCell), 1, pPage);
       idx = get2byte(pCell);
     }
-    sqlite3BtreePageDump(pBt, get4byte(&data[hdr+8]), 1);
+    btreePageDump(pBt, get4byte(&data[hdr+8]), 1, pPage);
   }
   pPage->isInit = isInit;
   sqlite3pager_unref(data);
   fflush(stdout);
   return SQLITE_OK;
 }
+int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
+  return btreePageDump(pBt, pgno, recursive, 0);
+}
 #endif
 
 #ifdef SQLITE_TEST
@@ -4058,6 +5185,7 @@ struct IntegrityCk {
   char *zErrMsg; /* An error message.  NULL of no errors seen. */
 };
 
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
 /*
 ** Append a message to the error message string.
 */
@@ -4083,7 +5211,9 @@ static void checkAppendMsg(
   }
   sqliteFree(zMsg2);
 }
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
 
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
 /*
 ** Add 1 to the reference count for page iPage.  If this is the second
 ** reference to the page, add an error message to pCheck->zErrMsg.
@@ -4105,6 +5235,37 @@ static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){
   return  (pCheck->anRef[iPage]++)>1;
 }
 
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** Check that the entry in the pointer-map for page iChild maps to 
+** page iParent, pointer type ptrType. If not, append an error message
+** to pCheck.
+*/
+static void checkPtrmap(
+  IntegrityCk *pCheck,   /* Integrity check context */
+  Pgno iChild,           /* Child page number */
+  u8 eType,              /* Expected pointer map type */
+  Pgno iParent,          /* Expected pointer map parent page number */
+  char *zContext         /* Context description (used for error msg) */
+){
+  int rc;
+  u8 ePtrmapType;
+  Pgno iPtrmapParent;
+
+  rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
+  if( rc!=SQLITE_OK ){
+    checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild);
+    return;
+  }
+
+  if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
+    checkAppendMsg(pCheck, zContext, 
+      "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", 
+      iChild, eType, iParent, ePtrmapType, iPtrmapParent);
+  }
+}
+#endif
+
 /*
 ** Check the integrity of the freelist or of an overflow page list.
 ** Verify that the number of pages on the list is N.
@@ -4134,22 +5295,47 @@ static void checkList(
     }
     if( isFreeList ){
       int n = get4byte(&pOvfl[4]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+      if( pCheck->pBt->autoVacuum ){
+        checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext);
+      }
+#endif
       if( n>pCheck->pBt->usableSize/4-8 ){
         checkAppendMsg(pCheck, zContext,
            "freelist leaf count too big on page %d", iPage);
         N--;
       }else{
         for(i=0; i<n; i++){
-          checkRef(pCheck, get4byte(&pOvfl[8+i*4]), zContext);
+          Pgno iFreePage = get4byte(&pOvfl[8+i*4]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+          if( pCheck->pBt->autoVacuum ){
+            checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0, zContext);
+          }
+#endif
+          checkRef(pCheck, iFreePage, zContext);
         }
         N -= n;
       }
     }
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    else{
+      /* If this database supports auto-vacuum and iPage is not the last
+      ** page in this overflow list, check that the pointer-map entry for
+      ** the following page matches iPage.
+      */
+      if( pCheck->pBt->autoVacuum && N>0 ){
+        i = get4byte(pOvfl);
+        checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage, zContext);
+      }
+    }
+#endif
     iPage = get4byte(pOvfl);
     sqlite3pager_unref(pOvfl);
   }
 }
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
 
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
 /*
 ** Do various sanity checks on a single page of a tree.  Return
 ** the tree depth.  Root pages return 0.  Parents of root pages
@@ -4189,6 +5375,8 @@ static int checkTreePage(
   char zContext[100];
   char *hit;
 
+  sprintf(zContext, "Page %d: ", iPage);
+
   /* Check that the page exists
   */
   cur.pBt = pBt = pCheck->pBt;
@@ -4225,13 +5413,24 @@ static int checkTreePage(
     if( !pPage->intKey ) sz += info.nKey;
     if( sz>info.nLocal ){
       int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
-      checkList(pCheck, 0, get4byte(&pCell[info.iOverflow]),nPage,zContext);
+      Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+      if( pBt->autoVacuum ){
+        checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage, zContext);
+      }
+#endif
+      checkList(pCheck, 0, pgnoOvfl, nPage, zContext);
     }
 
     /* Check sanity of left child page.
     */
     if( !pPage->leaf ){
       pgno = get4byte(pCell);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+      if( pBt->autoVacuum ){
+        checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
+      }
+#endif
       d2 = checkTreePage(pCheck,pgno,pPage,zContext,0,0,0,0);
       if( i>0 && d2!=depth ){
         checkAppendMsg(pCheck, zContext, "Child page depth differs");
@@ -4242,6 +5441,11 @@ static int checkTreePage(
   if( !pPage->leaf ){
     pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
     sprintf(zContext, "On page %d at right child: ", iPage);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    if( pBt->autoVacuum ){
+      checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0);
+    }
+#endif
     checkTreePage(pCheck, pgno, pPage, zContext,0,0,0,0);
   }
  
@@ -4258,13 +5462,23 @@ static int checkTreePage(
       int pc = get2byte(&data[cellStart+i*2]);
       int size = cellSizePtr(pPage, &data[pc]);
       int j;
-      for(j=pc+size-1; j>=pc; j--) hit[j]++;
+      if( (pc+size-1)>=usableSize || pc<0 ){
+        checkAppendMsg(pCheck, 0, 
+            "Corruption detected in cell %d on page %d",i,iPage,0);
+      }else{
+        for(j=pc+size-1; j>=pc; j--) hit[j]++;
+      }
     }
     for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<usableSize && cnt<10000; 
            cnt++){
       int size = get2byte(&data[i+2]);
       int j;
-      for(j=i+size-1; j>=i; j--) hit[j]++;
+      if( (i+size-1)>=usableSize || i<0 ){
+        checkAppendMsg(pCheck, 0,  
+            "Corruption detected in cell %d on page %d",i,iPage,0);
+      }else{
+        for(j=i+size-1; j>=i; j--) hit[j]++;
+      }
       i = get2byte(&data[i]);
     }
     for(i=cnt=0; i<usableSize; i++){
@@ -4287,7 +5501,9 @@ static int checkTreePage(
   releasePage(pPage);
   return depth+1;
 }
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
 
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
 /*
 ** This routine does a complete check of the given BTree file.  aRoot[] is
 ** an array of pages numbers were each page number is the root page of
@@ -4315,8 +5531,13 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
     return 0;
   }
   sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) );
+  if( !sCheck.anRef ){
+    unlockBtreeIfUnused(pBt);
+    return sqlite3MPrintf("Unable to malloc %d bytes", 
+        (sCheck.nPage+1)*sizeof(sCheck.anRef[0]));
+  }
   for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; }
-  i = PENDING_BYTE/pBt->pageSize + 1;
+  i = PENDING_BYTE_PAGE(pBt);
   if( i<=sCheck.nPage ){
     sCheck.anRef[i] = 1;
   }
@@ -4331,15 +5552,34 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
   */
   for(i=0; i<nRoot; i++){
     if( aRoot[i]==0 ) continue;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    if( pBt->autoVacuum && aRoot[i]>1 ){
+      checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
+    }
+#endif
     checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ", 0,0,0,0);
   }
 
   /* Make sure every page in the file is referenced
   */
   for(i=1; i<=sCheck.nPage; i++){
+#ifdef SQLITE_OMIT_AUTOVACUUM
     if( sCheck.anRef[i]==0 ){
       checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
     }
+#else
+    /* If the database supports auto-vacuum, make sure no tables contain
+    ** references to pointer-map pages.
+    */
+    if( sCheck.anRef[i]==0 && 
+       (PTRMAP_PAGENO(pBt->usableSize, 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) ){
+      checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i);
+    }
+#endif
   }
 
   /* Make sure this analysis did not leave any unref() pages
@@ -4357,6 +5597,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
   sqliteFree(sCheck.anRef);
   return sCheck.zErrMsg;
 }
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
 
 /*
 ** Return the full pathname of the underlying database file.
@@ -4384,6 +5625,7 @@ const char *sqlite3BtreeGetJournalname(Btree *pBt){
   return sqlite3pager_journalname(pBt->pPager);
 }
 
+#ifndef SQLITE_OMIT_VACUUM
 /*
 ** Copy the complete content of pBtFrom into pBtTo.  A transaction
 ** must be active for both files.
@@ -4425,6 +5667,7 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
   }
   return rc;  
 }
+#endif /* SQLITE_OMIT_VACUUM */
 
 /*
 ** Return non-zero if a transaction is active.
@@ -4456,7 +5699,15 @@ int sqlite3BtreeIsInStmt(Btree *pBt){
 */
 int sqlite3BtreeSync(Btree *pBt, const char *zMaster){
   if( pBt->inTrans==TRANS_WRITE ){
-    return sqlite3pager_sync(pBt->pPager, zMaster);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    Pgno nTrunc = 0;
+    if( pBt->autoVacuum ){
+      int 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);
   }
   return SQLITE_OK;
 }
index 48524aefc185b3f2fdf1a4cb4f350c038d31e903..d4ee97ef38e8390d73387f994643956f2dd8b694 100644 (file)
 */
 #define SQLITE_N_BTREE_META 10
 
+/*
+** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
+** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
+*/
+#ifndef SQLITE_DEFAULT_AUTOVACUUM
+  #define SQLITE_DEFAULT_AUTOVACUUM 0
+#endif
+
 /*
 ** Forward declarations of structure
 */
@@ -38,9 +46,13 @@ int sqlite3BtreeOpen(
 
 /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
 ** following values.
+**
+** NOTE:  These values must match the corresponding PAGER_ values in
+** pager.h.
 */
 #define BTREE_OMIT_JOURNAL  1  /* Do not use journal.  No argument */
-#define BTREE_MEMORY        2  /* In-memory DB.  No argument */
+#define BTREE_NO_READLOCK   2  /* Omit readlocks on readonly files */
+#define BTREE_MEMORY        4  /* In-memory DB.  No argument */
 
 int sqlite3BtreeClose(Btree*);
 int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
@@ -49,6 +61,8 @@ int sqlite3BtreeSetSafetyLevel(Btree*,int);
 int sqlite3BtreeSetPageSize(Btree*,int,int);
 int sqlite3BtreeGetPageSize(Btree*);
 int sqlite3BtreeGetReserve(Btree*);
+int sqlite3BtreeSetAutoVacuum(Btree *, int);
+int sqlite3BtreeGetAutoVacuum(Btree *);
 int sqlite3BtreeBeginTrans(Btree*,int);
 int sqlite3BtreeCommit(Btree*);
 int sqlite3BtreeRollback(Btree*);
@@ -72,7 +86,7 @@ int sqlite3BtreeCopyFile(Btree *, Btree *);
 #define BTREE_ZERODATA   2    /* Table has keys only - no data */
 #define BTREE_LEAFDATA   4    /* Data stored in leaves only.  Implies INTKEY */
 
-int sqlite3BtreeDropTable(Btree*, int);
+int sqlite3BtreeDropTable(Btree*, int, int*);
 int sqlite3BtreeClearTable(Btree*, int);
 int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
 int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
@@ -117,8 +131,12 @@ struct Pager *sqlite3BtreePager(Btree*);
 #ifdef SQLITE_TEST
 int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
 void sqlite3BtreeCursorList(Btree*);
-int sqlite3BtreePageDump(Btree*, int, int recursive);
 #endif
 
+#ifdef SQLITE_DEBUG
+int sqlite3BtreePageDump(Btree*, int, int recursive);
+#else
+#define sqlite3BtreePageDump(X,Y,Z) SQLITE_OK
+#endif
 
 #endif /* _BTREE_H_ */
index 3e5e08a54198bc3dfc12f3628d2b3e38820acea0..1908a4711852b5ca90bcd25267e9bf4a7ea05379 100644 (file)
@@ -21,7 +21,6 @@
 **     BEGIN TRANSACTION
 **     COMMIT
 **     ROLLBACK
-**     PRAGMA
 **
 ** $Id$
 */
@@ -30,9 +29,7 @@
 
 /*
 ** This routine is called when a new SQL statement is beginning to
-** be parsed.  Check to see if the schema for the database needs
-** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables.
-** If it does, then read it.
+** be parsed.  Initialize the pParse structure as needed.
 */
 void sqlite3BeginParse(Parse *pParse, int explainFlag){
   pParse->explain = explainFlag;
@@ -54,6 +51,13 @@ void sqlite3FinishCoding(Parse *pParse){
   Vdbe *v;
 
   if( sqlite3_malloc_failed ) return;
+  if( pParse->nested ) return;
+  if( !pParse->pVdbe ){
+    if( pParse->rc==SQLITE_OK && pParse->nErr ){
+      pParse->rc = SQLITE_ERROR;
+    }
+    return;
+  }
 
   /* Begin by generating some termination code at the end of the
   ** vdbe program
@@ -85,7 +89,7 @@ void sqlite3FinishCoding(Parse *pParse){
     ** statement as its P3 argument.  This does not change the functionality
     ** of the program. 
     **
-    ** This is used to implement sqlite3_trace() functionality.
+    ** This is used to implement sqlite3_trace().
     */
     sqlite3VdbeOp3(v, OP_Noop, 0, 0, pParse->zSql, pParse->zTail-pParse->zSql);
   }
@@ -97,8 +101,8 @@ void sqlite3FinishCoding(Parse *pParse){
     FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
     sqlite3VdbeTrace(v, trace);
     sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,
-                         pParse->nTab+3, pParse->explain);
-    pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE;
+                         pParse->nTab+3, pParse->nMaxDepth+1, pParse->explain);
+    pParse->rc = SQLITE_DONE;
     pParse->colNamesSet = 0;
   }else if( pParse->rc==SQLITE_OK ){
     pParse->rc = SQLITE_ERROR;
@@ -106,12 +110,47 @@ void sqlite3FinishCoding(Parse *pParse){
   pParse->nTab = 0;
   pParse->nMem = 0;
   pParse->nSet = 0;
-  pParse->nAgg = 0;
   pParse->nVar = 0;
   pParse->cookieMask = 0;
   pParse->cookieGoto = 0;
 }
 
+/*
+** Run the parser and code generator recursively in order to generate
+** code for the SQL statement given onto the end of the pParse context
+** currently under construction.  When the parser is run recursively
+** this way, the final OP_Halt is not appended and other initialization
+** and finalization steps are omitted because those are handling by the
+** outermost parser.
+**
+** Not everything is nestable.  This facility is designed to permit
+** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER.  Use
+** care if you decide to try to use this routine for some other purposes.
+*/
+void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
+  va_list ap;
+  char *zSql;
+  int rc;
+# define SAVE_SZ  (sizeof(Parse) - offsetof(Parse,nVar))
+  char saveBuf[SAVE_SZ];
+
+  if( pParse->nErr ) return;
+  assert( pParse->nested<10 );  /* Nesting should only be of limited depth */
+  va_start(ap, zFormat);
+  zSql = sqlite3VMPrintf(zFormat, ap);
+  va_end(ap);
+  if( zSql==0 ){
+    return;   /* A malloc must have failed */
+  }
+  pParse->nested++;
+  memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
+  memset(&pParse->nVar, 0, SAVE_SZ);
+  rc = sqlite3RunParser(pParse, zSql, 0);
+  sqliteFree(zSql);
+  memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
+  pParse->nested--;
+}
+
 /*
 ** Locate the in-memory structure that describes a particular database
 ** table given the name of that table and (optionally) the name of the
@@ -279,8 +318,7 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
     sqlite3HashClear(&pDb->aFKey);
     sqlite3HashClear(&pDb->idxHash);
     for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
-      Trigger *pTrigger = sqliteHashData(pElem);
-      sqlite3DeleteTrigger(pTrigger);
+      sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem));
     }
     sqlite3HashClear(&temp2);
     sqlite3HashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0);
@@ -289,6 +327,7 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
       sqlite3DeleteTable(db, pTab);
     }
     sqlite3HashClear(&temp1);
+    pDb->pSeqTab = 0;
     DbClearProperty(db, i, DB_SchemaLoaded);
     if( iDb>0 ) return;
   }
@@ -356,7 +395,7 @@ static void sqliteResetColumnNames(Table *pTable){
   assert( pTable!=0 );
   for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
     sqliteFree(pCol->zName);
-    sqliteFree(pCol->zDflt);
+    sqlite3ExprDelete(pCol->pDflt);
     sqliteFree(pCol->zType);
   }
   sqliteFree(pTable->aCol);
@@ -393,6 +432,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
     sqliteDeleteIndex(db, pIndex);
   }
 
+#ifndef SQLITE_OMIT_FOREIGN_KEY
   /* Delete all foreign keys associated with this table.  The keys
   ** should have already been unlinked from the db->aFKey hash table 
   */
@@ -403,6 +443,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
                            pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
     sqliteFree(pFKey);
   }
+#endif
 
   /* Delete the Table structure itself.
   */
@@ -428,6 +469,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
   pDb = &db->aDb[iDb];
   p = sqlite3HashInsert(&pDb->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);
@@ -440,6 +482,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
         }
       }
     }
+#endif
     sqlite3DeleteTable(db, p);
   }
   db->flags |= SQLITE_InternChanges;
@@ -482,16 +525,23 @@ void sqlite3OpenMasterTable(Vdbe *v, int iDb){
 ** index of the named database in db->aDb[], or -1 if the named db 
 ** does not exist.
 */
-int findDb(sqlite3 *db, Token *pName){
-  int i;
-  Db *pDb;
-  for(pDb=db->aDb, i=0; i<db->nDb; i++, pDb++){
-    if( pName->n==strlen(pDb->zName) && 
-        0==sqlite3StrNICmp(pDb->zName, pName->z, pName->n) ){
-      return i;
+static int findDb(sqlite3 *db, Token *pName){
+  int i = -1;    /* Database number */
+  int n;         /* Number of characters in the name */
+  Db *pDb;       /* A database whose name space is being searched */
+  char *zName;   /* Name we are searching for */
+
+  zName = sqlite3NameFromToken(pName);
+  if( zName ){
+    n = strlen(zName);
+    for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
+      if( n==strlen(pDb->zName) && 0==sqlite3StrICmp(pDb->zName, zName) ){
+        break;
+      }
     }
+    sqliteFree(zName);
   }
-  return -1;
+  return i;
 }
 
 /* The table or view or trigger name is passed to this routine via tokens
@@ -544,7 +594,8 @@ int sqlite3TwoPartName(
 ** is reserved for internal use.
 */
 int sqlite3CheckObjectName(Parse *pParse, const char *zName){
-  if( !pParse->db->init.busy && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
+  if( !pParse->db->init.busy && pParse->nested==0 
+          && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
     sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
     return SQLITE_ERROR;
   }
@@ -578,7 +629,7 @@ void sqlite3StartTable(
 ){
   Table *pTable;
   Index *pIdx;
-  char *zName;
+  char *zName = 0; /* The name of the new table */
   sqlite3 *db = pParse->db;
   Vdbe *v;
   int iDb;         /* Database number to create the table in */
@@ -606,7 +657,6 @@ void sqlite3StartTable(
   if( isTemp && iDb>1 ){
     /* If creating a temp table, the name may not be qualified */
     sqlite3ErrorMsg(pParse, "temporary table name must be unqualified");
-    pParse->nErr++;
     return;
   }
   if( isTemp ) iDb = 1;
@@ -615,8 +665,7 @@ void sqlite3StartTable(
   zName = sqlite3NameFromToken(pName);
   if( zName==0 ) return;
   if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
-    sqliteFree(zName);
-    return;
+    goto begin_table_error;
   }
   if( db->init.iDb==1 ) isTemp = 1;
 #ifndef SQLITE_OMIT_AUTHORIZATION
@@ -625,8 +674,7 @@ void sqlite3StartTable(
     int code;
     char *zDb = db->aDb[iDb].zName;
     if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
-      sqliteFree(zName);
-      return;
+      goto begin_table_error;
     }
     if( isView ){
       if( isTemp ){
@@ -642,8 +690,7 @@ void sqlite3StartTable(
       }
     }
     if( sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){
-      sqliteFree(zName);
-      return;
+      goto begin_table_error;
     }
   }
 #endif
@@ -652,25 +699,24 @@ void sqlite3StartTable(
   ** index or table name in the same database.  Issue an error message if
   ** it does.
   */
-  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) return;
+  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);
-    sqliteFree(zName);
-    return;
+    goto begin_table_error;
   }
   if( (pIdx = sqlite3FindIndex(db, zName, 0))!=0 && 
       ( iDb==0 || !db->init.busy) ){
     sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
-    sqliteFree(zName);
-    return;
+    goto begin_table_error;
   }
   pTable = sqliteMalloc( sizeof(Table) );
   if( pTable==0 ){
     pParse->rc = SQLITE_NOMEM;
     pParse->nErr++;
-    sqliteFree(zName);
-    return;
+    goto begin_table_error;
   }
   pTable->zName = zName;
   pTable->nCol = 0;
@@ -681,6 +727,16 @@ void sqlite3StartTable(
   if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable);
   pParse->pNewTable = pTable;
 
+  /* If this is the magic sqlite_sequence table used by autoincrement,
+  ** then record a pointer to this table in the main database structure
+  ** so that INSERT can find the table easily.
+  */
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+  if( strcmp(zName, "sqlite_sequence")==0 ){
+    db->aDb[iDb].pSeqTab = pTable;
+  }
+#endif
+
   /* Begin generating the code that will insert the table record into
   ** the SQLITE_MASTER table.  Note in particular that we must go ahead
   ** and allocate the record number for the table entry now.  Before any
@@ -690,24 +746,68 @@ void sqlite3StartTable(
   ** now.
   */
   if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){
+    int lbl;
     sqlite3BeginWriteOperation(pParse, 0, iDb);
-    /* Every time a new table is created the file-format
-    ** and encoding meta-values are set in the database, in
-    ** case this is the first table created.
+
+    /* 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);
     sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1);
     sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0);
     sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4);
+    sqlite3VdbeResolveLabel(v, lbl);
 
+    /* This just creates a place-holder record in the sqlite_master table.
+    ** The record created does not contain anything yet.  It will be replaced
+    ** by the real entry in code generated at sqlite3EndTable().
+    **
+    ** The rowid for the new entry is left on the top of the stack.
+    ** The rowid value is needed by the code that sqlite3EndTable will
+    ** generate.
+    */
+#ifndef SQLITE_OMIT_VIEW
+    if( isView ){
+      sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
+    }else
+#endif
+    {
+      sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0);
+    }
     sqlite3OpenMasterTable(v, iDb);
     sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0);
     sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
     sqlite3VdbeAddOp(v, OP_String8, 0, 0);
     sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
+    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+    sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
   }
+
+  /* Normal (non-error) return. */
+  return;
+
+  /* If an error occurs, we jump here */
+begin_table_error:
+  sqliteFree(zName);
+  return;
 }
 
+/*
+** This macro is used to compare two strings in a case-insensitive manner.
+** It is slightly faster than calling sqlite3StrICmp() directly, but
+** produces larger code.
+**
+** WARNING: This macro is not compatible with the strcmp() family. It
+** returns true if the two strings are equal, otherwise false.
+*/
+#define STRICMP(x, y) (\
+sqlite3UpperToLower[*(unsigned char *)(x)]==   \
+sqlite3UpperToLower[*(unsigned char *)(y)]     \
+&& sqlite3StrICmp((x)+1,(y)+1)==0 )
+
 /*
 ** Add a new column to the table currently being constructed.
 **
@@ -725,7 +825,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
   z = sqlite3NameFromToken(pName);
   if( z==0 ) return;
   for(i=0; i<p->nCol; i++){
-    if( sqlite3StrICmp(z, p->aCol[i].zName)==0 ){
+    if( STRICMP(z, p->aCol[i].zName) ){
       sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
       sqliteFree(z);
       return;
@@ -764,6 +864,55 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
   if( i>=0 ) p->aCol[i].notNull = onError;
 }
 
+/*
+** Scan the column type name zType (length nType) and return the
+** associated affinity type.
+**
+** This routine does a case-independent search of zType for the 
+** substrings in the following table. If one of the substrings is
+** found, the corresponding affinity is returned. If zType contains
+** more than one of the substrings, entries toward the top of 
+** the table take priority. For example, if zType is 'BLOBINT', 
+** SQLITE_AFF_INTEGER is returned.
+**
+** Substring     | Affinity
+** --------------------------------
+** 'INT'         | SQLITE_AFF_INTEGER
+** 'CHAR'        | SQLITE_AFF_TEXT
+** 'CLOB'        | SQLITE_AFF_TEXT
+** 'TEXT'        | SQLITE_AFF_TEXT
+** 'BLOB'        | SQLITE_AFF_NONE
+**
+** If none of the substrings in the above table are found,
+** SQLITE_AFF_NUMERIC is returned.
+*/
+static char sqlite3AffinityType(const char *zType, int nType){
+  u32 h = 0;
+  char aff = SQLITE_AFF_NUMERIC;
+  const unsigned char *zIn = zType;
+  const unsigned char *zEnd = (zIn+nType);
+
+  while( zIn!=zEnd ){
+    h = (h<<8) + sqlite3UpperToLower[*zIn];
+    zIn++;
+    if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){             /* CHAR */
+      aff = SQLITE_AFF_TEXT; 
+    }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){       /* CLOB */
+      aff = SQLITE_AFF_TEXT;
+    }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_NONE;
+    }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){    /* INT */
+      aff = SQLITE_AFF_INTEGER; 
+      break;
+    }
+  }
+
+  return aff;
+}
+
 /*
 ** This routine is called by the parser while in the middle of
 ** parsing a CREATE TABLE statement.  The pFirst token is the first
@@ -777,19 +926,21 @@ void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
   Table *p;
   int i, j;
   int n;
-  char *z, **pz;
+  char *z;
+  const unsigned char *zIn;
+
   Column *pCol;
   if( (p = pParse->pNewTable)==0 ) return;
   i = p->nCol-1;
   if( i<0 ) return;
   pCol = &p->aCol[i];
-  pz = &pCol->zType;
-  n = pLast->n + (pLast->z - pFirst->z);
+  zIn = pFirst->z;
+  n = pLast->n + (pLast->z - zIn);
   assert( pCol->zType==0 );
-  z = pCol->zType = sqlite3MPrintf("%.*s", n, pFirst->z);
+  z = pCol->zType = sqliteMallocRaw(n+1);
   if( z==0 ) return;
-  for(i=j=0; z[i]; i++){
-    int c = z[i];
+  for(i=j=0; i<n; i++){
+    int c = zIn[i];
     if( isspace(c) ) continue;
     z[j++] = c;
   }
@@ -798,23 +949,28 @@ void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
 }
 
 /*
-** The given token is the default value for the last column added to
-** the table currently under construction.  If "minusFlag" is true, it
-** means the value token was preceded by a minus sign.
+** The expression is the default value for the most recently added column
+** of the table currently under construction.
+**
+** Default value expressions must be constant.  Raise an exception if this
+** is not the case.
 **
 ** This routine is called by the parser while in the middle of
 ** parsing a CREATE TABLE statement.
 */
-void sqlite3AddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
+void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
   Table *p;
-  int i;
-  char *z;
+  Column *pCol;
   if( (p = pParse->pNewTable)==0 ) return;
-  i = p->nCol-1;
-  if( i<0 ) return;
-  assert( p->aCol[i].zDflt==0 );
-  z = p->aCol[i].zDflt = sqlite3MPrintf("%s%T", minusFlag ? "-" : "", pVal);
-  sqlite3Dequote(z);
+  pCol = &(p->aCol[p->nCol-1]);
+  if( !sqlite3ExprIsConstant(pExpr) ){
+    sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
+        pCol->zName);
+  }else{
+    sqlite3ExprDelete(pCol->pDflt);
+    pCol->pDflt = sqlite3ExprDup(pExpr);
+  }
+  sqlite3ExprDelete(pExpr);
 }
 
 /*
@@ -827,9 +983,7 @@ void sqlite3AddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
 ** error.
 **
 ** If the PRIMARY KEY is on a single column whose datatype is INTEGER,
-** then we will try to use that column as the row id.  (Exception:
-** For backwards compatibility with older databases, do not do this
-** if the file format version number is less than 1.)  Set the Table.iPKey
+** then we will try to use that column as the rowid.  Set the Table.iPKey
 ** field of the table under construction to be the index of the
 ** INTEGER PRIMARY KEY column.  Table.iPKey is set to -1 if there is
 ** no INTEGER PRIMARY KEY.
@@ -837,7 +991,12 @@ void sqlite3AddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
 ** If the key is not an INTEGER PRIMARY KEY, then create a unique
 ** index for the key.  No index is created for INTEGER PRIMARY KEYs.
 */
-void sqlite3AddPrimaryKey(Parse *pParse, ExprList *pList, int onError){
+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 */
+){
   Table *pTab = pParse->pNewTable;
   char *zType = 0;
   int iCol = -1, i;
@@ -868,6 +1027,12 @@ void sqlite3AddPrimaryKey(Parse *pParse, ExprList *pList, int onError){
   if( zType && sqlite3StrICmp(zType, "INTEGER")==0 ){
     pTab->iPKey = iCol;
     pTab->keyConf = onError;
+    pTab->autoInc = autoInc;
+  }else if( autoInc ){
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+    sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
+       "INTEGER PRIMARY KEY");
+#endif
   }else{
     sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0);
     pList = 0;
@@ -980,6 +1145,7 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
     db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal);
     sqliteFree(zExternal);
   }
+#ifndef SQLITE_OMIT_UTF16
   if( db->xCollNeeded16 ){
     char const *zExternal;
     sqlite3_value *pTmp = sqlite3GetTransientValue(db);
@@ -988,6 +1154,7 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
     if( !zExternal ) return;
     db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal);
   }
+#endif
 }
 
 /*
@@ -1105,44 +1272,6 @@ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
 }
 
 
-
-/*
-** Scan the column type name zType (length nType) and return the
-** associated affinity type.
-*/
-char sqlite3AffinityType(const char *zType, int nType){
-  int n, i;
-  static const struct {
-    const char *zSub;  /* Keywords substring to search for */
-    char nSub;         /* length of zSub */
-    char affinity;     /* Affinity to return if it matches */
-  } substrings[] = {
-    {"INT",  3, SQLITE_AFF_INTEGER},
-    {"CHAR", 4, SQLITE_AFF_TEXT},
-    {"CLOB", 4, SQLITE_AFF_TEXT},
-    {"TEXT", 4, SQLITE_AFF_TEXT},
-    {"BLOB", 4, SQLITE_AFF_NONE},
-  };
-
-  if( nType==0 ){
-    return SQLITE_AFF_NONE;
-  }
-  for(i=0; i<sizeof(substrings)/sizeof(substrings[0]); i++){
-    int c1 = substrings[i].zSub[0];
-    int c2 = tolower(c1);
-    int limit = nType - substrings[i].nSub;
-    const char *z = substrings[i].zSub;
-    for(n=0; n<=limit; n++){
-      int c = zType[n];
-      if( (c==c1 || c==c2)
-             && 0==sqlite3StrNICmp(&zType[n], z, substrings[i].nSub) ){
-        return substrings[i].affinity;
-      }
-    }
-  }
-  return SQLITE_AFF_NUMERIC;
-}
-
 /*
 ** Generate code that will increment the schema cookie.
 **
@@ -1303,20 +1432,33 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
   if( !db->init.busy ){
     int n;
     Vdbe *v;
+    char *zType;    /* "view" or "table" */
+    char *zType2;   /* "VIEW" or "TABLE" */
+    char *zStmt;    /* Text of the CREATE TABLE or CREATE VIEW statement */
 
     v = sqlite3GetVdbe(pParse);
     if( v==0 ) return;
 
+    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+
+    /* Create the rootpage for the new table and push it onto the stack.
+    ** A view has no rootpage, so just push a zero onto the stack for
+    ** views.  Initialize zType at the same time.
+    */
     if( p->pSelect==0 ){
       /* A regular table */
-      sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0);
+      /* sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0); */
+      zType = "table";
+      zType2 = "TABLE";
+#ifndef SQLITE_OMIT_VIEW
     }else{
       /* A view */
-      sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
+    /*  sqlite3VdbeAddOp(v, OP_Integer, 0, 0); */
+      zType = "view";
+      zType2 = "VIEW";
+#endif
     }
 
-    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
-
     /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
     ** statement to populate the new table. The root-page number for the
     ** new table is on the top of the vdbe stack.
@@ -1344,40 +1486,55 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
         sqlite3DeleteTable(0, pSelTab);
       }
     }
-  
-    sqlite3OpenMasterTable(v, p->iDb);
-
-    sqlite3VdbeOp3(v, OP_String8, 0, 0, p->pSelect==0?"table":"view",P3_STATIC);
-    sqlite3VdbeOp3(v, OP_String8, 0, 0, p->zName, 0);
-    sqlite3VdbeOp3(v, OP_String8, 0, 0, p->zName, 0);
-    sqlite3VdbeAddOp(v, OP_Pull, 3, 0);
 
+    /* Compute the complete text of the CREATE statement */
     if( pSelect ){
-      char *z = createTableStmt(p);
-      n = z ? strlen(z) : 0;
-      sqlite3VdbeAddOp(v, OP_String8, 0, 0);
-      sqlite3VdbeChangeP3(v, -1, z, n);
-      sqliteFree(z);
+      zStmt = createTableStmt(p);
     }else{
-      if( p->pSelect ){
-        sqlite3VdbeOp3(v, OP_String8, 0, 0, "CREATE VIEW ", P3_STATIC);
-      }else{
-        sqlite3VdbeOp3(v, OP_String8, 0, 0, "CREATE TABLE ", P3_STATIC);
-      }
-      assert( pEnd!=0 );
       n = Addr(pEnd->z) - Addr(pParse->sNameToken.z) + 1;
-      sqlite3VdbeAddOp(v, OP_String8, 0, 0);
-      sqlite3VdbeChangeP3(v, -1, pParse->sNameToken.z, n);
-      sqlite3VdbeAddOp(v, OP_Concat, 0, 0);
+      zStmt = sqlite3MPrintf("CREATE %s %.*s", zType2, n, pParse->sNameToken.z);
     }
-    sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC);
-    sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
+
+    /* A slot for the record has already been allocated in the 
+    ** SQLITE_MASTER table.  We just need to update that slot with all
+    ** the information we've collected.  The rowid for the preallocated
+    ** slot is the 2nd item on the stack.  The top of the stack is the
+    ** root page for the new table (or a 0 if this is a view).
+    */
+    sqlite3NestedParse(pParse,
+      "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),
+      zType,
+      p->zName,
+      p->zName,
+      zStmt
+    );
+    sqliteFree(zStmt);
     sqlite3ChangeCookie(db, v, p->iDb);
-    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+
+#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 ){
+        sqlite3NestedParse(pParse,
+          "CREATE TABLE %Q.sqlite_sequence(name,seq)",
+          pDb->zName
+        );
+      }
+    }
+#endif
+
+    /* Reparse everything to update our internal data structures */
     sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0,
         sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC);
   }
 
+
   /* Add the table to the in-memory representation of the database.
   */
   if( db->init.busy && pParse->nErr==0 ){
@@ -1389,17 +1546,20 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
       assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
       return;
     }
+#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);
     }
+#endif
     pParse->pNewTable = 0;
     db->nTable++;
     db->flags |= SQLITE_InternChanges;
   }
 }
 
+#ifndef SQLITE_OMIT_VIEW
 /*
 ** The parser calls this routine in order to create a new VIEW
 */
@@ -1461,17 +1621,19 @@ void sqlite3CreateView(
   sqlite3EndTable(pParse, &sEnd, 0);
   return;
 }
+#endif /* SQLITE_OMIT_VIEW */
 
+#ifndef SQLITE_OMIT_VIEW
 /*
 ** 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
 ** of errors.  If an error is seen leave an error message in pParse->zErrMsg.
 */
 int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
-  ExprList *pEList;
-  Select *pSel;
-  Table *pSelTab;
-  int nErr = 0;
+  Table *pSelTab;   /* A fake table from which we get the result set */
+  Select *pSel;     /* Copy of the SELECT that implements the view */
+  int nErr = 0;     /* Number of errors encountered */
+  int n;            /* Temporarily holds the number of cursors assigned */
 
   assert( pTable );
 
@@ -1496,23 +1658,19 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
   }
 
   /* If we get this far, it means we need to compute the table names.
+  ** Note that the call to sqlite3ResultSetOfSelect() will expand any
+  ** "*" elements in the results set of the view and will assign cursors
+  ** to the elements of the FROM clause.  But we do not want these changes
+  ** to be permanent.  So the computation is done on a copy of the SELECT
+  ** statement that defines the view.
   */
-  assert( pTable->pSelect ); /* If nCol==0, then pTable must be a VIEW */
-  pSel = pTable->pSelect;
-
-  /* Note that the call to sqlite3ResultSetOfSelect() will expand any
-  ** "*" elements in this list.  But we will need to restore the list
-  ** back to its original configuration afterwards, so we save a copy of
-  ** the original in pEList.
-  */
-  pEList = pSel->pEList;
-  pSel->pEList = sqlite3ExprListDup(pEList);
-  if( pSel->pEList==0 ){
-    pSel->pEList = pEList;
-    return 1;  /* Malloc failed */
-  }
+  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;
@@ -1525,12 +1683,12 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
     pTable->nCol = 0;
     nErr++;
   }
-  sqlite3SelectUnbind(pSel);
-  sqlite3ExprListDelete(pSel->pEList);
-  pSel->pEList = pEList;
+  sqlite3SelectDelete(pSel);
   return nErr;  
 }
+#endif /* SQLITE_OMIT_VIEW */
 
+#ifndef SQLITE_OMIT_VIEW
 /*
 ** Clear the column names from every VIEW in database idx.
 */
@@ -1545,6 +1703,115 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
   }
   DbClearProperty(db, idx, DB_UnresetViews);
 }
+#else
+# define sqliteViewResetAll(A,B)
+#endif /* SQLITE_OMIT_VIEW */
+
+/*
+** This function is called by the VDBE to adjust the internal schema
+** 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.
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
+  HashElem *pElem;
+  
+  for(pElem=sqliteHashFirst(&pDb->tblHash); 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)){
+    Index *pIdx = sqliteHashData(pElem);
+    if( pIdx->tnum==iFrom ){
+      pIdx->tnum = iTo;
+      return;
+    }
+  }
+  assert(0);
+}
+#endif
+
+/*
+** Write code to erase the table with root-page iTable from database iDb.
+** Also write code to modify the sqlite_master table and internal schema
+** if a root-page of another table is moved by the btree-layer whilst
+** erasing iTable (this can happen with an auto-vacuum database).
+*/ 
+static void destroyRootPage(Parse *pParse, int iTable, int iDb){
+  Vdbe *v = sqlite3GetVdbe(pParse);
+  sqlite3VdbeAddOp(v, OP_Destroy, iTable, iDb);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  /* OP_Destroy pushes an integer onto the stack. If this integer
+  ** is non-zero, then it is the root page number of a table moved to
+  ** location iTable. The following code modifies the sqlite_master table to
+  ** reflect this.
+  **
+  ** The "#0" in the SQL is a special constant that means whatever value
+  ** is on the top of the stack.  See sqlite3RegisterExpr().
+  */
+  sqlite3NestedParse(pParse, 
+     "UPDATE %Q.%s SET rootpage=%d WHERE #0 AND rootpage=#0",
+     pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable);
+#endif
+}
+
+/*
+** Write VDBE code to erase table pTab and all associated indices on disk.
+** Code to update the sqlite_master tables and internal schema definitions
+** in case a root-page belonging to another table is moved by the btree layer
+** is also added (this can happen with an auto-vacuum database).
+*/
+static void destroyTable(Parse *pParse, Table *pTab){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+  Index *pIdx;
+  destroyRootPage(pParse, pTab->tnum, pTab->iDb);
+  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+    destroyRootPage(pParse, pIdx->tnum, pIdx->iDb);
+  }
+#else
+  /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
+  ** is not defined), then it is important to call OP_Destroy on the
+  ** table and index root-pages in order, starting with the numerically 
+  ** largest root-page number. This guarantees that none of the root-pages
+  ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
+  ** following were coded:
+  **
+  ** OP_Destroy 4 0
+  ** ...
+  ** OP_Destroy 5 0
+  **
+  ** and root page 5 happened to be the largest root-page number in the
+  ** database, then root page 5 would be moved to page 4 by the 
+  ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
+  ** a free-list page.
+  */
+  int iTab = pTab->tnum;
+  int iDestroyed = 0;
+
+  while( 1 ){
+    Index *pIdx;
+    int iLargest = 0;
+
+    if( iDestroyed==0 || iTab<iDestroyed ){
+      iLargest = iTab;
+    }
+    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+      int iIdx = pIdx->tnum;
+      assert( pIdx->iDb==pTab->iDb );
+      if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){
+        iLargest = iIdx;
+      }
+    }
+    if( iLargest==0 ) return;
+    destroyRootPage(pParse, iLargest, pTab->iDb);
+    iDestroyed = iLargest;
+  }
+#endif
+}
 
 /*
 ** This routine is called to do the work of a DROP TABLE statement.
@@ -1553,7 +1820,6 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
 void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
   Table *pTab;
   Vdbe *v;
-  int base;
   sqlite3 *db = pParse->db;
   int iDb;
 
@@ -1593,11 +1859,15 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
     }
   }
 #endif
-  if( pTab->readOnly ){
+  if( pTab->readOnly || pTab==db->aDb[iDb].pSeqTab ){
     sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
-    pParse->nErr++;
     goto exit_drop_table;
   }
+
+#ifndef SQLITE_OMIT_VIEW
+  /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
+  ** on a table.
+  */
   if( isView && pTab->pSelect==0 ){
     sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
     goto exit_drop_table;
@@ -1606,30 +1876,17 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
     sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
     goto exit_drop_table;
   }
+#endif
 
   /* Generate code to remove the table from the master table
   ** on disk.
   */
   v = sqlite3GetVdbe(pParse);
   if( v ){
-    static const VdbeOpList dropTable[] = {
-      { OP_Rewind,     0, ADDR(13), 0},
-      { OP_String8,    0, 0,        0}, /* 1 */
-      { OP_MemStore,   1, 1,        0},
-      { OP_MemLoad,    1, 0,        0}, /* 3 */
-      { OP_Column,     0, 2,        0}, /* sqlite_master.tbl_name */
-      { OP_Ne,         0, ADDR(12), 0},
-      { OP_String8,    0, 0,        "trigger"},
-      { OP_Column,     0, 2,        0}, /* sqlite_master.type */
-      { OP_Eq,         0, ADDR(12), 0},
-      { OP_Delete,     0, 0,        0},
-      { OP_Rewind,     0, ADDR(13), 0},
-      { OP_Goto,       0, ADDR(3),  0},
-      { OP_Next,       0, ADDR(3),  0}, /* 12 */
-    };
-    Index *pIdx;
     Trigger *pTrigger;
-    sqlite3BeginWriteOperation(pParse, 0, pTab->iDb);
+    int iDb = pTab->iDb;
+    Db *pDb = &db->aDb[iDb];
+    sqlite3BeginWriteOperation(pParse, 0, iDb);
 
     /* Drop all triggers associated with the table being dropped. Code
     ** is generated to remove entries from sqlite_master and/or
@@ -1637,11 +1894,25 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
     */
     pTrigger = pTab->pTrigger;
     while( pTrigger ){
-      assert( pTrigger->iDb==pTab->iDb || pTrigger->iDb==1 );
+      assert( pTrigger->iDb==iDb || pTrigger->iDb==1 );
       sqlite3DropTriggerPtr(pParse, pTrigger, 1);
       pTrigger = pTrigger->pNext;
     }
 
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+    /* Remove any entries of the sqlite_sequence table associated with
+    ** the table being dropped. This is done before the table is dropped
+    ** at the btree level, in case the sqlite_sequence table needs to
+    ** move as a result of the drop (can happen in auto-vacuum mode).
+    */
+    if( pTab->autoInc ){
+      sqlite3NestedParse(pParse,
+        "DELETE FROM %s.sqlite_sequence WHERE name=%Q",
+        pDb->zName, pTab->zName
+      );
+    }
+#endif
+
     /* Drop all SQLITE_MASTER table and index entries that refer to the
     ** table. The program name loops through the master table and deletes
     ** every row that refers to a table of the same name as the one being
@@ -1649,18 +1920,18 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
     ** created in the temp database that refers to a table in another
     ** database.
     */
-    sqlite3OpenMasterTable(v, pTab->iDb);
-    base = sqlite3VdbeAddOpList(v, ArraySize(dropTable), dropTable);
-    sqlite3VdbeChangeP3(v, base+1, pTab->zName, 0);
-    sqlite3ChangeCookie(db, v, pTab->iDb);
-    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+    sqlite3NestedParse(pParse, 
+        "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
+        pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
     if( !isView ){
-      sqlite3VdbeAddOp(v, OP_Destroy, pTab->tnum, pTab->iDb);
-      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
-        sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
-      }
+      destroyTable(pParse, pTab);
     }
-    sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0);
+
+    /* Remove the table entry from SQLite's internal schema and modify
+    ** the schema cookie.
+    */
+    sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
+    sqlite3ChangeCookie(db, v, iDb);
   }
   sqliteViewResetAll(db, iDb);
 
@@ -1693,12 +1964,13 @@ void sqlite3CreateForeignKey(
   ExprList *pToCol,    /* Columns in the other table */
   int flags            /* Conflict resolution algorithms. */
 ){
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+  FKey *pFKey = 0;
   Table *p = pParse->pNewTable;
   int nByte;
   int i;
   int nCol;
   char *z;
-  FKey *pFKey = 0;
 
   assert( pTo!=0 );
   if( p==0 || pParse->nErr ) goto fk_end;
@@ -1779,6 +2051,7 @@ void sqlite3CreateForeignKey(
 
 fk_end:
   sqliteFree(pFKey);
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
   sqlite3ExprListDelete(pFromCol);
   sqlite3ExprListDelete(pToCol);
 }
@@ -1791,15 +2064,80 @@ fk_end:
 ** accordingly.
 */
 void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
+#ifndef SQLITE_OMIT_FOREIGN_KEY
   Table *pTab;
   FKey *pFKey;
   if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
   pFKey->isDeferred = isDeferred;
+#endif
+}
+
+/*
+** Generate code that will erase and refill index *pIdx.  This is
+** used to initialize a newly created index or to recompute the
+** content of an index in response to a REINDEX command.
+**
+** if memRootPage is not negative, it means that the index is newly
+** created.  The memory cell specified by memRootPage contains the
+** root page number of the index.  If memRootPage is negative, then
+** the index already exists and must be cleared before being refilled and
+** the root page number of the index is taken from pIndex->tnum.
+*/
+static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
+  Table *pTab = pIndex->pTable;  /* The table that is indexed */
+  int iTab = pParse->nTab;       /* Btree cursor used for pTab */
+  int iIdx = pParse->nTab+1;     /* Btree cursor used for pIndex */
+  int addr1;                     /* Address of top of loop */
+  int tnum;                      /* Root page of index */
+  Vdbe *v;                       /* Generate code into this virtual machine */
+  int isUnique;                  /* True for a unique index */
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+  if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
+      pParse->db->aDb[pIndex->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;
+  }
+
+  v = sqlite3GetVdbe(pParse);
+  if( v==0 ) return;
+  if( memRootPage>=0 ){
+    sqlite3VdbeAddOp(v, OP_MemLoad, memRootPage, 0);
+    tnum = 0;
+  }else{
+    tnum = pIndex->tnum;
+    sqlite3VdbeAddOp(v, OP_Clear, tnum, pIndex->iDb);
+  }
+  sqlite3VdbeAddOp(v, OP_Integer, pIndex->iDb, 0);
+  sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum,
+                    (char*)&pIndex->keyInfo, P3_KEYINFO);
+  sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
+  sqlite3VdbeAddOp(v, OP_OpenRead, iTab, pTab->tnum);
+  sqlite3VdbeAddOp(v, OP_SetNumColumns, iTab, pTab->nCol);
+  addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
+  sqlite3GenerateIndexKey(v, pIndex, iTab);
+  isUnique = pIndex->onError!=OE_None;
+  sqlite3VdbeAddOp(v, OP_IdxPut, iIdx, isUnique);
+  if( isUnique ){
+    sqlite3VdbeChangeP3(v, -1, "indexed columns are not unique", P3_STATIC);
+  }
+  sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1);
+  sqlite3VdbeChangeP2(v, addr1, sqlite3VdbeCurrentAddr(v));
+  sqlite3VdbeAddOp(v, OP_Close, iTab, 0);
+  sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
 }
 
 /*
-** Create a new index for an SQL table.  pIndex is the name of the index 
-** and pTable is the name of the table that is to be indexed.  Both will 
+** Create a new index for an SQL table.  pName1.pName2 is the name of the index 
+** and pTblList is the name of the table that is to be indexed.  Both will 
 ** be NULL for a primary key or an index that is created to satisfy a
 ** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
 ** as the table to be indexed.  pParse->pNewTable is a table that is
@@ -1810,16 +2148,16 @@ void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
 ** to the table currently under construction.  
 */
 void sqlite3CreateIndex(
-  Parse *pParse,   /* All information about this parse */
-  Token *pName1,   /* First part of index name. May be NULL */
-  Token *pName2,   /* Second part of index name. May be NULL */
-  SrcList *pTblName,  /* Table to index. Use pParse->pNewTable if 0 */
+  Parse *pParse,     /* All information about this parse */
+  Token *pName1,     /* First part of index name. May be NULL */
+  Token *pName2,     /* Second part of index name. May be NULL */
+  SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */
   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 */
+  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 */
 ){
-  Table *pTab = 0; /* Table to be indexed */
+  Table *pTab = 0;   /* Table to be indexed */
   Index *pIndex = 0; /* The index to be created */
   char *zName = 0;
   int i, j;
@@ -1874,10 +2212,12 @@ void sqlite3CreateIndex(
     sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
     goto exit_create_index;
   }
+#ifndef SQLITE_OMIT_VIEW
   if( pTab->pSelect ){
     sqlite3ErrorMsg(pParse, "views may not be indexed");
     goto exit_create_index;
   }
+#endif
   isTemp = pTab->iDb==1;
 
   /*
@@ -1913,7 +2253,7 @@ void sqlite3CreateIndex(
         goto exit_create_index;
       }
     }
-  }else if( pName==0 ){
+  }else{
     char zBuf[30];
     int n;
     Index *pLoop;
@@ -2076,60 +2416,55 @@ void sqlite3CreateIndex(
   ** step can be skipped.
   */
   else if( db->init.busy==0 ){
-    int n;
     Vdbe *v;
-    int lbl1, lbl2;
+    char *zStmt;
+    int iMem = pParse->nMem++;
 
     v = sqlite3GetVdbe(pParse);
     if( v==0 ) goto exit_create_index;
-    if( pTblName!=0 ){
-      sqlite3BeginWriteOperation(pParse, 0, iDb);
-      sqlite3OpenMasterTable(v, iDb);
-    }
-    sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0);
-    sqlite3VdbeOp3(v, OP_String8, 0, 0, "index", P3_STATIC);
-    sqlite3VdbeOp3(v, OP_String8, 0, 0, pIndex->zName, 0);
-    sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
+
+    /* Create the rootpage for the index
+    */
+    sqlite3BeginWriteOperation(pParse, 1, iDb);
     sqlite3VdbeAddOp(v, OP_CreateIndex, iDb, 0);
-    if( pTblName ){
-      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
-      sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
-      sqlite3VdbeOp3(v, OP_OpenWrite, 1, 0,
-                     (char*)&pIndex->keyInfo, P3_KEYINFO);
-    }
-    sqlite3VdbeAddOp(v, OP_String8, 0, 0);
+    sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0);
+
+    /* Gather the complete text of the CREATE INDEX statement into
+    ** the zStmt variable
+    */
     if( pStart && pEnd ){
-      if( onError==OE_None ){
-        sqlite3VdbeChangeP3(v, -1, "CREATE INDEX ", P3_STATIC);
-      }else{
-        sqlite3VdbeChangeP3(v, -1, "CREATE UNIQUE INDEX ", P3_STATIC);
-      }
-      sqlite3VdbeAddOp(v, OP_String8, 0, 0);
-      n = Addr(pEnd->z) - Addr(pName->z) + 1;
-      sqlite3VdbeChangeP3(v, -1, pName->z, n);
-      sqlite3VdbeAddOp(v, OP_Concat, 0, 0);
+      /* A named index with an explicit CREATE INDEX statement */
+      zStmt = sqlite3MPrintf("CREATE%s INDEX %.*s",
+        onError==OE_None ? "" : " UNIQUE",
+        Addr(pEnd->z) - Addr(pName->z) + 1,
+        pName->z);
+    }else{
+      /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
+      /* zStmt = sqlite3MPrintf(""); */
+      zStmt = 0;
     }
-    sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC);
-    sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
+
+    /* Add an entry in sqlite_master for this index
+    */
+    sqlite3NestedParse(pParse, 
+        "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#0,%Q);",
+        db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+        pIndex->zName,
+        pTab->zName,
+        zStmt
+    );
+    sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
+    sqliteFree(zStmt);
+
+    /* Fill the index with data and reparse the schema. Code an OP_Expire
+    ** to invalidate all pre-compiled statements.
+    */
     if( pTblName ){
-      sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-      sqlite3VdbeAddOp(v, OP_OpenRead, 2, pTab->tnum);
-      /* VdbeComment((v, "%s", pTab->zName)); */
-      sqlite3VdbeAddOp(v, OP_SetNumColumns, 2, pTab->nCol);
-      lbl2 = sqlite3VdbeMakeLabel(v);
-      sqlite3VdbeAddOp(v, OP_Rewind, 2, lbl2);
-      lbl1 = sqlite3VdbeCurrentAddr(v);
-      sqlite3GenerateIndexKey(v, pIndex, 2);
-      sqlite3VdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
-                      "indexed columns are not unique", P3_STATIC);
-      sqlite3VdbeAddOp(v, OP_Next, 2, lbl1);
-      sqlite3VdbeResolveLabel(v, lbl2);
-      sqlite3VdbeAddOp(v, OP_Close, 2, 0);
-      sqlite3VdbeAddOp(v, OP_Close, 1, 0);
+      sqlite3RefillIndex(pParse, pIndex, iMem);
       sqlite3ChangeCookie(db, v, iDb);
-      sqlite3VdbeAddOp(v, OP_Close, 0, 0);
       sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
          sqlite3MPrintf("name='%q'", pIndex->zName), P3_DYNAMIC);
+      sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
     }
   }
 
@@ -2207,27 +2542,15 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){
   /* Generate code to remove the index and from the master table */
   v = sqlite3GetVdbe(pParse);
   if( v ){
-    static const VdbeOpList dropIndex[] = {
-      { OP_Rewind,     0, ADDR(9), 0}, 
-      { OP_String8,    0, 0,       0}, /* 1 */
-      { OP_MemStore,   1, 1,       0},
-      { OP_MemLoad,    1, 0,       0}, /* 3 */
-      { OP_Column,     0, 1,       0},
-      { OP_Eq,         0, ADDR(8), 0},
-      { OP_Next,       0, ADDR(3), 0},
-      { OP_Goto,       0, ADDR(9), 0},
-      { OP_Delete,     0, 0,       0}, /* 8 */
-    };
-    int base;
-
-    sqlite3BeginWriteOperation(pParse, 0, pIndex->iDb);
-    sqlite3OpenMasterTable(v, pIndex->iDb);
-    base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
-    sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0);
-    sqlite3ChangeCookie(db, v, pIndex->iDb);
-    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
-    sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
-    sqlite3VdbeOp3(v, OP_DropIndex, pIndex->iDb, 0, pIndex->zName, 0);
+    int iDb = pIndex->iDb;
+    sqlite3NestedParse(pParse,
+       "DELETE FROM %Q.%s WHERE name=%Q",
+       db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+       pIndex->zName
+    );
+    sqlite3ChangeCookie(db, v, iDb);
+    destroyRootPage(pParse, pIndex->tnum, iDb);
+    sqlite3VdbeOp3(v, OP_DropIndex, iDb, 0, pIndex->zName, 0);
   }
 
 exit_drop_index:
@@ -2327,9 +2650,12 @@ SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
 */
 void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
   int i;
-  for(i=0; i<pList->nSrc; i++){
-    if( pList->a[i].iCursor<0 ){
-      pList->a[i].iCursor = pParse->nTab++;
+  struct SrcList_item *pItem;
+  for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
+    if( pItem->iCursor>=0 ) break;
+    pItem->iCursor = pParse->nTab++;
+    if( pItem->pSelect ){
+      sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
     }
   }
 }
@@ -2544,7 +2870,7 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
   if( v==0 ) return;
   sqlite3CodeVerifySchema(pParse, iDb);
   pParse->writeMask |= 1<<iDb;
-  if( setStatement ){
+  if( setStatement && pParse->nested==0 ){
     sqlite3VdbeAddOp(v, OP_Statement, iDb, 0);
   }
   if( iDb!=1 && pParse->db->aDb[1].pBt!=0 ){
@@ -2552,6 +2878,7 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
   }
 }
 
+#ifndef SQLITE_OMIT_UTF16
 /* 
 ** Return the transient sqlite3_value object used for encoding conversions
 ** during SQL compilation.
@@ -2562,3 +2889,121 @@ sqlite3_value *sqlite3GetTransientValue(sqlite3 *db){
   }
   return db->pValue;
 }
+#endif
+
+/*
+** Check to see if pIndex uses the collating sequence pColl.  Return
+** 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++;
+  }
+  return 0;
+}
+#endif
+
+/*
+** Recompute all indices of pTab that use the collating sequence pColl.
+** If pColl==0 then recompute all indices of pTab.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
+  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);
+      sqlite3RefillIndex(pParse, pIndex, -1);
+    }
+  }
+}
+#endif
+
+/*
+** Recompute all indices of all tables in all databases where the
+** indices use the collating sequence pColl.  If pColl==0 then recompute
+** all indices everywhere.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+void reindexDatabases(Parse *pParse, CollSeq *pColl){
+  Db *pDb;                    /* A single database */
+  int iDb;                    /* The database index number */
+  sqlite3 *db = pParse->db;   /* The database connection */
+  HashElem *k;                /* For looping over tables in pDb */
+  Table *pTab;                /* A table in the database */
+
+  for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
+    if( pDb==0 ) continue;
+      for(k=sqliteHashFirst(&pDb->tblHash);  k; k=sqliteHashNext(k)){
+      pTab = (Table*)sqliteHashData(k);
+      reindexTable(pParse, pTab, pColl);
+    }
+  }
+}
+#endif
+
+/*
+** Generate code for the REINDEX command.
+**
+**        REINDEX                            -- 1
+**        REINDEX  <collation>               -- 2
+**        REINDEX  ?<database>.?<tablename>  -- 3
+**        REINDEX  ?<database>.?<indexname>  -- 4
+**
+** Form 1 causes all indices in all attached databases to be rebuilt.
+** Form 2 rebuilds all indices in all databases that use the named
+** collating function.  Forms 3 and 4 rebuild the named index or all
+** indices associated with the named table.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
+  CollSeq *pColl;             /* Collating sequence to be reindexed, or NULL */
+  char *z;                    /* Name of a table or index */
+  const char *zDb;            /* Name of the database */
+  Table *pTab;                /* A table in the database */
+  Index *pIndex;              /* An index associated with pTab */
+  int iDb;                    /* The database index number */
+  sqlite3 *db = pParse->db;   /* The database connection */
+  Token *pObjName;            /* Name of the table or index to be reindexed */
+
+  /* Read the database schema. If an error occurs, leave an error message
+  ** and code in pParse and return NULL. */
+  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+    return;
+  }
+
+  if( pName1==0 || pName1->z==0 ){
+    reindexDatabases(pParse, 0);
+    return;
+  }else if( pName2==0 || pName2->z==0 ){
+    pColl = sqlite3FindCollSeq(db, db->enc, pName1->z, pName1->n, 0);
+    if( pColl ){
+      reindexDatabases(pParse, pColl);
+      return;
+    }
+  }
+  iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
+  if( iDb<0 ) return;
+  z = sqlite3NameFromToken(pObjName);
+  zDb = db->aDb[iDb].zName;
+  pTab = sqlite3FindTable(db, z, zDb);
+  if( pTab ){
+    reindexTable(pParse, pTab, 0);
+    sqliteFree(z);
+    return;
+  }
+  pIndex = sqlite3FindIndex(db, z, zDb);
+  sqliteFree(z);
+  if( pIndex ){
+    sqlite3BeginWriteOperation(pParse, 0, iDb);
+    sqlite3RefillIndex(pParse, pIndex, -1);
+    return;
+  }
+  sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
+}
+#endif
index 634e81d5ed8ec857ef95826a5814afc1bad2650d..8780a51b6dd8f36a7dc40c9aa93f28582306ab06 100644 (file)
@@ -315,12 +315,10 @@ static int parseDateOrTime(const char *zDate, DateTime *p){
     return 0;
   }else if( sqlite3StrICmp(zDate,"now")==0){
     double r;
-    if( sqlite3OsCurrentTime(&r)==0 ){
-      p->rJD = r;
-      p->validJD = 1;
-      return 0;
-    }
-    return 1;
+    sqlite3OsCurrentTime(&r);
+    p->rJD = r;
+    p->validJD = 1;
+    return 0;
   }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
     p->rJD = sqlite3AtoF(zDate, 0);
     p->validJD = 1;
@@ -862,9 +860,100 @@ static void strftimeFunc(
   }
 }
 
+/*
+** current_time()
+**
+** This function returns the same value as time('now').
+*/
+static void ctimeFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  sqlite3_value *pVal = sqlite3ValueNew();
+  if( pVal ){
+    sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
+    timeFunc(context, 1, &pVal);
+    sqlite3ValueFree(pVal);
+  }
+}
 
+/*
+** current_date()
+**
+** This function returns the same value as date('now').
+*/
+static void cdateFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  sqlite3_value *pVal = sqlite3ValueNew();
+  if( pVal ){
+    sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
+    dateFunc(context, 1, &pVal);
+    sqlite3ValueFree(pVal);
+  }
+}
+
+/*
+** current_timestamp()
+**
+** This function returns the same value as datetime('now').
+*/
+static void ctimestampFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  sqlite3_value *pVal = sqlite3ValueNew();
+  if( pVal ){
+    sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
+    datetimeFunc(context, 1, &pVal);
+    sqlite3ValueFree(pVal);
+  }
+}
 #endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
 
+#ifdef SQLITE_OMIT_DATETIME_FUNCS
+/*
+** If the library is compiled to omit the full-scale date and time
+** handling (to get a smaller binary), the following minimal version
+** of the functions current_time(), current_date() and current_timestamp()
+** are included instead. This is to support column declarations that
+** include "DEFAULT CURRENT_TIME" etc.
+**
+** This function uses the C-library functions time(), gmtime()
+** and strftime(). The format string to pass to strftime() is supplied
+** as the user-data for the function.
+*/
+static void currentTimeFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  time_t t;
+  char *zFormat = (char *)sqlite3_user_data(context);
+  char zBuf[20];
+
+  time(&t);
+#ifdef SQLITE_TEST
+  {
+    extern int sqlite3_current_time;  /* See os_XXX.c */
+    if( sqlite3_current_time ){
+      t = sqlite3_current_time;
+    }
+  }
+#endif
+
+  sqlite3OsEnterMutex();
+  strftime(zBuf, 20, zFormat, gmtime(&t));
+  sqlite3OsLeaveMutex();
+
+  sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+}
+#endif
+
 /*
 ** This function registered all of the above C functions as SQL
 ** functions.  This should be the only routine in this file with
@@ -882,6 +971,9 @@ void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
     { "time",      -1, timeFunc        },
     { "datetime",  -1, datetimeFunc    },
     { "strftime",  -1, strftimeFunc    },
+    { "current_time",       0, ctimeFunc      },
+    { "current_timestamp",  0, ctimestampFunc },
+    { "current_date",       0, cdateFunc      },
   };
   int i;
 
@@ -889,5 +981,20 @@ void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
     sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
         SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
   }
+#else
+  static const struct {
+     char *zName;
+     char *zFormat;
+  } aFuncs[] = {
+    { "current_time", "%H:%M:%S" },
+    { "current_date", "%Y-%m-%d" },
+    { "current_timestamp", "%Y-%m-%d %H:%M:%S" }
+  };
+  int i;
+
+  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
+    sqlite3_create_function(db, aFuncs[i].zName, 0, SQLITE_UTF8, 
+        aFuncs[i].zFormat, currentTimeFunc, 0, 0);
+  }
 #endif
 }
index 866da61d92487c05356167d60f545e64730ff7ed..fa661977d7caefa3cb7824a83ec6c32e7c4f05c8 100644 (file)
@@ -10,7 +10,7 @@
 **
 *************************************************************************
 ** This file contains C code routines that are called by the parser
-** to handle DELETE FROM statements.
+** in order to generate code for DELETE FROM statements.
 **
 ** $Id$
 */
@@ -38,14 +38,17 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
 ** writable return 0;
 */
 int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
-  if( pTab->readOnly ){
+  if( pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
+        && pParse->nested==0 ){
     sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
     return 1;
   }
+#ifndef SQLITE_OMIT_VIEW
   if( !viewOk && pTab->pSelect ){
     sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
     return 1;
   }
+#endif
   return 0;
 }
 
@@ -65,7 +68,11 @@ void sqlite3OpenTableForReading(
 
 
 /*
-** Process a DELETE FROM statement.
+** Generate code for a DELETE FROM statement.
+**
+**     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
+**                 \________/       \________________/
+**                  pTabList              pWhere
 */
 void sqlite3DeleteFrom(
   Parse *pParse,         /* The parser context */
@@ -81,13 +88,14 @@ void sqlite3DeleteFrom(
   Index *pIdx;           /* For looping over indices of the table */
   int iCur;              /* VDBE Cursor number for pTab */
   sqlite3 *db;           /* Main database structure */
-  int isView;            /* True if attempting to delete from a view */
   AuthContext sContext;  /* Authorization context */
+  int oldIdx = -1;       /* Cursor for the OLD table of AFTER triggers */
+  NameContext sNC;       /* Name context to resolve expressions in */
 
-  int row_triggers_exist = 0;  /* True if any triggers exist */
-  int before_triggers;         /* True if there are BEFORE triggers */
-  int after_triggers;          /* True if there are AFTER triggers */
-  int oldIdx = -1;             /* Cursor for the OLD table of AFTER triggers */
+#ifndef SQLITE_OMIT_TRIGGER
+  int isView;                  /* True if attempting to delete from a view */
+  int triggers_exist = 0;      /* True if any triggers exist */
+#endif
 
   sContext.pParse = 0;
   if( pParse->nErr || sqlite3_malloc_failed ){
@@ -104,13 +112,23 @@ void sqlite3DeleteFrom(
   */
   pTab = sqlite3SrcListLookup(pParse, pTabList);
   if( pTab==0 )  goto delete_from_cleanup;
-  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
-                         TK_DELETE, TK_BEFORE, TK_ROW, 0);
-  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
-                         TK_DELETE, TK_AFTER, TK_ROW, 0);
-  row_triggers_exist = before_triggers || after_triggers;
+
+  /* Figure out if we have any triggers and if the table being
+  ** deleted from is a view
+  */
+#ifndef SQLITE_OMIT_TRIGGER
+  triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0);
   isView = pTab->pSelect!=0;
-  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
+#else
+# define triggers_exist 0
+# define isView 0
+#endif
+#ifdef SQLITE_OMIT_VIEW
+# undef isView
+# define isView 0
+#endif
+
+  if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
     goto delete_from_cleanup;
   }
   assert( pTab->iDb<db->nDb );
@@ -127,15 +145,18 @@ void sqlite3DeleteFrom(
 
   /* Allocate a cursor used to store the old.* data for a trigger.
   */
-  if( row_triggers_exist ){ 
+  if( triggers_exist ){ 
     oldIdx = pParse->nTab++;
   }
 
-  /* Resolve the column names in all the expressions.
+  /* Resolve the column names in the WHERE clause.
   */
   assert( pTabList->nSrc==1 );
   iCur = pTabList->a[0].iCursor = pParse->nTab++;
-  if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){
+  memset(&sNC, 0, sizeof(sNC));
+  sNC.pParse = pParse;
+  sNC.pSrcList = pTabList;
+  if( sqlite3ExprResolveNames(&sNC, pWhere) ){
     goto delete_from_cleanup;
   }
 
@@ -151,8 +172,8 @@ void sqlite3DeleteFrom(
   if( v==0 ){
     goto delete_from_cleanup;
   }
-  sqlite3VdbeCountChanges(v);
-  sqlite3BeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
+  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
+  sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb);
 
   /* If we are trying to delete from a view, construct that view into
   ** a temporary table.
@@ -174,7 +195,7 @@ 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 && !row_triggers_exist ){
+  if( pWhere==0 && !triggers_exist ){
     if( db->flags & SQLITE_CountRows ){
       /* If counting rows deleted, just count the total number of
       ** entries in the table. */
@@ -210,11 +231,12 @@ void sqlite3DeleteFrom(
 
     /* Begin the database scan
     */
-    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0);
+    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
     if( pWInfo==0 ) goto delete_from_cleanup;
 
-    /* Remember the key of every item to be deleted.
+    /* Remember the rowid of every item to be deleted.
     */
+    sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
     sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
     if( db->flags & SQLITE_CountRows ){
       sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
@@ -226,7 +248,7 @@ void sqlite3DeleteFrom(
 
     /* Open the pseudo-table used to store OLD if there are triggers.
     */
-    if( row_triggers_exist ){
+    if( triggers_exist ){
       sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
       sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
     }
@@ -241,7 +263,7 @@ void sqlite3DeleteFrom(
     /* This is the beginning of the delete loop when there are
     ** row triggers.
     */
-    if( row_triggers_exist ){
+    if( triggers_exist ){
       addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
       sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
       if( !isView ){
@@ -255,8 +277,8 @@ void sqlite3DeleteFrom(
         sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
       }
 
-      sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, 
-          oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
+      (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,
+          -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
          addr);
     }
 
@@ -271,25 +293,25 @@ void sqlite3DeleteFrom(
 
       /* This is the beginning of the delete loop when there are no
       ** row triggers */
-      if( !row_triggers_exist ){ 
+      if( !triggers_exist ){ 
         addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
       }
 
       /* Delete the row */
-      sqlite3GenerateRowDelete(db, v, pTab, iCur, 1);
+      sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
     }
 
     /* If there are row triggers, close all cursors then invoke
     ** the AFTER triggers
     */
-    if( row_triggers_exist ){
+    if( triggers_exist ){
       if( !isView ){
         for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
           sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
         }
         sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
       }
-      sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, 
+      (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1,
           oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
          addr);
     }
@@ -300,7 +322,7 @@ void sqlite3DeleteFrom(
     sqlite3VdbeAddOp(v, OP_ListReset, 0, 0);
 
     /* Close the cursors after the loop if there are no row triggers */
-    if( !row_triggers_exist ){
+    if( !triggers_exist ){
       for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
         sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
       }
@@ -309,9 +331,11 @@ void sqlite3DeleteFrom(
   }
 
   /*
-  ** Return the number of rows that were deleted.
+  ** Return the number of rows that were deleted. If this routine is 
+  ** generating code because of a call to sqlite3NestedParse(), do not
+  ** invoke the callback function.
   */
-  if( db->flags & SQLITE_CountRows ){
+  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);
diff --git a/ext/pdo_sqlite/sqlite/src/experimental.c b/ext/pdo_sqlite/sqlite/src/experimental.c
new file mode 100644 (file)
index 0000000..073f218
--- /dev/null
@@ -0,0 +1,38 @@
+
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains C code routines that are called by the parser
+** to handle SELECT statements in SQLite.
+**
+** $Id$
+*/
+#include "sqliteInt.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);
+}
+
index 2da3645b9b727e0f8cd51aafa9c6c1d1ad5109b2..c4943b1f838c0a8b24acaffa077fd46a77383b98 100644 (file)
@@ -62,8 +62,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
 }
 
 /*
-** pExpr is the left operand of a comparison operator.  aff2 is the
-** type affinity of the right operand.  This routine returns the
+** pExpr is an operand of a comparison operator.  aff2 is the
+** type affinity of the other operand.  This routine returns the
 ** type affinity that should be used for the comparison operator.
 */
 char sqlite3CompareAffinity(Expr *pExpr, char aff2){
@@ -179,7 +179,7 @@ static int codeCompare(
 ** for this node is obtained from sqliteMalloc().  The calling function
 ** is responsible for making sure the node eventually gets freed.
 */
-Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
+Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
   Expr *pNew;
   pNew = sqliteMalloc( sizeof(Expr) );
   if( pNew==0 ){
@@ -189,6 +189,7 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
   pNew->op = op;
   pNew->pLeft = pLeft;
   pNew->pRight = pRight;
+  pNew->iAgg = -1;
   if( pToken ){
     assert( pToken->dyn==0 );
     pNew->span = pNew->token = *pToken;
@@ -198,6 +199,42 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
   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
+** on the stack.  "#0" (or just "#") means the top of the stack.
+** "#1" means the next down on the stack.  And so forth.  #-1 means
+** memory location 0.  #-2 means memory location 1.  And so forth.
+**
+** This routine is called by the parser to deal with on of those terms.
+** It immediately generates code to store the value in a memory location.
+** The returns an expression that will code to extract the value from
+** that memory location as needed.
+*/
+Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
+  Vdbe *v = pParse->pVdbe;
+  Expr *p;
+  int depth;
+  if( v==0 ) return 0;
+  if( pParse->nested==0 ){
+    sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken);
+    return 0;
+  }
+  p = sqlite3Expr(TK_REGISTER, 0, 0, pToken);
+  if( p==0 ){
+    return 0;  /* Malloc failed */
+  }
+  depth = atoi(&pToken->z[1]);
+  if( depth>=0 ){
+    p->iTable = pParse->nMem++;
+    sqlite3VdbeAddOp(v, OP_Dup, depth, 0);
+    sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1);
+  }else{
+    p->iTable = -1-depth;
+  }
+  return p;
+}
+
 /*
 ** Join two expressions using an AND operator.  If either expression is
 ** NULL, then just return the other expression.
@@ -356,7 +393,7 @@ Expr *sqlite3ExprDup(Expr *p){
   if( pNew==0 ) return 0;
   memcpy(pNew, p, sizeof(*pNew));
   if( p->token.z!=0 ){
-    pNew->token.z = sqliteStrDup(p->token.z);
+    pNew->token.z = sqliteStrNDup(p->token.z, p->token.n);
     pNew->token.dyn = 1;
   }else{
     assert( pNew->token.z==0 );
@@ -410,6 +447,15 @@ ExprList *sqlite3ExprListDup(ExprList *p){
   }
   return pNew;
 }
+
+/*
+** If cursors, triggers, views and subqueries are all omitted from
+** the build, then none of the following routines, except for 
+** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
+** called with a NULL argument.
+*/
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
+ || !defined(SQLITE_OMIT_SUBQUERY)
 SrcList *sqlite3SrcListDup(SrcList *p){
   SrcList *pNew;
   int i;
@@ -427,10 +473,14 @@ SrcList *sqlite3SrcListDup(SrcList *p){
     pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
     pNewItem->jointype = pOldItem->jointype;
     pNewItem->iCursor = pOldItem->iCursor;
-    pNewItem->pTab = 0;
+    pNewItem->pTab = pOldItem->pTab;
+    if( pNewItem->pTab ){
+      pNewItem->pTab->isTransient = 0;
+    }
     pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect);
     pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn);
     pNewItem->pUsing = sqlite3IdListDup(pOldItem->pUsing);
+    pNewItem->colUsed = pOldItem->colUsed;
   }
   return pNew;
 }
@@ -465,14 +515,22 @@ Select *sqlite3SelectDup(Select *p){
   pNew->pOrderBy = sqlite3ExprListDup(p->pOrderBy);
   pNew->op = p->op;
   pNew->pPrior = sqlite3SelectDup(p->pPrior);
-  pNew->nLimit = p->nLimit;
-  pNew->nOffset = p->nOffset;
-  pNew->zSelect = 0;
+  pNew->pLimit = sqlite3ExprDup(p->pLimit);
+  pNew->pOffset = sqlite3ExprDup(p->pOffset);
   pNew->iLimit = -1;
   pNew->iOffset = -1;
   pNew->ppOpenTemp = 0;
+  pNew->pFetch = 0;
+  pNew->isResolved = p->isResolved;
+  pNew->isAgg = p->isAgg;
   return pNew;
 }
+#else
+Select *sqlite3SelectDup(Select *p){
+  assert( p==0 );
+  return 0;
+}
+#endif
 
 
 /*
@@ -525,44 +583,104 @@ void sqlite3ExprListDelete(ExprList *pList){
 }
 
 /*
-** Walk an expression tree.  Return 1 if the expression is constant
-** and 0 if it involves variables.
+** Walk an expression tree.  Call xFunc for each node visited.
 **
-** For the purposes of this function, a double-quoted string (ex: "abc")
-** is considered a variable but a single-quoted string (ex: 'abc') is
-** a constant.
+** The return value from xFunc determines whether the tree walk continues.
+** 0 means continue walking the tree.  1 means do not walk children
+** of the current node but continue with siblings.  2 means abandon
+** the tree walk completely.
+**
+** The return value from this routine is 1 to abandon the tree walk
+** and 0 to continue.
 */
-int sqlite3ExprIsConstant(Expr *p){
-  switch( p->op ){
+static int walkExprList(ExprList *, int (*)(void *, Expr*), void *);
+static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
+  int rc;
+  if( pExpr==0 ) return 0;
+  rc = (*xFunc)(pArg, pExpr);
+  if( rc==0 ){
+    if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1;
+    if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1;
+    if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1;
+  }
+  return rc>1;
+}
+
+/*
+** Call walkExprTree() for every expression in list p.
+*/
+static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){
+  int i;
+  struct ExprList_item *pItem;
+  if( !p ) return 0;
+  for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
+    if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1;
+  }
+  return 0;
+}
+
+/*
+** Call walkExprTree() for every expression in Select p, not including
+** expressions that are part of sub-selects in any FROM clause or the LIMIT
+** or OFFSET expressions..
+*/
+static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){
+  walkExprList(p->pEList, xFunc, pArg);
+  walkExprTree(p->pWhere, xFunc, pArg);
+  walkExprList(p->pGroupBy, xFunc, pArg);
+  walkExprTree(p->pHaving, xFunc, pArg);
+  walkExprList(p->pOrderBy, xFunc, pArg);
+  return 0;
+}
+
+
+/*
+** This routine is designed as an xFunc for walkExprTree().
+**
+** pArg is really a pointer to an integer.  If we can tell by looking
+** at pExpr that the expression that contains pExpr is not a constant
+** expression, then set *pArg to 0 and return 2 to abandon the tree walk.
+** If pExpr does does not disqualify the expression from being a constant
+** then do nothing.
+**
+** After walking the whole tree, if no nodes are found that disqualify
+** the expression as constant, then we assume the whole expression
+** is constant.  See sqlite3ExprIsConstant() for additional information.
+*/
+static int exprNodeIsConstant(void *pArg, Expr *pExpr){
+  switch( pExpr->op ){
     case TK_ID:
     case TK_COLUMN:
     case TK_DOT:
+    case TK_AGG_FUNCTION:
     case TK_FUNCTION:
+#ifndef SQLITE_OMIT_SUBQUERY
+    case TK_SELECT:
+    case TK_EXISTS:
+#endif
+      *((int*)pArg) = 0;
+      return 2;
+    default:
       return 0;
-    case TK_NULL:
-    case TK_STRING:
-    case TK_BLOB:
-    case TK_INTEGER:
-    case TK_FLOAT:
-    case TK_VARIABLE:
-      return 1;
-    default: {
-      if( p->pLeft && !sqlite3ExprIsConstant(p->pLeft) ) return 0;
-      if( p->pRight && !sqlite3ExprIsConstant(p->pRight) ) return 0;
-      if( p->pList ){
-        int i;
-        for(i=0; i<p->pList->nExpr; i++){
-          if( !sqlite3ExprIsConstant(p->pList->a[i].pExpr) ) return 0;
-        }
-      }
-      return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0);
-    }
   }
-  return 0;
 }
 
 /*
-** If the given expression codes a constant integer that is small enough
+** Walk an expression tree.  Return 1 if the expression is constant
+** and 0 if it involves variables.
+**
+** For the purposes of this function, a double-quoted string (ex: "abc")
+** is considered a variable but a single-quoted string (ex: 'abc') is
+** a constant.
+*/
+int sqlite3ExprIsConstant(Expr *p){
+  int isConst = 1;
+  walkExprTree(p, exprNodeIsConstant, &isConst);
+  return isConst;
+}
+
+/*
+** If the expression p codes a constant integer that is small enough
 ** to fit in a 32-bit integer, return 1 and put the value of the integer
 ** in *pValue.  If the expression is not an integer or if it is too big
 ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
@@ -575,16 +693,6 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
       }
       break;
     }
-    case TK_STRING: {
-      const u8 *z = (u8*)p->token.z;
-      int n = p->token.n;
-      if( n>0 && z[0]=='-' ){ z++; n--; }
-      while( n>0 && *z && isdigit(*z) ){ z++; n--; }
-      if( n==0 && sqlite3GetInt32(p->token.z, pValue) ){
-        return 1;
-      }
-      break;
-    }
     case TK_UPLUS: {
       return sqlite3ExprIsInteger(p->pLeft, pValue);
     }
@@ -641,8 +749,7 @@ static int lookupName(
   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. */
-  SrcList *pSrcList,   /* List of tables used to resolve column names */
-  ExprList *pEList,    /* List of expressions used to resolve "AS" */
+  NameContext *pNC,    /* The name context used to resolve the name */
   Expr *pExpr          /* Make this EXPR node point to the selected column */
 ){
   char *zDb = 0;       /* Name of the database.  The "X" in X.Y.Z */
@@ -652,6 +759,9 @@ static int lookupName(
   int cnt = 0;         /* Number of matching column names */
   int cntTab = 0;      /* Number of matching table names */
   sqlite3 *db = pParse->db;  /* The database */
+  struct SrcList_item *pItem;       /* Use for looping over pSrcList items */
+  struct SrcList_item *pMatch = 0;  /* The matching pSrcList item */
+  NameContext *pTopNC = pNC;        /* First namecontext in the list */
 
   assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
   zDb = sqlite3NameFromToken(pDbToken);
@@ -660,114 +770,132 @@ static int lookupName(
   if( sqlite3_malloc_failed ){
     return 1;  /* Leak memory (zDb and zTab) if malloc fails */
   }
-  assert( zTab==0 || pEList==0 );
 
   pExpr->iTable = -1;
-  for(i=0; i<pSrcList->nSrc; i++){
-    struct SrcList_item *pItem = &pSrcList->a[i];
-    Table *pTab = pItem->pTab;
-    Column *pCol;
-
-    if( pTab==0 ) continue;
-    assert( pTab->nCol>0 );
-    if( zTab ){
-      if( pItem->zAlias ){
-        char *zTabName = pItem->zAlias;
-        if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
-      }else{
-        char *zTabName = pTab->zName;
-        if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
-        if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
-          continue;
+  while( pNC && cnt==0 ){
+    SrcList *pSrcList = pNC->pSrcList;
+    ExprList *pEList = pNC->pEList;
+
+    pNC->nRef++;
+    /* assert( zTab==0 || pEList==0 ); */
+    if( pSrcList ){
+      for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
+        Table *pTab = pItem->pTab;
+        Column *pCol;
+  
+        if( pTab==0 ) continue;
+        assert( pTab->nCol>0 );
+        if( zTab ){
+          if( pItem->zAlias ){
+            char *zTabName = pItem->zAlias;
+            if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+          }else{
+            char *zTabName = pTab->zName;
+            if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+            if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
+              continue;
+            }
+          }
+        }
+        if( 0==(cntTab++) ){
+          pExpr->iTable = pItem->iCursor;
+          pExpr->iDb = pTab->iDb;
+          pMatch = pItem;
+        }
+        for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
+          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+            cnt++;
+            pExpr->iTable = pItem->iCursor;
+            pMatch = pItem;
+            pExpr->iDb = pTab->iDb;
+            /* 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;
+            break;
+          }
         }
       }
     }
-    if( 0==(cntTab++) ){
-      pExpr->iTable = pItem->iCursor;
-      pExpr->iDb = pTab->iDb;
-    }
-    for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
-      if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
-        cnt++;
-        pExpr->iTable = pItem->iCursor;
-        pExpr->iDb = pTab->iDb;
-        /* 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;
-        break;
+
+#ifndef SQLITE_OMIT_TRIGGER
+    /* If we have not already resolved the name, then maybe 
+    ** it is a new.* or old.* trigger argument reference
+    */
+    if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
+      TriggerStack *pTriggerStack = pParse->trigStack;
+      Table *pTab = 0;
+      if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
+        pExpr->iTable = pTriggerStack->newIdx;
+        assert( pTriggerStack->pTab );
+        pTab = pTriggerStack->pTab;
+      }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
+        pExpr->iTable = pTriggerStack->oldIdx;
+        assert( pTriggerStack->pTab );
+        pTab = pTriggerStack->pTab;
       }
-    }
-  }
 
-  /* If we have not already resolved the name, then maybe 
-  ** it is a new.* or old.* trigger argument reference
-  */
-  if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
-    TriggerStack *pTriggerStack = pParse->trigStack;
-    Table *pTab = 0;
-    if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
-      pExpr->iTable = pTriggerStack->newIdx;
-      assert( pTriggerStack->pTab );
-      pTab = pTriggerStack->pTab;
-    }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab) == 0 ){
-      pExpr->iTable = pTriggerStack->oldIdx;
-      assert( pTriggerStack->pTab );
-      pTab = pTriggerStack->pTab;
-    }
-
-    if( pTab ){ 
-      int j;
-      Column *pCol = pTab->aCol;
-      
-      pExpr->iDb = pTab->iDb;
-      cntTab++;
-      for(j=0; j < pTab->nCol; j++, pCol++) {
-        if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
-          cnt++;
-          pExpr->iColumn = j==pTab->iPKey ? -1 : j;
-          pExpr->affinity = pTab->aCol[j].affinity;
-          pExpr->pColl = pTab->aCol[j].pColl;
-          break;
+      if( pTab ){ 
+        int j;
+        Column *pCol = pTab->aCol;
+
+        pExpr->iDb = pTab->iDb;
+        cntTab++;
+        for(j=0; j < pTab->nCol; j++, pCol++) {
+          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+            cnt++;
+            pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+            pExpr->affinity = pTab->aCol[j].affinity;
+            pExpr->pColl = pTab->aCol[j].pColl;
+            break;
+          }
         }
       }
     }
-  }
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
 
-  /*
-  ** Perhaps the name is a reference to the ROWID
-  */
-  if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
-    cnt = 1;
-    pExpr->iColumn = -1;
-    pExpr->affinity = SQLITE_AFF_INTEGER;
-  }
+    /*
+    ** Perhaps the name is a reference to the ROWID
+    */
+    if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
+      cnt = 1;
+      pExpr->iColumn = -1;
+      pExpr->affinity = SQLITE_AFF_INTEGER;
+    }
 
-  /*
-  ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
-  ** might refer to an result-set alias.  This happens, for example, when
-  ** we are resolving names in the WHERE clause of the following command:
-  **
-  **     SELECT a+b AS x FROM table WHERE x<10;
-  **
-  ** In cases like this, replace pExpr with a copy of the expression that
-  ** forms the result set entry ("a+b" in the example) and return immediately.
-  ** Note that the expression in the result set should have already been
-  ** resolved by the time the WHERE clause is resolved.
-  */
-  if( cnt==0 && pEList!=0 ){
-    for(j=0; j<pEList->nExpr; j++){
-      char *zAs = pEList->a[j].zName;
-      if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
-        assert( pExpr->pLeft==0 && pExpr->pRight==0 );
-        pExpr->op = TK_AS;
-        pExpr->iColumn = j;
-        pExpr->pLeft = sqlite3ExprDup(pEList->a[j].pExpr);
-        sqliteFree(zCol);
-        assert( zTab==0 && zDb==0 );
-        return 0;
-      }
-    } 
+    /*
+    ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
+    ** might refer to an result-set alias.  This happens, for example, when
+    ** we are resolving names in the WHERE clause of the following command:
+    **
+    **     SELECT a+b AS x FROM table WHERE x<10;
+    **
+    ** In cases like this, replace pExpr with a copy of the expression that
+    ** forms the result set entry ("a+b" in the example) and return immediately.
+    ** Note that the expression in the result set should have already been
+    ** resolved by the time the WHERE clause is resolved.
+    */
+    if( cnt==0 && pEList!=0 && zTab==0 ){
+      for(j=0; j<pEList->nExpr; j++){
+        char *zAs = pEList->a[j].zName;
+        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+          pExpr->op = TK_AS;
+          pExpr->iColumn = j;
+          pExpr->pLeft = sqlite3ExprDup(pEList->a[j].pExpr);
+          sqliteFree(zCol);
+          assert( zTab==0 && zDb==0 );
+          return 0;
+        }
+      } 
+    }
+
+    /* Advance to the next name context.  The loop will exit when either
+    ** we have a match (cnt>0) or when we run out of name contexts.
+    */
+    if( cnt==0 ){
+      pNC = pNC->pNext;
+    }
   }
 
   /*
@@ -799,6 +927,22 @@ static int lookupName(
     }
     sqlite3ErrorMsg(pParse, zErr, z);
     sqliteFree(z);
+    pTopNC->nErr++;
+  }
+
+  /* If a column from a table in pSrcList is referenced, then record
+  ** this fact in the pSrcList.a[].colUsed bitmask.  Column 0 causes
+  ** bit 0 to be set.  Column 1 sets bit 1.  And so forth.  If the
+  ** column number is greater than the number of bits in the bitmask
+  ** then set the high-order bit of the bitmask.
+  */
+  if( pExpr->iColumn>=0 && pMatch!=0 ){
+    int n = pExpr->iColumn;
+    if( n>=sizeof(Bitmask)*8 ){
+      n = sizeof(Bitmask)*8-1;
+    }
+    assert( pMatch->iCursor==pExpr->iTable );
+    pMatch->colUsed |= 1<<n;
   }
 
   /* Clean up and return
@@ -811,53 +955,87 @@ static int lookupName(
   sqlite3ExprDelete(pExpr->pRight);
   pExpr->pRight = 0;
   pExpr->op = TK_COLUMN;
-  sqlite3AuthRead(pParse, pExpr, pSrcList);
+  if( cnt==1 ){
+    assert( pNC!=0 );
+    sqlite3AuthRead(pParse, pExpr, pNC->pSrcList);
+  }
   return cnt!=1;
 }
 
 /*
-** This routine walks an expression tree and resolves references to
-** table columns.  Nodes of the form ID.ID or ID resolve into an
-** index to the table in the table list and a column offset.  The 
-** Expr.opcode for such nodes is changed to TK_COLUMN.  The Expr.iTable
-** value is changed to the index of the referenced table in pTabList
-** plus the "base" value.  The base value will ultimately become the
-** VDBE cursor number for a cursor that is pointing into the referenced
-** table.  The Expr.iColumn value is changed to the index of the column 
-** of the referenced table.  The Expr.iColumn value for the special
-** ROWID column is -1.  Any INTEGER PRIMARY KEY column is tried as an
-** alias for ROWID.
-**
-** We also check for instances of the IN operator.  IN comes in two
-** forms:
-**
-**           expr IN (exprlist)
-** and
-**           expr IN (SELECT ...)
+** pExpr is a node that defines a function of some kind.  It might
+** be a syntactic function like "count(x)" or it might be a function
+** that implements an operator, like "a LIKE b".  
 **
-** 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.
+** This routine makes *pzName point to the name of the function and 
+** *pnName hold the number of characters in the function name.
+*/
+static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
+  switch( pExpr->op ){
+    case TK_FUNCTION: {
+      *pzName = pExpr->token.z;
+      *pnName = pExpr->token.n;
+      break;
+    }
+    case TK_LIKE: {
+      *pzName = "like";
+      *pnName = 4;
+      break;
+    }
+    case TK_GLOB: {
+      *pzName = "glob";
+      *pnName = 4;
+      break;
+    }
+    case TK_CTIME: {
+      *pzName = "current_time";
+      *pnName = 12;
+      break;
+    }
+    case TK_CDATE: {
+      *pzName = "current_date";
+      *pnName = 12;
+      break;
+    }
+    case TK_CTIMESTAMP: {
+      *pzName = "current_timestamp";
+      *pnName = 17;
+      break;
+    }
+  }
+}
+
+/*
+** This routine is designed as an xFunc for walkExprTree().
 **
-** This routine also looks for scalar SELECTs that are part of an expression.
-** If it finds any, it generates code to write the value of that select
-** into a memory cell.
+** Resolve symbolic names into TK_COLUMN operators for the current
+** node in the expression tree.  Return 0 to continue the search down
+** the tree or 2 to abort the tree walk.
 **
-** Unknown columns or tables provoke an error.  The function returns
-** the number of errors seen and leaves an error message on pParse->zErrMsg.
+** This routine also does error checking and name resolution for
+** function names.  The operator for aggregate functions is changed
+** to TK_AGG_FUNCTION.
 */
-int sqlite3ExprResolveIds(
-  Parse *pParse,     /* The parser context */
-  SrcList *pSrcList, /* List of tables used to resolve column names */
-  ExprList *pEList,  /* List of expressions used to resolve "AS" */
-  Expr *pExpr        /* The expression to be analyzed. */
-){
-  int i;
-
-  if( pExpr==0 || pSrcList==0 ) return 0;
-  for(i=0; i<pSrcList->nSrc; i++){
-    assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab );
+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 ){
+    int i;
+    for(i=0; i<pSrcList->nSrc; i++){
+      assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
+    }
   }
+#endif
   switch( pExpr->op ){
     /* Double-quoted strings (ex: "abc") are used as identifiers if
     ** possible.  Otherwise they remain as strings.  Single-quoted
@@ -867,13 +1045,11 @@ int sqlite3ExprResolveIds(
       if( pExpr->token.z[0]=='\'' ) break;
       /* Fall thru into the TK_ID case if this is a double-quoted string */
     }
-    /* A lone identifier is the name of a columnd.
+    /* A lone identifier is the name of a column.
     */
     case TK_ID: {
-      if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){
-        return 1;
-      }
-      break; 
+      lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
+      return 1;
     }
   
     /* A table name and column name:     ID.ID
@@ -885,6 +1061,7 @@ int sqlite3ExprResolveIds(
       Token *pDb;
       Expr *pRight;
 
+      /* if( pSrcList==0 ) break; */
       pRight = pExpr->pRight;
       if( pRight->op==TK_ID ){
         pDb = 0;
@@ -896,22 +1073,171 @@ int sqlite3ExprResolveIds(
         pTable = &pRight->pLeft->token;
         pColumn = &pRight->pRight->token;
       }
-      if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){
-        return 1;
+      lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
+      return 1;
+    }
+
+    /* Resolve function names
+    */
+    case TK_CTIME:
+    case TK_CTIMESTAMP:
+    case TK_CDATE:
+    case TK_GLOB:
+    case TK_LIKE:
+    case TK_FUNCTION: {
+      ExprList *pList = pExpr->pList;    /* The argument list */
+      int n = pList ? pList->nExpr : 0;  /* Number of arguments */
+      int no_such_func = 0;       /* True if no such function exists */
+      int wrong_num_args = 0;     /* True if wrong number of arguments */
+      int is_agg = 0;             /* True if is an aggregate function */
+      int i;
+      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 */
+
+      getFunctionName(pExpr, &zId, &nId);
+      pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
+      if( pDef==0 ){
+        pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
+        if( pDef==0 ){
+          no_such_func = 1;
+        }else{
+          wrong_num_args = 1;
+        }
+      }else{
+        is_agg = pDef->xFunc==0;
+      }
+      if( is_agg && !pNC->allowAgg ){
+        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
+        pNC->nErr++;
+        is_agg = 0;
+      }else if( no_such_func ){
+        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+        pNC->nErr++;
+      }else if( wrong_num_args ){
+        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
+             nId, zId);
+        pNC->nErr++;
+      }
+      if( is_agg ){
+        pExpr->op = TK_AGG_FUNCTION;
+        pNC->hasAgg = 1;
+      }
+      if( is_agg ) pNC->allowAgg = 0;
+      for(i=0; pNC->nErr==0 && i<n; i++){
+        walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC);
+      }
+      if( is_agg ) pNC->allowAgg = 1;
+      /* FIX ME:  Compute pExpr->affinity based on the expected return
+      ** type of the function 
+      */
+      return is_agg;
+    }
+#ifndef SQLITE_OMIT_SUBQUERY
+    case TK_SELECT:
+    case TK_EXISTS:
+#endif
+    case TK_IN: {
+      if( pExpr->pSelect ){
+        int nRef = pNC->nRef;
+        sqlite3SelectResolve(pParse, pExpr->pSelect, pNC);
+        assert( pNC->nRef>=nRef );
+        if( nRef!=pNC->nRef ){
+          ExprSetProperty(pExpr, EP_VarSelect);
+        }
       }
-      break;
     }
+  }
+  return 0;
+}
 
+/*
+** This routine walks an expression tree and resolves references to
+** table columns.  Nodes of the form ID.ID or ID resolve into an
+** index to the table in the table list and a column offset.  The 
+** Expr.opcode for such nodes is changed to TK_COLUMN.  The Expr.iTable
+** value is changed to the index of the referenced table in pTabList
+** plus the "base" value.  The base value will ultimately become the
+** VDBE cursor number for a cursor that is pointing into the referenced
+** table.  The Expr.iColumn value is changed to the index of the column 
+** of the referenced table.  The Expr.iColumn value for the special
+** ROWID column is -1.  Any INTEGER PRIMARY KEY column is tried as an
+** alias for ROWID.
+**
+** Also resolve function names and check the functions for proper
+** usage.  Make sure all function names are recognized and all functions
+** have the correct number of arguments.  Leave an error message
+** in pParse->zErrMsg if anything is amiss.  Return the number of errors.
+**
+** If the expression contains aggregate functions then set the EP_Agg
+** property on the expression.
+*/
+int sqlite3ExprResolveNames(
+  NameContext *pNC,       /* Namespace to resolve expressions in. */
+  Expr *pExpr             /* The expression to be analyzed. */
+){
+  if( pExpr==0 ) return 0;
+  walkExprTree(pExpr, nameResolverStep, pNC);
+  if( pNC->nErr>0 ){
+    ExprSetProperty(pExpr, EP_Error);
+  }
+  return ExprHasProperty(pExpr, EP_Error);
+}
+
+/*
+** A pointer instance of this structure is used to pass information
+** through walkExprTree into codeSubqueryStep().
+*/
+typedef struct QueryCoder QueryCoder;
+struct QueryCoder {
+  Parse *pParse;       /* The parsing context */
+  NameContext *pNC;    /* Namespace of first enclosing query */
+};
+
+
+/*
+** Generate code for subqueries and IN operators.
+**
+** IN operators comes in two forms:
+**
+**           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.
+*/
+#ifndef SQLITE_OMIT_SUBQUERY
+void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
+  int label = 0;                         /* Address after sub-select code */
+  Vdbe *v = sqlite3GetVdbe(pParse);
+  if( v==0 ) return;
+
+  /* If this is not a variable (correlated) select, then execute
+  ** it only once. Unless this is part of a trigger program. In
+  ** that case re-execute every time (this could be optimized).
+  */
+  if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
+    int mem = pParse->nMem++;
+    sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0);
+    label = sqlite3VdbeMakeLabel(v);
+    sqlite3VdbeAddOp(v, OP_If, 0, label);
+    sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
+    sqlite3VdbeAddOp(v, OP_MemStore, mem, 1);
+  }
+
+  if( pExpr->pSelect ){
+    sqlite3VdbeAddOp(v, OP_AggContextPush, 0, 0);
+  }
+
+  switch( pExpr->op ){
     case TK_IN: {
       char affinity;
-      Vdbe *v = sqlite3GetVdbe(pParse);
       KeyInfo keyInfo;
       int addr;        /* Address of OP_OpenTemp instruction */
 
-      if( v==0 ) return 1;
-      if( sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
-        return 1;
-      }
       affinity = sqlite3ExprAffinity(pExpr->pLeft);
 
       /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
@@ -970,10 +1296,7 @@ int sqlite3ExprResolveIds(
           if( !sqlite3ExprIsConstant(pE2) ){
             sqlite3ErrorMsg(pParse,
               "right-hand side of IN operator must be constant");
-            return 1;
-          }
-          if( sqlite3ExprCheck(pParse, pE2, 0, 0) ){
-            return 1;
+            return;
           }
 
           /* Evaluate the expression and insert it into the temp table */
@@ -984,183 +1307,43 @@ int sqlite3ExprResolveIds(
         }
       }
       sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO);
-
       break;
     }
 
+    case TK_EXISTS:
     case TK_SELECT: {
       /* This has to be a scalar SELECT.  Generate code to put the
       ** value of this select in a memory cell and record the number
       ** of the memory cell in iColumn.
       */
-      pExpr->iColumn = pParse->nMem++;
-      if(sqlite3Select(pParse, pExpr->pSelect, SRT_Mem,pExpr->iColumn,0,0,0,0)){
-        return 1;
-      }
-      break;
-    }
-
-    /* For all else, just recursively walk the tree */
-    default: {
-      if( pExpr->pLeft
-      && sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
-        return 1;
-      }
-      if( pExpr->pRight 
-      && sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){
-        return 1;
-      }
-      if( pExpr->pList ){
-        int i;
-        ExprList *pList = pExpr->pList;
-        for(i=0; i<pList->nExpr; i++){
-          Expr *pArg = pList->a[i].pExpr;
-          if( sqlite3ExprResolveIds(pParse, pSrcList, pEList, pArg) ){
-            return 1;
-          }
-        }
-      }
-    }
-  }
-  return 0;
-}
-
-/*
-** pExpr is a node that defines a function of some kind.  It might
-** be a syntactic function like "count(x)" or it might be a function
-** that implements an operator, like "a LIKE b".  
-**
-** This routine makes *pzName point to the name of the function and 
-** *pnName hold the number of characters in the function name.
-*/
-static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
-  switch( pExpr->op ){
-    case TK_FUNCTION: {
-      *pzName = pExpr->token.z;
-      *pnName = pExpr->token.n;
-      break;
-    }
-    case TK_LIKE: {
-      *pzName = "like";
-      *pnName = 4;
-      break;
-    }
-    case TK_GLOB: {
-      *pzName = "glob";
-      *pnName = 4;
-      break;
-    }
-    default: {
-      *pzName = "can't happen";
-      *pnName = 12;
-      break;
-    }
-  }
-}
-
-/*
-** Error check the functions in an expression.  Make sure all
-** function names are recognized and all functions have the correct
-** number of arguments.  Leave an error message in pParse->zErrMsg
-** if anything is amiss.  Return the number of errors.
-**
-** if pIsAgg is not null and this expression is an aggregate function
-** (like count(*) or max(value)) then write a 1 into *pIsAgg.
-*/
-int sqlite3ExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
-  int nErr = 0;
-  if( pExpr==0 ) return 0;
-  switch( pExpr->op ){
-    case TK_GLOB:
-    case TK_LIKE:
-    case TK_FUNCTION: {
-      int n = pExpr->pList ? pExpr->pList->nExpr : 0;  /* Number of arguments */
-      int no_such_func = 0;       /* True if no such function exists */
-      int wrong_num_args = 0;     /* True if wrong number of arguments */
-      int is_agg = 0;             /* True if is an aggregate function */
-      int i;
-      int nId;                    /* Number of characters in function name */
-      const char *zId;            /* The function name. */
-      FuncDef *pDef;
-      int enc = pParse->db->enc;
+      int sop;
+      Select *pSel;
 
-      getFunctionName(pExpr, &zId, &nId);
-      pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
-      if( pDef==0 ){
-        pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
-        if( pDef==0 ){
-          no_such_func = 1;
-        }else{
-          wrong_num_args = 1;
-        }
+      pExpr->iColumn = pParse->nMem++;
+      pSel = pExpr->pSelect;
+      if( pExpr->op==TK_SELECT ){
+        sop = SRT_Mem;
       }else{
-        is_agg = pDef->xFunc==0;
-      }
-      if( is_agg && !allowAgg ){
-        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId, zId);
-        nErr++;
-        is_agg = 0;
-      }else if( no_such_func ){
-        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
-        nErr++;
-      }else if( wrong_num_args ){
-        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
-             nId, zId);
-        nErr++;
-      }
-      if( is_agg ){
-        pExpr->op = TK_AGG_FUNCTION;
-        if( pIsAgg ) *pIsAgg = 1;
-      }
-      for(i=0; nErr==0 && i<n; i++){
-        nErr = sqlite3ExprCheck(pParse, pExpr->pList->a[i].pExpr,
-                               allowAgg && !is_agg, pIsAgg);
-      }
-      /* FIX ME:  Compute pExpr->affinity based on the expected return
-      ** type of the function 
-      */
-    }
-    default: {
-      if( pExpr->pLeft ){
-        nErr = sqlite3ExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg);
-      }
-      if( nErr==0 && pExpr->pRight ){
-        nErr = sqlite3ExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg);
-      }
-      if( nErr==0 && pExpr->pList ){
-        int n = pExpr->pList->nExpr;
-        int i;
-        for(i=0; nErr==0 && i<n; i++){
-          Expr *pE2 = pExpr->pList->a[i].pExpr;
-          nErr = sqlite3ExprCheck(pParse, pE2, allowAgg, pIsAgg);
-        }
+        static const Token one = { "1", 0, 1 };
+        sop = SRT_Exists;
+        sqlite3ExprListDelete(pSel->pEList);
+        pSel->pEList = sqlite3ExprListAppend(0, 
+                          sqlite3Expr(TK_INTEGER, 0, 0, &one), 0);
       }
+      sqlite3Select(pParse, pSel, sop, pExpr->iColumn, 0, 0, 0, 0);
       break;
     }
   }
-  return nErr;
-}
 
-/*
-** Call sqlite3ExprResolveIds() followed by sqlite3ExprCheck().
-**
-** This routine is provided as a convenience since it is very common
-** to call ResolveIds() and Check() back to back.
-*/
-int sqlite3ExprResolveAndCheck(
-  Parse *pParse,     /* The parser context */
-  SrcList *pSrcList, /* List of tables used to resolve column names */
-  ExprList *pEList,  /* List of expressions used to resolve "AS" */
-  Expr *pExpr,       /* The expression to be analyzed. */
-  int allowAgg,      /* True to allow aggregate expressions */
-  int *pIsAgg        /* Set to TRUE if aggregates are found */
-){
-  if( pExpr==0 ) return 0;
-  if( sqlite3ExprResolveIds(pParse,pSrcList,pEList,pExpr) ){
-    return 1;
+  if( pExpr->pSelect ){
+    sqlite3VdbeAddOp(v, OP_AggContextPop, 0, 0);
+  }
+  if( label<0 ){
+    sqlite3VdbeResolveLabel(v, label);
   }
-  return sqlite3ExprCheck(pParse, pExpr, allowAgg, pIsAgg);
+  return;
 }
+#endif /* SQLITE_OMIT_SUBQUERY */
 
 /*
 ** Generate an instruction that will put the integer describe by
@@ -1190,12 +1373,16 @@ static void codeInteger(Vdbe *v, const char *z, int n){
 void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
   Vdbe *v = pParse->pVdbe;
   int op;
-  if( v==0 || pExpr==0 ) return;
+  if( v==0 ) return;
+  if( pExpr==0 ){
+    sqlite3VdbeAddOp(v, OP_String8, 0, 0);  /* Empty expression evals to NULL */
+    return;
+  }
   op = pExpr->op;
   switch( op ){
     case TK_COLUMN: {
-      if( pParse->useAgg ){
-        sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
+      if( !pParse->fillAgg && pExpr->iAgg>=0 ){
+        sqlite3VdbeAddOp(v, OP_AggGet, pExpr->iAggCtx, pExpr->iAgg);
       }else if( pExpr->iColumn>=0 ){
         sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
 #ifndef NDEBUG
@@ -1220,12 +1407,14 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
       sqlite3VdbeDequoteP3(v, -1);
       break;
     }
+#ifndef SQLITE_OMIT_BLOB_LITERAL
     case TK_BLOB: {
       assert( TK_BLOB==OP_HexBlob );
       sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z+1, pExpr->token.n-1);
       sqlite3VdbeDequoteP3(v, -1);
       break;
     }
+#endif
     case TK_NULL: {
       sqlite3VdbeAddOp(v, OP_String8, 0, 0);
       break;
@@ -1237,6 +1426,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
       }
       break;
     }
+    case TK_REGISTER: {
+      sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0);
+      break;
+    }
     case TK_LT:
     case TK_LE:
     case TK_GT:
@@ -1323,6 +1516,9 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
       sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
       break;
     }
+    case TK_CDATE:
+    case TK_CTIME:
+    case TK_CTIMESTAMP:
     case TK_GLOB:
     case TK_LIKE:
     case TK_FUNCTION: {
@@ -1354,7 +1550,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
       sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF);
       break;
     }
+#ifndef SQLITE_OMIT_SUBQUERY
+    case TK_EXISTS:
     case TK_SELECT: {
+      sqlite3CodeSubselect(pParse, pExpr);
       sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0);
       VdbeComment((v, "# load subquery result"));
       break;
@@ -1362,6 +1561,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
     case TK_IN: {
       int addr;
       char affinity;
+      sqlite3CodeSubselect(pParse, pExpr);
 
       /* Figure out the affinity to use to create a key from the results
       ** of the expression. affinityStr stores a static string suitable for
@@ -1386,6 +1586,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
 
       break;
     }
+#endif
     case TK_BETWEEN: {
       Expr *pLeft = pExpr->pLeft;
       struct ExprList_item *pLItem = pExpr->pList->a;
@@ -1452,6 +1653,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
       sqlite3VdbeResolveLabel(v, expr_end_label);
       break;
     }
+#ifndef SQLITE_OMIT_TRIGGER
     case TK_RAISE: {
       if( !pParse->trigStack ){
         sqlite3ErrorMsg(pParse,
@@ -1472,10 +1674,38 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
          VdbeComment((v, "# raise(IGNORE)"));
       }
     }
+#endif
     break;
   }
 }
 
+#ifndef SQLITE_OMIT_TRIGGER
+/*
+** Generate code that evalutes the given expression and leaves the result
+** on the stack.  See also sqlite3ExprCode().
+**
+** This routine might also cache the result and modify the pExpr tree
+** so that it will make use of the cached result on subsequent evaluations
+** rather than evaluate the whole expression again.  Trivial expressions are
+** not cached.  If the expression is cached, its result is stored in a 
+** memory location.
+*/
+void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){
+  Vdbe *v = pParse->pVdbe;
+  int iMem;
+  int addr1, addr2;
+  if( v==0 ) return;
+  addr1 = sqlite3VdbeCurrentAddr(v);
+  sqlite3ExprCode(pParse, pExpr);
+  addr2 = sqlite3VdbeCurrentAddr(v);
+  if( addr2>addr1+1 || sqlite3VdbeGetOp(v, addr1)->opcode==OP_Function ){
+    iMem = pExpr->iTable = pParse->nMem++;
+    sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0);
+    pExpr->op = TK_REGISTER;
+  }
+}
+#endif
+
 /*
 ** Generate code that pushes the value of every element of the given
 ** expression list onto the stack.
@@ -1737,6 +1967,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
 
 /*
 ** Add a new element to the pParse->aAgg[] array and return its index.
+** The new element is initialized to zero.  The calling function is
+** expected to fill it in.
 */
 static int appendAggInfo(Parse *pParse){
   if( (pParse->nAgg & 0x7)==0 ){
@@ -1752,80 +1984,91 @@ static int appendAggInfo(Parse *pParse){
 }
 
 /*
-** Analyze the given expression looking for aggregate functions and
-** for variables that need to be added to the pParse->aAgg[] array.
-** Make additional entries to the pParse->aAgg[] array as necessary.
+** This is an xFunc for walkExprTree() used to implement 
+** sqlite3ExprAnalyzeAggregates().  See sqlite3ExprAnalyzeAggregates
+** for additional information.
 **
-** This routine should only be called after the expression has been
-** analyzed by sqlite3ExprResolveIds() and sqlite3ExprCheck().
-**
-** If errors are seen, leave an error message in zErrMsg and return
-** the number of errors.
+** This routine analyzes the aggregate function at pExpr.
 */
-int sqlite3ExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){
+static int analyzeAggregate(void *pArg, Expr *pExpr){
   int i;
   AggExpr *aAgg;
-  int nErr = 0;
+  NameContext *pNC = (NameContext *)pArg;
+  Parse *pParse = pNC->pParse;
+  SrcList *pSrcList = pNC->pSrcList;
 
-  if( pExpr==0 ) return 0;
   switch( pExpr->op ){
     case TK_COLUMN: {
-      aAgg = pParse->aAgg;
-      for(i=0; i<pParse->nAgg; i++){
-        if( aAgg[i].isAgg ) continue;
-        if( aAgg[i].pExpr->iTable==pExpr->iTable
-         && aAgg[i].pExpr->iColumn==pExpr->iColumn ){
-          break;
+      for(i=0; pSrcList && i<pSrcList->nSrc; i++){
+        if( pExpr->iTable==pSrcList->a[i].iCursor ){
+          aAgg = pParse->aAgg;
+          for(i=0; i<pParse->nAgg; i++){
+            if( aAgg[i].isAgg ) continue;
+            if( aAgg[i].pExpr->iTable==pExpr->iTable
+             && aAgg[i].pExpr->iColumn==pExpr->iColumn ){
+              break;
+            }
+          }
+          if( i>=pParse->nAgg ){
+            i = appendAggInfo(pParse);
+            if( i<0 ) return 1;
+            pParse->aAgg[i].isAgg = 0;
+            pParse->aAgg[i].pExpr = pExpr;
+          }
+          pExpr->iAgg = i;
+          pExpr->iAggCtx = pNC->nDepth;
+          return 1;
         }
       }
-      if( i>=pParse->nAgg ){
-        i = appendAggInfo(pParse);
-        if( i<0 ) return 1;
-        pParse->aAgg[i].isAgg = 0;
-        pParse->aAgg[i].pExpr = pExpr;
-      }
-      pExpr->iAgg = i;
-      break;
+      return 1;
     }
     case TK_AGG_FUNCTION: {
-      aAgg = pParse->aAgg;
-      for(i=0; i<pParse->nAgg; i++){
-        if( !aAgg[i].isAgg ) continue;
-        if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){
-          break;
+      if( pNC->nDepth==0 ){
+        aAgg = pParse->aAgg;
+        for(i=0; i<pParse->nAgg; i++){
+          if( !aAgg[i].isAgg ) continue;
+          if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){
+            break;
+          }
         }
-      }
-      if( i>=pParse->nAgg ){
-        u8 enc = pParse->db->enc;
-        i = appendAggInfo(pParse);
-        if( i<0 ) return 1;
-        pParse->aAgg[i].isAgg = 1;
-        pParse->aAgg[i].pExpr = pExpr;
-        pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db,
-             pExpr->token.z, pExpr->token.n,
-             pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0);
-      }
-      pExpr->iAgg = i;
-      break;
-    }
-    default: {
-      if( pExpr->pLeft ){
-        nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pLeft);
-      }
-      if( nErr==0 && pExpr->pRight ){
-        nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pRight);
-      }
-      if( nErr==0 && pExpr->pList ){
-        int n = pExpr->pList->nExpr;
-        int i;
-        for(i=0; nErr==0 && i<n; i++){
-          nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pList->a[i].pExpr);
+        if( i>=pParse->nAgg ){
+          u8 enc = pParse->db->enc;
+          i = appendAggInfo(pParse);
+          if( i<0 ) return 1;
+          pParse->aAgg[i].isAgg = 1;
+          pParse->aAgg[i].pExpr = pExpr;
+          pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db,
+               pExpr->token.z, pExpr->token.n,
+               pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0);
         }
+        pExpr->iAgg = i;
+        return 1;
       }
-      break;
     }
   }
-  return nErr;
+  if( pExpr->pSelect ){
+    pNC->nDepth++;
+    walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC);
+    pNC->nDepth--;
+  }
+  return 0;
+}
+
+/*
+** Analyze the given expression looking for aggregate functions and
+** for variables that need to be added to the pParse->aAgg[] array.
+** Make additional entries to the pParse->aAgg[] array as necessary.
+**
+** This routine should only be called after the expression has been
+** analyzed by sqlite3ExprResolveNames().
+**
+** If errors are seen, leave an error message in zErrMsg and return
+** the number of errors.
+*/
+int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
+  int nErr = pNC->pParse->nErr;
+  walkExprTree(pExpr, analyzeAggregate, pNC);
+  return pNC->pParse->nErr - nErr;
 }
 
 /*
@@ -1917,7 +2160,10 @@ FuncDef *sqlite3FindFunction(
     pBest->iPrefEnc = enc;
     memcpy(pBest->zName, zName, nName);
     pBest->zName[nName] = 0;
-    sqlite3HashInsert(&db->aFunc, pBest->zName, nName, (void*)pBest);
+    if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
+      sqliteFree(pBest);
+      return 0;
+    }
   }
 
   if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
index f61bdae3fd37610d414241dc8d887e9c5833e4b4..49ceed39ead275c6e6384ee0b0e482e77ed7e379 100644 (file)
 **
 ** $Id$
 */
+#include "sqliteInt.h"
 #include <ctype.h>
 #include <math.h>
 #include <stdlib.h>
 #include <assert.h>
-#include "sqliteInt.h"
 #include "vdbeInt.h"
 #include "os.h"
 
@@ -347,10 +347,11 @@ static const struct compareInfo likeInfo = { '%', '_',   0, 1 };
 **
 **         abc[*]xyz        Matches "abc*xyz" only
 */
-int patternCompare(
+static int patternCompare(
   const u8 *zPattern,              /* The glob pattern */
   const u8 *zString,               /* The string to compare against the glob */
-  const struct compareInfo *pInfo  /* Information about how to do the compare */
+  const struct compareInfo *pInfo, /* Information about how to do the compare */
+  const int esc                    /* The escape character */
 ){
   register int c;
   int invert;
@@ -360,9 +361,10 @@ int patternCompare(
   u8 matchAll = pInfo->matchAll;
   u8 matchSet = pInfo->matchSet;
   u8 noCase = pInfo->noCase; 
+  int prevEscape = 0;     /* True if the previous character was 'escape' */
 
   while( (c = *zPattern)!=0 ){
-    if( c==matchAll ){
+    if( !prevEscape && c==matchAll ){
       while( (c=zPattern[1]) == matchAll || c == matchOne ){
         if( c==matchOne ){
           if( *zString==0 ) return 0;
@@ -370,9 +372,15 @@ int patternCompare(
         }
         zPattern++;
       }
+      if( c && esc && sqlite3ReadUtf8(&zPattern[1])==esc ){
+        u8 const *zTemp = &zPattern[1];
+        sqliteNextChar(zTemp);
+        c = *zTemp;
+      }
       if( c==0 ) return 1;
       if( c==matchSet ){
-        while( *zString && patternCompare(&zPattern[1],zString,pInfo)==0 ){
+        assert( esc==0 );   /* This is GLOB, not LIKE */
+        while( *zString && patternCompare(&zPattern[1],zString,pInfo,esc)==0 ){
           sqliteNextChar(zString);
         }
         return *zString!=0;
@@ -386,17 +394,18 @@ int patternCompare(
             while( c2 != 0 && c2 != c ){ c2 = *++zString; }
           }
           if( c2==0 ) return 0;
-          if( patternCompare(&zPattern[1],zString,pInfo) ) return 1;
+          if( patternCompare(&zPattern[1],zString,pInfo,esc) ) return 1;
           sqliteNextChar(zString);
         }
         return 0;
       }
-    }else if( c==matchOne ){
+    }else if( !prevEscape && c==matchOne ){
       if( *zString==0 ) return 0;
       sqliteNextChar(zString);
       zPattern++;
     }else if( c==matchSet ){
       int prior_c = 0;
+      assert( esc==0 );    /* This only occurs for GLOB, not LIKE */
       seen = 0;
       invert = 0;
       c = sqliteCharVal(zString);
@@ -424,6 +433,9 @@ int patternCompare(
       if( c2==0 || (seen ^ invert)==0 ) return 0;
       sqliteNextChar(zString);
       zPattern++;
+    }else if( esc && !prevEscape && sqlite3ReadUtf8(zPattern)==esc){
+      prevEscape = 1;
+      sqliteNextChar(zPattern);
     }else{
       if( noCase ){
         if( sqlite3UpperToLower[c] != sqlite3UpperToLower[*zString] ) return 0;
@@ -432,6 +444,7 @@ int patternCompare(
       }
       zPattern++;
       zString++;
+      prevEscape = 0;
     }
   }
   return *zString==0;
@@ -457,8 +470,21 @@ static void likeFunc(
 ){
   const unsigned char *zA = sqlite3_value_text(argv[0]);
   const unsigned char *zB = sqlite3_value_text(argv[1]);
+  int escape = 0;
+  if( argc==3 ){
+    /* The escape character string must consist of a single UTF-8 character.
+    ** Otherwise, return an error.
+    */
+    const unsigned char *zEsc = sqlite3_value_text(argv[2]);
+    if( sqlite3utf8CharLen(zEsc, -1)!=1 ){
+      sqlite3_result_error(context, 
+          "ESCAPE expression must be a single character", -1);
+      return;
+    }
+    escape = sqlite3ReadUtf8(zEsc);
+  }
   if( zA && zB ){
-    sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo));
+    sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo, escape));
   }
 }
 
@@ -469,13 +495,13 @@ static void likeFunc(
 **
 **       A GLOB B
 **
-** is implemented as glob(A,B).
+** is implemented as glob(B,A).
 */
 static void globFunc(sqlite3_context *context, int arg, sqlite3_value **argv){
   const unsigned char *zA = sqlite3_value_text(argv[0]);
   const unsigned char *zB = sqlite3_value_text(argv[1]);
   if( zA && zB ){
-    sqlite3_result_int(context, patternCompare(zA, zB, &globInfo));
+    sqlite3_result_int(context, patternCompare(zA, zB, &globInfo, 0));
   }
 }
 
@@ -507,6 +533,7 @@ static void versionFunc(
   sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
 }
 
+
 /*
 ** EXPERIMENTAL - This is not an official function.  The interface may
 ** change.  This function may disappear.  Do not write code that depends
@@ -704,10 +731,12 @@ static void test_destructor(
   memcpy(zVal, sqlite3ValueText(argv[0], db->enc), len);
   if( db->enc==SQLITE_UTF8 ){
     sqlite3_result_text(pCtx, zVal, -1, destructor);
+#ifndef SQLITE_OMIT_UTF16
   }else if( db->enc==SQLITE_UTF16LE ){
     sqlite3_result_text16le(pCtx, zVal, -1, destructor);
   }else{
     sqlite3_result_text16be(pCtx, zVal, -1, destructor);
+#endif /* SQLITE_OMIT_UTF16 */
   }
 }
 static void test_destructor_count(
@@ -762,6 +791,20 @@ static void test_auxdata(
 }
 #endif /* SQLITE_TEST */
 
+#ifdef SQLITE_TEST
+/*
+** A function to test error reporting from user functions. This function
+** returns a copy of it's first argument as an error.
+*/
+static void test_error(
+  sqlite3_context *pCtx, 
+  int nArg,
+  sqlite3_value **argv
+){
+  sqlite3_result_error(pCtx, sqlite3_value_text(argv[0]), 0);
+}
+#endif /* SQLITE_TEST */
+
 /*
 ** An instance of the following structure holds the context of a
 ** sum() or avg() aggregate computation.
@@ -808,33 +851,6 @@ struct StdDevCtx {
   int cnt;        /* Number of terms counted */
 };
 
-#if 0   /* Omit because math library is required */
-/*
-** Routines used to compute the standard deviation as an aggregate.
-*/
-static void stdDevStep(sqlite3_context *context, int argc, const char **argv){
-  StdDevCtx *p;
-  double x;
-  if( argc<1 ) return;
-  p = sqlite3_aggregate_context(context, sizeof(*p));
-  if( p && argv[0] ){
-    x = sqlite3AtoF(argv[0], 0);
-    p->sum += x;
-    p->sum2 += x*x;
-    p->cnt++;
-  }
-}
-static void stdDevFinalize(sqlite3_context *context){
-  double rN = sqlite3_aggregate_count(context);
-  StdDevCtx *p = sqlite3_aggregate_context(context, sizeof(*p));
-  if( p && p->cnt>1 ){
-    double rCnt = cnt;
-    sqlite3_set_result_double(context, 
-       sqrt((p->sum2 - p->sum*p->sum/rCnt)/(rCnt-1.0)));
-  }
-}
-#endif
-
 /*
 ** The following structure keeps track of state information for the
 ** count() aggregate function.
@@ -933,7 +949,9 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
     { "typeof",             1, 0, SQLITE_UTF8,    0, typeofFunc },
     { "length",             1, 0, SQLITE_UTF8,    0, lengthFunc },
     { "substr",             3, 0, SQLITE_UTF8,    0, substrFunc },
+#ifndef SQLITE_OMIT_UTF16
     { "substr",             3, 0, SQLITE_UTF16LE, 0, sqlite3utf16Substr },
+#endif
     { "abs",                1, 0, SQLITE_UTF8,    0, absFunc    },
     { "round",              1, 0, SQLITE_UTF8,    0, roundFunc  },
     { "round",              2, 0, SQLITE_UTF8,    0, roundFunc  },
@@ -945,6 +963,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
     { "ifnull",             2, 0, SQLITE_UTF8,    1, ifnullFunc },
     { "random",            -1, 0, SQLITE_UTF8,    0, randomFunc },
     { "like",               2, 0, SQLITE_UTF8,    0, likeFunc   },
+    { "like",               3, 0, SQLITE_UTF8,    0, likeFunc   },
     { "glob",               2, 0, SQLITE_UTF8,    0, globFunc   },
     { "nullif",             2, 0, SQLITE_UTF8,    1, nullifFunc },
     { "sqlite_version",     0, 0, SQLITE_UTF8,    0, versionFunc},
@@ -960,6 +979,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
     { "test_destructor",       1, 1, SQLITE_UTF8, 0, test_destructor},
     { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count},
     { "test_auxdata",         -1, 0, SQLITE_UTF8, 0, test_auxdata},
+    { "test_error",            1, 0, SQLITE_UTF8, 0, test_error},
 #endif
   };
   static const struct {
@@ -976,9 +996,6 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
     { "avg",    1, 0, 0, sumStep,      avgFinalize    },
     { "count",  0, 0, 0, countStep,    countFinalize  },
     { "count",  1, 0, 0, countStep,    countFinalize  },
-#if 0
-    { "stddev", 1, 0, stdDevStep,   stdDevFinalize },
-#endif
   };
   int i;
 
@@ -998,6 +1015,9 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
       }
     }
   }
+#ifndef SQLITE_OMIT_ALTERTABLE
+  sqlite3AlterFunctions(db);
+#endif
   for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
     void *pArg = 0;
     switch( aAggs[i].argType ){
index 23e2e197487778836453c2a8f1d5292f587b4621..e01aae71630dc61a4adcb37f8dd43aeb8a24d7e5 100644 (file)
@@ -98,7 +98,14 @@ static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
 ** Hash and comparison functions when the mode is SQLITE_HASH_STRING
 */
 static int strHash(const void *pKey, int nKey){
-  return sqlite3HashNoCase((const char*)pKey, nKey); 
+  const char *z = (const char *)pKey;
+  int h = 0;
+  if( nKey<=0 ) nKey = strlen(z);
+  while( nKey > 0  ){
+    h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
+    nKey--;
+  }
+  return h & 0x7fffffff;
 }
 static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
   if( n1!=n2 ) return 1;
index 65cbdc8ff1cecda71599f4205b04c2dfc3de38c1..c9485fe24752c4902332d8feecf05cda85676cd9 100644 (file)
@@ -94,6 +94,27 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
   sqlite3VdbeChangeP3(v, -1, pTab->zColAff, 0);
 }
 
+/*
+** Return non-zero if SELECT statement p opens the table with rootpage
+** iTab in database iDb.  This is used to see if a statement of the form 
+** "INSERT INTO <iDb, iTab> SELECT ..." can run without using temporary
+** table for the results of the SELECT. 
+**
+** No checking is done for sub-selects that are part of expressions.
+*/
+static int selectReadsTable(Select *p, int iDb, int iTab){
+  int i;
+  struct SrcList_item *pItem;
+  if( p->pSrc==0 ) return 0;
+  for(i=0, pItem=p->pSrc->a; i<p->pSrc->nSrc; i++, pItem++){
+    if( pItem->pSelect ){
+      if( selectReadsTable(p, iDb, iTab) ) return 1;
+    }else{
+      if( pItem->pTab->iDb==iDb && pItem->pTab->tnum==iTab ) return 1;
+    }
+  }
+  return 0;
+}
 
 /*
 ** This routine is call to handle SQL of the following forms:
@@ -182,18 +203,24 @@ void sqlite3Insert(
   sqlite3 *db;          /* The main database structure */
   int keyColumn = -1;   /* Column that is the INTEGER PRIMARY KEY */
   int endOfLoop;        /* Label for the end of the insertion loop */
-  int useTempTable;     /* Store SELECT results in intermediate table */
+  int useTempTable = 0; /* Store SELECT results in intermediate table */
   int srcTab = 0;       /* Data comes from this temporary cursor if >=0 */
   int iSelectLoop = 0;  /* Address of code that implements the SELECT */
   int iCleanup = 0;     /* Address of the cleanup code */
   int iInsertBlock = 0; /* Address of the subroutine used to insert data */
   int iCntMem = 0;      /* Memory cell used for the row counter */
-  int isView;           /* True if attempting to insert into a view */
+  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 row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
-  int before_triggers;        /* True if there are BEFORE triggers */
-  int after_triggers;         /* True if there are AFTER triggers */
-  int newIdx = -1;            /* Cursor for the NEW table */
+#ifndef SQLITE_OMIT_TRIGGER
+  int isView;                 /* True if attempting to insert into a view */
+  int triggers_exist = 0;     /* True if there are FOR EACH ROW triggers */
+#endif
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+  int counterRowid;     /* Memory cell holding rowid of autoinc counter */
+#endif
 
   if( pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup;
   db = pParse->db;
@@ -208,22 +235,32 @@ void sqlite3Insert(
     goto insert_cleanup;
   }
   assert( pTab->iDb<db->nDb );
-  zDb = db->aDb[pTab->iDb].zName;
+  pDb = &db->aDb[pTab->iDb];
+  zDb = pDb->zName;
   if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
     goto insert_cleanup;
   }
 
+  /* Figure out if we have any triggers and if the table being
+  ** inserted into is a view
+  */
+#ifndef SQLITE_OMIT_TRIGGER
+  triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0);
+  isView = pTab->pSelect!=0;
+#else
+# define triggers_exist 0
+# define isView 0
+#endif
+#ifdef SQLITE_OMIT_VIEW
+# undef isView
+# define isView 0
+#endif
+
   /* Ensure that:
   *  (a) the table is not read-only, 
   *  (b) that if it is a view then ON INSERT triggers exist
   */
-  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_INSERT, 
-                                       TK_BEFORE, TK_ROW, 0);
-  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_INSERT,
-                                       TK_AFTER, TK_ROW, 0);
-  row_triggers_exist = before_triggers || after_triggers;
-  isView = pTab->pSelect!=0;
-  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
+  if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
     goto insert_cleanup;
   }
   if( pTab==0 ) goto insert_cleanup;
@@ -245,14 +282,42 @@ void sqlite3Insert(
   */
   v = sqlite3GetVdbe(pParse);
   if( v==0 ) goto insert_cleanup;
-  sqlite3VdbeCountChanges(v);
-  sqlite3BeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb);
+  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
+  sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, pTab->iDb);
 
   /* if there are row triggers, allocate a temp table for new.* references. */
-  if( row_triggers_exist ){
+  if( triggers_exist ){
     newIdx = pParse->nTab++;
   }
 
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+  /* If this is an AUTOINCREMENT table, look up the sequence number in the
+  ** sqlite_sequence table and store it in memory cell counterMem.  Also
+  ** remember the rowid of the sqlite_sequence table entry in memory cell
+  ** counterRowid.
+  */
+  if( pTab->autoInc ){
+    int iCur = pParse->nTab;
+    int base = 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);
+    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_Recno, 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_Close, iCur, 0);
+  }
+#endif /* SQLITE_OMIT_AUTOINCREMENT */
+
   /* Figure out how many columns of data are supplied.  If the data
   ** is coming from a SELECT statement, then this step also generates
   ** all the code to implement the SELECT statement and invoke a subroutine
@@ -268,8 +333,11 @@ void sqlite3Insert(
     iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
     iSelectLoop = sqlite3VdbeCurrentAddr(v);
     iInsertBlock = sqlite3VdbeMakeLabel(v);
-    rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock, 0,0,0,0);
+
+    /* 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;
+
     iCleanup = sqlite3VdbeMakeLabel(v);
     sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup);
     assert( pSelect->pEList );
@@ -283,20 +351,8 @@ void sqlite3Insert(
     ** of the tables being read by the SELECT statement.  Also use a 
     ** temp table in the case of row triggers.
     */
-    if( row_triggers_exist ){
+    if( triggers_exist || selectReadsTable(pSelect, pTab->iDb, pTab->tnum) ){
       useTempTable = 1;
-    }else{
-      int addr = 0;
-      useTempTable = 0;
-      while( useTempTable==0 ){
-        VdbeOp *pOp;
-        addr = sqlite3VdbeFindOp(v, addr, OP_OpenRead, pTab->tnum);
-        if( addr==0 ) break;
-        pOp = sqlite3VdbeGetOp(v, addr-2);
-        if( pOp->opcode==OP_Integer && pOp->p1==pTab->iDb ){
-          useTempTable = 1;
-        }
-      }
     }
 
     if( useTempTable ){
@@ -328,15 +384,16 @@ void sqlite3Insert(
     /* This is the case if the data for the INSERT is coming from a VALUES
     ** clause
     */
-    SrcList dummy;
+    NameContext sNC;
+    memset(&sNC, 0, sizeof(sNC));
+    sNC.pParse = pParse;
     assert( pList!=0 );
     srcTab = -1;
     useTempTable = 0;
     assert( pList );
     nColumn = pList->nExpr;
-    dummy.nSrc = 0;
     for(i=0; i<nColumn; i++){
-      if( sqlite3ExprResolveAndCheck(pParse,&dummy,0,pList->a[i].pExpr,0,0) ){
+      if( sqlite3ExprResolveNames(&sNC, pList->a[i].pExpr) ){
         goto insert_cleanup;
       }
     }
@@ -404,7 +461,7 @@ void sqlite3Insert(
 
   /* Open the temp table for FOR EACH ROW triggers
   */
-  if( row_triggers_exist ){
+  if( triggers_exist ){
     sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
     sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
   }
@@ -418,7 +475,7 @@ void sqlite3Insert(
   }
 
   /* Open tables and indices if there are no row triggers */
-  if( !row_triggers_exist ){
+  if( !triggers_exist ){
     base = pParse->nTab;
     sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
   }
@@ -440,7 +497,7 @@ void sqlite3Insert(
   /* Run the BEFORE and INSTEAD OF triggers, if there are any
   */
   endOfLoop = sqlite3VdbeMakeLabel(v);
-  if( before_triggers ){
+  if( triggers_exist & TRIGGER_BEFORE ){
 
     /* build the NEW.* reference row.  Note that if there is an INTEGER
     ** PRIMARY KEY into which a NULL is being inserted, that NULL will be
@@ -452,9 +509,8 @@ void sqlite3Insert(
       sqlite3VdbeAddOp(v, OP_Integer, -1, 0);
     }else if( useTempTable ){
       sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn);
-    }else if( pSelect ){
-      sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
     }else{
+      assert( pSelect==0 );  /* Otherwise useTempTable is true */
       sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);
       sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
       sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
@@ -473,13 +529,12 @@ void sqlite3Insert(
         }
       }
       if( pColumn && j>=pColumn->nId ){
-        sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
+        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
       }else if( useTempTable ){
         sqlite3VdbeAddOp(v, OP_Column, srcTab, j); 
-      }else if( pSelect ){
-        sqlite3VdbeAddOp(v, OP_Dup, nColumn-j-1, 1);
       }else{
-        sqlite3ExprCode(pParse, pList->a[j].pExpr);
+        assert( pSelect==0 ); /* Otherwise useTempTable is true */
+        sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr);
       }
     }
     sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
@@ -495,7 +550,7 @@ void sqlite3Insert(
     sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
 
     /* Fire BEFORE or INSTEAD OF triggers */
-    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, 
+    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab, 
         newIdx, -1, onError, endOfLoop) ){
       goto insert_cleanup;
     }
@@ -504,7 +559,7 @@ void sqlite3Insert(
   /* If any triggers exists, the opening of tables and indices is deferred
   ** until now.
   */
-  if( row_triggers_exist && !isView ){
+  if( triggers_exist && !isView ){
     base = pParse->nTab;
     sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
   }
@@ -528,11 +583,16 @@ void sqlite3Insert(
       */
       sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
       sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
-      sqlite3VdbeAddOp(v, OP_NewRecno, base, 0);
+      sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
       sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
     }else{
-      sqlite3VdbeAddOp(v, OP_NewRecno, base, 0);
+      sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
+    }
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+    if( pTab->autoInc ){
+      sqlite3VdbeAddOp(v, OP_MemMax, counterMem, 0);
     }
+#endif /* SQLITE_OMIT_AUTOINCREMENT */
 
     /* Push onto the stack, data for all columns of the new entry, beginning
     ** with the first column.
@@ -554,7 +614,7 @@ void sqlite3Insert(
         }
       }
       if( pColumn && j>=pColumn->nId ){
-        sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
+        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
       }else if( useTempTable ){
         sqlite3VdbeAddOp(v, OP_Column, srcTab, j); 
       }else if( pSelect ){
@@ -570,7 +630,7 @@ void sqlite3Insert(
     sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
                                    0, onError, endOfLoop);
     sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
-                            after_triggers ? newIdx : -1);
+                            (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1);
   }
 
   /* Update the count of rows that are inserted
@@ -579,7 +639,7 @@ void sqlite3Insert(
     sqlite3VdbeAddOp(v, OP_MemIncr, iCntMem, 0);
   }
 
-  if( row_triggers_exist ){
+  if( triggers_exist ){
     /* Close all tables opened */
     if( !isView ){
       sqlite3VdbeAddOp(v, OP_Close, base, 0);
@@ -589,8 +649,8 @@ void sqlite3Insert(
     }
 
     /* Code AFTER triggers */
-    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1, 
-          onError, endOfLoop) ){
+    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab,
+          newIdx, -1, onError, endOfLoop) ){
       goto insert_cleanup;
     }
   }
@@ -608,7 +668,7 @@ void sqlite3Insert(
     sqlite3VdbeResolveLabel(v, iCleanup);
   }
 
-  if( !row_triggers_exist ){
+  if( !triggers_exist ){
     /* Close all tables opened */
     sqlite3VdbeAddOp(v, OP_Close, base, 0);
     for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
@@ -616,10 +676,35 @@ void sqlite3Insert(
     }
   }
 
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+  /* Update the sqlite_sequence table by storing the content of the
+  ** counter value in memory counterMem back into the sqlite_sequence
+  ** table.
+  */
+  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);
+    sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0);
+    sqlite3VdbeAddOp(v, OP_NotNull, -1, base+7);
+    sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
+    sqlite3VdbeAddOp(v, OP_NewRecno, iCur, 0);
+    sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
+    sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0);
+    sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0);
+    sqlite3VdbeAddOp(v, OP_PutIntKey, iCur, 0);
+    sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
+  }
+#endif
+
   /*
-  ** Return the number of rows inserted.
+  ** Return the number of rows inserted. If this routine is 
+  ** generating code because of a call to sqlite3NestedParse(), do not
+  ** invoke the callback function.
   */
-  if( db->flags & SQLITE_CountRows ){
+  if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
     sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0);
     sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
     sqlite3VdbeSetNumCols(v, 1);
@@ -753,11 +838,13 @@ void sqlite3GenerateConstraintChecks(
     }else if( onError==OE_Default ){
       onError = OE_Abort;
     }
-    if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){
+    if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
       onError = OE_Abort;
     }
     sqlite3VdbeAddOp(v, OP_Dup, nCol-1-i, 1);
     addr = sqlite3VdbeAddOp(v, OP_NotNull, 1, 0);
+    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
+        || onError==OE_Ignore || onError==OE_Replace );
     switch( onError ){
       case OE_Rollback:
       case OE_Abort:
@@ -775,11 +862,10 @@ void sqlite3GenerateConstraintChecks(
         break;
       }
       case OE_Replace: {
-        sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
+        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
         sqlite3VdbeAddOp(v, OP_Push, nCol-i, 0);
         break;
       }
-      default: assert(0);
     }
     sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
   }
@@ -885,6 +971,8 @@ void sqlite3GenerateConstraintChecks(
     jumpInst2 = sqlite3VdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
 
     /* Generate code that executes if the new index entry is not unique */
+    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
+        || onError==OE_Ignore || onError==OE_Replace );
     switch( onError ){
       case OE_Rollback:
       case OE_Abort:
@@ -929,7 +1017,6 @@ void sqlite3GenerateConstraintChecks(
         seenReplace = 1;
         break;
       }
-      default: assert(0);
     }
     contAddr = sqlite3VdbeCurrentAddr(v);
     assert( contAddr<(1<<24) );
@@ -975,12 +1062,18 @@ void sqlite3CompleteInsertion(
   }
   sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
   sqlite3TableAffinityStr(v, pTab);
+#ifndef SQLITE_OMIT_TRIGGER
   if( newIdx>=0 ){
     sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
     sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
     sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
   }
-  pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID));
+#endif
+  if( pParse->nested ){
+    pik_flags = 0;
+  }else{
+    pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID));
+  }
   sqlite3VdbeAddOp(v, OP_PutIntKey, base, pik_flags);
   
   if( isUpdate && recnoChng ){
index 0ae7e1b2637782030ad8bfef8389884feee52cae..1d6dec3a3cd0ae481d985fad58cdc617bc5d3b16 100644 (file)
@@ -202,7 +202,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
   **    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[5]
+  **    meta[5]   The user cookie. Used by the application.
   **    meta[6]   
   **    meta[7]
   **    meta[8]
@@ -257,12 +257,23 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
       /* This happens if the database was initially empty */
       db->file_format = 1;
     }
+
+    if( db->file_format==2 ){
+      /* File format 2 is treated exactly as file format 1. New 
+      ** databases are created with file format 1.
+      */ 
+      db->file_format = 1;
+    }
   }
 
   /*
-  **  file_format==1    Version 3.0.0.
+  ** file_format==1    Version 3.0.0.
+  ** file_format==2    Version 3.1.3.
+  **
+  ** 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.
   */
-  if( meta[1]>1 ){
+  if( meta[1]>2 ){
     sqlite3BtreeCloseCursor(curMain);
     sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
     return SQLITE_ERROR;
@@ -279,7 +290,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
   }else{
     char *zSql;
     zSql = sqlite3MPrintf(
-        "SELECT name, rootpage, sql, %s FROM '%q'.%s",
+        "SELECT name, rootpage, sql, '%s' FROM '%q'.%s",
         zDbNum, db->aDb[iDb].zName, zMasterName);
     sqlite3SafetyOff(db);
     rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
@@ -373,12 +384,13 @@ int sqlite3ReadSchema(Parse *pParse){
 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; }
 
 /*
 ** This is the default collating function named "BINARY" which is always
 ** available.
 */
-static int binaryCollatingFunc(
+static int binCollFunc(
   void *NotUsed,
   int nKey1, const void *pKey1,
   int nKey2, const void *pKey2
@@ -553,7 +565,7 @@ const char *sqlite3ErrStr(int rc){
     case SQLITE_NOLFS:      z = "kernel lacks large file support";       break;
     case SQLITE_AUTH:       z = "authorization denied";                  break;
     case SQLITE_FORMAT:     z = "auxiliary database format error";       break;
-    case SQLITE_RANGE:      z = "bind index out of range";               break;
+    case SQLITE_RANGE:      z = "bind or column index out of range";     break;
     case SQLITE_NOTADB:     z = "file is encrypted or is not a database";break;
     default:                z = "unknown error";                         break;
   }
@@ -706,6 +718,7 @@ int sqlite3_create_function(
     return SQLITE_ERROR;
   }
   
+#ifndef SQLITE_OMIT_UTF16
   /* 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.
@@ -725,6 +738,25 @@ int sqlite3_create_function(
     if( rc!=SQLITE_OK ) return rc;
     enc = SQLITE_UTF16BE;
   }
+#else
+  enc = SQLITE_UTF8;
+#endif
+  
+  /* Check if an existing function is being overridden or deleted. If so,
+  ** and there are active VMs, then return SQLITE_BUSY. If a function
+  ** is being overridden/deleted but there are no active VMs, allow the
+  ** operation to continue but invalidate all precompiled statements.
+  */
+  p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 0);
+  if( p && p->iPrefEnc==enc && p->nArg==nArg ){
+    if( db->activeVdbeCnt ){
+      sqlite3Error(db, SQLITE_BUSY, 
+        "Unable to delete/modify user-function due to active statements");
+      return SQLITE_BUSY;
+    }else{
+      sqlite3ExpirePreparedStatements(db);
+    }
+  }
 
   p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);
   if( p==0 ) return SQLITE_NOMEM;
@@ -734,6 +766,7 @@ int sqlite3_create_function(
   p->pUserData = pUserData;
   return SQLITE_OK;
 }
+#ifndef SQLITE_OMIT_UTF16
 int sqlite3_create_function16(
   sqlite3 *db,
   const void *zFunctionName,
@@ -762,6 +795,7 @@ int sqlite3_create_function16(
       pUserData, xFunc, xStep, xFinal);
   return rc;
 }
+#endif
 
 /*
 ** Register a trace function.  The pArg from the previously registered trace
@@ -835,13 +869,14 @@ int sqlite3BtreeFactory(
   if( omitJournal ){
     btree_flags |= BTREE_OMIT_JOURNAL;
   }
+  if( db->flags & SQLITE_NoReadlock ){
+    btree_flags |= BTREE_NO_READLOCK;
+  }
   if( zFilename==0 ){
-#ifndef TEMP_STORE
-# define TEMP_STORE 1
-#endif
 #if TEMP_STORE==0
     /* Do nothing */
 #endif
+#ifndef SQLITE_OMIT_MEMORYDB
 #if TEMP_STORE==1
     if( db->temp_store==2 ) zFilename = ":memory:";
 #endif
@@ -851,6 +886,7 @@ int sqlite3BtreeFactory(
 #if TEMP_STORE==3
     zFilename = ":memory:";
 #endif
+#endif /* SQLITE_OMIT_MEMORYDB */
   }
 
   rc = sqlite3BtreeOpen(zFilename, ppBtree, btree_flags);
@@ -880,6 +916,7 @@ const char *sqlite3_errmsg(sqlite3 *db){
   return z;
 }
 
+#ifndef SQLITE_OMIT_UTF16
 /*
 ** Return UTF-16 encoded English language explanation of the most recent
 ** error.
@@ -919,6 +956,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){
   }
   return z;
 }
+#endif /* SQLITE_OMIT_UTF16 */
 
 /*
 ** Return the most recent error code generated by an SQLite routine.
@@ -1005,6 +1043,7 @@ int sqlite3_prepare(
   if( pzTail ) *pzTail = sParse.zTail;
   rc = sParse.rc;
 
+#ifndef SQLITE_OMIT_EXPLAIN
   if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
     sqlite3VdbeSetNumCols(sParse.pVdbe, 5);
     sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC);
@@ -1013,6 +1052,7 @@ int sqlite3_prepare(
     sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC);
     sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC);
   } 
+#endif
 
 prepare_out:
   if( sqlite3SafetyOff(db) ){
@@ -1033,6 +1073,7 @@ prepare_out:
   return rc;
 }
 
+#ifndef SQLITE_OMIT_UTF16
 /*
 ** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
 */
@@ -1076,6 +1117,7 @@ int sqlite3_prepare16(
  
   return rc;
 }
+#endif /* SQLITE_OMIT_UTF16 */
 
 /*
 ** This routine does the work of opening a database on behalf of
@@ -1091,7 +1133,6 @@ static int openDatabase(
 ){
   sqlite3 *db;
   int rc, i;
-  char *zErrMsg = 0;
 
   /* Allocate the sqlite data structure */
   db = sqliteMalloc( sizeof(sqlite3) );
@@ -1102,7 +1143,7 @@ static int openDatabase(
   db->aDb = db->aDbStatic;
   db->enc = SQLITE_UTF8;
   db->autoCommit = 1;
-  /* db->flags |= SQLITE_ShortColNames; */
+  db->flags |= SQLITE_ShortColNames;
   sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
   sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0);
   for(i=0; i<db->nDb; i++){
@@ -1116,11 +1157,9 @@ static int openDatabase(
   ** 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.
   */
-  sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binaryCollatingFunc);
-  sqlite3_create_collation(db, "BINARY", SQLITE_UTF16LE, 0,binaryCollatingFunc);
-  sqlite3_create_collation(db, "BINARY", SQLITE_UTF16BE, 0,binaryCollatingFunc);
-  db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0);
-  if( !db->pDfltColl ){
+  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 );
     db->magic = SQLITE_MAGIC_CLOSED;
@@ -1150,14 +1189,8 @@ static int openDatabase(
   ** is accessed.
   */
   sqlite3RegisterBuiltinFunctions(db);
-  if( rc==SQLITE_OK ){
-    sqlite3Error(db, SQLITE_OK, 0);
-    db->magic = SQLITE_MAGIC_OPEN;
-  }else{
-    sqlite3Error(db, rc, "%s", zErrMsg, 0);
-    if( zErrMsg ) sqliteFree(zErrMsg);
-    db->magic = SQLITE_MAGIC_CLOSED;
-  }
+  sqlite3Error(db, SQLITE_OK, 0);
+  db->magic = SQLITE_MAGIC_OPEN;
 
 opendb_out:
   if( sqlite3_errcode(db)==SQLITE_OK && sqlite3_malloc_failed ){
@@ -1177,6 +1210,7 @@ int sqlite3_open(
   return openDatabase(zFilename, ppDb);
 }
 
+#ifndef SQLITE_OMIT_UTF16
 /*
 ** Open a new database handle.
 */
@@ -1205,6 +1239,7 @@ int sqlite3_open16(
 
   return rc;
 }
+#endif /* SQLITE_OMIT_UTF16 */
 
 /*
 ** The following routine destroys a virtual machine that is created by
@@ -1239,7 +1274,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt){
     rc = SQLITE_OK;
   }else{
     rc = sqlite3VdbeReset((Vdbe*)pStmt);
-    sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0);
+    sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0, 0);
   }
   return rc;
 }
@@ -1276,6 +1311,21 @@ int sqlite3_create_collation(
     );
     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;
@@ -1288,6 +1338,7 @@ int sqlite3_create_collation(
   return rc;
 }
 
+#ifndef SQLITE_OMIT_UTF16
 /*
 ** Register a new collation sequence with the database handle db.
 */
@@ -1308,6 +1359,7 @@ int sqlite3_create_collation16(
   zName8 = sqlite3ValueText(pTmp, SQLITE_UTF8);
   return sqlite3_create_collation(db, zName8, enc, pCtx, xCompare);
 }
+#endif /* SQLITE_OMIT_UTF16 */
 
 /*
 ** Register a collation sequence factory callback with the database handle
@@ -1327,6 +1379,7 @@ int sqlite3_collation_needed(
   return SQLITE_OK;
 }
 
+#ifndef SQLITE_OMIT_UTF16
 /*
 ** Register a collation sequence factory callback with the database handle
 ** db. Replace any previously installed collation sequence factory.
@@ -1344,3 +1397,4 @@ int sqlite3_collation_needed16(
   db->pCollNeededArg = pCollNeededArg;
   return SQLITE_OK;
 }
+#endif /* SQLITE_OMIT_UTF16 */
index b6f012198d24e03b7bdf557d689d405471f06866..734d1a5409eaa0ee2d5743e4e47043069445a7c5 100644 (file)
 /* Automatically generated.  Do not edit */
-/* See the mkopcodec.h script for details. */
+/* See the mkopcodec.awk script for details. */
+#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
 const char *const sqlite3OpcodeNames[] = { "?",
-  "ContextPop",
-  "IntegrityCk",
-  "DropTrigger",
-  "DropIndex",
-  "Recno",
-  "KeyAsData",
-  "Delete",
-  "MoveGt",
-  "VerifyCookie",
-  "Push",
-  "Dup",
-  "Blob",
-  "IdxGT",
-  "IdxRecno",
-  "RowKey",
-  "PutStrKey",
-  "IsUnique",
-  "SetNumColumns",
-  "IdxIsNull",
-  "NullRow",
-  "OpenPseudo",
-  "OpenWrite",
-  "OpenRead",
-  "Transaction",
-  "AutoCommit",
-  "Pop",
-  "Halt",
-  "Vacuum",
-  "ListRead",
-  "RowData",
-  "NotExists",
-  "MoveLe",
-  "SetCookie",
-  "Variable",
-  "AggNext",
-  "AggReset",
-  "Sort",
-  "IdxDelete",
-  "ResetCount",
-  "OpenTemp",
-  "IdxColumn",
-  "Integer",
-  "AggSet",
-  "CreateIndex",
-  "IdxPut",
-  "MoveLt",
-  "Return",
-  "MemLoad",
-  "SortNext",
-  "IdxLT",
-  "Rewind",
-  "AddImm",
-  "AggFunc",
-  "AggInit",
-  "MemIncr",
-  "ListReset",
-  "Clear",
-  "Or",
-  "And",
-  "Not",
-  "PutIntKey",
-  "If",
-  "Callback",
-  "IsNull",
-  "NotNull",
-  "Ne",
-  "Eq",
-  "Gt",
-  "Le",
-  "Lt",
-  "Ge",
-  "BitAnd",
-  "BitOr",
-  "ShiftLeft",
-  "ShiftRight",
-  "Add",
-  "Subtract",
-  "Multiply",
-  "Divide",
-  "Remainder",
-  "Concat",
-  "Negative",
-  "SortReset",
-  "BitNot",
-  "String8",
-  "SortPut",
-  "Last",
-  "NotFound",
-  "MakeRecord",
-  "String",
-  "Goto",
-  "AggFocus",
-  "DropTable",
-  "Column",
-  "Noop",
-  "AggGet",
-  "CreateTable",
-  "NewRecno",
-  "Found",
-  "Distinct",
-  "Close",
-  "Statement",
-  "IfNot",
-  "Pull",
-  "MemStore",
-  "Next",
-  "Prev",
-  "MoveGe",
-  "MustBeInt",
-  "ForceInt",
-  "CollSeq",
-  "Gosub",
-  "ContextPush",
-  "ListRewind",
-  "ListWrite",
-  "ParseSchema",
-  "Destroy",
-  "IdxGE",
-  "FullKey",
-  "ReadCookie",
-  "AbsValue",
-  "Real",
-  "HexBlob",
-  "Function",
+ /*   1 */ "MemLoad",
+ /*   2 */ "Column",
+ /*   3 */ "SetCookie",
+ /*   4 */ "IfMemPos",
+ /*   5 */ "MoveGt",
+ /*   6 */ "AggFocus",
+ /*   7 */ "RowKey",
+ /*   8 */ "IdxRecno",
+ /*   9 */ "AggNext",
+ /*  10 */ "OpenWrite",
+ /*  11 */ "If",
+ /*  12 */ "PutStrKey",
+ /*  13 */ "Pop",
+ /*  14 */ "SortPut",
+ /*  15 */ "AggContextPush",
+ /*  16 */ "CollSeq",
+ /*  17 */ "OpenRead",
+ /*  18 */ "Expire",
+ /*  19 */ "SortReset",
+ /*  20 */ "AutoCommit",
+ /*  21 */ "Sort",
+ /*  22 */ "ListRewind",
+ /*  23 */ "IntegrityCk",
+ /*  24 */ "Function",
+ /*  25 */ "Noop",
+ /*  26 */ "Return",
+ /*  27 */ "Variable",
+ /*  28 */ "String",
+ /*  29 */ "ParseSchema",
+ /*  30 */ "PutIntKey",
+ /*  31 */ "AggFunc",
+ /*  32 */ "Close",
+ /*  33 */ "ListWrite",
+ /*  34 */ "CreateIndex",
+ /*  35 */ "IsUnique",
+ /*  36 */ "IdxIsNull",
+ /*  37 */ "NotFound",
+ /*  38 */ "MustBeInt",
+ /*  39 */ "Halt",
+ /*  40 */ "IdxLT",
+ /*  41 */ "AddImm",
+ /*  42 */ "Statement",
+ /*  43 */ "RowData",
+ /*  44 */ "MemMax",
+ /*  45 */ "Push",
+ /*  46 */ "KeyAsData",
+ /*  47 */ "NotExists",
+ /*  48 */ "OpenTemp",
+ /*  49 */ "MemIncr",
+ /*  50 */ "Gosub",
+ /*  51 */ "AggSet",
+ /*  52 */ "Integer",
+ /*  53 */ "SortNext",
+ /*  54 */ "Prev",
+ /*  55 */ "CreateTable",
+ /*  56 */ "Last",
+ /*  57 */ "ResetCount",
+ /*  58 */ "Callback",
+ /*  59 */ "ContextPush",
+ /*  60 */ "DropTrigger",
+ /*  61 */ "DropIndex",
+ /*  62 */ "FullKey",
+ /*  63 */ "IdxGE",
+ /*  64 */ "Or",
+ /*  65 */ "And",
+ /*  66 */ "Not",
+ /*  67 */ "IdxDelete",
+ /*  68 */ "Vacuum",
+ /*  69 */ "MoveLe",
+ /*  70 */ "IsNull",
+ /*  71 */ "NotNull",
+ /*  72 */ "Ne",
+ /*  73 */ "Eq",
+ /*  74 */ "Gt",
+ /*  75 */ "Le",
+ /*  76 */ "Lt",
+ /*  77 */ "Ge",
+ /*  78 */ "IfNot",
+ /*  79 */ "BitAnd",
+ /*  80 */ "BitOr",
+ /*  81 */ "ShiftLeft",
+ /*  82 */ "ShiftRight",
+ /*  83 */ "Add",
+ /*  84 */ "Subtract",
+ /*  85 */ "Multiply",
+ /*  86 */ "Divide",
+ /*  87 */ "Remainder",
+ /*  88 */ "Concat",
+ /*  89 */ "Negative",
+ /*  90 */ "DropTable",
+ /*  91 */ "BitNot",
+ /*  92 */ "String8",
+ /*  93 */ "MakeRecord",
+ /*  94 */ "Delete",
+ /*  95 */ "AggContextPop",
+ /*  96 */ "ListRead",
+ /*  97 */ "ListReset",
+ /*  98 */ "Dup",
+ /*  99 */ "Goto",
+ /* 100 */ "Clear",
+ /* 101 */ "IdxGT",
+ /* 102 */ "MoveLt",
+ /* 103 */ "VerifyCookie",
+ /* 104 */ "Pull",
+ /* 105 */ "SetNumColumns",
+ /* 106 */ "AbsValue",
+ /* 107 */ "Transaction",
+ /* 108 */ "AggGet",
+ /* 109 */ "ContextPop",
+ /* 110 */ "Next",
+ /* 111 */ "AggInit",
+ /* 112 */ "Distinct",
+ /* 113 */ "NewRecno",
+ /* 114 */ "AggReset",
+ /* 115 */ "Destroy",
+ /* 116 */ "ReadCookie",
+ /* 117 */ "ForceInt",
+ /* 118 */ "Recno",
+ /* 119 */ "OpenPseudo",
+ /* 120 */ "Blob",
+ /* 121 */ "MemStore",
+ /* 122 */ "Rewind",
+ /* 123 */ "MoveGe",
+ /* 124 */ "IdxPut",
+ /* 125 */ "Found",
+ /* 126 */ "NullRow",
+ /* 127 */ "NotUsed_127",
+ /* 128 */ "NotUsed_128",
+ /* 129 */ "NotUsed_129",
+ /* 130 */ "Real",
+ /* 131 */ "HexBlob",
 };
+#endif
index 7b792c5a1170d1a39181824010d6d1648247737e..8be3dc7ea17439aabf992ca6604a0022abf0f964 100644 (file)
 /* Automatically generated.  Do not edit */
 /* See the mkopcodeh.awk script for details */
-#define OP_ContextPop                  1
-#define OP_IntegrityCk                 2
-#define OP_DropTrigger                 3
-#define OP_DropIndex                   4
-#define OP_Recno                       5
-#define OP_KeyAsData                   6
-#define OP_Delete                      7
-#define OP_MoveGt                      8
-#define OP_VerifyCookie                9
-#define OP_Push                        10
-#define OP_Dup                         11
-#define OP_Blob                        12
-#define OP_IdxGT                       13
-#define OP_IdxRecno                    14
-#define OP_RowKey                      15
-#define OP_PutStrKey                   16
-#define OP_IsUnique                    17
-#define OP_SetNumColumns               18
-#define OP_Eq                          67
-#define OP_IdxIsNull                   19
-#define OP_NullRow                     20
-#define OP_OpenPseudo                  21
-#define OP_OpenWrite                   22
-#define OP_OpenRead                    23
-#define OP_Transaction                 24
-#define OP_AutoCommit                  25
-#define OP_Negative                    82
-#define OP_Pop                         26
-#define OP_Halt                        27
-#define OP_Vacuum                      28
-#define OP_ListRead                    29
-#define OP_RowData                     30
-#define OP_NotExists                   31
-#define OP_MoveLe                      32
-#define OP_SetCookie                   33
-#define OP_Variable                    34
-#define OP_AggNext                     35
-#define OP_AggReset                    36
-#define OP_Sort                        37
-#define OP_IdxDelete                   38
-#define OP_ResetCount                  39
-#define OP_OpenTemp                    40
-#define OP_IdxColumn                   41
-#define OP_NotNull                     65
-#define OP_Ge                          71
-#define OP_Remainder                   80
-#define OP_Divide                      79
-#define OP_Integer                     42
-#define OP_AggSet                      43
-#define OP_CreateIndex                 44
-#define OP_IdxPut                      45
-#define OP_MoveLt                      46
-#define OP_And                         59
-#define OP_ShiftLeft                   74
-#define OP_Real                        122
-#define OP_Return                      47
-#define OP_MemLoad                     48
-#define OP_SortNext                    49
-#define OP_IdxLT                       50
-#define OP_Rewind                      51
-#define OP_Gt                          68
-#define OP_AddImm                      52
-#define OP_Subtract                    77
-#define OP_AggFunc                     53
-#define OP_AggInit                     54
-#define OP_MemIncr                     55
-#define OP_ListReset                   56
-#define OP_Clear                       57
-#define OP_PutIntKey                   61
-#define OP_IsNull                      64
-#define OP_If                          62
-#define OP_Callback                    63
-#define OP_SortReset                   83
-#define OP_SortPut                     86
-#define OP_Last                        87
-#define OP_NotFound                    88
-#define OP_MakeRecord                  89
-#define OP_BitAnd                      72
-#define OP_Add                         76
-#define OP_HexBlob                     123
-#define OP_String                      90
-#define OP_Goto                        91
-#define OP_AggFocus                    92
-#define OP_DropTable                   93
-#define OP_Column                      94
-#define OP_Noop                        95
-#define OP_Not                         60
-#define OP_Le                          69
-#define OP_BitOr                       73
-#define OP_Multiply                    78
-#define OP_String8                     85
-#define OP_AggGet                      96
-#define OP_CreateTable                 97
-#define OP_NewRecno                    98
-#define OP_Found                       99
-#define OP_Distinct                    100
-#define OP_Close                       101
-#define OP_Statement                   102
-#define OP_IfNot                       103
-#define OP_Pull                        104
-#define OP_MemStore                    105
-#define OP_Next                        106
-#define OP_Prev                        107
-#define OP_MoveGe                      108
-#define OP_Lt                          70
-#define OP_Ne                          66
-#define OP_MustBeInt                   109
-#define OP_ForceInt                    110
-#define OP_ShiftRight                  75
-#define OP_CollSeq                     111
-#define OP_Gosub                       112
-#define OP_ContextPush                 113
-#define OP_ListRewind                  114
-#define OP_ListWrite                   115
-#define OP_ParseSchema                 116
-#define OP_Destroy                     117
-#define OP_IdxGE                       118
-#define OP_FullKey                     119
-#define OP_ReadCookie                  120
-#define OP_BitNot                      84
-#define OP_AbsValue                    121
-#define OP_Or                          58
-#define OP_Function                    124
-#define OP_Concat                      81
+#define OP_MemLoad                              1
+#define OP_HexBlob                            131   /* same as TK_BLOB     */
+#define OP_Column                               2
+#define OP_SetCookie                            3
+#define OP_IfMemPos                             4
+#define OP_Real                               130   /* same as TK_FLOAT    */
+#define OP_MoveGt                               5
+#define OP_Ge                                  77   /* same as TK_GE       */
+#define OP_AggFocus                             6
+#define OP_RowKey                               7
+#define OP_IdxRecno                             8
+#define OP_AggNext                              9
+#define OP_Eq                                  73   /* same as TK_EQ       */
+#define OP_OpenWrite                           10
+#define OP_NotNull                             71   /* same as TK_NOTNULL  */
+#define OP_If                                  11
+#define OP_PutStrKey                           12
+#define OP_String8                             92   /* same as TK_STRING   */
+#define OP_Pop                                 13
+#define OP_SortPut                             14
+#define OP_AggContextPush                      15
+#define OP_CollSeq                             16
+#define OP_OpenRead                            17
+#define OP_Expire                              18
+#define OP_SortReset                           19
+#define OP_AutoCommit                          20
+#define OP_Gt                                  74   /* same as TK_GT       */
+#define OP_Sort                                21
+#define OP_ListRewind                          22
+#define OP_IntegrityCk                         23
+#define OP_Function                            24
+#define OP_Subtract                            84   /* same as TK_MINUS    */
+#define OP_And                                 65   /* same as TK_AND      */
+#define OP_Noop                                25
+#define OP_Return                              26
+#define OP_Remainder                           87   /* same as TK_REM      */
+#define OP_Multiply                            85   /* same as TK_STAR     */
+#define OP_Variable                            27
+#define OP_String                              28
+#define OP_ParseSchema                         29
+#define OP_PutIntKey                           30
+#define OP_AggFunc                             31
+#define OP_Close                               32
+#define OP_ListWrite                           33
+#define OP_CreateIndex                         34
+#define OP_IsUnique                            35
+#define OP_IdxIsNull                           36
+#define OP_NotFound                            37
+#define OP_MustBeInt                           38
+#define OP_Halt                                39
+#define OP_IdxLT                               40
+#define OP_AddImm                              41
+#define OP_Statement                           42
+#define OP_RowData                             43
+#define OP_MemMax                              44
+#define OP_Push                                45
+#define OP_Or                                  64   /* same as TK_OR       */
+#define OP_KeyAsData                           46
+#define OP_NotExists                           47
+#define OP_OpenTemp                            48
+#define OP_MemIncr                             49
+#define OP_Gosub                               50
+#define OP_Divide                              86   /* same as TK_SLASH    */
+#define OP_AggSet                              51
+#define OP_Integer                             52
+#define OP_SortNext                            53
+#define OP_Prev                                54
+#define OP_Concat                              88   /* same as TK_CONCAT   */
+#define OP_BitAnd                              79   /* same as TK_BITAND   */
+#define OP_CreateTable                         55
+#define OP_Last                                56
+#define OP_IsNull                              70   /* same as TK_ISNULL   */
+#define OP_ShiftRight                          82   /* same as TK_RSHIFT   */
+#define OP_ResetCount                          57
+#define OP_Callback                            58
+#define OP_ContextPush                         59
+#define OP_DropTrigger                         60
+#define OP_DropIndex                           61
+#define OP_FullKey                             62
+#define OP_IdxGE                               63
+#define OP_IdxDelete                           67
+#define OP_Vacuum                              68
+#define OP_MoveLe                              69
+#define OP_IfNot                               78
+#define OP_DropTable                           90
+#define OP_MakeRecord                          93
+#define OP_Delete                              94
+#define OP_AggContextPop                       95
+#define OP_ListRead                            96
+#define OP_ListReset                           97
+#define OP_ShiftLeft                           81   /* same as TK_LSHIFT   */
+#define OP_Dup                                 98
+#define OP_Goto                                99
+#define OP_Clear                              100
+#define OP_IdxGT                              101
+#define OP_MoveLt                             102
+#define OP_Le                                  75   /* same as TK_LE       */
+#define OP_VerifyCookie                       103
+#define OP_Pull                               104
+#define OP_Not                                 66   /* same as TK_NOT      */
+#define OP_SetNumColumns                      105
+#define OP_AbsValue                           106
+#define OP_Transaction                        107
+#define OP_Negative                            89   /* same as TK_UMINUS   */
+#define OP_Ne                                  72   /* same as TK_NE       */
+#define OP_AggGet                             108
+#define OP_ContextPop                         109
+#define OP_BitOr                               80   /* same as TK_BITOR    */
+#define OP_Next                               110
+#define OP_AggInit                            111
+#define OP_Distinct                           112
+#define OP_NewRecno                           113
+#define OP_Lt                                  76   /* same as TK_LT       */
+#define OP_AggReset                           114
+#define OP_Destroy                            115
+#define OP_ReadCookie                         116
+#define OP_ForceInt                           117
+#define OP_Recno                              118
+#define OP_OpenPseudo                         119
+#define OP_Blob                               120
+#define OP_Add                                 83   /* same as TK_PLUS     */
+#define OP_MemStore                           121
+#define OP_Rewind                             122
+#define OP_MoveGe                             123
+#define OP_IdxPut                             124
+#define OP_BitNot                              91   /* same as TK_BITNOT   */
+#define OP_Found                              125
+#define OP_NullRow                            126
+
+/* The following opcode values are never used */
+#define OP_NotUsed_127                        127
+#define OP_NotUsed_128                        128
+#define OP_NotUsed_129                        129
index fc478baa93e26b763dd206c563983d33c5cad797..d39d62d80998a7e2a07e09b306ae4224a24e81f5 100644 (file)
 */
 #if !defined(OS_UNIX) && !defined(OS_TEST)
 # ifndef OS_WIN
-#  ifndef OS_MAC
-#    if defined(__MACOS__)
-#      define OS_MAC 1
-#      define OS_WIN 0
-#      define OS_UNIX 0
-#    elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
-#      define OS_MAC 0
-#      define OS_WIN 1
-#      define OS_UNIX 0
-#    else
-#      define OS_MAC 0
-#      define OS_WIN 0
-#      define OS_UNIX 1
-#    endif
-#  else
-#    define OS_WIN 0
-#    define OS_UNIX 0
+#   if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
+#     define OS_WIN 1
+#     define OS_UNIX 0
+#   else
+#     define OS_WIN 0
+#     define OS_UNIX 1
 #  endif
 # else
-#  define OS_MAC 0
 #  define OS_UNIX 0
 # endif
 #else
-# define OS_MAC 0
 # ifndef OS_WIN
 #  define OS_WIN 0
 # endif
@@ -66,9 +53,6 @@
 #if OS_WIN
 # include "os_win.h"
 #endif
-#if OS_MAC
-# include "os_mac.h"
-#endif
 
 /*
 ** Temporary files are named starting with this prefix followed by 16 random
 **
 */
 #define PENDING_BYTE      0x40000000  /* First byte past the 1GB boundary */
-/* #define PENDING_BYTE     0x5400   // Page 20 - for testing */
+/* #define PENDING_BYTE     0x5400   // Page 22 - for testing */
 #define RESERVED_BYTE     (PENDING_BYTE+1)
 #define SHARED_FIRST      (PENDING_BYTE+2)
 #define SHARED_SIZE       510
@@ -176,6 +160,7 @@ int sqlite3OsOpenReadOnly(const char*, OsFile*);
 int sqlite3OsOpenDirectory(const char*, OsFile*);
 int sqlite3OsSyncDirectory(const char*);
 int sqlite3OsTempFileName(char*);
+int sqlite3OsIsDirWritable(char*);
 int sqlite3OsClose(OsFile*);
 int sqlite3OsRead(OsFile*, void*, int amt);
 int sqlite3OsWrite(OsFile*, const void*, int amt);
index 0e292bc428ee496dfeb8f2870dd0aedcadfc0a95..8199f5b18327af8eeac7008d344dacaf275d711d 100644 (file)
@@ -239,10 +239,12 @@ printf("Writing block %d of %s\n", i, pFile->zName);
         if( BLOCK_OFFSET(i+1)>nMax ){
           len = nMax-BLOCK_OFFSET(i);
         }
-        if( trash ){
-          sqlite3Randomness(len, p);
+        if( len>0 ){
+          if( trash ){
+            sqlite3Randomness(len, p);
+          }
+          rc = sqlite3RealWrite(&pFile->fd, p, len);
         }
-        rc = sqlite3RealWrite(&pFile->fd, p, len);
       }
       sqliteFree(p);
     }
index 94fca70199a5482b1b0db8afd3d117a9ebcf1efe..0e270c0bb6e71f3e474d3a28bac309ae00868a69 100644 (file)
@@ -574,7 +574,7 @@ int sqlite3OsOpenDirectory(
 ** name of a directory, then that directory will be used to store
 ** temporary files.
 */
-const char *sqlite3_temp_directory = 0;
+char *sqlite3_temp_directory = 0;
 
 /*
 ** Create a temporary file name in zBuf.  zBuf must be big enough to
@@ -616,6 +616,22 @@ 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){
+  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;
+  return 1;
+}
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
+
 /*
 ** Read data from a file into a buffer.  Return SQLITE_OK if all
 ** bytes were read successfully and SQLITE_IOERR if anything goes
@@ -645,6 +661,7 @@ int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
 int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
   int wrote = 0;
   assert( id->isOpen );
+  assert( amt>0 );
   SimulateIOError(SQLITE_IOERR);
   SimulateDiskfullError;
   TIMER_START;
@@ -675,8 +692,17 @@ int sqlite3OsSeek(OsFile *id, i64 offset){
 ** The fsync() system call does not work as advertised on many
 ** unix systems.  The following procedure is an attempt to make
 ** it work better.
+**
+** The SQLITE_NO_SYNC macro disables all fsync()s.  This is useful
+** for testing when we want to run through the test suite quickly.
+** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
+** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
+** or power failure will likely corrupt the database file.
 */
 static int full_fsync(int fd){
+#ifdef SQLITE_NO_SYNC
+  return SQLITE_OK;
+#else
   int rc;
 #ifdef F_FULLFSYNC
   rc = fcntl(fd, F_FULLFSYNC, 0);
@@ -685,6 +711,7 @@ static int full_fsync(int fd){
   rc = fsync(fd);
 #endif
   return rc;
+#endif
 }
 
 /*
@@ -1157,10 +1184,16 @@ int sqlite3OsRandomSeed(char *zBuf){
   memset(zBuf, 0, 256);
 #if !defined(SQLITE_TEST)
   {
-    int pid;
-    time((time_t*)zBuf);
-    pid = getpid();
-    memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));
+    int pid, fd;
+    fd = open("/dev/urandom", O_RDONLY);
+    if( fd<0 ){
+      time((time_t*)zBuf);
+      pid = getpid();
+      memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));
+    }else{
+      read(fd, zBuf, 256);
+      close(fd);
+    }
   }
 #endif
   return SQLITE_OK;
index f6e3e3ea83bd3edccb1491e38b48f3767cbb1328..2614ed08a6c31624ea037d88cbda5dbb7f0f97f6 100644 (file)
@@ -202,7 +202,7 @@ int sqlite3OsOpenDirectory(
 ** name of a directory, then that directory will be used to store
 ** temporary files.
 */
-const char *sqlite3_temp_directory = 0;
+char *sqlite3_temp_directory = 0;
 
 /*
 ** Create a temporary file name in zBuf.  zBuf must be big enough to
@@ -275,12 +275,13 @@ int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
 ** or some other error code on failure.
 */
 int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
-  int rc;
+  int rc = 0;
   DWORD wrote;
   assert( id->isOpen );
   SimulateIOError(SQLITE_IOERR);
   SimulateDiskfullError;
   TRACE3("WRITE %d lock=%d\n", id->h, id->locktype);
+  assert( amt>0 );
   while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){
     amt -= wrote;
     pBuf = &((char*)pBuf)[wrote];
@@ -409,6 +410,24 @@ static int unlockReadLock(OsFile *id){
   return res;
 }
 
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+/*
+** Check that a given pathname is a directory and is writable 
+**
+*/
+int sqlite3OsIsDirWritable(char *zBuf){
+  int fileAttr;
+  if(! zBuf ) return 0;
+  if(! isNT() && strlen(zBuf) > MAX_PATH ) return 0;
+  fileAttr = GetFileAttributesA(zBuf);
+  if( fileAttr == 0xffffffff ) return 0;
+  if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){
+    return 0;
+  }
+  return 1;
+}
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
+
 /*
 ** Lock the file with the lock specified by parameter locktype - one
 ** of the following:
index a374562bc74ebab439ff9058ebd58be051828969..47d895240c5fbede7256df52eb1ee0ef92d99cfd 100644 (file)
 #define TRACE2(X,Y)     sqlite3DebugPrintf(X,Y)
 #define TRACE3(X,Y,Z)   sqlite3DebugPrintf(X,Y,Z)
 #define TRACE4(X,Y,Z,W) sqlite3DebugPrintf(X,Y,Z,W)
+#define TRACE5(X,Y,Z,W,V) sqlite3DebugPrintf(X,Y,Z,W,V)
 #else
 #define TRACE1(X)
 #define TRACE2(X,Y)
 #define TRACE3(X,Y,Z)
 #define TRACE4(X,Y,Z,W)
+#define TRACE5(X,Y,Z,W,V)
 #endif
 
+/*
+** 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.
+**
+** 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
 
 /*
 ** The page cache as a whole is always in one of the following
 # define SQLITE_BUSY_RESERVED_LOCK 0
 #endif
 
+/*
+** This macro rounds values up so that if the value is an address it
+** is guaranteed to be an address that is aligned to an 8-byte boundary.
+*/
+#define FORCE_ALIGNMENT(X)   (((X)+7)&~7)
+
 /*
 ** Each in-memory image of a page begins with the following header.
 ** This header is only visible to this pager module.  The client
@@ -143,7 +168,10 @@ struct PgHdr {
   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 */
-  /* pPager->pageSize bytes of page data follow this header */
+#ifdef SQLITE_CHECK_PAGES
+  u32 pageHash;
+#endif
+  /* pPager->psAligned bytes of page data follow this header */
   /* Pager.nExtra bytes of local data follow the page data */
 };
 
@@ -179,9 +207,9 @@ struct PgHistory {
 */
 #define PGHDR_TO_DATA(P)  ((void*)(&(P)[1]))
 #define DATA_TO_PGHDR(D)  (&((PgHdr*)(D))[-1])
-#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->pageSize])
+#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->psAligned])
 #define PGHDR_TO_HIST(P,PGR)  \
-            ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra])
+            ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->psAligned+(PGR)->nExtra])
 
 /*
 ** How big to make the hash table used for locating in-memory pages
@@ -214,15 +242,18 @@ struct Pager {
   void (*xDestructor)(void*,int); /* Call this routine when freeing pages */
   void (*xReiniter)(void*,int);   /* Call this routine when reloading pages */
   int pageSize;               /* Number of bytes in a page */
+  int psAligned;              /* pageSize rounded up to a multiple of 8 */
   int nPage;                  /* Total number of in-memory pages */
   int nRef;                   /* Number of in-memory pages with PgHdr.nRef>0 */
   int mxPage;                 /* Maximum number of pages to hold in cache */
   int nHit, nMiss, nOvfl;     /* Cache hits, missing, and LRU overflows */
+  int nRead,nWrite;           /* Database pages read/written */
   void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
   void *pCodecArg;            /* First argument to xCodec() */
   u8 journalOpen;             /* True if journal file descriptors is valid */
   u8 journalStarted;          /* True if header of journal is synced */
   u8 useJournal;              /* Use a rollback journal on this file */
+  u8 noReadlock;              /* Do not bother to obtain readlocks */
   u8 stmtOpen;                /* True if the statement subjournal is open */
   u8 stmtInUse;               /* True we are in a statement subtransaction */
   u8 stmtAutoopen;            /* Open stmt journal when main journal is opened*/
@@ -301,6 +332,21 @@ static const unsigned char aJournalMagic[] = {
 */
 #define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
 
+/*
+** The macro MEMDB is true if we are dealing with an in-memory database.
+** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
+** the value of MEMDB will be a constant and the compiler will optimize
+** out code that would never execute.
+*/
+#ifdef SQLITE_OMIT_MEMORYDB
+# define MEMDB 0
+#else
+# define MEMDB pPager->memDb
+#endif
+
+/*
+** The default size of a disk sector
+*/
 #define PAGER_SECTOR_SIZE 512
 
 /*
@@ -310,12 +356,18 @@ static const unsigned char aJournalMagic[] = {
 ** is devoted to storing a master journal name - there are no more pages to
 ** roll back. See comments for function writeMasterJournal() for details.
 */
-#define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize))
+/* #define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize)) */
+#define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1)
+
+/*
+** The maximum legal page number is (2^31 - 1).
+*/
+#define PAGER_MAX_PGNO 2147483647
 
 /*
 ** Enable reference count tracking (for debugging) here:
 */
-#ifdef SQLITE_TEST
+#ifdef SQLITE_DEBUG
   int pager3_refinfo_enable = 0;
   static void pager_refinfo(PgHdr *p){
     static int cnt = 0;
@@ -402,6 +454,36 @@ static int pager_errcode(Pager *pPager){
   return rc;
 }
 
+#ifdef SQLITE_CHECK_PAGES
+/*
+** Return a 32-bit hash of the page data for pPage.
+*/
+static u32 pager_pagehash(PgHdr *pPage){
+  u32 hash = 0;
+  int i;
+  unsigned char *pData = (unsigned char *)PGHDR_TO_DATA(pPage);
+  for(i=0; i<pPage->pPager->pageSize; i++){
+    hash = (hash+i)^pData[i];
+  }
+  return hash;
+}
+
+/*
+** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
+** is defined, and NDEBUG is not defined, an assert() statement checks
+** that the page is either dirty or still matches the calculated page-hash.
+*/
+#define CHECK_PAGE(x) checkPage(x)
+static void checkPage(PgHdr *pPg){
+  Pager *pPager = pPg->pPager;
+  assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty || 
+      pPg->pageHash==pager_pagehash(pPg) );
+}
+
+#else
+#define CHECK_PAGE(x)
+#endif
+
 /*
 ** When this is called the journal file for pager pPager must be open.
 ** The master journal file name is read from the end of the file and 
@@ -463,8 +545,9 @@ static int readMasterJournal(OsFile *pJrnl, char **pzMaster){
     */
     sqliteFree(*pzMaster);
     *pzMaster = 0;
+  }else{
+    (*pzMaster)[len] = '\0';
   }
-  (*pzMaster)[len] = '\0';
    
   return SQLITE_OK;
 }
@@ -772,7 +855,7 @@ static void pager_reset(Pager *pPager){
 static int pager_unwritelock(Pager *pPager){
   PgHdr *pPg;
   int rc;
-  assert( !pPager->memDb );
+  assert( !MEMDB );
   if( pPager->state<PAGER_RESERVED ){
     return SQLITE_OK;
   }
@@ -791,6 +874,9 @@ static int pager_unwritelock(Pager *pPager){
       pPg->inJournal = 0;
       pPg->dirty = 0;
       pPg->needSync = 0;
+#ifdef SQLITE_CHECK_PAGES
+      pPg->pageHash = pager_pagehash(pPg);
+#endif
     }
     pPager->dirtyCache = 0;
     pPager->nRec = 0;
@@ -886,18 +972,20 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
   */
   pPg = pager_lookup(pPager, pgno);
   assert( pPager->state>=PAGER_EXCLUSIVE || pPg );
-  TRACE3("PLAYBACK %d page %d\n", pPager->fd.h, pgno);
+  TRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno);
   if( pPager->state>=PAGER_EXCLUSIVE ){
     sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
     rc = sqlite3OsWrite(&pPager->fd, aData, pPager->pageSize);
   }
   if( pPg ){
-    /* No page should ever be rolled back that is in use, except for page
-    ** 1 which is held in use in order to keep the lock on the database
-    ** active.
+    /* No page should ever be explicitly rolled back that is in use, except
+    ** for page 1 which is held in use in order to keep the lock on the
+    ** database active. However such a page may be rolled back as a result
+    ** of an internal error resulting in an automatic call to
+    ** sqlite3pager_rollback().
     */
     void *pData;
-    assert( pPg->nRef==0 || pPg->pgno==1 );
+    /* assert( pPg->nRef==0 || pPg->pgno==1 ); */
     pData = PGHDR_TO_DATA(pPg);
     memcpy(pData, aData, pPager->pageSize);
     if( pPager->xDestructor ){  /*** FIX ME:  Should this be xReinit? ***/
@@ -906,6 +994,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
     if( pPager->state>=PAGER_EXCLUSIVE ){
       pPg->dirty = 0;
       pPg->needSync = 0;
+#ifdef SQLITE_CHECK_PAGES
+      pPg->pageHash = pager_pagehash(pPg);
+#endif
     }
     CODEC(pPager, pData, pPg->pgno, 3);
   }
@@ -963,6 +1054,7 @@ static int pager_delmaster(const char *zMaster){
         ** so, return without deleting the master journal file.
         */
         OsFile journal;
+        int c;
 
         memset(&journal, 0, sizeof(journal));
         rc = sqlite3OsOpenReadOnly(zJournal, &journal);
@@ -976,7 +1068,9 @@ static int pager_delmaster(const char *zMaster){
           goto delmaster_out;
         }
 
-        if( zMasterPtr && !strcmp(zMasterPtr, zMaster) ){
+        c = zMasterPtr!=0 && strcmp(zMasterPtr, zMaster)==0;
+        sqliteFree(zMasterPtr);
+        if( c ){
           /* We have a match. Do not delete the master journal file. */
           goto delmaster_out;
         }
@@ -1015,7 +1109,7 @@ static int pager_reload_cache(Pager *pPager){
     if( (int)pPg->pgno <= pPager->origDbSize ){
       sqlite3OsSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1));
       rc = sqlite3OsRead(&pPager->fd, zBuf, pPager->pageSize);
-      TRACE3("REFETCH %d page %d\n", pPager->fd.h, pPg->pgno);
+      TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
       if( rc ) break;
       CODEC(pPager, zBuf, pPg->pgno, 2);
     }else{
@@ -1031,6 +1125,9 @@ static int pager_reload_cache(Pager *pPager){
     }
     pPg->needSync = 0;
     pPg->dirty = 0;
+#ifdef SQLITE_CHECK_PAGES
+    pPg->pageHash = pager_pagehash(pPg);
+#endif
   }
   return rc;
 }
@@ -1040,6 +1137,7 @@ static int pager_reload_cache(Pager *pPager){
 ** indicated.
 */
 static int pager_truncate(Pager *pPager, int nPage){
+  assert( pPager->state>=PAGER_EXCLUSIVE );
   return sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(i64)nPage);
 }
 
@@ -1159,7 +1257,8 @@ static int pager_playback(Pager *pPager){
     /* If this is the first header read from the journal, truncate the
     ** database file back to it's original size.
     */
-    if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
+    if( pPager->state>=PAGER_EXCLUSIVE && 
+        pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
       assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg );
       rc = pager_truncate(pPager, mxPg);
       if( rc!=SQLITE_OK ){
@@ -1200,11 +1299,10 @@ end_playback:
   }
   if( zMaster ){
     /* If there was a master journal and this routine will return true,
-    ** see if it is possible to delete the master journal. If errors 
-    ** occur during this process, ignore them.
+    ** see if it is possible to delete the master journal.
     */
     if( rc==SQLITE_OK ){
-      pager_delmaster(zMaster);
+      rc = pager_delmaster(zMaster);
     }
     sqliteFree(zMaster);
   }
@@ -1258,10 +1356,11 @@ static int pager_stmt_playback(Pager *pPager){
     hdrOff = szJ;
   }
   
-
   /* Truncate the database back to its original size.
   */
-  rc = pager_truncate(pPager, pPager->stmtSize);
+  if( pPager->state>=PAGER_EXCLUSIVE ){
+    rc = pager_truncate(pPager, pPager->stmtSize);
+  }
   pPager->dbSize = pPager->stmtSize;
 
   /* Figure out how many records are in the statement journal.
@@ -1384,11 +1483,13 @@ void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){
 ** Numeric values associated with these states are OFF==1, NORMAL=2,
 ** and FULL=3.
 */
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
 void sqlite3pager_set_safety_level(Pager *pPager, int level){
   pPager->noSync =  level==1 || pPager->tempFile;
   pPager->fullSync = level==3 && !pPager->tempFile;
   if( pPager->noSync ) pPager->needSync = 0;
 }
+#endif
 
 /*
 ** Open a temporary file.  Write the name of the file into zName
@@ -1428,7 +1529,7 @@ int sqlite3pager_open(
   Pager **ppPager,         /* Return the Pager structure here */
   const char *zFilename,   /* Name of the database file to open */
   int nExtra,              /* Extra bytes append to each in-memory page */
-  int useJournal           /* TRUE to use a rollback journal on this file */
+  int flags                /* flags controlling this file */
 ){
   Pager *pPager;
   char *zFullPathname = 0;
@@ -1439,6 +1540,8 @@ int sqlite3pager_open(
   int tempFile = 0;
   int memDb = 0;
   int readOnly = 0;
+  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
+  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
   char zTemp[SQLITE_TEMPNAME_SIZE];
 
   *ppPager = 0;
@@ -1447,11 +1550,14 @@ int sqlite3pager_open(
     return SQLITE_NOMEM;
   }
   if( zFilename && zFilename[0] ){
+#ifndef SQLITE_OMIT_MEMORYDB
     if( strcmp(zFilename,":memory:")==0 ){
       memDb = 1;
       zFullPathname = sqliteStrDup("");
       rc = SQLITE_OK;
-    }else{
+    }else
+#endif
+    {
       zFullPathname = sqlite3OsFullPathname(zFilename);
       if( zFullPathname ){
         rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly);
@@ -1481,7 +1587,7 @@ int sqlite3pager_open(
     sqliteFree(zFullPathname);
     return SQLITE_NOMEM;
   }
-  TRACE3("OPEN %d %s\n", fd.h, zFullPathname);
+  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];
@@ -1498,11 +1604,13 @@ int sqlite3pager_open(
 #endif
   pPager->journalOpen = 0;
   pPager->useJournal = useJournal && !memDb;
+  pPager->noReadlock = noReadlock && readOnly;
   pPager->stmtOpen = 0;
   pPager->stmtInUse = 0;
   pPager->nRef = 0;
   pPager->dbSize = memDb-1;
   pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE;
+  pPager->psAligned = FORCE_ALIGNMENT(pPager->pageSize);
   pPager->stmtSize = 0;
   pPager->stmtJSize = 0;
   pPager->nPage = 0;
@@ -1518,7 +1626,7 @@ int sqlite3pager_open(
   pPager->pFirst = 0;
   pPager->pFirstSynced = 0;
   pPager->pLast = 0;
-  pPager->nExtra = nExtra;
+  pPager->nExtra = FORCE_ALIGNMENT(nExtra);
   pPager->sectorSize = PAGER_SECTOR_SIZE;
   pPager->pBusyHandler = 0;
   memset(pPager->aHash, 0, sizeof(pPager->aHash));
@@ -1564,6 +1672,7 @@ void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){
 void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){
   assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE );
   pPager->pageSize = pageSize;
+  pPager->psAligned = FORCE_ALIGNMENT(pageSize);
 }
 
 /*
@@ -1572,7 +1681,7 @@ void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){
 */
 void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){
   memset(pDest, 0, N);
-  if( pPager->memDb==0 ){
+  if( MEMDB==0 ){
     sqlite3OsSeek(&pPager->fd, 0);
     sqlite3OsRead(&pPager->fd, pDest, N);
   }
@@ -1593,7 +1702,7 @@ int sqlite3pager_pagecount(Pager *pPager){
     return 0;
   }
   n /= pPager->pageSize;
-  if( !pPager->memDb && n==PENDING_BYTE/pPager->pageSize ){
+  if( !MEMDB && n==PENDING_BYTE/pPager->pageSize ){
     n++;
   }
   if( pPager->state!=PAGER_UNLOCK ){
@@ -1608,6 +1717,33 @@ int sqlite3pager_pagecount(Pager *pPager){
 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
+** sqlite3pager_movepage() routine can leave a page in the 
+** pNextFree/pPrevFree list that is not a part of any hash-chain.
+*/
+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. */
+    return;
+  }
+  if( pPg->pNextHash ){
+    pPg->pNextHash->pPrevHash = pPg->pPrevHash;
+  }
+  if( pPg->pPrevHash ){
+    assert( pPager->aHash[pager_hash(pPg->pgno)]!=pPg );
+    pPg->pPrevHash->pNextHash = pPg->pNextHash;
+  }else{
+    int h = pager_hash(pPg->pgno);
+    assert( pPager->aHash[h]==pPg );
+    pPager->aHash[h] = pPg->pNextHash;
+  }
+
+  pPg->pgno = 0;
+  pPg->pNextHash = pPg->pPrevHash = 0;
+}
+
 /*
 ** Unlink a page from the free list (the list of all pages where nRef==0)
 ** and from its hash collision chain.
@@ -1638,19 +1774,10 @@ static void unlinkPage(PgHdr *pPg){
   pPg->pNextFree = pPg->pPrevFree = 0;
 
   /* Unlink from the pgno hash table */
-  if( pPg->pNextHash ){
-    pPg->pNextHash->pPrevHash = pPg->pPrevHash;
-  }
-  if( pPg->pPrevHash ){
-    pPg->pPrevHash->pNextHash = pPg->pNextHash;
-  }else{
-    int h = pager_hash(pPg->pgno);
-    assert( pPager->aHash[h]==pPg );
-    pPager->aHash[h] = pPg->pNextHash;
-  }
-  pPg->pNextHash = pPg->pPrevHash = 0;
+  unlinkHashChain(pPager, pPg);
 }
 
+#ifndef SQLITE_OMIT_MEMORYDB
 /*
 ** This routine is used to truncate an in-memory database.  Delete
 ** all pages whose pgno is larger than pPager->dbSize and is unreferenced.
@@ -1676,6 +1803,40 @@ static void memoryTruncate(Pager *pPager){
     }
   }
 }
+#else
+#define memoryTruncate(p)
+#endif
+
+/*
+** Try to obtain a lock on a file.  Invoke the busy callback if the lock
+** is currently not available.  Repeate until the busy callback returns
+** false or until the lock succeeds.
+**
+** Return SQLITE_OK on success and an error code if we cannot obtain
+** the lock.
+*/
+static int pager_wait_on_lock(Pager *pPager, int locktype){
+  int rc;
+  assert( PAGER_SHARED==SHARED_LOCK );
+  assert( PAGER_RESERVED==RESERVED_LOCK );
+  assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
+  if( pPager->state>=locktype ){
+    rc = SQLITE_OK;
+  }else{
+    int busy = 1;
+    do {
+      rc = sqlite3OsLock(&pPager->fd, locktype);
+    }while( rc==SQLITE_BUSY && 
+        pPager->pBusyHandler && 
+        pPager->pBusyHandler->xFunc && 
+        pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
+    );
+    if( rc==SQLITE_OK ){
+      pPager->state = locktype;
+    }
+  }
+  return rc;
+}
 
 /*
 ** Truncate the file to the number of pages specified.
@@ -1690,7 +1851,7 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
   if( nPage>=(unsigned)pPager->dbSize ){
     return SQLITE_OK;
   }
-  if( pPager->memDb ){
+  if( MEMDB ){
     pPager->dbSize = nPage;
     memoryTruncate(pPager);
     return SQLITE_OK;
@@ -1699,6 +1860,13 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
   if( rc!=SQLITE_OK ){
     return rc;
   }
+
+  /* Get an exclusive lock on the database before truncating. */
+  rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+
   rc = pager_truncate(pPager, nPage);
   if( rc==SQLITE_OK ){
     pPager->dbSize = nPage;
@@ -1721,15 +1889,27 @@ int sqlite3pager_close(Pager *pPager){
     case PAGER_RESERVED:
     case PAGER_SYNCED: 
     case PAGER_EXCLUSIVE: {
+      /* We ignore any IO errors that occur during the rollback
+      ** 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
       sqlite3pager_rollback(pPager);
-      if( !pPager->memDb ){
+#if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN))
+      sqlite3_io_error_pending = ioerr_cnt;
+#endif
+      if( !MEMDB ){
         sqlite3OsUnlock(&pPager->fd, NO_LOCK);
       }
       assert( pPager->journalOpen==0 );
       break;
     }
     case PAGER_SHARED: {
-      if( !pPager->memDb ){
+      if( !MEMDB ){
         sqlite3OsUnlock(&pPager->fd, NO_LOCK);
       }
       break;
@@ -1741,7 +1921,7 @@ int sqlite3pager_close(Pager *pPager){
   }
   for(pPg=pPager->pAll; pPg; pPg=pNext){
 #ifndef NDEBUG
-    if( pPager->memDb ){
+    if( MEMDB ){
       PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
       assert( !pPg->alwaysRollback );
       assert( !pHist->pOrig );
@@ -1751,7 +1931,7 @@ int sqlite3pager_close(Pager *pPager){
     pNext = pPg->pNextAll;
     sqliteFree(pPg);
   }
-  TRACE2("CLOSE %d\n", pPager->fd.h);
+  TRACE2("CLOSE %d\n", PAGERID(pPager));
   sqlite3OsClose(&pPager->fd);
   assert( pPager->journalOpen==0 );
   /* Temp files are automatically deleted by the OS
@@ -1759,12 +1939,7 @@ int sqlite3pager_close(Pager *pPager){
   **   sqlite3OsDelete(pPager->zFilename);
   ** }
   */
-  if( pPager->zFilename!=(char*)&pPager[1] ){
-    assert( 0 );  /* Cannot happen */
-    sqliteFree(pPager->zFilename);
-    sqliteFree(pPager->zJournal);
-    sqliteFree(pPager->zDirectory);
-  }
+
   sqliteFree(pPager);
   return SQLITE_OK;
 }
@@ -1809,7 +1984,7 @@ static void _page_ref(PgHdr *pPg){
   pPg->nRef++;
   REFINFO(pPg);
 }
-#ifdef SQLITE_TEST
+#ifdef SQLITE_DEBUG
   static void page_ref(PgHdr *pPg){
     if( pPg->nRef==0 ){
       _page_ref(pPg);
@@ -1882,7 +2057,7 @@ static int syncJournal(Pager *pPager){
         ** it as a candidate for rollback. 
         */
         if( pPager->fullSync ){
-          TRACE2("SYNC journal of %d\n", pPager->fd.h);
+          TRACE2("SYNC journal of %d\n", PAGERID(pPager));
           rc = sqlite3OsSync(&pPager->jfd);
           if( rc!=0 ) return rc;
         }
@@ -1892,7 +2067,7 @@ static int syncJournal(Pager *pPager){
 
         sqlite3OsSeek(&pPager->jfd, pPager->journalOff);
       }
-      TRACE2("SYNC journal of %d\n", pPager->fd.h);
+      TRACE2("SYNC journal of %d\n", PAGERID(pPager));
       rc = sqlite3OsSync(&pPager->jfd);
       if( rc!=0 ) return rc;
       pPager->journalStarted = 1;
@@ -1923,37 +2098,6 @@ static int syncJournal(Pager *pPager){
   return rc;
 }
 
-/*
-** Try to obtain a lock on a file.  Invoke the busy callback if the lock
-** is currently not available.  Repeate until the busy callback returns
-** false or until the lock succeeds.
-**
-** Return SQLITE_OK on success and an error code if we cannot obtain
-** the lock.
-*/
-static int pager_wait_on_lock(Pager *pPager, int locktype){
-  int rc;
-  assert( PAGER_SHARED==SHARED_LOCK );
-  assert( PAGER_RESERVED==RESERVED_LOCK );
-  assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
-  if( pPager->state>=locktype ){
-    rc = SQLITE_OK;
-  }else{
-    int busy = 1;
-    do {
-      rc = sqlite3OsLock(&pPager->fd, locktype);
-    }while( rc==SQLITE_BUSY && 
-        pPager->pBusyHandler && 
-        pPager->pBusyHandler->xFunc && 
-        pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
-    );
-    if( rc==SQLITE_OK ){
-      pPager->state = locktype;
-    }
-  }
-  return rc;
-}
-
 /*
 ** Given a list of pages (connected by the PgHdr.pDirty pointer) write
 ** every one of those pages out to the database file and mark them all
@@ -1990,12 +2134,28 @@ static int pager_write_pagelist(PgHdr *pList){
   while( pList ){
     assert( pList->dirty );
     sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize);
-    CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
-    TRACE3("STORE %d page %d\n", pPager->fd.h, pList->pgno);
-    rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize);
-    CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0);
+    /* If there are dirty pages in the page cache with page numbers greater
+    ** than Pager.dbSize, this means sqlite3pager_truncate() was called to
+    ** make the file smaller (presumably by auto-vacuum code). Do not write
+    ** any such pages to the file.
+    */
+    if( pList->pgno<=pPager->dbSize ){
+      CODEC(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);
+      pPager->nWrite++;
+    }
+#ifndef NDEBUG
+    else{
+      TRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno);
+    }
+#endif
     if( rc ) return rc;
     pList->dirty = 0;
+#ifdef SQLITE_CHECK_PAGES
+    pList->pageHash = pager_pagehash(pList);
+#endif
     pList = pList->pDirty;
   }
   return SQLITE_OK;
@@ -2043,12 +2203,18 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
 */
 int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
   PgHdr *pPg;
-  int rc;
+  int rc, n;
+
+  /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
+  ** number greater than this, or zero, is requested.
+  */
+  if( pgno>PAGER_MAX_PGNO || pgno==0 ){
+    return SQLITE_CORRUPT;
+  }
 
   /* Make sure we have not hit any critical errors.
   */ 
   assert( pPager!=0 );
-  assert( pgno!=0 );
   *ppPage = 0;
   if( pPager->errMask & ~(PAGER_ERR_FULL) ){
     return pager_errcode(pPager);
@@ -2057,10 +2223,12 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
   /* If this is the first page accessed, then get a SHARED lock
   ** on the database file.
   */
-  if( pPager->nRef==0 && !pPager->memDb ){
-    rc = pager_wait_on_lock(pPager, SHARED_LOCK);
-    if( rc!=SQLITE_OK ){
-      return rc;
+  if( pPager->nRef==0 && !MEMDB ){
+    if( !pPager->noReadlock ){
+      rc = pager_wait_on_lock(pPager, SHARED_LOCK);
+      if( rc!=SQLITE_OK ){
+        return rc;
+      }
     }
 
     /* If a journal file exists, and there is no RESERVED lock on the
@@ -2123,7 +2291,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
   }else{
     /* Search for page in cache */
     pPg = pager_lookup(pPager, pgno);
-    if( pPager->memDb && pPager->state==PAGER_UNLOCK ){
+    if( MEMDB && pPager->state==PAGER_UNLOCK ){
       pPager->state = PAGER_SHARED;
     }
   }
@@ -2131,20 +2299,20 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
     /* The requested page is not in the page cache. */
     int h;
     pPager->nMiss++;
-    if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || pPager->memDb ){
+    if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || MEMDB ){
       /* Create a new page */
-      pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize 
+      pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->psAligned
                               + sizeof(u32) + pPager->nExtra
-                              + pPager->memDb*sizeof(PgHistory) );
+                              + MEMDB*sizeof(PgHistory) );
       if( pPg==0 ){
-        if( !pPager->memDb ){
+        if( !MEMDB ){
           pager_unwritelock(pPager);
         }
         pPager->errMask |= PAGER_ERR_MEM;
         return SQLITE_NOMEM;
       }
       memset(pPg, 0, sizeof(*pPg));
-      if( pPager->memDb ){
+      if( MEMDB ){
         memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory));
       }
       pPg->pPager = pPager;
@@ -2247,20 +2415,20 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
     if( pPager->nExtra>0 ){
       memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
     }
-    sqlite3pager_pagecount(pPager);
+    n = sqlite3pager_pagecount(pPager);
     if( pPager->errMask!=0 ){
       sqlite3pager_unref(PGHDR_TO_DATA(pPg));
       rc = pager_errcode(pPager);
       return rc;
     }
-    if( pPager->dbSize<(int)pgno ){
+    if( n<(int)pgno ){
       memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
     }else{
       int rc;
-      assert( pPager->memDb==0 );
+      assert( MEMDB==0 );
       sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
       rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize);
-      TRACE3("FETCH %d page %d\n", pPager->fd.h, pPg->pgno);
+      TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
       CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
       if( rc!=SQLITE_OK ){
         i64 fileSize;
@@ -2271,8 +2439,13 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
         }else{
           memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
         }
+      }else{
+        pPager->nRead++;
       }
     }
+#ifdef SQLITE_CHECK_PAGES
+    pPg->pageHash = pager_pagehash(pPg);
+#endif
   }else{
     /* The requested page is in the page cache. */
     pPager->nHit++;
@@ -2325,6 +2498,8 @@ int sqlite3pager_unref(void *pData){
   pPg->nRef--;
   REFINFO(pPg);
 
+  CHECK_PAGE(pPg);
+
   /* When the number of references to a page reach 0, call the
   ** destructor and add the page to the freelist.
   */
@@ -2351,7 +2526,7 @@ int sqlite3pager_unref(void *pData){
     */
     pPager->nRef--;
     assert( pPager->nRef>=0 );
-    if( pPager->nRef==0 && !pPager->memDb ){
+    if( pPager->nRef==0 && !MEMDB ){
       pager_reset(pPager);
     }
   }
@@ -2367,7 +2542,7 @@ int sqlite3pager_unref(void *pData){
 */
 static int pager_open_journal(Pager *pPager){
   int rc;
-  assert( !pPager->memDb );
+  assert( !MEMDB );
   assert( pPager->state>=PAGER_RESERVED );
   assert( pPager->journalOpen==0 );
   assert( pPager->useJournal );
@@ -2452,7 +2627,7 @@ int sqlite3pager_begin(void *pData, int exFlag){
   assert( pPager->state!=PAGER_UNLOCK );
   if( pPager->state==PAGER_SHARED ){
     assert( pPager->aInJournal==0 );
-    if( pPager->memDb ){
+    if( MEMDB ){
       pPager->state = PAGER_EXCLUSIVE;
       pPager->origDbSize = pPager->dbSize;
     }else{
@@ -2471,7 +2646,7 @@ int sqlite3pager_begin(void *pData, int exFlag){
         return rc;
       }
       pPager->dirtyCache = 0;
-      TRACE2("TRANSACTION %d\n", pPager->fd.h);
+      TRACE2("TRANSACTION %d\n", PAGERID(pPager));
       if( pPager->useJournal && !pPager->tempFile ){
         rc = pager_open_journal(pPager);
       }
@@ -2513,128 +2688,130 @@ int sqlite3pager_write(void *pData){
 
   assert( !pPager->setMaster );
 
+  CHECK_PAGE(pPg);
+
   /* Mark the page as dirty.  If the page has already been written
   ** to the journal then we can return right away.
   */
   pPg->dirty = 1;
   if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){
     pPager->dirtyCache = 1;
-    return SQLITE_OK;
-  }
-
-  /* If we get this far, it means that the page needs to be
-  ** written to the transaction journal or the ckeckpoint journal
-  ** or both.
-  **
-  ** First check to see that the transaction journal exists and
-  ** create it if it does not.
-  */
-  assert( pPager->state!=PAGER_UNLOCK );
-  rc = sqlite3pager_begin(pData, 0);
-  if( rc!=SQLITE_OK ){
-    return rc;
-  }
-  assert( pPager->state>=PAGER_RESERVED );
-  if( !pPager->journalOpen && pPager->useJournal ){
-    rc = pager_open_journal(pPager);
-    if( rc!=SQLITE_OK ) return rc;
-  }
-  assert( pPager->journalOpen || !pPager->useJournal );
-  pPager->dirtyCache = 1;
+  }else{
 
-  /* The transaction journal now exists and we have a RESERVED or an
-  ** EXCLUSIVE lock on the main database file.  Write the current page to
-  ** the transaction journal if it is not there already.
-  */
-  if( !pPg->inJournal && (pPager->useJournal || pPager->memDb) ){
-    if( (int)pPg->pgno <= pPager->origDbSize ){
-      int szPg;
-      u32 saved;
-      if( pPager->memDb ){
+    /* If we get this far, it means that the page needs to be
+    ** written to the transaction journal or the ckeckpoint journal
+    ** or both.
+    **
+    ** First check to see that the transaction journal exists and
+    ** create it if it does not.
+    */
+    assert( pPager->state!=PAGER_UNLOCK );
+    rc = sqlite3pager_begin(pData, 0);
+    if( rc!=SQLITE_OK ){
+      return rc;
+    }
+    assert( pPager->state>=PAGER_RESERVED );
+    if( !pPager->journalOpen && pPager->useJournal ){
+      rc = pager_open_journal(pPager);
+      if( rc!=SQLITE_OK ) return rc;
+    }
+    assert( pPager->journalOpen || !pPager->useJournal );
+    pPager->dirtyCache = 1;
+  
+    /* The transaction journal now exists and we have a RESERVED or an
+    ** EXCLUSIVE lock on the main database file.  Write the current page to
+    ** the transaction journal if it is not there already.
+    */
+    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);
+          assert( pHist->pOrig==0 );
+          pHist->pOrig = sqliteMallocRaw( pPager->pageSize );
+          if( pHist->pOrig ){
+            memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
+          }
+        }else{
+          u32 cksum;
+          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);
+          szPg = pPager->pageSize+8;
+          store32bits(pPg->pgno, pPg, -4);
+          rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], 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;
+          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);
+          pPg->needSync = !pPager->noSync;
+          if( pPager->stmtInUse ){
+            pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
+            page_add_to_stmt_list(pPg);
+          }
+        }
+      }else{
+        pPg->needSync = !pPager->journalStarted && !pPager->noSync;
+        TRACE4("APPEND %d page %d needSync=%d\n",
+                PAGERID(pPager), pPg->pgno, pPg->needSync);
+      }
+      if( pPg->needSync ){
+        pPager->needSync = 1;
+      }
+      pPg->inJournal = 1;
+    }
+  
+    /* If the statement journal is open and the page is not in it,
+    ** then write the current page to the statement journal.  Note that
+    ** the statement journal format differs from the standard journal format
+    ** in that it omits the checksums and the header.
+    */
+    if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
+      assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
+      if( MEMDB ){
         PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
-        TRACE3("JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno);
-        assert( pHist->pOrig==0 );
-        pHist->pOrig = sqliteMallocRaw( pPager->pageSize );
-        if( pHist->pOrig ){
-          memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
+        assert( pHist->pStmt==0 );
+        pHist->pStmt = sqliteMallocRaw( pPager->pageSize );
+        if( pHist->pStmt ){
+          memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
         }
+        TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
       }else{
-        u32 cksum;
-        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);
-        szPg = pPager->pageSize+8;
         store32bits(pPg->pgno, pPg, -4);
-        rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], szPg);
-        pPager->journalOff += szPg;
-        TRACE4("JOURNAL %d page %d needSync=%d\n",
-                pPager->fd.h, pPg->pgno, pPg->needSync);
+        CODEC(pPager, pData, pPg->pgno, 7);
+        rc = sqlite3OsWrite(&pPager->stfd,((char*)pData)-4, pPager->pageSize+4);
+        TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
         CODEC(pPager, pData, pPg->pgno, 0);
-        *(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved;
         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);
-        pPg->needSync = !pPager->noSync;
-        if( pPager->stmtInUse ){
-          pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
-          page_add_to_stmt_list(pPg);
-        }
+        pPager->stmtNRec++;
+        assert( pPager->aInStmt!=0 );
+        pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
       }
-    }else{
-      pPg->needSync = !pPager->journalStarted && !pPager->noSync;
-      TRACE4("APPEND %d page %d needSync=%d\n",
-              pPager->fd.h, pPg->pgno, pPg->needSync);
-    }
-    if( pPg->needSync ){
-      pPager->needSync = 1;
-    }
-    pPg->inJournal = 1;
-  }
-
-  /* If the statement journal is open and the page is not in it,
-  ** then write the current page to the statement journal.  Note that
-  ** the statement journal format differs from the standard journal format
-  ** in that it omits the checksums and the header.
-  */
-  if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
-    assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
-    if( pPager->memDb ){
-      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
-      assert( pHist->pStmt==0 );
-      pHist->pStmt = sqliteMallocRaw( pPager->pageSize );
-      if( pHist->pStmt ){
-        memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
-      }
-      TRACE3("STMT-JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno);
-    }else{
-      store32bits(pPg->pgno, pPg, -4);
-      CODEC(pPager, pData, pPg->pgno, 7);
-      rc = sqlite3OsWrite(&pPager->stfd, ((char*)pData)-4, pPager->pageSize+4);
-      TRACE3("STMT-JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno);
-      CODEC(pPager, pData, pPg->pgno, 0);
-      if( rc!=SQLITE_OK ){
-        sqlite3pager_rollback(pPager);
-        pPager->errMask |= PAGER_ERR_FULL;
-        return rc;
-      }
-      pPager->stmtNRec++;
-      assert( pPager->aInStmt!=0 );
-      pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
+      page_add_to_stmt_list(pPg);
     }
-    page_add_to_stmt_list(pPg);
   }
 
   /* Update the database size and return.
   */
   if( pPager->dbSize<(int)pPg->pgno ){
     pPager->dbSize = pPg->pgno;
-    if( !pPager->memDb && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
+    if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
       pPager->dbSize++;
     }
   }
@@ -2651,6 +2828,7 @@ int sqlite3pager_iswriteable(void *pData){
   return pPg->dirty;
 }
 
+#ifndef SQLITE_OMIT_VACUUM
 /*
 ** Replace the content of a single page with the information in the third
 ** argument.
@@ -2669,6 +2847,7 @@ int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){
   }
   return rc;
 }
+#endif
 
 /*
 ** A call to this routine tells the pager that it is not necessary to
@@ -2697,7 +2876,7 @@ int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){
 void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
   PgHdr *pPg;
 
-  if( pPager->memDb ) return;
+  if( MEMDB ) return;
 
   pPg = pager_lookup(pPager, pgno);
   pPg->alwaysRollback = 1;
@@ -2712,8 +2891,11 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
       ** corruption during the next transaction.
       */
     }else{
-      TRACE3("DONT_WRITE page %d of %d\n", pgno, pPager->fd.h);
+      TRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager));
       pPg->dirty = 0;
+#ifdef SQLITE_CHECK_PAGES
+      pPg->pageHash = pager_pagehash(pPg);
+#endif
     }
   }
 }
@@ -2729,7 +2911,7 @@ void sqlite3pager_dont_rollback(void *pData){
   Pager *pPager = pPg->pPager;
 
   if( pPager->state!=PAGER_EXCLUSIVE || pPager->journalOpen==0 ) return;
-  if( pPg->alwaysRollback || pPager->alwaysRollback || pPager->memDb ) return;
+  if( pPg->alwaysRollback || pPager->alwaysRollback || MEMDB ) return;
   if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
     assert( pPager->aInJournal!=0 );
     pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
@@ -2738,7 +2920,7 @@ void sqlite3pager_dont_rollback(void *pData){
       pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
       page_add_to_stmt_list(pPg);
     }
-    TRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, pPager->fd.h);
+    TRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
   }
   if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
     assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
@@ -2749,6 +2931,7 @@ void sqlite3pager_dont_rollback(void *pData){
 }
 
 
+#ifndef SQLITE_OMIT_MEMORYDB
 /*
 ** Clear a PgHistory block
 */
@@ -2758,6 +2941,9 @@ static void clearHistory(PgHistory *pHist){
   pHist->pOrig = 0;
   pHist->pStmt = 0;
 }
+#else
+#define clearHistory(x)
+#endif
 
 /*
 ** Commit all changes to the database and release the write lock.
@@ -2784,8 +2970,8 @@ int sqlite3pager_commit(Pager *pPager){
   if( pPager->state<PAGER_RESERVED ){
     return SQLITE_ERROR;
   }
-  TRACE2("COMMIT %d\n", pPager->fd.h);
-  if( pPager->memDb ){
+  TRACE2("COMMIT %d\n", PAGERID(pPager));
+  if( MEMDB ){
     pPg = pager_get_all_dirty_pages(pPager);
     while( pPg ){
       clearHistory(PGHDR_TO_HIST(pPg, pPager));
@@ -2816,7 +3002,7 @@ int sqlite3pager_commit(Pager *pPager){
     return rc;
   }
   assert( pPager->journalOpen );
-  rc = sqlite3pager_sync(pPager, 0);
+  rc = sqlite3pager_sync(pPager, 0, 0);
   if( rc!=SQLITE_OK ){
     goto commit_abort;
   }
@@ -2845,8 +3031,8 @@ commit_abort:
 */
 int sqlite3pager_rollback(Pager *pPager){
   int rc;
-  TRACE2("ROLLBACK %d\n", pPager->fd.h);
-  if( pPager->memDb ){
+  TRACE2("ROLLBACK %d\n", PAGERID(pPager));
+  if( MEMDB ){
     PgHdr *p;
     for(p=pPager->pAll; p; p=p->pNextAll){
       PgHistory *pHist;
@@ -2860,9 +3046,9 @@ int sqlite3pager_rollback(Pager *pPager){
       pHist = PGHDR_TO_HIST(p, pPager);
       if( pHist->pOrig ){
         memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize);
-        TRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, pPager->fd.h);
+        TRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager));
       }else{
-        TRACE3("PAGE %d is clean on %d\n", p->pgno, pPager->fd.h);
+        TRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager));
       }
       clearHistory(pHist);
       p->dirty = 0;
@@ -2896,13 +3082,11 @@ int sqlite3pager_rollback(Pager *pPager){
     return pager_errcode(pPager);
   }
   if( pPager->state==PAGER_RESERVED ){
-    int rc2, rc3;
+    int rc2;
     rc = pager_reload_cache(pPager);
-    rc2 = pager_truncate(pPager, pPager->origDbSize);
-    rc3 = pager_unwritelock(pPager);
+    rc2 = pager_unwritelock(pPager);
     if( rc==SQLITE_OK ){
       rc = rc2;
-      if( rc3 ) rc = rc3;
     }
   }else{
     rc = pager_playback(pPager);
@@ -2927,7 +3111,7 @@ int sqlite3pager_isreadonly(Pager *pPager){
 ** This routine is used for testing and analysis only.
 */
 int *sqlite3pager_stats(Pager *pPager){
-  static int a[9];
+  static int a[11];
   a[0] = pPager->nRef;
   a[1] = pPager->nPage;
   a[2] = pPager->mxPage;
@@ -2937,6 +3121,8 @@ int *sqlite3pager_stats(Pager *pPager){
   a[6] = pPager->nHit;
   a[7] = pPager->nMiss;
   a[8] = pPager->nOvfl;
+  a[9] = pPager->nRead;
+  a[10] = pPager->nWrite;
   return a;
 }
 
@@ -2952,8 +3138,8 @@ int sqlite3pager_stmt_begin(Pager *pPager){
   char zTemp[SQLITE_TEMPNAME_SIZE];
   assert( !pPager->stmtInUse );
   assert( pPager->dbSize>=0 );
-  TRACE2("STMT-BEGIN %d\n", pPager->fd.h);
-  if( pPager->memDb ){
+  TRACE2("STMT-BEGIN %d\n", PAGERID(pPager));
+  if( MEMDB ){
     pPager->stmtInUse = 1;
     pPager->stmtSize = pPager->dbSize;
     return SQLITE_OK;
@@ -3000,8 +3186,8 @@ stmt_begin_failed:
 int sqlite3pager_stmt_commit(Pager *pPager){
   if( pPager->stmtInUse ){
     PgHdr *pPg, *pNext;
-    TRACE2("STMT-COMMIT %d\n", pPager->fd.h);
-    if( !pPager->memDb ){
+    TRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
+    if( !MEMDB ){
       sqlite3OsSeek(&pPager->stfd, 0);
       /* sqlite3OsTruncate(&pPager->stfd, 0); */
       sqliteFree( pPager->aInStmt );
@@ -3012,7 +3198,7 @@ int sqlite3pager_stmt_commit(Pager *pPager){
       assert( pPg->inStmt );
       pPg->inStmt = 0;
       pPg->pPrevStmt = pPg->pNextStmt = 0;
-      if( pPager->memDb ){
+      if( MEMDB ){
         PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
         sqliteFree(pHist->pStmt);
         pHist->pStmt = 0;
@@ -3032,8 +3218,8 @@ int sqlite3pager_stmt_commit(Pager *pPager){
 int sqlite3pager_stmt_rollback(Pager *pPager){
   int rc;
   if( pPager->stmtInUse ){
-    TRACE2("STMT-ROLLBACK %d\n", pPager->fd.h);
-    if( pPager->memDb ){
+    TRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
+    if( MEMDB ){
       PgHdr *pPg;
       for(pPg=pPager->pStmt; pPg; pPg=pPg->pNextStmt){
         PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
@@ -3132,14 +3318,20 @@ static int pager_incr_changecounter(Pager *pPager){
 **
 ** Note that if zMaster==NULL, this does not overwrite a previous value
 ** passed to an sqlite3pager_sync() call.
+**
+** If parameter nTrunc is non-zero, then the pager file is truncated to
+** nTrunc pages (this is used by auto-vacuum databases).
 */
-int sqlite3pager_sync(Pager *pPager, const char *zMaster){
+int sqlite3pager_sync(Pager *pPager, const char *zMaster, Pgno nTrunc){
   int rc = SQLITE_OK;
 
+  TRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", 
+      pPager->zFilename, zMaster, nTrunc);
+
   /* If this is an in-memory db, or no pages have been written to, or this
   ** function has already been called, it is a no-op.
   */
-  if( pPager->state!=PAGER_SYNCED && !pPager->memDb && pPager->dirtyCache ){
+  if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){
     PgHdr *pPg;
     assert( pPager->journalOpen );
 
@@ -3152,12 +3344,38 @@ int sqlite3pager_sync(Pager *pPager, const char *zMaster){
     if( !pPager->setMaster ){
       rc = pager_incr_changecounter(pPager);
       if( rc!=SQLITE_OK ) goto sync_exit;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+      if( nTrunc!=0 ){
+        /* If this transaction has made the database smaller, then all pages
+        ** being discarded by the truncation must be written to the journal
+        ** file.
+        */
+        Pgno i;
+        void *pPage;
+        for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){
+          if( !(pPager->aInJournal[i/8] & (1<<(i&7))) ){
+            rc = sqlite3pager_get(pPager, i, &pPage);
+            if( rc!=SQLITE_OK ) goto sync_exit;
+            rc = sqlite3pager_write(pPage);
+            sqlite3pager_unref(pPage);
+            if( rc!=SQLITE_OK ) goto sync_exit;
+          }
+        } 
+      }
+#endif
       rc = writeMasterJournal(pPager, zMaster);
       if( rc!=SQLITE_OK ) goto sync_exit;
       rc = syncJournal(pPager);
       if( rc!=SQLITE_OK ) goto sync_exit;
     }
 
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    if( nTrunc!=0 ){
+      rc = sqlite3pager_truncate(pPager, nTrunc);
+      if( rc!=SQLITE_OK ) goto sync_exit;
+    }
+#endif
+
     /* Write all dirty pages to the database file */
     pPg = pager_get_all_dirty_pages(pPager);
     rc = pager_write_pagelist(pPg);
@@ -3175,6 +3393,102 @@ sync_exit:
   return rc;
 }
 
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** Move the page identified by pData to location pgno in the file. 
+**
+** There must be no references to the current page pgno. If current page
+** pgno is not already in the rollback journal, it is not written there by
+** by this routine. The same applies to the page pData refers to on entry to
+** this routine.
+**
+** References to the page refered to by pData remain valid. Updating any
+** meta-data associated with page pData (i.e. data stored in the nExtra bytes
+** allocated along with the page) is the responsibility of the caller.
+**
+** A transaction must be active when this routine is called, however it is 
+** illegal to call this routine if a statment transaction is active.
+*/
+int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){
+  PgHdr *pPg = DATA_TO_PGHDR(pData);
+  PgHdr *pPgOld; 
+  int h;
+  Pgno needSyncPgno = 0;
+
+  assert( !pPager->stmtInUse );
+  assert( pPg->nRef>0 );
+
+  TRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", 
+      PAGERID(pPager), pPg->pgno, pPg->needSync, pgno);
+
+  if( pPg->needSync ){
+    needSyncPgno = pPg->pgno;
+    assert( pPg->inJournal );
+    assert( pPg->dirty );
+    assert( pPager->needSync );
+  }
+
+  /* Unlink pPg from it's hash-chain */
+  unlinkHashChain(pPager, pPg);
+
+  /* If the cache contains a page with page-number pgno, remove it
+  ** from it's hash chain. Also, if the PgHdr.needSync was set for 
+  ** page pgno before the 'move' operation, it needs to be retained 
+  ** for the page moved there.
+  */
+  pPgOld = pager_lookup(pPager, pgno);
+  if( pPgOld ){
+    assert( pPgOld->nRef==0 );
+    unlinkHashChain(pPager, pPgOld);
+    pPgOld->dirty = 0;
+    if( pPgOld->needSync ){
+      assert( pPgOld->inJournal );
+      pPg->inJournal = 1;
+      pPg->needSync = 1;
+      assert( pPager->needSync );
+    }
+  }
+
+  /* Change the page number for pPg and insert it into the new hash-chain. */
+  pPg->pgno = pgno;
+  h = pager_hash(pgno);
+  if( pPager->aHash[h] ){
+    assert( pPager->aHash[h]->pPrevHash==0 );
+    pPager->aHash[h]->pPrevHash = pPg;
+  }
+  pPg->pNextHash = pPager->aHash[h];
+  pPager->aHash[h] = pPg;
+  pPg->pPrevHash = 0;
+
+  pPg->dirty = 1;
+  pPager->dirtyCache = 1;
+
+  if( needSyncPgno ){
+    /* If needSyncPgno is non-zero, then the journal file needs to be 
+    ** sync()ed before any data is written to database file page needSyncPgno.
+    ** Currently, no such page exists in the page-cache and the 
+    ** Pager.aInJournal bit has been set. This needs to be remedied by loading
+    ** the page into the pager-cache and setting the PgHdr.needSync flag.
+    **
+    ** The sqlite3pager_get() call may cause the journal to sync. So make
+    ** sure the Pager.needSync flag is set too.
+    */
+    int rc;
+    void *pNeedSync;
+    assert( pPager->needSync );
+    rc = sqlite3pager_get(pPager, needSyncPgno, &pNeedSync);
+    if( rc!=SQLITE_OK ) return rc;
+    pPager->needSync = 1;
+    DATA_TO_PGHDR(pNeedSync)->needSync = 1;
+    DATA_TO_PGHDR(pNeedSync)->inJournal = 1;
+    DATA_TO_PGHDR(pNeedSync)->dirty = 1;
+    sqlite3pager_unref(pNeedSync);
+  }
+
+  return SQLITE_OK;
+}
+#endif
+
 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
 /*
 ** Return the current state of the file lock for the given pager.
@@ -3190,7 +3504,7 @@ int sqlite3pager_lockstate(Pager *pPager){
 }
 #endif
 
-#ifdef SQLITE_TEST
+#ifdef SQLITE_DEBUG
 /*
 ** Print a listing of all referenced pages and their ref count.
 */
index 0231e27a93cb979d2067282b0433566b096991b5..a592b1944b3de7868b110f576d3c537dffd66c5d 100644 (file)
@@ -50,13 +50,21 @@ typedef unsigned int Pgno;
 */
 typedef struct Pager Pager;
 
+/*
+** Allowed values for the flags parameter to sqlite3pager_open().
+**
+** NOTE: This values must match the corresponding BTREE_ values in btree.h.
+*/
+#define PAGER_OMIT_JOURNAL  0x0001    /* Do not use a rollback journal */
+#define PAGER_NO_READLOCK   0x0002    /* Omit readlocks on readonly files */
+
 
 /*
 ** See source code comments for a detailed description of the following
 ** routines:
 */
 int sqlite3pager_open(Pager **ppPager, const char *zFilename,
-                     int nExtra, int useJournal);
+                     int nExtra, int flags);
 void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler);
 void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
 void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int));
@@ -76,7 +84,7 @@ int sqlite3pager_pagecount(Pager*);
 int sqlite3pager_truncate(Pager*,Pgno);
 int sqlite3pager_begin(void*, int exFlag);
 int sqlite3pager_commit(Pager*);
-int sqlite3pager_sync(Pager*,const char *zMaster);
+int sqlite3pager_sync(Pager*,const char *zMaster, Pgno);
 int sqlite3pager_rollback(Pager*);
 int sqlite3pager_isreadonly(Pager*);
 int sqlite3pager_stmt_begin(Pager*);
@@ -91,6 +99,7 @@ const char *sqlite3pager_dirname(Pager*);
 const char *sqlite3pager_journalname(Pager*);
 int sqlite3pager_rename(Pager*, const char *zNewName);
 void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
+int sqlite3pager_movepage(Pager*,void*,Pgno);
 
 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
 int sqlite3pager_lockstate(Pager*);
index 1856c3ea970aee8477eba7214532617751ec4549..bec7a0a4336eb5e3860f458131779b0e0bacb9f8 100644 (file)
@@ -1,10 +1,10 @@
-/* Driver template for the LEMON parser generator. 
+/* Driver template for the LEMON parser generator.
 ** The author disclaims copyright to this source code.
 */
 /* First off, code is include which follows the "include" declaration
 ** in the input file. */
 #include <stdio.h>
-#line 33 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 33 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 
 #include "sqliteInt.h"
 #include "parse.h"
@@ -14,8 +14,8 @@
 ** LIMIT clause of a SELECT statement.
 */
 struct LimitVal {
-  int limit;    /* The LIMIT value.  -1 if there is no limit */
-  int offset;   /* The OFFSET.  0 if there is none */
+  Expr *pLimit;    /* The LIMIT expression.  NULL if there is no limit */
+  Expr *pOffset;   /* The OFFSET expression.  NULL if there is none */
 };
 
 /*
@@ -43,7 +43,7 @@ struct TrigEvent { int a; IdList * b; };
 */
 struct AttachKey { int type;  Token key; };
 
-#line 48 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 48 "/home/wez/php5-HEAD/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,35 +93,35 @@ struct AttachKey { int type;  Token key; };
 **                       defined, then do no error processing.
 */
 #define YYCODETYPE unsigned char
-#define YYNOCODE 225
+#define YYNOCODE 239
 #define YYACTIONTYPE unsigned short int
 #define sqlite3ParserTOKENTYPE Token
 typedef union {
   sqlite3ParserTOKENTYPE yy0;
-  struct {int value; int mask;} yy47;
-  TriggerStep* yy91;
-  Token yy98;
-  Select* yy107;
-  struct TrigEvent yy146;
-  ExprList* yy210;
-  Expr* yy258;
-  SrcList* yy259;
+  struct AttachKey yy40;
+  int yy60;
+  struct TrigEvent yy62;
+  struct {int value; int mask;} yy243;
+  struct LikeOp yy258;
+  ExprList* yy266;
   IdList* yy272;
-  int yy284;
-  struct AttachKey yy292;
-  struct LikeOp yy342;
-  struct LimitVal yy404;
-  int yy449;
+  Select* yy331;
+  struct LimitVal yy348;
+  Token yy406;
+  SrcList* yy427;
+  Expr* yy454;
+  TriggerStep* yy455;
+  int yy477;
 } YYMINORTYPE;
 #define YYSTACKDEPTH 100
 #define sqlite3ParserARG_SDECL Parse *pParse;
 #define sqlite3ParserARG_PDECL ,Parse *pParse
 #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
 #define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 537
-#define YYNRULE 292
-#define YYERRORSYMBOL 130
-#define YYERRSYMDT yy449
+#define YYNSTATE 564
+#define YYNRULE 305
+#define YYERRORSYMBOL 141
+#define YYERRSYMDT yy477
 #define YYFALLBACK 1
 #define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
 #define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
@@ -175,430 +175,481 @@ typedef union {
 **  yy_default[]       Default action for each state.
 */
 static const YYACTIONTYPE yy_action[] = {
- /*     0 */   257,  325,  255,  138,  140,  142,  144,  146,  148,  150,
- /*    10 */   152,  154,  156,   89,   87,   88,  159,   12,    4,    6,
- /*    20 */   158,  537,   38,   24,  830,    1,  536,    3,  329,  488,
- /*    30 */   534,  535,  319,   50,  124,  112,  160,  169,  174,  179,
- /*    40 */   168,  173,  134,  136,  128,  130,  126,  132,  138,  140,
- /*    50 */   142,  144,  146,  148,  150,  152,  154,  156,   26,   73,
- /*    60 */   384,  256,   39,   58,   64,   66,  299,  330,  612,  611,
- /*    70 */   351,   30,   92,  332,  326,  159,   13,   14,  353,  158,
- /*    80 */     5,  355,  361,  366,  499,  146,  148,  150,  152,  154,
- /*    90 */   156,   12,  369,  124,  112,  160,  169,  174,  179,  168,
- /*   100 */   173,  134,  136,  128,  130,  126,  132,  138,  140,  142,
- /*   110 */   144,  146,  148,  150,  152,  154,  156,  128,  130,  126,
- /*   120 */   132,  138,  140,  142,  144,  146,  148,  150,  152,  154,
- /*   130 */   156,  659,  353,  244,   62,  355,  361,  366,   79,   12,
- /*   140 */    63,   98,   96,  289,  159,  280,  369,  349,  158,  181,
- /*   150 */    13,   14,   27,   12,  546,  383,   32,   10,  368,  273,
- /*   160 */   515,  765,  124,  112,  160,  169,  174,  179,  168,  173,
- /*   170 */   134,  136,  128,  130,  126,  132,  138,  140,  142,  144,
- /*   180 */   146,  148,  150,  152,  154,  156,  810,  349,   47,   73,
- /*   190 */   222,  763,  223,  114,  246,   31,   32,   48,   13,   14,
- /*   200 */    74,  274,  252,  166,  175,  180,  275,  304,   49,    8,
- /*   210 */   255,   45,   13,   14,  159,  290,  350,  382,  158,  245,
- /*   220 */   441,   46,  378,  183,  247,  185,  186,   15,   16,   17,
- /*   230 */    73,  205,  124,  112,  160,  169,  174,  179,  168,  173,
- /*   240 */   134,  136,  128,  130,  126,  132,  138,  140,  142,  144,
- /*   250 */   146,  148,  150,  152,  154,  156,  542,  306,  438,  159,
- /*   260 */    98,   96,  332,  158,  272,  475,  447,  437,   12,  256,
- /*   270 */   288,   12,  304,  339,  287,   50,   77,  124,  112,  160,
- /*   280 */   169,  174,  179,  168,  173,  134,  136,  128,  130,  126,
- /*   290 */   132,  138,  140,  142,  144,  146,  148,  150,  152,  154,
- /*   300 */   156,  547,   36,  335,   39,   58,   64,   66,  299,  330,
- /*   310 */    35,  334,  291,  545,  114,  332,  114,  329,   12,  625,
- /*   320 */   353,  187,  306,  355,  361,  366,  422,   13,   14,  159,
- /*   330 */    13,   14,  184,  158,  369,  636,  188,  259,  188,  764,
- /*   340 */    91,   87,   88,  100,   87,   88,  219,  124,  112,  160,
- /*   350 */   169,  174,  179,  168,  173,  134,  136,  128,  130,  126,
- /*   360 */   132,  138,  140,  142,  144,  146,  148,  150,  152,  154,
- /*   370 */   156,  297,  282,  114,  292,   51,  237,   13,   14,  150,
- /*   380 */   152,  154,  156,  114,   12,  225,   53,  225,  159,  166,
- /*   390 */   175,  180,  158,  380,  303,  111,  433,  658,   69,   92,
- /*   400 */   379,  183,   92,  185,  186,  111,  124,  112,  160,  169,
- /*   410 */   174,  179,  168,  173,  134,  136,  128,  130,  126,  132,
- /*   420 */   138,  140,  142,  144,  146,  148,  150,  152,  154,  156,
- /*   430 */   103,  230,  561,  159,  773,   12,  286,  158,  631,  534,
- /*   440 */   535,  105,  815,   13,   14,  166,  175,  180,  203,  808,
- /*   450 */   215,  124,  112,  160,  169,  174,  179,  168,  173,  134,
- /*   460 */   136,  128,  130,  126,  132,  138,  140,  142,  144,  146,
- /*   470 */   148,  150,  152,  154,  156,    2,    3,  183,  159,  185,
- /*   480 */   186,  813,  158,   43,   44,  569,   33,  633,   41,  348,
- /*   490 */   340,  413,  415,  414,   13,   14,  124,  112,  160,  169,
- /*   500 */   174,  179,  168,  173,  134,  136,  128,  130,  126,  132,
- /*   510 */   138,  140,  142,  144,  146,  148,  150,  152,  154,  156,
- /*   520 */   249,  336,  697,  159,  337,  338,  183,  158,  185,  186,
- /*   530 */    56,   57,  183,   11,  185,  186,  183,  416,  185,  186,
- /*   540 */   402,  124,  112,  160,  169,  174,  179,  168,  173,  134,
- /*   550 */   136,  128,  130,  126,  132,  138,  140,  142,  144,  146,
- /*   560 */   148,  150,  152,  154,  156,  342,   87,   88,  159,  345,
- /*   570 */    87,   88,  158,   98,   96,  183,  404,  185,  186,  240,
- /*   580 */     9,  183,   92,  185,  186,  802,  124,  177,  160,  169,
- /*   590 */   174,  179,  168,  173,  134,  136,  128,  130,  126,  132,
- /*   600 */   138,  140,  142,  144,  146,  148,  150,  152,  154,  156,
- /*   610 */   787,  341,  257,  159,  255,  255,  183,  158,  185,  186,
- /*   620 */    94,   95,  480,  518,   92,  307,  314,  316,   92,  548,
- /*   630 */   325,  171,  112,  160,  169,  174,  179,  168,  173,  134,
- /*   640 */   136,  128,  130,  126,  132,  138,  140,  142,  144,  146,
- /*   650 */   148,  150,  152,  154,  156,  255,   25,  486,  159,  482,
- /*   660 */   170,  358,  158,   19,  241,  242,  252,  266,  513,  267,
- /*   670 */   259,  553,   72,  256,  256,  402,   68,  244,  160,  169,
- /*   680 */   174,  179,  168,  173,  134,  136,  128,  130,  126,  132,
- /*   690 */   138,  140,  142,  144,  146,  148,  150,  152,  154,  156,
- /*   700 */   207,  255,   72,  326,  780,  260,   68,  267,  514,   47,
- /*   710 */   189,  428,  388,  385,  256,  325,  259,   21,   48,  162,
- /*   720 */   395,   12,  114,  161,  516,  517,  195,  193,  294,   49,
- /*   730 */   207,  484,  209,  312,  191,   70,   71,  387,  246,  113,
- /*   740 */   189,  164,  165,   73,  198,  114,  363,  396,  114,  391,
- /*   750 */    73,  277,  529,  313,  436,  182,  195,  193,   72,  467,
- /*   760 */   256,  623,   68,  245,  191,   70,   71,  188,  163,  113,
- /*   770 */   188,  119,  120,  121,  122,  197,  114,  803,  691,   72,
- /*   780 */    13,   14,   92,   68,   73,   73,  207,   77,  326,   73,
- /*   790 */   199,  807,   99,  436,  452,  293,  189,  223,  474,  325,
- /*   800 */   309,  119,  120,  121,  122,  197,  423,  207,  221,  460,
- /*   810 */   434,  419,  195,  193,  418,   90,  224,  189,   77,  225,
- /*   820 */   191,   70,   71,   73,  442,  113,  420,  114,  325,  444,
- /*   830 */   372,  468,  114,  195,  193,  283,  325,  311,  310,  402,
- /*   840 */   470,  191,   70,   71,  114,    7,  113,   41,  460,  474,
- /*   850 */    18,   20,   22,  386,  296,  114,  457,  119,  120,  121,
- /*   860 */   122,  197,  766,  446,  521,  554,  123,  430,  444,   23,
- /*   870 */   531,  114,  326,  114,  114,  481,  114,  125,  119,  120,
- /*   880 */   121,  122,  197,  510,   72,  441,  114,  238,   68,  114,
- /*   890 */   508,  506,  114,  127,  114,  129,  131,  114,  133,  411,
- /*   900 */   412,  322,  114,  114,  114,  114,  407,  114,  135,  326,
- /*   910 */   660,  137,  207,  114,  139,  114,  141,  451,  114,  143,
- /*   920 */   114,  114,  189,  114,  145,  147,  149,  151,  114,  153,
- /*   930 */   489,  493,  437,  114,  114,  155,  479,  157,  195,  193,
- /*   940 */   167,   77,  176,  178,  114,  190,  191,   70,   71,  114,
- /*   950 */   192,  113,  114,  114,  114,  194,  196,  114,  691,  114,
- /*   960 */   269,  320,  343,  321,  344,  269,  204,  114,  359,  284,
- /*   970 */   321,  206,  114,  555,  216,  218,  220,  114,  364,  234,
- /*   980 */   321,  239,  660,  119,  120,  121,  122,  197,  373,  271,
- /*   990 */   321,  281,  114,  114,  367,  227,  227,  269,  431,  408,
- /*  1000 */   321,  503,  439,   44,  465,  473,  267,  471,  114,   77,
- /*  1010 */   402,  402,  402,  402,  455,  459,  265,  457,  402,  402,
- /*  1020 */   823,  417,  504,  507,  556,  471,   28,   29,  560,   37,
- /*  1030 */   472,   73,   34,   55,   40,   41,   42,   54,   59,   67,
- /*  1040 */   570,  571,   52,   75,   60,   78,  483,  485,  487,  491,
- /*  1050 */    61,   65,   76,  464,  495,  501,  101,  527,   77,  238,
- /*  1060 */   233,  235,   85,   93,   86,   80,   97,  238,  102,   81,
- /*  1070 */   104,   82,  108,  107,  109,  110,   83,  115,  497,   84,
- /*  1080 */   117,  116,  156,  172,  637,  217,  638,  118,  202,  226,
- /*  1090 */   639,  208,  106,  211,  227,  210,  213,  214,  212,  229,
- /*  1100 */   228,  231,  236,  223,  200,  243,  201,  251,  248,  250,
- /*  1110 */   254,  253,  232,  258,  261,  270,  264,  263,  262,  268,
- /*  1120 */   276,  278,  285,  295,  318,  279,  300,  303,  301,  305,
- /*  1130 */   333,  346,  298,  323,  327,  356,  357,  362,  370,  302,
- /*  1140 */   371,   53,  374,  394,  399,  354,  331,  375,  401,  409,
- /*  1150 */   308,  347,  315,  324,  406,  317,  405,  328,  795,  390,
- /*  1160 */   389,  392,  397,  410,  421,  800,  360,  381,  365,  393,
- /*  1170 */   398,  352,  376,  403,  801,  377,  400,  425,  426,  424,
- /*  1180 */   427,  429,  771,  432,  772,  435,  440,  698,  443,  794,
- /*  1190 */   445,  438,  809,  449,  699,  450,  453,  448,  454,  456,
- /*  1200 */   811,  458,  461,  462,  463,  469,  812,  814,  476,  630,
- /*  1210 */   478,  632,  779,  821,  490,  477,  690,  492,  494,  496,
- /*  1220 */   498,  693,  500,  505,  696,  509,  781,  511,  782,  783,
- /*  1230 */   466,  784,  785,  502,  512,  786,  520,  822,  519,  530,
- /*  1240 */   524,  824,  523,  825,  525,  528,  533,  828,  518,  518,
- /*  1250 */   518,  518,  518,  518,  522,  518,  526,  518,  518,  532,
+ /*     0 */   263,  261,  261,  154,  124,  126,  128,  130,  132,  134,
+ /*    10 */   136,  138,  140,  142,  350,  567,  145,  641,  261,  369,
+ /*    20 */   144,  114,  116,  112,  118,    7,  124,  126,  128,  130,
+ /*    30 */   132,  134,  136,  138,  140,  142,  136,  138,  140,  142,
+ /*    40 */   110,   94,  146,  157,  162,  167,  156,  161,  120,  122,
+ /*    50 */   114,  116,  112,  118,    9,  124,  126,  128,  130,  132,
+ /*    60 */   134,  136,  138,  140,  142,  574,  223,  262,  262,  124,
+ /*    70 */   126,  128,  130,  132,  134,  136,  138,  140,  142,   13,
+ /*    80 */    96,  145,   13,    2,  262,  144,    4,   78,  371,   92,
+ /*    90 */    10,  373,  380,  385,  132,  134,  136,  138,  140,  142,
+ /*   100 */    75,    3,  562,  388,  296,  110,   94,  146,  157,  162,
+ /*   110 */   167,  156,  161,  120,  122,  114,  116,  112,  118,   77,
+ /*   120 */   124,  126,  128,  130,  132,  134,  136,  138,  140,  142,
+ /*   130 */   145,   65,  573,   13,  144,   11,  371,   66,  292,  373,
+ /*   140 */   380,  385,  870,    1,  563,   14,   15,    4,   14,   15,
+ /*   150 */   172,  388,   51,  665,  110,   94,  146,  157,  162,  167,
+ /*   160 */   156,  161,  120,  122,  114,  116,  112,  118,   72,  124,
+ /*   170 */   126,  128,  130,  132,  134,  136,  138,  140,  142,   51,
+ /*   180 */    37,  341,   40,   59,   67,   69,  305,  336,  107,  106,
+ /*   190 */   108,  847,  572,   34,  338,   96,  366,  349,   13,   14,
+ /*   200 */    15,  371,   12,  145,  373,  380,  385,  144,  564,   40,
+ /*   210 */    59,   67,   69,  305,  336,   75,  388,    3,  562,  190,
+ /*   220 */   345,  338,   44,   45,   95,  460,  802,  110,   94,  146,
+ /*   230 */   157,  162,  167,  156,  161,  120,  122,  114,  116,  112,
+ /*   240 */   118,  575,  124,  126,  128,  130,  132,  134,  136,  138,
+ /*   250 */   140,  142,   20,   48,  800,  364,  362,  101,  102,  367,
+ /*   260 */   499,  295,   49,  596,   14,   15,  191,   32,   33,   27,
+ /*   270 */   148,  403,   96,   50,  147,  534,   46,  145,  494,  466,
+ /*   280 */   456,  144,  580,  279,   36,  340,   47,  399,  309,   81,
+ /*   290 */   368,  401,   75,  335,  398,  505,  176,  501,  150,  151,
+ /*   300 */   197,  110,   94,  146,  157,  162,  167,  156,  161,  120,
+ /*   310 */   122,  114,  116,  112,  118,   77,  124,  126,  128,  130,
+ /*   320 */   132,  134,  136,  138,  140,  142,  149,  280,  258,  169,
+ /*   330 */    96,   39,  281,   13,  298,  367,   96,  175,   22,  335,
+ /*   340 */    28,  145,  188,  402,   33,  144,  217,    6,    5,  171,
+ /*   350 */    75,  173,  174,   25,  176,  581,   75,   57,   58,  507,
+ /*   360 */   235,  351,  356,  357,  265,  110,   94,  146,  157,  162,
+ /*   370 */   167,  156,  161,  120,  122,  114,  116,  112,  118,  503,
+ /*   380 */   124,  126,  128,  130,  132,  134,  136,  138,  140,  142,
+ /*   390 */   457,   77,  243,  294,   48,  227,  236,  293,  297,   14,
+ /*   400 */    15,  288,   96,   49,  217,  152,  222,  163,  168,  278,
+ /*   410 */    24,   13,  687,   13,   50,  145,  518,  201,  152,  144,
+ /*   420 */   163,  168,   75,  358,  582,  171,  176,  173,  174,  263,
+ /*   430 */   171,  261,  173,  174,  354,  356,  357,  588,  211,  110,
+ /*   440 */    94,  146,  157,  162,  167,  156,  161,  120,  122,  114,
+ /*   450 */   116,  112,  118,  654,  124,  126,  128,  130,  132,  134,
+ /*   460 */   136,  138,  140,  142,  303,   13,  688,   96,  250,  817,
+ /*   470 */    96,   16,   17,   18,  246,   81,  216,   14,   15,   14,
+ /*   480 */    15,  145,   13,  406,  435,  144,   13,   75,  487,  387,
+ /*   490 */    75,  493,  248,  258,  235,  660,  358,  262,  310,  852,
+ /*   500 */   171,   26,  173,  174,  253,  110,   94,  146,  157,  162,
+ /*   510 */   167,  156,  161,  120,  122,  114,  116,  112,  118,  397,
+ /*   520 */   124,  126,  128,  130,  132,  134,  136,  138,  140,  142,
+ /*   530 */   229,   14,   15,  489,  250,  152,  252,  163,  168,  171,
+ /*   540 */   839,  173,  174,  360,  361,   96,  145,  533,   14,   15,
+ /*   550 */   144,  866,   14,   15,  801,  442,  312,  275,  255,  453,
+ /*   560 */   850,  338,  251,  535,  536,   75,  662,  247,   13,  493,
+ /*   570 */   110,   94,  146,  157,  162,  167,  156,  161,  120,  122,
+ /*   580 */   114,  116,  112,  118,  845,  124,  126,  128,  130,  132,
+ /*   590 */   134,  136,  138,  140,  142,  726,   96,  171,   96,  173,
+ /*   600 */   174,  171,  252,  173,  174,  152,  583,  163,  168,   42,
+ /*   610 */   720,  525,   96,  145,  441,  271,   75,  144,   75,  170,
+ /*   620 */   302,  640,   91,   31,  358,  313,  320,  322,  251,  432,
+ /*   630 */   434,  433,   75,  844,   14,   15,  176,  110,   94,  146,
+ /*   640 */   157,  162,  167,  156,  161,  120,  122,  114,  116,  112,
+ /*   650 */   118,   77,  124,  126,  128,  130,  132,  134,  136,  138,
+ /*   660 */   140,  142,  171,   96,  173,  174,  331,   52,  171,   96,
+ /*   670 */   173,  174,   96,  195,  213,  207,   29,  348,  145,   54,
+ /*   680 */   310,  318,  144,   75,  455,  342,  217,   93,   83,   75,
+ /*   690 */    30,  452,   75,  109,  587,  286,  111,  171,  265,  173,
+ /*   700 */   174,  319,  110,   94,  146,  157,  162,  167,  156,  161,
+ /*   710 */   120,  122,  114,  116,  112,  118,   77,  124,  126,  128,
+ /*   720 */   130,  132,  134,  136,  138,  140,  142,  244,   96,  187,
+ /*   730 */    96,   96,  810,  331,  214,  266,  215,   35,  312,   96,
+ /*   740 */    96,  479,  328,  145,  623,   38,  327,  144,   75,  455,
+ /*   750 */    75,   75,  113,  689,  115,  117,  315,  461,  426,   75,
+ /*   760 */    75,   77,  463,  119,  121,  407,  325,  110,  165,  146,
+ /*   770 */   157,  162,  167,  156,  161,  120,  122,  114,  116,  112,
+ /*   780 */   118,   77,  124,  126,  128,  130,  132,  134,  136,  138,
+ /*   790 */   140,  142,   42,   96,   96,   96,   96,  824,  273,  159,
+ /*   800 */   415,   96,  410,  272,   96,  273,  479,   41,  145,  332,
+ /*   810 */   537,   43,  144,   75,   75,   75,   75,  123,  125,  127,
+ /*   820 */   129,   75,  465,   64,   75,  131,   53,  463,  133,  158,
+ /*   830 */   317,  316,  265,   94,  146,  157,  162,  167,  156,  161,
+ /*   840 */   120,  122,  114,  116,  112,  118,  219,  124,  126,  128,
+ /*   850 */   130,  132,  134,  136,  138,  140,  142,   96,  689,   96,
+ /*   860 */    96,  532,   96,  331,  299,   96,  215,   96,   96,  283,
+ /*   870 */    96,  261,  219,   96,  145,   96,  840,   75,  144,   75,
+ /*   880 */    75,  135,   75,  137,  139,   75,  141,   75,   75,  143,
+ /*   890 */    75,  153,  155,   75,  164,   75,  376,  166,   56,  178,
+ /*   900 */   146,  157,  162,  167,  156,  161,  120,  122,  114,  116,
+ /*   910 */   112,  118,  652,  124,  126,  128,  130,  132,  134,  136,
+ /*   920 */   138,  140,  142,   76,   96,   96,   96,   71,  438,  364,
+ /*   930 */   362,  437,   96,   96,   96,   96,  331,  262,  233,  332,
+ /*   940 */    96,   55,  331,  439,   75,   75,   75,  331,  180,  182,
+ /*   950 */   184,  199,   75,   75,   75,   75,  196,  198,  208,  210,
+ /*   960 */    75,  107,  106,  108,  212,  720,  326,  177,  327,  382,
+ /*   970 */   430,  431,  107,  106,  108,  391,  548,   61,   96,   96,
+ /*   980 */   449,  471,  458,   45,  183,  181,  300,   96,  476,  352,
+ /*   990 */    96,  353,  179,   73,   74,  343,  346,   95,   75,   75,
+ /*  1000 */   290,   96,  224,  240,  345,  275,   42,   75,   95,   76,
+ /*  1010 */    75,  245,  332,   71,  277,  383,  275,  327,  332,   96,
+ /*  1020 */    75,   75,  404,  332,  287,  386,   96,  392,  421,  327,
+ /*  1030 */   101,  102,  103,  104,  105,  185,  189,  199,   96,   75,
+ /*  1040 */    96,  101,  102,  427,  414,   60,   75,  107,  106,  108,
+ /*  1050 */   474,  470,  486,  177,   77,  450,  421,  327,   75,  484,
+ /*  1060 */    75,  273,  478,  436,  491,  492,  423,  490,  421,  421,
+ /*  1070 */   183,  181,  421,  421,  483,  421,   77,  421,  179,   73,
+ /*  1080 */    74,  476,  244,   95,   77,   81,  526,  860,  490,  421,
+ /*  1090 */   689,  522,   62,   64,  500,   70,  597,   63,  523,   68,
+ /*  1100 */   598,   76,   81,   79,   81,   71,  502,  504,   84,   80,
+ /*  1110 */   506,  510,  244,  514,  239,  520,  101,  102,  103,  104,
+ /*  1120 */   105,  185,  189,   77,  546,  241,   82,  558,   86,  199,
+ /*  1130 */    85,  225,   90,   87,   97,   88,   99,  142,   89,  107,
+ /*  1140 */   106,  108,  160,   98,  516,  177,  100,  218,  666,  667,
+ /*  1150 */   668,  186,  209,  193,  192,  194,  200,  204,  203,  202,
+ /*  1160 */   206,  205,  183,  181,  219,  220,  221,  226,  228,  232,
+ /*  1170 */   179,   73,   74,  230,  233,   95,  234,  231,  237,  242,
+ /*  1180 */   238,  215,  260,  249,  257,  276,  267,  254,  256,  259,
+ /*  1190 */   264,  269,  270,   76,  274,  282,  301,   71,  219,  268,
+ /*  1200 */   285,  291,  284,  306,  324,  307,  311,  308,  101,  102,
+ /*  1210 */   103,  104,  105,  185,  189,  803,  355,  329,  375,  304,
+ /*  1220 */   314,  199,  321,  337,  330,  365,  334,  372,  309,  333,
+ /*  1230 */   323,  107,  106,  108,  344,  339,  347,  177,  374,  378,
+ /*  1240 */   400,  359,  370,  377,  381,  379,  384,  389,  363,  390,
+ /*  1250 */   393,  394,  396,   54,  183,  181,  289,  408,  395,  409,
+ /*  1260 */   411,  413,  179,   73,   74,  412,  416,   95,  417,  420,
+ /*  1270 */   428,  422,  832,  429,  443,  440,  444,  837,  838,   76,
+ /*  1280 */   446,  445,  448,   71,  451,  808,  809,  459,  454,  447,
+ /*  1290 */   418,  727,  728,  831,  464,  462,  846,  457,  469,  419,
+ /*  1300 */   101,  102,  103,  104,  105,  185,  189,  199,  467,  468,
+ /*  1310 */   472,  473,  475,  424,  848,  477,  480,  107,  106,  108,
+ /*  1320 */   425,  482,  488,  177,  485,  849,  481,  495,  496,  851,
+ /*  1330 */   659,  661,  816,  858,  497,  509,  511,  719,  513,  515,
+ /*  1340 */   183,  181,  722,  517,  725,  519,  521,  524,  179,   73,
+ /*  1350 */    74,  818,  528,   95,  530,  819,  820,  531,  538,  821,
+ /*  1360 */     8,  822,  539,  823,  549,   19,   21,   23,  405,  541,
+ /*  1370 */   542,  544,  543,  859,  547,  861,  862,  865,  545,  540,
+ /*  1380 */   551,  867,  557,  555,  552,  550,  101,  102,  103,  104,
+ /*  1390 */   105,  185,  189,  554,  560,  559,  561,  868,  529,  545,
+ /*  1400 */   460,  545,  545,  545,  545,  527,  545,  553,  545,  545,
+ /*  1410 */   545,  545,  556,  545,  545,  545,  545,  545,  545,  545,
+ /*  1420 */   545,  545,  545,  545,  545,  545,  545,  545,  545,  545,
+ /*  1430 */   545,  545,  545,  545,  545,  545,  545,  545,  545,  545,
+ /*  1440 */   545,  545,  545,  545,  545,  545,  545,  545,  545,  545,
+ /*  1450 */   545,  545,  545,  508,  512,  456,  545,  545,  545,  498,
+ /*  1460 */   545,  545,  545,  545,   81,
 };
 static const YYCODETYPE yy_lookahead[] = {
- /*     0 */    24,  139,   26,   72,   73,   74,   75,   76,   77,   78,
- /*    10 */    79,   80,   81,  154,  155,  156,   40,   26,  135,  136,
- /*    20 */    44,    0,  158,  140,  131,  132,  133,  134,  164,  146,
- /*    30 */     9,   10,  170,   60,   58,   59,   60,   61,   62,   63,
+ /*     0 */    24,   26,   26,   78,   79,   80,   81,   82,   83,   84,
+ /*    10 */    85,   86,   87,   88,   22,    9,   40,   23,   26,   25,
+ /*    20 */    44,   74,   75,   76,   77,    9,   79,   80,   81,   82,
+ /*    30 */    83,   84,   85,   86,   87,   88,   85,   86,   87,   88,
  /*    40 */    64,   65,   66,   67,   68,   69,   70,   71,   72,   73,
- /*    50 */    74,   75,   76,   77,   78,   79,   80,   81,   22,  176,
- /*    60 */    24,   85,   89,   90,   91,   92,   93,   94,   23,   23,
- /*    70 */    25,   25,  213,  100,  212,   40,   85,   86,   87,   44,
- /*    80 */     9,   90,   91,   92,  201,   76,   77,   78,   79,   80,
- /*    90 */    81,   26,  101,   58,   59,   60,   61,   62,   63,   64,
- /*   100 */    65,   66,   67,   68,   69,   70,   71,   72,   73,   74,
- /*   110 */    75,   76,   77,   78,   79,   80,   81,   68,   69,   70,
- /*   120 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
- /*   130 */    81,   23,   87,   25,   29,   90,   91,   92,  179,   26,
- /*   140 */    35,   76,   77,   23,   40,  186,  101,  139,   44,   22,
- /*   150 */    85,   86,  144,   26,    9,  147,  148,   12,  159,  146,
- /*   160 */    95,  126,   58,   59,   60,   61,   62,   63,   64,   65,
- /*   170 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75,
- /*   180 */    76,   77,   78,   79,   80,   81,   17,  139,   18,  176,
- /*   190 */    23,   17,   25,  139,   86,  147,  148,   27,   85,   86,
- /*   200 */   146,  188,  189,  204,  205,  206,  193,   45,   38,  137,
- /*   210 */    26,   41,   85,   86,   40,  161,  168,  169,   44,  111,
- /*   220 */    51,   51,   60,  103,  111,  105,  106,   13,   14,   15,
- /*   230 */   176,  127,   58,   59,   60,   61,   62,   63,   64,   65,
- /*   240 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75,
- /*   250 */    76,   77,   78,   79,   80,   81,    9,   95,   58,   40,
- /*   260 */    76,   77,  100,   44,   22,   96,   97,   98,   26,   85,
- /*   270 */   104,   26,   45,   89,  108,   60,  107,   58,   59,   60,
- /*   280 */    61,   62,   63,   64,   65,   66,   67,   68,   69,   70,
- /*   290 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
- /*   300 */    81,    9,   87,   88,   89,   90,   91,   92,   93,   94,
- /*   310 */   157,  158,   23,    9,  139,  100,  139,  164,   26,  119,
- /*   320 */    87,   23,   95,   90,   91,   92,   21,   85,   86,   40,
- /*   330 */    85,   86,  104,   44,  101,  107,  161,  152,  161,   17,
- /*   340 */   154,  155,  156,  154,  155,  156,  127,   58,   59,   60,
- /*   350 */    61,   62,   63,   64,   65,   66,   67,   68,   69,   70,
- /*   360 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
- /*   370 */    81,   23,  187,  139,  199,   89,  199,   85,   86,   78,
- /*   380 */    79,   80,   81,  139,   26,  210,  100,  210,   40,  204,
- /*   390 */   205,  206,   44,  164,  165,  161,   91,   23,   22,  213,
- /*   400 */   171,  103,  213,  105,  106,  161,   58,   59,   60,   61,
- /*   410 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71,
- /*   420 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81,
- /*   430 */   196,  197,    9,   40,  129,   26,   78,   44,    9,    9,
- /*   440 */    10,  197,    9,   85,   86,  204,  205,  206,  126,   11,
- /*   450 */   128,   58,   59,   60,   61,   62,   63,   64,   65,   66,
- /*   460 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   76,
- /*   470 */    77,   78,   79,   80,   81,  133,  134,  103,   40,  105,
- /*   480 */   106,    9,   44,  173,  174,  109,  149,    9,   95,  152,
- /*   490 */   153,   96,   97,   98,   85,   86,   58,   59,   60,   61,
- /*   500 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71,
- /*   510 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81,
- /*   520 */   111,  152,    9,   40,  155,  156,  103,   44,  105,  106,
- /*   530 */    13,   14,  103,  139,  105,  106,  103,   47,  105,  106,
- /*   540 */   139,   58,   59,   60,   61,   62,   63,   64,   65,   66,
- /*   550 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   76,
- /*   560 */    77,   78,   79,   80,   81,  154,  155,  156,   40,  154,
- /*   570 */   155,  156,   44,   76,   77,  103,  175,  105,  106,   25,
- /*   580 */   138,  103,  213,  105,  106,   95,   58,   59,   60,   61,
- /*   590 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71,
- /*   600 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81,
- /*   610 */     9,   22,   24,   40,   26,   26,  103,   44,  105,  106,
- /*   620 */   121,  122,   20,   22,  213,   96,   97,   98,  213,    9,
- /*   630 */   139,   60,   59,   60,   61,   62,   63,   64,   65,   66,
+ /*    50 */    74,   75,   76,   77,  148,   79,   80,   81,   82,   83,
+ /*    60 */    84,   85,   86,   87,   88,    9,   25,   92,   92,   79,
+ /*    70 */    80,   81,   82,   83,   84,   85,   86,   87,   88,   26,
+ /*    80 */   150,   40,   26,  144,   92,   44,  147,  157,   94,   48,
+ /*    90 */   149,   97,   98,   99,   83,   84,   85,   86,   87,   88,
+ /*   100 */   170,    9,   10,  109,  174,   64,   65,   66,   67,   68,
+ /*   110 */    69,   70,   71,   72,   73,   74,   75,   76,   77,  189,
+ /*   120 */    79,   80,   81,   82,   83,   84,   85,   86,   87,   88,
+ /*   130 */    40,   29,    9,   26,   44,   12,   94,   35,   85,   97,
+ /*   140 */    98,   99,  142,  143,  144,   92,   93,  147,   92,   93,
+ /*   150 */   112,  109,   66,  115,   64,   65,   66,   67,   68,   69,
+ /*   160 */    70,   71,   72,   73,   74,   75,   76,   77,   22,   79,
+ /*   170 */    80,   81,   82,   83,   84,   85,   86,   87,   88,   66,
+ /*   180 */    94,   95,   96,   97,   98,   99,  100,  101,   60,   61,
+ /*   190 */    62,   17,    9,  160,  108,  150,  163,  164,   26,   92,
+ /*   200 */    93,   94,  150,   40,   97,   98,   99,   44,    0,   96,
+ /*   210 */    97,   98,   99,  100,  101,  170,  109,    9,   10,  174,
+ /*   220 */    92,  108,  186,  187,   96,   51,  136,   64,   65,   66,
+ /*   230 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   76,
+ /*   240 */    77,    9,   79,   80,   81,   82,   83,   84,   85,   86,
+ /*   250 */    87,   88,  149,   18,   17,   83,   84,  129,  130,  150,
+ /*   260 */    20,   23,   27,  117,   92,   93,  221,  158,  159,   22,
+ /*   270 */    40,   24,  150,   38,   44,  103,   41,   40,  104,  105,
+ /*   280 */   106,   44,    9,  157,  168,  169,   51,  177,  178,  115,
+ /*   290 */   181,  182,  170,  177,  184,   55,  174,   57,   68,   69,
+ /*   300 */   137,   64,   65,   66,   67,   68,   69,   70,   71,   72,
+ /*   310 */    73,   74,   75,   76,   77,  189,   79,   80,   81,   82,
+ /*   320 */    83,   84,   85,   86,   87,   88,   96,  201,  202,   22,
+ /*   330 */   150,  169,  206,   26,  212,  150,  150,   23,  149,  177,
+ /*   340 */   155,   40,   23,  158,  159,   44,  224,  145,  146,  111,
+ /*   350 */   170,  113,  114,  151,  174,    9,  170,   13,   14,  157,
+ /*   360 */   174,  165,  166,  167,  163,   64,   65,   66,   67,   68,
+ /*   370 */    69,   70,   71,   72,   73,   74,   75,   76,   77,  139,
+ /*   380 */    79,   80,   81,   82,   83,   84,   85,   86,   87,   88,
+ /*   390 */    64,  189,  212,  112,   18,  209,  210,  116,   23,   92,
+ /*   400 */    93,  200,  150,   27,  224,  217,  218,  219,  220,   22,
+ /*   410 */   149,   26,   23,   26,   38,   40,  214,   41,  217,   44,
+ /*   420 */   219,  220,  170,  227,    9,  111,  174,  113,  114,   24,
+ /*   430 */   111,   26,  113,  114,  165,  166,  167,    9,  137,   64,
+ /*   440 */    65,   66,   67,   68,   69,   70,   71,   72,   73,   74,
+ /*   450 */    75,   76,   77,  127,   79,   80,   81,   82,   83,   84,
+ /*   460 */    85,   86,   87,   88,   23,   26,   23,  150,   25,    9,
+ /*   470 */   150,   13,   14,   15,   25,  115,  224,   92,   93,   92,
+ /*   480 */    93,   40,   26,  153,   47,   44,   26,  170,  128,  171,
+ /*   490 */   170,  174,  201,  202,  174,    9,  227,   92,   45,    9,
+ /*   500 */   111,  152,  113,  114,  119,   64,   65,   66,   67,   68,
+ /*   510 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   66,
+ /*   520 */    79,   80,   81,   82,   83,   84,   85,   86,   87,   88,
+ /*   530 */   210,   92,   93,  216,   25,  217,   93,  219,  220,  111,
+ /*   540 */   103,  113,  114,  129,  130,  150,   40,  150,   92,   93,
+ /*   550 */    44,    9,   92,   93,   17,  225,  103,  150,  119,  229,
+ /*   560 */     9,  108,  119,  166,  167,  170,    9,  118,   26,  174,
+ /*   570 */    64,   65,   66,   67,   68,   69,   70,   71,   72,   73,
+ /*   580 */    74,   75,   76,   77,   11,   79,   80,   81,   82,   83,
+ /*   590 */    84,   85,   86,   87,   88,    9,  150,  111,  150,  113,
+ /*   600 */   114,  111,   93,  113,  114,  217,    9,  219,  220,  103,
+ /*   610 */     9,  216,  150,   40,   21,  208,  170,   44,  170,  157,
+ /*   620 */   174,   23,  174,   25,  227,  104,  105,  106,  119,  104,
+ /*   630 */   105,  106,  170,   11,   92,   93,  174,   64,   65,   66,
  /*   640 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   76,
- /*   650 */    77,   78,   79,   80,   81,   26,  141,   55,   40,   57,
- /*   660 */    89,  170,   44,  138,  110,  188,  189,   23,   67,   25,
- /*   670 */   152,    9,   22,   85,   85,  139,   26,   25,   60,   61,
- /*   680 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71,
- /*   690 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81,
- /*   700 */    50,   26,   22,  212,    9,  187,   26,   25,  139,   18,
- /*   710 */    60,  175,   20,  146,   85,  139,  152,  138,   27,   40,
- /*   720 */   146,   26,  139,   44,  155,  156,   76,   77,   78,   38,
- /*   730 */    50,  129,   41,   32,   84,   85,   86,  142,   86,   89,
- /*   740 */    60,   62,   63,  176,  161,  139,  170,   55,  139,   57,
- /*   750 */   176,  187,  123,   52,  146,  146,   76,   77,   22,  146,
- /*   760 */    85,    9,   26,  111,   84,   85,   86,  161,   89,   89,
- /*   770 */   161,  121,  122,  123,  124,  125,  139,   95,    9,   22,
- /*   780 */    85,   86,  213,   26,  176,  176,   50,  107,  212,  176,
- /*   790 */   207,   11,   25,  146,   25,   23,   60,   25,  161,  139,
- /*   800 */    99,  121,  122,  123,  124,  125,  211,   50,  199,  201,
- /*   810 */   215,   28,   76,   77,   31,   48,  210,   60,  107,  210,
- /*   820 */    84,   85,   86,  176,  216,   89,   43,  139,  139,  221,
- /*   830 */   170,  120,  139,   76,   77,   78,  139,   88,   89,  139,
- /*   840 */   203,   84,   85,   86,  139,   11,   89,   95,  201,  161,
- /*   850 */    16,   17,   18,   19,  161,  139,  139,  121,  122,  123,
- /*   860 */   124,  125,  126,  216,   30,    9,  161,  170,  221,  138,
- /*   870 */    36,  139,  212,  139,  139,  175,  139,  161,  121,  122,
- /*   880 */   123,  124,  125,   49,   22,   51,  139,  118,   26,  139,
- /*   890 */    56,  203,  139,  161,  139,  161,  161,  139,  161,   53,
- /*   900 */    54,  212,  139,  139,  139,  139,  126,  139,  161,  212,
- /*   910 */    24,  161,   50,  139,  161,  139,  161,  200,  139,  161,
- /*   920 */   139,  139,   60,  139,  161,  161,  161,  161,  139,  161,
- /*   930 */    96,   97,   98,  139,  139,  161,  102,  161,   76,   77,
- /*   940 */   161,  107,  161,  161,  139,  161,   84,   85,   86,  139,
- /*   950 */   161,   89,  139,  139,  139,  161,  161,  139,    9,  139,
- /*   960 */   139,   23,   23,   25,   25,  139,  161,  139,   23,  139,
- /*   970 */    25,  161,  139,    9,  161,  161,  161,  139,   23,  161,
- /*   980 */    25,  161,   95,  121,  122,  123,  124,  125,   23,  161,
- /*   990 */    25,  161,  139,  139,  161,  109,  109,  139,   23,  161,
- /*  1000 */    25,  146,  173,  174,   23,   23,   25,   25,  139,  107,
- /*  1010 */   139,  139,  139,  139,  161,  161,  195,  139,  139,  139,
- /*  1020 */     9,  195,  120,   23,    9,   25,  145,   23,    9,  139,
- /*  1030 */   161,  176,  150,   42,  159,   95,   33,  167,   46,   22,
- /*  1040 */   109,  109,  159,  177,  160,  178,  175,  175,  175,  175,
- /*  1050 */   159,  159,  176,  195,  175,  175,  113,   46,  107,  118,
- /*  1060 */   116,  115,  185,  214,  117,  180,  214,  118,  114,  181,
- /*  1070 */    25,  182,   94,  160,   26,  151,  183,  109,  200,  184,
- /*  1080 */   109,  139,   81,   89,  107,  126,  107,  139,   17,  139,
- /*  1090 */   107,   22,  198,  174,  109,   23,  139,   23,   25,  143,
- /*  1100 */   139,  198,  114,   25,  208,  190,  209,  111,  139,  139,
- /*  1110 */   143,  139,  160,  139,  191,   95,   22,  112,  192,  139,
- /*  1120 */    23,  191,  109,   23,   22,  192,  139,  165,  162,  139,
- /*  1130 */   167,   23,  159,  198,  198,   46,   22,   22,   46,  163,
- /*  1140 */    22,  100,   93,   24,  217,  139,  151,  139,   95,   39,
- /*  1150 */   166,  152,  166,  160,  220,  166,  219,  160,   11,  143,
- /*  1160 */   139,  139,  139,   37,   47,   95,  159,  169,  159,  143,
- /*  1170 */   143,  169,  162,  143,   95,  163,  218,  139,  143,  129,
- /*  1180 */    95,   22,    9,  159,  129,   11,  172,  119,   17,    9,
- /*  1190 */     9,   58,   17,  139,  119,   99,  139,  172,   67,  181,
- /*  1200 */     9,   67,  119,  139,   22,   22,    9,    9,  110,    9,
- /*  1210 */   181,    9,    9,    9,  110,  139,    9,  181,  172,   99,
- /*  1220 */   181,    9,  119,   22,    9,  139,    9,  139,    9,    9,
- /*  1230 */   202,    9,    9,  202,  143,    9,   23,    9,  139,   34,
- /*  1240 */    24,    9,  152,    9,  139,  152,  139,    9,  224,  224,
- /*  1250 */   224,  224,  224,  224,  222,  224,  223,  224,  224,  222,
+ /*   650 */    77,  189,   79,   80,   81,   82,   83,   84,   85,   86,
+ /*   660 */    87,   88,  111,  150,  113,  114,  150,   96,  111,  150,
+ /*   670 */   113,  114,  150,  136,  212,  138,  156,  162,   40,  108,
+ /*   680 */    45,   32,   44,  170,  157,  170,  224,  174,  192,  170,
+ /*   690 */    23,   98,  170,  174,    9,  199,  174,  111,  163,  113,
+ /*   700 */   114,   52,   64,   65,   66,   67,   68,   69,   70,   71,
+ /*   710 */    72,   73,   74,   75,   76,   77,  189,   79,   80,   81,
+ /*   720 */    82,   83,   84,   85,   86,   87,   88,  126,  150,  157,
+ /*   730 */   150,  150,  139,  150,   23,  200,   25,  161,  103,  150,
+ /*   740 */   150,  214,  226,   40,   23,  150,   25,   44,  170,  157,
+ /*   750 */   170,  170,  174,   24,  174,  174,  107,  230,  136,  170,
+ /*   760 */   170,  189,  235,  174,  174,   20,  183,   64,   65,   66,
+ /*   770 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   76,
+ /*   780 */    77,  189,   79,   80,   81,   82,   83,   84,   85,   86,
+ /*   790 */    87,   88,  103,  150,  150,  150,  150,    9,   25,   66,
+ /*   800 */    55,  150,   57,   23,  150,   25,  214,  171,   40,  226,
+ /*   810 */    22,   33,   44,  170,  170,  170,  170,  174,  174,  174,
+ /*   820 */   174,  170,  230,  102,  170,  174,  171,  235,  174,   96,
+ /*   830 */    95,   96,  163,   65,   66,   67,   68,   69,   70,   71,
+ /*   840 */    72,   73,   74,   75,   76,   77,  117,   79,   80,   81,
+ /*   850 */    82,   83,   84,   85,   86,   87,   88,  150,  103,  150,
+ /*   860 */   150,   73,  150,  150,   23,  150,   25,  150,  150,  200,
+ /*   870 */   150,   26,  117,  150,   40,  150,  103,  170,   44,  170,
+ /*   880 */   170,  174,  170,  174,  174,  170,  174,  170,  170,  174,
+ /*   890 */   170,  174,  174,  170,  174,  170,  183,  174,   42,  174,
+ /*   900 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75,
+ /*   910 */    76,   77,    9,   79,   80,   81,   82,   83,   84,   85,
+ /*   920 */    86,   87,   88,   22,  150,  150,  150,   26,   28,   83,
+ /*   930 */    84,   31,  150,  150,  150,  150,  150,   92,   26,  226,
+ /*   940 */   150,  180,  150,   43,  170,  170,  170,  150,  174,  174,
+ /*   950 */   174,   50,  170,  170,  170,  170,  174,  174,  174,  174,
+ /*   960 */   170,   60,   61,   62,  174,    9,   23,   66,   25,  183,
+ /*   970 */    53,   54,   60,   61,   62,  183,  131,  172,  150,  150,
+ /*   980 */   183,   25,  186,  187,   83,   84,   85,  150,  150,   23,
+ /*   990 */   150,   25,   91,   92,   93,   83,   84,   96,  170,  170,
+ /*  1000 */   150,  150,  174,  174,   92,  150,  103,  170,   96,   22,
+ /*  1010 */   170,  174,  226,   26,  174,   23,  150,   25,  226,  150,
+ /*  1020 */   170,  170,  157,  226,  174,  174,  150,   23,  150,   25,
+ /*  1030 */   129,  130,  131,  132,  133,  134,  135,   50,  150,  170,
+ /*  1040 */   150,  129,  130,  174,  157,   46,  170,   60,   61,   62,
+ /*  1050 */   174,  213,  157,   66,  189,   23,  150,   25,  170,   23,
+ /*  1060 */   170,   25,  174,  208,  174,   23,  188,   25,  150,  150,
+ /*  1070 */    83,   84,  150,  150,  208,  150,  189,  150,   91,   92,
+ /*  1080 */    93,  150,  126,   96,  189,  115,   23,    9,   25,  150,
+ /*  1090 */     9,  157,  171,  102,  188,   22,  117,  173,  128,  171,
+ /*  1100 */   117,   22,  115,  190,  115,   26,  188,  188,  193,  189,
+ /*  1110 */   188,  188,  126,  188,  124,  188,  129,  130,  131,  132,
+ /*  1120 */   133,  134,  135,  189,   46,  123,  191,  188,  195,   50,
+ /*  1130 */   194,  121,  125,  196,  117,  197,  117,   88,  198,   60,
+ /*  1140 */    61,   62,   96,  150,  213,   66,  150,  150,  115,  115,
+ /*  1150 */   115,   22,  136,  223,  222,   17,   22,   25,  187,   23,
+ /*  1160 */    23,  150,   83,   84,  117,  150,  154,  122,   25,  101,
+ /*  1170 */    91,   92,   93,  211,   26,   96,  162,  172,  211,  122,
+ /*  1180 */   172,   25,  154,  203,  119,  103,  204,  150,  150,  150,
+ /*  1190 */   150,  120,   22,   22,  150,   23,   23,   26,  117,  205,
+ /*  1200 */   205,  117,  204,  150,   22,  175,  150,  176,  129,  130,
+ /*  1210 */   131,  132,  133,  134,  135,  136,   23,  211,   22,  171,
+ /*  1220 */   179,   50,  179,  162,  172,  163,  172,  150,  178,  211,
+ /*  1230 */   179,   60,   61,   62,  170,  180,  170,   66,   46,   23,
+ /*  1240 */   182,  228,  182,  173,   22,  171,  171,   46,  228,   22,
+ /*  1250 */   100,  150,  176,  108,   83,   84,   85,  150,  175,  154,
+ /*  1260 */   150,   24,   91,   92,   93,  154,  150,   96,  154,  103,
+ /*  1270 */    39,  154,   11,   37,  139,   47,  150,  103,  103,   22,
+ /*  1280 */   103,  154,   22,   26,  171,    9,  139,  185,   11,  150,
+ /*  1290 */   231,  127,  127,    9,    9,   17,   17,   64,  107,  232,
+ /*  1300 */   129,  130,  131,  132,  133,  134,  135,   50,  185,  150,
+ /*  1310 */   150,   73,  194,  233,    9,   73,  127,   60,   61,   62,
+ /*  1320 */   234,   22,   22,   66,  215,    9,  150,  118,  150,    9,
+ /*  1330 */     9,    9,    9,    9,  194,  118,  194,    9,  185,  107,
+ /*  1340 */    83,   84,    9,  194,    9,  127,  215,   22,   91,   92,
+ /*  1350 */    93,    9,  150,   96,  150,    9,    9,  154,  150,    9,
+ /*  1360 */    11,    9,   23,    9,   34,   16,   17,   18,   19,  236,
+ /*  1370 */   163,  150,   24,    9,  163,    9,    9,    9,  237,   30,
+ /*  1380 */   236,    9,   20,  154,  150,   36,  129,  130,  131,  132,
+ /*  1390 */   133,  134,  135,  150,  140,   59,  150,    9,   49,  238,
+ /*  1400 */    51,  238,  238,  238,  238,   56,  238,   58,  238,  238,
+ /*  1410 */   238,  238,   63,  238,  238,  238,  238,  238,  238,  238,
+ /*  1420 */   238,  238,  238,  238,  238,  238,  238,  238,  238,  238,
+ /*  1430 */   238,  238,  238,  238,  238,  238,  238,  238,  238,  238,
+ /*  1440 */   238,  238,  238,  238,  238,  238,  238,  238,  238,  238,
+ /*  1450 */   238,  238,  238,  104,  105,  106,  238,  238,  238,  110,
+ /*  1460 */   238,  238,  238,  238,  115,
 };
-#define YY_SHIFT_USE_DFLT (-70)
+#define YY_SHIFT_USE_DFLT (-76)
 static const short yy_shift_ofst[] = {
- /*     0 */   430,   21,  -70,  834,   71,  -70,  247,  214,  145,  304,
- /*    10 */   292,  620,  -70,  -70,  -70,  -70,  -70,  -70,  145,  662,
- /*    20 */   145,  856,  145,  964,   36, 1015,  245,   46, 1004, 1019,
- /*    30 */    -9,  -70,  675,  -70,  215,  -70,  245,  -27,  -70,  940,
- /*    40 */   -70, 1003,  170,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
- /*    50 */   286,  940,  -70,  991,  -70,  517,  -70,  -70,  992,  105,
- /*    60 */   940,  -70,  -70,  -70,  940,  -70, 1017,  862,  376,  650,
- /*    70 */   931,  932,  680,  -70,  120,  951,  -70,  166,  -70,  554,
- /*    80 */   941,  946,  944,  943,  947,  -70,  497,  -70,  -70,  767,
- /*    90 */   497,  -70,  499,  -70,  -70,  -70,  499,  -70,  -70,  497,
- /*   100 */   -70,  954,  862, 1045,  862,  978,  105,  -70, 1048,  -70,
- /*   110 */   -70,  483,  862,  -70,  968,  245,  971,  245,  -70,  -70,
- /*   120 */   -70,  -70,  -70,  618,  862,  573,  862,  -69,  862,  -69,
- /*   130 */   862,  -69,  862,  -69,  862,   49,  862,   49,  862,    9,
- /*   140 */   862,    9,  862,    9,  862,    9,  862,  301,  862,  301,
- /*   150 */   862, 1001,  862, 1001,  862, 1001,  862,  -70,  -70,  -70,
- /*   160 */   679,  -70,  -70,  -70,  -70,  -70,  862,   49,  -70,  571,
- /*   170 */   -70,  994,  -70,  -70,  -70,  862,  528,  862,   49,  -70,
- /*   180 */   127,  680,  298,  228,  977,  979,  983,  -70,  483,  862,
- /*   190 */   618,  862,  -70,  862,  -70,  862,  -70,  736,   35,  959,
- /*   200 */   322, 1071,  -70,  862,  104,  862,  483, 1069,  691, 1072,
- /*   210 */   -70, 1073,  245, 1074,  -70,  862,  174,  862,  219,  862,
- /*   220 */   483,  167,  -70,  862,  -70,  -70,  985,  245,  -70,  -70,
- /*   230 */   978,  105,  -70,  862,  483,  988,  862, 1078,  862,  483,
- /*   240 */   -70,  -70,  652,  -70,  -70,  -70,  113,  -70,  409,  -70,
- /*   250 */   996,  -70,  242,  985,  588,  -70,  -70,  245,  -70,  -70,
- /*   260 */  1020, 1005,  -70, 1094,  245,  644,  -70,  245,  -70,  -70,
- /*   270 */   862,  483,  951,  374,  108, 1097,  588, 1020, 1005,  -70,
- /*   280 */   757,  -24,  -70,  -70, 1013,  358,  -70,  -70,  -70,  -70,
- /*   290 */   289,  -70,  772,  -70, 1100,  -70,  348,  940,  -70,  245,
- /*   300 */  1102,  -70,  227,  -70,  245,  -70,  529,  701,  -70,  749,
- /*   310 */   -70,  -70,  -70,  -70,  701,  -70,  701,  -70,  245,  938,
- /*   320 */   -70,  245,  978,  105,  -70,  -70,  978,  105,  -70,  -70,
- /*   330 */  1048,  -70,  991,  -70,  -70,  184,  -70,  -70,  -70,  -70,
- /*   340 */   589,  497,  939,  -70,  497, 1108,  -70,  -70,  -70,  -70,
- /*   350 */    45,  233,  -70,  245,  -70, 1089, 1114,  245,  945,  940,
- /*   360 */   -70, 1115,  245,  955,  940,  -70,  862,  393,  -70, 1092,
- /*   370 */  1118,  245,  965, 1049,  245, 1102,  -70,  162, 1041,  -70,
- /*   380 */   -70,  -70,  -70,  -70,  951,  423,  305,  692,  245,  985,
- /*   390 */   -70,  245,  886, 1119,  951,  429,  245,  985,  783,  395,
- /*   400 */  1053,  245,  985,  -70, 1110,  780, 1147,  862,  438, 1126,
- /*   410 */   846,  -70,  -70, 1070, 1079,  490,  245,  682,  -70,  -70,
- /*   420 */  1117,  -70,  -70, 1050,  245,  887, 1085,  245, 1159,  245,
- /*   430 */   975,  752, 1173, 1055, 1174,  169,  433,  200,  170,  -70,
- /*   440 */  1068, 1075, 1171, 1180, 1181,  169, 1175, 1133,  245, 1096,
- /*   450 */   245,  769,  245, 1131,  862,  483, 1191, 1134,  862,  483,
- /*   460 */  1083,  245, 1182,  245,  981,  -70,  711,  472, 1183,  862,
- /*   470 */   982,  862,  483, 1197,  483, 1098,  245,  949, 1198,  602,
- /*   480 */   245, 1200,  245, 1202,  245, 1203,  245, 1204,  478, 1104,
- /*   490 */   245,  949, 1207, 1133,  245, 1120,  245,  769, 1212, 1103,
- /*   500 */   245, 1182,  902,  513, 1201,  862, 1000, 1215,  695, 1217,
- /*   510 */   245,  985,  601,   65, 1219, 1220, 1222, 1223,  245, 1213,
- /*   520 */  1226, 1205,  675, 1216,  245, 1011, 1228,  629, 1232, 1234,
- /*   530 */   -70, 1205,  245, 1238,  -70,  -70,  -70,
+ /*     0 */    92,  208,  -76,  -76, 1349,    6,   16,  -76,  458,  123,
+ /*    10 */   183,   56,  232,  -76,  -76,  -76,  -76,  -76,  -76,  123,
+ /*    20 */   273,  123,  346,  123,  415,  247,  597,  456,  598,  667,
+ /*    30 */   685,  107,  -76,  -25,  -76,   86,  -76,  456,  113,  -76,
+ /*    40 */   689,  -76,  778,  235,  -76,  -76,  -76,  -76,  -76,  -76,
+ /*    50 */   -76,  571,  689,  -76,  856,  -76,  344,  -76,  -76,  999,
+ /*    60 */   102,  689,  991,  -76,  -76,  -76,  -76,  689,  -76, 1073,
+ /*    70 */  1257,  146,  901,  979,  983,  -76,  987,  -76,  238,  989,
+ /*    80 */   -76,  281,  -76,  449,  986, 1002,  990, 1010, 1007,  -76,
+ /*    90 */  1257,   41, 1257,  638, 1257,  -76, 1017,  456, 1019,  456,
+ /*   100 */   -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  834,
+ /*   110 */  1257,  768, 1257,  -10, 1257,  -10, 1257,  -10, 1257,  -10,
+ /*   120 */  1257,  -53, 1257,  -53, 1257,   11, 1257,   11, 1257,   11,
+ /*   130 */  1257,   11, 1257,  -49, 1257,  -49, 1257, 1049, 1257, 1049,
+ /*   140 */  1257, 1049, 1257,  -76,  -76,  -76,  230,  -76,  -76,  -76,
+ /*   150 */   -76,  -76, 1257,  -75, 1257,  -10,  -76,  733,  -76, 1046,
+ /*   160 */   -76,  -76,  -76, 1257,  703, 1257,  -53,  -76,  307,  987,
+ /*   170 */   314,   38, 1033, 1034, 1035,  -76,  638, 1257,  834, 1257,
+ /*   180 */   -76, 1257,  -76, 1257,  -76, 1129,  989,  319,  -76, 1079,
+ /*   190 */    90, 1016,  537, 1138,  -76, 1257,  163, 1257,  638, 1134,
+ /*   200 */   376, 1136,  -76, 1132,  456, 1137,  -76, 1257,  237, 1257,
+ /*   210 */   301, 1257,  638,  711,  -76, 1257,  -76,  -76, 1047,  456,
+ /*   220 */   -76,  -76,  -76, 1257,  638, 1045, 1257, 1143, 1257, 1068,
+ /*   230 */   102,  -76, 1148,  -76,  -76,  638, 1068,  102,  -76, 1257,
+ /*   240 */   638, 1057, 1257, 1156, 1257,  638,  -76,  -76,  509,  -76,
+ /*   250 */   -76,  -76,  385,  -76,  439,  -76, 1065,  -76,  387, 1047,
+ /*   260 */   405,  -76,  -76,  456,  -76,  -76, 1082, 1071,  -76, 1170,
+ /*   270 */   456,  780,  -76,  456,  -76,  -76, 1257,  638,  989,  389,
+ /*   280 */   443, 1172,  405, 1082, 1071,  -76, 1171,  -24,  -76,  -76,
+ /*   290 */  1084,   53,  -76,  -76,  -76,  -76,  375,  -76,  841,  -76,
+ /*   300 */  1173,  -76,  441,  689,  -76,  456, 1182,  -76,  635,  -76,
+ /*   310 */   456,  -76,  521,  649,  -76,  735,  -76,  -76,  -76,  -76,
+ /*   320 */   649,  -76,  649,  -76,  456,  943,  -76,  456, 1068,  102,
+ /*   330 */   -76,  -76, 1068,  102,  -76,  -76, 1148,  -76,  856,  -76,
+ /*   340 */   -76,  912,  -76,  128,  -76,  -76,  128,  -76,  -76,   -8,
+ /*   350 */   846,  966,  -76,  846, 1193,  -76,  -76,  -76,  414,  -76,
+ /*   360 */   -76,  -76,  414,  -76,  -76,  -76,  -76,  -76,   -6,   42,
+ /*   370 */   -76,  456,  -76, 1192, 1196,  456,  721, 1216,  689,  -76,
+ /*   380 */  1222,  456,  992,  689,  -76, 1257,  506,  -76, 1201, 1227,
+ /*   390 */   456, 1004, 1150,  456, 1182,  -76,  453, 1145,  -76,  -76,
+ /*   400 */   -76,  -76,  -76,  989,  428,  593,  745,  456, 1047,  -76,
+ /*   410 */   456,  729, 1237,  989,  486,  456, 1047,  900,  525, 1166,
+ /*   420 */   456, 1047,  -76, 1231,  622, 1261, 1257,  573, 1236,  917,
+ /*   430 */   -76,  -76, 1174, 1175,  437,  456,  773,  -76,  -76, 1228,
+ /*   440 */   -76,  -76, 1135,  456,  755, 1177,  456, 1260,  456, 1032,
+ /*   450 */   903, 1276, 1147, 1277,  174,  490,  326,  235,  -76, 1164,
+ /*   460 */  1165, 1278, 1284, 1285,  174, 1279, 1233,  456, 1191,  456,
+ /*   470 */   956,  456, 1238, 1257,  638, 1305, 1242, 1257,  638, 1189,
+ /*   480 */   456, 1299,  456, 1036,  -76,  360,  551, 1300, 1257, 1042,
+ /*   490 */  1257,  638, 1316,  638, 1209,  456,  601, 1320,  240,  456,
+ /*   500 */  1321,  456, 1322,  456, 1323,  456, 1324,  557, 1217,  456,
+ /*   510 */   601, 1328, 1233,  456, 1232,  456,  956, 1333, 1218,  456,
+ /*   520 */  1299,  970,  586, 1325, 1257, 1063, 1335,  460, 1342,  456,
+ /*   530 */  1047,  788,  172, 1346, 1347, 1350, 1352,  456, 1339, 1354,
+ /*   540 */  1330,  -25, 1348,  456, 1078, 1364,  845, 1366, 1367,  -76,
+ /*   550 */  1330,  456, 1368,  542, 1081, 1372, 1362,  456, 1336, 1254,
+ /*   560 */   456, 1388,  -76,  -76,
 };
-#define YY_REDUCE_USE_DFLT (-142)
+#define YY_REDUCE_USE_DFLT (-95)
 static const short yy_reduce_ofst[] = {
- /*     0 */  -107,  342, -142, -117, -142, -142, -142,   72,  442, -142,
- /*    10 */   394, -142, -142, -142, -142, -142, -142, -142,  525, -142,
- /*    20 */   579, -142,  731, -142,  515, -142,    8,  881, -142, -142,
- /*    30 */    48, -142,  337,  882,  153, -142,  890, -136, -142,  875,
- /*    40 */  -142, -142,  310, -142, -142, -142, -142, -142, -142, -142,
- /*    50 */  -142,  883, -142,  870, -142, -142, -142, -142, -142,  884,
- /*    60 */   891, -142, -142, -142,  892, -142, -142,  693, -142,  175,
- /*    70 */  -142, -142,   54, -142,  866,  876, -142,  867,  -41,  885,
- /*    80 */   888,  889,  893,  895,  877, -142, -141, -142, -142, -142,
- /*    90 */   186, -142,  849, -142, -142, -142,  852, -142, -142,  189,
- /*   100 */  -142, -142,  234, -142,  244,  894,  913, -142,  924, -142,
- /*   110 */  -142,  241,  705, -142, -142,  942, -142,  948, -142, -142,
- /*   120 */  -142, -142, -142,  241,  716,  241,  732,  241,  734,  241,
- /*   130 */   735,  241,  737,  241,  747,  241,  750,  241,  753,  241,
- /*   140 */   755,  241,  758,  241,  763,  241,  764,  241,  765,  241,
- /*   150 */   766,  241,  768,  241,  774,  241,  776,  241, -142, -142,
- /*   160 */  -142, -142, -142, -142, -142, -142,  779,  241, -142, -142,
- /*   170 */  -142, -142, -142, -142, -142,  781,  241,  782,  241, -142,
- /*   180 */   950,  609,  866, -142, -142, -142, -142, -142,  241,  784,
- /*   190 */   241,  789,  241,  794,  241,  795,  241,  583,  241,  896,
- /*   200 */   897, -142, -142,  805,  241,  810,  241, -142,  919, -142,
- /*   210 */  -142, -142,  957, -142, -142,  813,  241,  814,  241,  815,
- /*   220 */   241, -142, -142,  606, -142, -142,  956,  961, -142, -142,
- /*   230 */   903,  952, -142,  818,  241, -142,  177, -142,  820,  241,
- /*   240 */  -142,  477,  915, -142, -142, -142,  969, -142,  970, -142,
- /*   250 */  -142, -142,  972,  967,  518, -142, -142,  974, -142, -142,
- /*   260 */   923,  926, -142, -142,  821, -142, -142,  980, -142, -142,
- /*   270 */   828,  241,   13,  866,  915, -142,  564,  930,  933, -142,
- /*   280 */   830,  185, -142, -142, -142,  942, -142, -142, -142, -142,
- /*   290 */   241, -142, -142, -142, -142, -142,  241,  973, -142,  987,
- /*   300 */   966,  976,  962, -142,  990, -142, -142,  984, -142, -142,
- /*   310 */  -142, -142, -142, -142,  986, -142,  989, -142, -138, -142,
- /*   320 */  -142,  689,  935,  993, -142, -142,  936,  997, -142, -142,
- /*   330 */   995, -142,  963, -142, -142,  369, -142, -142, -142, -142,
- /*   340 */   999,  411, -142, -142,  415, -142, -142, -142, -142, -142,
- /*   350 */   998, 1002, -142, 1006, -142, -142, -142,  491, -142, 1007,
- /*   360 */  -142, -142,  576, -142, 1009, -142,  833,   -1, -142, -142,
- /*   370 */  -142,  660, -142, -142, 1008, 1010, 1012,  229, -142, -142,
- /*   380 */  -142, -142, -142, -142,  567,  866,  595, -142, 1021, 1016,
- /*   390 */  -142, 1022, 1026, -142,  574,  866, 1023, 1027,  927,  958,
- /*   400 */  -142,  401, 1030, -142,  937,  934, -142,  838,  241, -142,
- /*   410 */  -142, -142, -142, -142, -142, -142,  826, -142, -142, -142,
- /*   420 */  -142, -142, -142, -142, 1038, 1035, -142,  536, -142,  697,
- /*   430 */  -142, 1024, -142, -142, -142,  608,  866, 1014,  829, -142,
- /*   440 */  -142, -142, -142, -142, -142,  647, -142, 1025, 1054, -142,
- /*   450 */   717, 1018, 1057, -142,  853,  241, -142, -142,  854,  241,
- /*   460 */  -142, 1064, 1028,  858, -142, -142,  613,  866, -142,  637,
- /*   470 */  -142,  869,  241, -142,  241, -142, 1076, 1029, -142, -142,
- /*   480 */   700, -142,  871, -142,  872, -142,  873, -142,  866, -142,
- /*   490 */   874, 1036, -142, 1046,  879, -142,  878, 1039, -142, -142,
- /*   500 */   880, 1031,  855,  866, -142,  688, -142, -142, 1086, -142,
- /*   510 */  1088, 1091, -142,  569, -142, -142, -142, -142, 1099, -142,
- /*   520 */  -142, 1032, 1090, -142, 1105, 1033, -142, 1093, -142, -142,
- /*   530 */  -142, 1037, 1107, -142, -142, -142, -142,
+ /*     0 */     0,  -61,  -95,  -95,  202,  -95,  -95,  -95,  -94,  -59,
+ /*    10 */   -95,   52,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  103,
+ /*    20 */   -95,  189,  -95,  261,  -95,  349,  -95,  185,  520,  -95,
+ /*    30 */   -95,  109,  -95,   33,  576,  116,  -95,  595,  162,  -95,
+ /*    40 */   636,  -95,  -95,   36,  -95,  -95,  -95,  -95,  -95,  -95,
+ /*    50 */   -95,  -95,  655,  -95,  761,  -95,  -95,  -95,  -95,  -95,
+ /*    60 */   805,  921,  924,  -95,  -95,  -95,  -95,  928,  -95,  -95,
+ /*    70 */   446,  -95,  122,  -95,  -95,  -95,  -70,  -95,  913,  920,
+ /*    80 */   -95,  935,  496,  915,  936,  933,  937,  938,  940,  -95,
+ /*    90 */   448,  388,  513,  388,  519,  -95,  -95,  993,  -95,  996,
+ /*   100 */   -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  388,
+ /*   110 */   522,  388,  578,  388,  580,  388,  581,  388,  589,  388,
+ /*   120 */   590,  388,  643,  388,  644,  388,  645,  388,  646,  388,
+ /*   130 */   651,  388,  654,  388,  707,  388,  709,  388,  710,  388,
+ /*   140 */   712,  388,  715,  388,  -95,  -95,  -95,  -95,  -95,  -95,
+ /*   150 */   -95,  -95,  717,  188,  718,  388,  -95,  -95,  -95,  -95,
+ /*   160 */   -95,  -95,  -95,  720,  388,  723,  388,  -95,  997,  462,
+ /*   170 */   913,  -95,  -95,  -95,  -95,  -95,  388,  725,  388,  774,
+ /*   180 */   388,  775,  388,  776,  388,  -95,  572,  913,  -95,   45,
+ /*   190 */   388,  932,  930,  -95,  -95,  782,  388,  783,  388,  -95,
+ /*   200 */   971,  -95,  -95,  -95, 1011,  -95,  -95,  784,  388,  785,
+ /*   210 */   388,  790,  388,  -95,  -95,  252,  -95,  -95, 1012, 1015,
+ /*   220 */   -95,  -95,  -95,  828,  388,  -95,  186,  -95,  320,  962,
+ /*   230 */  1005,  -95, 1014,  -95,  -95,  388,  967, 1008,  -95,  829,
+ /*   240 */   388,  -95,  180,  -95,  837,  388,  -95,  291,  980,  -95,
+ /*   250 */   -95,  -95, 1037,  -95, 1038,  -95,  -95,  -95, 1039, 1028,
+ /*   260 */   535,  -95,  -95, 1040,  -95,  -95,  982,  994,  -95,  -95,
+ /*   270 */   407,  -95,  -95, 1044,  -95,  -95,  840,  388,  126,  913,
+ /*   280 */   980,  -95,  669,  998,  995,  -95,  850,  201,  -95,  -95,
+ /*   290 */   -95,  993,  -95,  -95,  -95,  -95,  388,  -95,  -95,  -95,
+ /*   300 */   -95,  -95,  388, 1048,  -95, 1053, 1030, 1031, 1050,  -95,
+ /*   310 */  1056,  -95,  -95, 1041,  -95,  -95,  -95,  -95,  -95,  -95,
+ /*   320 */  1043,  -95, 1051,  -95,  583,  -95,  -95,  516, 1006, 1052,
+ /*   330 */   -95,  -95, 1018, 1054,  -95,  -95, 1061,  -95, 1055,  -95,
+ /*   340 */   -95,  515,  -95, 1064,  -95,  -95, 1066,  -95,  -95, 1062,
+ /*   350 */   196,  -95,  -95,  269,  -95,  -95,  -95,  -95, 1013,  -95,
+ /*   360 */   -95,  -95, 1020,  -95,  -95,  -95,  -95,  -95, 1058, 1060,
+ /*   370 */   -95, 1077,  -95,  -95,  -95,  713, 1070,  -95, 1074,  -95,
+ /*   380 */   -95,  786,  -95, 1075,  -95,  851,  318,  -95,  -95,  -95,
+ /*   390 */   792,  -95,  -95, 1101, 1083, 1076,  110,  -95,  -95,  -95,
+ /*   400 */   -95,  -95,  -95,  865,  913,  330,  -95, 1107, 1105,  -95,
+ /*   410 */  1110, 1111,  -95,  887,  913, 1116, 1114, 1059, 1067,  -95,
+ /*   420 */   878, 1117,  -95, 1080, 1086,  -95,  869,  388,  -95,  -95,
+ /*   430 */   -95,  -95,  -95,  -95,  -95,  855,  -95,  -95,  -95,  -95,
+ /*   440 */   -95,  -95,  -95, 1126, 1127,  -95, 1139,  -95,  797,  -95,
+ /*   450 */  1113,  -95,  -95,  -95,  527,  913, 1102,  796,  -95,  -95,
+ /*   460 */   -95,  -95,  -95,  -95,  592,  -95, 1123, 1159,  -95,  838,
+ /*   470 */  1118, 1160,  -95,  876,  388,  -95,  -95,  888,  388,  -95,
+ /*   480 */  1176, 1109,  866,  -95,  -95,  895,  913,  -95,  317,  -95,
+ /*   490 */   890,  388,  -95,  388,  -95, 1178, 1140,  -95,  -95,  906,
+ /*   500 */   -95,  918,  -95,  919,  -95,  922,  -95,  913,  -95,  923,
+ /*   510 */  1142,  -95, 1153,  925,  -95,  931, 1149,  -95,  -95,  927,
+ /*   520 */  1131,  934,  913,  -95,  395,  -95,  -95, 1202,  -95, 1204,
+ /*   530 */  1203,  -95,  397,  -95,  -95,  -95,  -95, 1208,  -95,  -95,
+ /*   540 */  1133, 1207,  -95, 1221, 1141,  -95, 1211,  -95,  -95,  -95,
+ /*   550 */  1144, 1234,  -95, 1243, 1229,  -95,  -95,  939,  -95,  -95,
+ /*   560 */  1246,  -95,  -95,  -95,
 };
 static const YYACTIONTYPE yy_default[] = {
- /*     0 */   544,  544,  538,  829,  829,  540,  829,  549,  829,  829,
- /*    10 */   829,  829,  569,  570,  571,  550,  551,  552,  829,  829,
- /*    20 */   829,  829,  829,  829,  829,  829,  829,  829,  829,  829,
- /*    30 */   829,  562,  572,  581,  564,  580,  829,  829,  582,  623,
- /*    40 */   588,  829,  829,  624,  627,  628,  629,  818,  819,  820,
- /*    50 */   829,  623,  589,  608,  606,  829,  609,  610,  829,  679,
- /*    60 */   623,  590,  677,  678,  623,  591,  829,  829,  708,  770,
- /*    70 */   714,  709,  829,  634,  829,  829,  635,  643,  645,  652,
- /*    80 */   691,  682,  684,  672,  686,  640,  793,  578,  579,  687,
- /*    90 */   793,  688,  829,  788,  790,  791,  829,  789,  792,  793,
- /*   100 */   689,  829,  829,  673,  829,  680,  679,  674,  829,  566,
- /*   110 */   681,  676,  829,  707,  829,  829,  710,  829,  711,  712,
- /*   120 */   713,  715,  716,  719,  829,  720,  829,  721,  829,  722,
- /*   130 */   829,  723,  829,  724,  829,  725,  829,  726,  829,  727,
- /*   140 */   829,  728,  829,  729,  829,  730,  829,  731,  829,  732,
- /*   150 */   829,  733,  829,  734,  829,  735,  829,  736,  737,  738,
- /*   160 */   829,  739,  740,  745,  753,  756,  829,  741,  742,  829,
- /*   170 */   743,  829,  746,  744,  752,  829,  829,  829,  754,  755,
- /*   180 */   829,  770,  829,  829,  829,  829,  829,  758,  769,  829,
- /*   190 */   747,  829,  748,  829,  749,  829,  750,  829,  829,  829,
- /*   200 */   829,  829,  760,  829,  829,  829,  761,  829,  829,  829,
- /*   210 */   816,  829,  829,  829,  817,  829,  829,  829,  829,  829,
- /*   220 */   762,  829,  757,  770,  767,  768,  660,  829,  661,  759,
- /*   230 */   680,  679,  675,  829,  685,  829,  770,  683,  829,  692,
- /*   240 */   644,  655,  653,  654,  663,  664,  829,  665,  829,  666,
- /*   250 */   829,  667,  829,  660,  651,  567,  568,  829,  649,  650,
- /*   260 */   669,  671,  656,  829,  829,  829,  670,  829,  704,  705,
- /*   270 */   829,  668,  655,  829,  829,  829,  651,  669,  671,  657,
- /*   280 */   829,  651,  646,  647,  829,  829,  648,  641,  642,  751,
- /*   290 */   829,  706,  829,  717,  829,  718,  829,  623,  592,  829,
- /*   300 */   774,  596,  593,  597,  829,  598,  829,  829,  599,  829,
- /*   310 */   602,  603,  604,  605,  829,  600,  829,  601,  829,  829,
- /*   320 */   775,  829,  680,  679,  776,  778,  680,  679,  777,  594,
- /*   330 */   829,  595,  608,  607,  583,  793,  584,  585,  586,  587,
- /*   340 */   573,  793,  829,  574,  793,  829,  575,  577,  576,  565,
- /*   350 */   829,  829,  613,  829,  616,  829,  829,  829,  829,  623,
- /*   360 */   617,  829,  829,  829,  623,  618,  829,  623,  619,  829,
- /*   370 */   829,  829,  829,  829,  829,  774,  596,  621,  829,  620,
- /*   380 */   622,  614,  615,  563,  829,  829,  559,  829,  829,  660,
- /*   390 */   557,  829,  829,  829,  829,  829,  829,  660,  799,  829,
- /*   400 */   829,  829,  660,  662,  804,  829,  829,  829,  829,  829,
- /*   410 */   829,  805,  806,  829,  829,  829,  829,  829,  796,  797,
- /*   420 */   829,  798,  558,  829,  829,  829,  829,  829,  829,  829,
- /*   430 */   829,  829,  829,  829,  829,  829,  829,  829,  829,  626,
- /*   440 */   829,  829,  829,  829,  829,  829,  829,  625,  829,  829,
- /*   450 */   829,  829,  829,  829,  829,  694,  829,  829,  829,  695,
- /*   460 */   829,  829,  702,  829,  829,  703,  829,  829,  829,  829,
- /*   470 */   829,  829,  700,  829,  701,  829,  829,  829,  829,  829,
- /*   480 */   829,  829,  829,  829,  829,  829,  829,  829,  829,  829,
- /*   490 */   829,  829,  829,  625,  829,  829,  829,  829,  829,  829,
- /*   500 */   829,  702,  829,  829,  829,  829,  829,  829,  829,  829,
- /*   510 */   829,  660,  829,  793,  829,  829,  829,  829,  829,  829,
- /*   520 */   829,  827,  829,  829,  829,  829,  829,  829,  829,  829,
- /*   530 */   826,  827,  829,  829,  541,  543,  539,
+ /*     0 */   570,  570,  565,  568,  869,  869,  869,  569,  576,  869,
+ /*    10 */   869,  869,  869,  596,  597,  598,  577,  578,  579,  869,
+ /*    20 */   869,  869,  869,  869,  869,  869,  869,  869,  869,  869,
+ /*    30 */   869,  869,  589,  599,  608,  591,  607,  869,  869,  609,
+ /*    40 */   652,  615,  869,  869,  653,  656,  657,  658,  855,  856,
+ /*    50 */   857,  869,  652,  616,  637,  635,  869,  638,  639,  869,
+ /*    60 */   708,  652,  623,  617,  624,  706,  707,  652,  618,  869,
+ /*    70 */   869,  738,  807,  744,  739,  735,  869,  663,  869,  869,
+ /*    80 */   664,  672,  674,  681,  720,  711,  713,  701,  715,  669,
+ /*    90 */   869,  716,  869,  717,  869,  737,  869,  869,  740,  869,
+ /*   100 */   741,  742,  743,  745,  746,  747,  750,  751,  752,  753,
+ /*   110 */   869,  754,  869,  755,  869,  756,  869,  757,  869,  758,
+ /*   120 */   869,  759,  869,  760,  869,  761,  869,  762,  869,  763,
+ /*   130 */   869,  764,  869,  765,  869,  766,  869,  767,  869,  768,
+ /*   140 */   869,  769,  869,  770,  771,  772,  869,  773,  774,  781,
+ /*   150 */   788,  791,  869,  776,  869,  775,  778,  869,  779,  869,
+ /*   160 */   782,  780,  787,  869,  869,  869,  789,  790,  869,  807,
+ /*   170 */   869,  869,  869,  869,  869,  794,  806,  869,  783,  869,
+ /*   180 */   784,  869,  785,  869,  786,  869,  869,  869,  796,  869,
+ /*   190 */   869,  869,  869,  869,  797,  869,  869,  869,  798,  869,
+ /*   200 */   869,  869,  853,  869,  869,  869,  854,  869,  869,  869,
+ /*   210 */   869,  869,  799,  869,  792,  807,  804,  805,  689,  869,
+ /*   220 */   690,  795,  777,  869,  718,  869,  869,  702,  869,  709,
+ /*   230 */   708,  703,  869,  593,  710,  705,  709,  708,  704,  869,
+ /*   240 */   714,  869,  807,  712,  869,  721,  673,  684,  682,  683,
+ /*   250 */   692,  693,  869,  694,  869,  695,  869,  696,  869,  689,
+ /*   260 */   680,  594,  595,  869,  678,  679,  698,  700,  685,  869,
+ /*   270 */   869,  869,  699,  869,  733,  734,  869,  697,  684,  869,
+ /*   280 */   869,  869,  680,  698,  700,  686,  869,  680,  675,  676,
+ /*   290 */   869,  869,  677,  670,  671,  793,  869,  736,  869,  748,
+ /*   300 */   869,  749,  869,  652,  619,  869,  811,  625,  620,  626,
+ /*   310 */   869,  627,  869,  869,  628,  869,  631,  632,  633,  634,
+ /*   320 */   869,  629,  869,  630,  869,  869,  812,  869,  709,  708,
+ /*   330 */   813,  815,  709,  708,  814,  621,  869,  622,  637,  636,
+ /*   340 */   610,  869,  611,  869,  612,  744,  869,  613,  614,  600,
+ /*   350 */   830,  869,  601,  830,  869,  602,  605,  606,  869,  825,
+ /*   360 */   827,  828,  869,  826,  829,  604,  603,  592,  869,  869,
+ /*   370 */   642,  869,  645,  869,  869,  869,  869,  869,  652,  646,
+ /*   380 */   869,  869,  869,  652,  647,  869,  652,  648,  869,  869,
+ /*   390 */   869,  869,  869,  869,  811,  625,  650,  869,  649,  651,
+ /*   400 */   643,  644,  590,  869,  869,  586,  869,  869,  689,  584,
+ /*   410 */   869,  869,  869,  869,  869,  869,  689,  836,  869,  869,
+ /*   420 */   869,  689,  691,  841,  869,  869,  869,  869,  869,  869,
+ /*   430 */   842,  843,  869,  869,  869,  869,  869,  833,  834,  869,
+ /*   440 */   835,  585,  869,  869,  869,  869,  869,  869,  869,  869,
+ /*   450 */   869,  869,  869,  869,  869,  869,  869,  869,  655,  869,
+ /*   460 */   869,  869,  869,  869,  869,  869,  654,  869,  869,  869,
+ /*   470 */   869,  869,  869,  869,  723,  869,  869,  869,  724,  869,
+ /*   480 */   869,  731,  869,  869,  732,  869,  869,  869,  869,  869,
+ /*   490 */   869,  729,  869,  730,  869,  869,  869,  869,  869,  869,
+ /*   500 */   869,  869,  869,  869,  869,  869,  869,  869,  869,  869,
+ /*   510 */   869,  869,  654,  869,  869,  869,  869,  869,  869,  869,
+ /*   520 */   731,  869,  869,  869,  869,  869,  869,  869,  869,  869,
+ /*   530 */   689,  869,  830,  869,  869,  869,  869,  869,  869,  869,
+ /*   540 */   864,  869,  869,  869,  869,  869,  869,  869,  869,  863,
+ /*   550 */   864,  869,  869,  869,  869,  869,  869,  869,  869,  869,
+ /*   560 */   869,  869,  571,  566,
 };
 #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
 
@@ -672,6 +723,12 @@ static const YYCODETYPE yyFallback[] = {
    26,  /*    TRIGGER => ID */
    26,  /*     VACUUM => ID */
    26,  /*       VIEW => ID */
+   26,  /*    REINDEX => ID */
+   26,  /*     RENAME => ID */
+   26,  /*      CDATE => ID */
+   26,  /*      CTIME => ID */
+   26,  /* CTIMESTAMP => ID */
+   26,  /*      ALTER => ID */
     0,  /*         OR => nothing */
     0,  /*        AND => nothing */
     0,  /*        NOT => nothing */
@@ -686,6 +743,7 @@ static const YYCODETYPE yyFallback[] = {
     0,  /*         LE => nothing */
     0,  /*         LT => nothing */
     0,  /*         GE => nothing */
+    0,  /*     ESCAPE => nothing */
     0,  /*     BITAND => nothing */
     0,  /*      BITOR => nothing */
     0,  /*     LSHIFT => nothing */
@@ -709,6 +767,7 @@ static const YYCODETYPE yyFallback[] = {
     0,  /*      CHECK => nothing */
     0,  /* REFERENCES => nothing */
     0,  /*    COLLATE => nothing */
+    0,  /*   AUTOINCR => nothing */
     0,  /*         ON => nothing */
     0,  /*     DELETE => nothing */
     0,  /*     UPDATE => nothing */
@@ -738,12 +797,15 @@ static const YYCODETYPE yyFallback[] = {
     0,  /*    INTEGER => nothing */
     0,  /*      FLOAT => nothing */
     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,  /*         TO => nothing */
 };
 #endif /* YYFALLBACK */
 
@@ -828,16 +890,18 @@ static const char *const yyTokenName[] = {
   "LIKE",          "MATCH",         "KEY",           "OF",          
   "OFFSET",        "PRAGMA",        "RAISE",         "REPLACE",     
   "RESTRICT",      "ROW",           "STATEMENT",     "TRIGGER",     
-  "VACUUM",        "VIEW",          "OR",            "AND",         
-  "NOT",           "IS",            "BETWEEN",       "IN",          
-  "ISNULL",        "NOTNULL",       "NE",            "EQ",          
-  "GT",            "LE",            "LT",            "GE",          
-  "BITAND",        "BITOR",         "LSHIFT",        "RSHIFT",      
-  "PLUS",          "MINUS",         "STAR",          "SLASH",       
-  "REM",           "CONCAT",        "UMINUS",        "UPLUS",       
-  "BITNOT",        "STRING",        "JOIN_KW",       "CONSTRAINT",  
-  "DEFAULT",       "NULL",          "PRIMARY",       "UNIQUE",      
-  "CHECK",         "REFERENCES",    "COLLATE",       "ON",          
+  "VACUUM",        "VIEW",          "REINDEX",       "RENAME",      
+  "CDATE",         "CTIME",         "CTIMESTAMP",    "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",      
@@ -845,31 +909,33 @@ static const char *const yyTokenName[] = {
   "USING",         "ORDER",         "BY",            "GROUP",       
   "HAVING",        "LIMIT",         "WHERE",         "INTO",        
   "VALUES",        "INTEGER",       "FLOAT",         "BLOB",        
-  "VARIABLE",      "CASE",          "WHEN",          "THEN",        
-  "ELSE",          "INDEX",         "error",         "input",       
-  "cmdlist",       "ecmd",          "explain",       "cmdx",        
-  "cmd",           "transtype",     "trans_opt",     "nm",          
-  "create_table",  "create_table_args",  "temp",          "dbnm",        
-  "columnlist",    "conslist_opt",  "select",        "column",      
-  "columnid",      "type",          "carglist",      "id",          
-  "ids",           "typename",      "signed",        "plus_num",    
-  "minus_num",     "carg",          "ccons",         "onconf",      
-  "sortorder",     "expr",          "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",        "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",     
+  "REGISTER",      "VARIABLE",      "EXISTS",        "CASE",        
+  "WHEN",          "THEN",          "ELSE",          "INDEX",       
+  "TO",            "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",         
+  "typename",      "signed",        "plus_num",      "minus_num",   
+  "carg",          "ccons",         "term",          "onconf",      
+  "sortorder",     "autoinc",       "expr",          "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",     
 };
 #endif /* NDEBUG */
 
@@ -880,11 +946,11 @@ static const char *const yyRuleName[] = {
  /*   0 */ "input ::= cmdlist",
  /*   1 */ "cmdlist ::= cmdlist ecmd",
  /*   2 */ "cmdlist ::= ecmd",
- /*   3 */ "ecmd ::= explain cmdx SEMI",
+ /*   3 */ "cmdx ::= cmd",
  /*   4 */ "ecmd ::= SEMI",
- /*   5 */ "cmdx ::= cmd",
- /*   6 */ "explain ::= EXPLAIN",
- /*   7 */ "explain ::=",
+ /*   5 */ "ecmd ::= explain cmdx SEMI",
+ /*   6 */ "explain ::=",
+ /*   7 */ "explain ::= EXPLAIN",
  /*   8 */ "cmd ::= BEGIN transtype trans_opt",
  /*   9 */ "trans_opt ::=",
  /*  10 */ "trans_opt ::= TRANSACTION",
@@ -924,251 +990,264 @@ static const char *const yyRuleName[] = {
  /*  44 */ "carglist ::=",
  /*  45 */ "carg ::= CONSTRAINT nm ccons",
  /*  46 */ "carg ::= ccons",
- /*  47 */ "carg ::= DEFAULT ids",
- /*  48 */ "carg ::= DEFAULT plus_num",
- /*  49 */ "carg ::= DEFAULT minus_num",
- /*  50 */ "carg ::= DEFAULT NULL",
+ /*  47 */ "carg ::= DEFAULT term",
+ /*  48 */ "carg ::= DEFAULT PLUS term",
+ /*  49 */ "carg ::= DEFAULT MINUS term",
+ /*  50 */ "carg ::= DEFAULT id",
  /*  51 */ "ccons ::= NULL onconf",
  /*  52 */ "ccons ::= NOT NULL onconf",
- /*  53 */ "ccons ::= PRIMARY KEY sortorder onconf",
+ /*  53 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
  /*  54 */ "ccons ::= UNIQUE onconf",
  /*  55 */ "ccons ::= CHECK LP expr RP onconf",
  /*  56 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
  /*  57 */ "ccons ::= defer_subclause",
  /*  58 */ "ccons ::= COLLATE id",
- /*  59 */ "refargs ::=",
- /*  60 */ "refargs ::= refargs refarg",
- /*  61 */ "refarg ::= MATCH nm",
- /*  62 */ "refarg ::= ON DELETE refact",
- /*  63 */ "refarg ::= ON UPDATE refact",
- /*  64 */ "refarg ::= ON INSERT refact",
- /*  65 */ "refact ::= SET NULL",
- /*  66 */ "refact ::= SET DEFAULT",
- /*  67 */ "refact ::= CASCADE",
- /*  68 */ "refact ::= RESTRICT",
- /*  69 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
- /*  70 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
- /*  71 */ "init_deferred_pred_opt ::=",
- /*  72 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
- /*  73 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
- /*  74 */ "conslist_opt ::=",
- /*  75 */ "conslist_opt ::= COMMA conslist",
- /*  76 */ "conslist ::= conslist COMMA tcons",
- /*  77 */ "conslist ::= conslist tcons",
- /*  78 */ "conslist ::= tcons",
- /*  79 */ "tcons ::= CONSTRAINT nm",
- /*  80 */ "tcons ::= PRIMARY KEY LP idxlist RP onconf",
- /*  81 */ "tcons ::= UNIQUE LP idxlist RP onconf",
- /*  82 */ "tcons ::= CHECK expr onconf",
- /*  83 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
- /*  84 */ "defer_subclause_opt ::=",
- /*  85 */ "defer_subclause_opt ::= defer_subclause",
- /*  86 */ "onconf ::=",
- /*  87 */ "onconf ::= ON CONFLICT resolvetype",
- /*  88 */ "orconf ::=",
- /*  89 */ "orconf ::= OR resolvetype",
- /*  90 */ "resolvetype ::= raisetype",
- /*  91 */ "resolvetype ::= IGNORE",
- /*  92 */ "resolvetype ::= REPLACE",
- /*  93 */ "cmd ::= DROP TABLE fullname",
- /*  94 */ "cmd ::= CREATE temp VIEW nm dbnm AS select",
- /*  95 */ "cmd ::= DROP VIEW fullname",
- /*  96 */ "cmd ::= select",
- /*  97 */ "select ::= oneselect",
- /*  98 */ "select ::= select multiselect_op oneselect",
- /*  99 */ "multiselect_op ::= UNION",
- /* 100 */ "multiselect_op ::= UNION ALL",
- /* 101 */ "multiselect_op ::= INTERSECT",
- /* 102 */ "multiselect_op ::= EXCEPT",
- /* 103 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 104 */ "distinct ::= DISTINCT",
- /* 105 */ "distinct ::= ALL",
- /* 106 */ "distinct ::=",
- /* 107 */ "sclp ::= selcollist COMMA",
- /* 108 */ "sclp ::=",
- /* 109 */ "selcollist ::= sclp expr as",
- /* 110 */ "selcollist ::= sclp STAR",
- /* 111 */ "selcollist ::= sclp nm DOT STAR",
- /* 112 */ "as ::= AS nm",
- /* 113 */ "as ::= ids",
- /* 114 */ "as ::=",
- /* 115 */ "from ::=",
- /* 116 */ "from ::= FROM seltablist",
- /* 117 */ "stl_prefix ::= seltablist joinop",
- /* 118 */ "stl_prefix ::=",
- /* 119 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt",
- /* 120 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt",
- /* 121 */ "seltablist_paren ::= select",
- /* 122 */ "seltablist_paren ::= seltablist",
- /* 123 */ "dbnm ::=",
- /* 124 */ "dbnm ::= DOT nm",
- /* 125 */ "fullname ::= nm dbnm",
- /* 126 */ "joinop ::= COMMA",
- /* 127 */ "joinop ::= JOIN",
- /* 128 */ "joinop ::= JOIN_KW JOIN",
- /* 129 */ "joinop ::= JOIN_KW nm JOIN",
- /* 130 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 131 */ "on_opt ::= ON expr",
- /* 132 */ "on_opt ::=",
- /* 133 */ "using_opt ::= USING LP inscollist RP",
- /* 134 */ "using_opt ::=",
- /* 135 */ "orderby_opt ::=",
- /* 136 */ "orderby_opt ::= ORDER BY sortlist",
- /* 137 */ "sortlist ::= sortlist COMMA sortitem collate sortorder",
- /* 138 */ "sortlist ::= sortitem collate sortorder",
- /* 139 */ "sortitem ::= expr",
- /* 140 */ "sortorder ::= ASC",
- /* 141 */ "sortorder ::= DESC",
- /* 142 */ "sortorder ::=",
- /* 143 */ "collate ::=",
- /* 144 */ "collate ::= COLLATE id",
- /* 145 */ "groupby_opt ::=",
- /* 146 */ "groupby_opt ::= GROUP BY exprlist",
- /* 147 */ "having_opt ::=",
- /* 148 */ "having_opt ::= HAVING expr",
- /* 149 */ "limit_opt ::=",
- /* 150 */ "limit_opt ::= LIMIT signed",
- /* 151 */ "limit_opt ::= LIMIT signed OFFSET signed",
- /* 152 */ "limit_opt ::= LIMIT signed COMMA signed",
- /* 153 */ "cmd ::= DELETE FROM fullname where_opt",
- /* 154 */ "where_opt ::=",
- /* 155 */ "where_opt ::= WHERE expr",
- /* 156 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt",
- /* 157 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 158 */ "setlist ::= nm EQ expr",
- /* 159 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
- /* 160 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
- /* 161 */ "insert_cmd ::= INSERT orconf",
- /* 162 */ "insert_cmd ::= REPLACE",
- /* 163 */ "itemlist ::= itemlist COMMA expr",
- /* 164 */ "itemlist ::= expr",
- /* 165 */ "inscollist_opt ::=",
- /* 166 */ "inscollist_opt ::= LP inscollist RP",
- /* 167 */ "inscollist ::= inscollist COMMA nm",
- /* 168 */ "inscollist ::= nm",
- /* 169 */ "expr ::= LP expr RP",
- /* 170 */ "expr ::= NULL",
- /* 171 */ "expr ::= ID",
- /* 172 */ "expr ::= JOIN_KW",
- /* 173 */ "expr ::= nm DOT nm",
- /* 174 */ "expr ::= nm DOT nm DOT nm",
- /* 175 */ "expr ::= INTEGER",
- /* 176 */ "expr ::= FLOAT",
- /* 177 */ "expr ::= STRING",
- /* 178 */ "expr ::= BLOB",
- /* 179 */ "expr ::= VARIABLE",
- /* 180 */ "expr ::= ID LP exprlist RP",
- /* 181 */ "expr ::= ID LP STAR RP",
- /* 182 */ "expr ::= expr AND expr",
- /* 183 */ "expr ::= expr OR expr",
- /* 184 */ "expr ::= expr LT expr",
- /* 185 */ "expr ::= expr GT expr",
- /* 186 */ "expr ::= expr LE expr",
- /* 187 */ "expr ::= expr GE expr",
- /* 188 */ "expr ::= expr NE expr",
- /* 189 */ "expr ::= expr EQ expr",
- /* 190 */ "expr ::= expr BITAND expr",
- /* 191 */ "expr ::= expr BITOR expr",
- /* 192 */ "expr ::= expr LSHIFT expr",
- /* 193 */ "expr ::= expr RSHIFT expr",
- /* 194 */ "expr ::= expr PLUS expr",
- /* 195 */ "expr ::= expr MINUS expr",
- /* 196 */ "expr ::= expr STAR expr",
- /* 197 */ "expr ::= expr SLASH expr",
- /* 198 */ "expr ::= expr REM expr",
- /* 199 */ "expr ::= expr CONCAT expr",
- /* 200 */ "likeop ::= LIKE",
- /* 201 */ "likeop ::= GLOB",
- /* 202 */ "likeop ::= NOT LIKE",
- /* 203 */ "likeop ::= NOT GLOB",
- /* 204 */ "expr ::= expr likeop expr",
- /* 205 */ "expr ::= expr ISNULL",
- /* 206 */ "expr ::= expr IS NULL",
- /* 207 */ "expr ::= expr NOTNULL",
- /* 208 */ "expr ::= expr NOT NULL",
- /* 209 */ "expr ::= expr IS NOT NULL",
- /* 210 */ "expr ::= NOT expr",
- /* 211 */ "expr ::= BITNOT expr",
- /* 212 */ "expr ::= MINUS expr",
- /* 213 */ "expr ::= PLUS expr",
- /* 214 */ "expr ::= LP select RP",
- /* 215 */ "between_op ::= BETWEEN",
- /* 216 */ "between_op ::= NOT BETWEEN",
- /* 217 */ "expr ::= expr between_op expr AND expr",
- /* 218 */ "in_op ::= IN",
- /* 219 */ "in_op ::= NOT IN",
- /* 220 */ "expr ::= expr in_op LP exprlist RP",
- /* 221 */ "expr ::= expr in_op LP select RP",
- /* 222 */ "expr ::= expr in_op nm dbnm",
- /* 223 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 224 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 225 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 226 */ "case_else ::= ELSE expr",
- /* 227 */ "case_else ::=",
- /* 228 */ "case_operand ::= expr",
- /* 229 */ "case_operand ::=",
- /* 230 */ "exprlist ::= exprlist COMMA expritem",
- /* 231 */ "exprlist ::= expritem",
- /* 232 */ "expritem ::= expr",
- /* 233 */ "expritem ::=",
- /* 234 */ "cmd ::= CREATE uniqueflag INDEX nm dbnm ON fullname LP idxlist RP onconf",
- /* 235 */ "uniqueflag ::= UNIQUE",
- /* 236 */ "uniqueflag ::=",
- /* 237 */ "idxlist_opt ::=",
- /* 238 */ "idxlist_opt ::= LP idxlist RP",
- /* 239 */ "idxlist ::= idxlist COMMA idxitem collate sortorder",
- /* 240 */ "idxlist ::= idxitem collate sortorder",
- /* 241 */ "idxitem ::= nm",
- /* 242 */ "cmd ::= DROP INDEX fullname",
- /* 243 */ "cmd ::= VACUUM",
- /* 244 */ "cmd ::= VACUUM nm",
- /* 245 */ "cmd ::= PRAGMA nm dbnm EQ nm",
- /* 246 */ "cmd ::= PRAGMA nm dbnm EQ ON",
- /* 247 */ "cmd ::= PRAGMA nm dbnm EQ plus_num",
- /* 248 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 249 */ "cmd ::= PRAGMA nm dbnm LP nm RP",
- /* 250 */ "cmd ::= PRAGMA nm dbnm",
- /* 251 */ "plus_num ::= plus_opt number",
- /* 252 */ "minus_num ::= MINUS number",
- /* 253 */ "number ::= INTEGER",
- /* 254 */ "number ::= FLOAT",
- /* 255 */ "plus_opt ::= PLUS",
- /* 256 */ "plus_opt ::=",
- /* 257 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 258 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 259 */ "trigger_time ::= BEFORE",
- /* 260 */ "trigger_time ::= AFTER",
- /* 261 */ "trigger_time ::= INSTEAD OF",
- /* 262 */ "trigger_time ::=",
- /* 263 */ "trigger_event ::= DELETE",
- /* 264 */ "trigger_event ::= INSERT",
- /* 265 */ "trigger_event ::= UPDATE",
- /* 266 */ "trigger_event ::= UPDATE OF inscollist",
- /* 267 */ "foreach_clause ::=",
- /* 268 */ "foreach_clause ::= FOR EACH ROW",
- /* 269 */ "foreach_clause ::= FOR EACH STATEMENT",
- /* 270 */ "when_clause ::=",
- /* 271 */ "when_clause ::= WHEN expr",
- /* 272 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list",
- /* 273 */ "trigger_cmd_list ::=",
- /* 274 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 277 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 278 */ "trigger_cmd ::= select",
- /* 279 */ "expr ::= RAISE LP IGNORE RP",
- /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 281 */ "raisetype ::= ROLLBACK",
- /* 282 */ "raisetype ::= ABORT",
- /* 283 */ "raisetype ::= FAIL",
- /* 284 */ "cmd ::= DROP TRIGGER fullname",
- /* 285 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt",
- /* 286 */ "key_opt ::=",
- /* 287 */ "key_opt ::= KEY ids",
- /* 288 */ "key_opt ::= KEY BLOB",
- /* 289 */ "database_kw_opt ::= DATABASE",
- /* 290 */ "database_kw_opt ::=",
- /* 291 */ "cmd ::= DETACH database_kw_opt nm",
+ /*  59 */ "autoinc ::=",
+ /*  60 */ "autoinc ::= AUTOINCR",
+ /*  61 */ "refargs ::=",
+ /*  62 */ "refargs ::= refargs refarg",
+ /*  63 */ "refarg ::= MATCH nm",
+ /*  64 */ "refarg ::= ON DELETE refact",
+ /*  65 */ "refarg ::= ON UPDATE refact",
+ /*  66 */ "refarg ::= ON INSERT refact",
+ /*  67 */ "refact ::= SET NULL",
+ /*  68 */ "refact ::= SET DEFAULT",
+ /*  69 */ "refact ::= CASCADE",
+ /*  70 */ "refact ::= RESTRICT",
+ /*  71 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
+ /*  72 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
+ /*  73 */ "init_deferred_pred_opt ::=",
+ /*  74 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
+ /*  75 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
+ /*  76 */ "conslist_opt ::=",
+ /*  77 */ "conslist_opt ::= COMMA conslist",
+ /*  78 */ "conslist ::= conslist COMMA tcons",
+ /*  79 */ "conslist ::= conslist tcons",
+ /*  80 */ "conslist ::= tcons",
+ /*  81 */ "tcons ::= CONSTRAINT nm",
+ /*  82 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
+ /*  83 */ "tcons ::= UNIQUE LP idxlist RP onconf",
+ /*  84 */ "tcons ::= CHECK expr onconf",
+ /*  85 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
+ /*  86 */ "defer_subclause_opt ::=",
+ /*  87 */ "defer_subclause_opt ::= defer_subclause",
+ /*  88 */ "onconf ::=",
+ /*  89 */ "onconf ::= ON CONFLICT resolvetype",
+ /*  90 */ "orconf ::=",
+ /*  91 */ "orconf ::= OR resolvetype",
+ /*  92 */ "resolvetype ::= raisetype",
+ /*  93 */ "resolvetype ::= IGNORE",
+ /*  94 */ "resolvetype ::= REPLACE",
+ /*  95 */ "cmd ::= DROP TABLE fullname",
+ /*  96 */ "cmd ::= CREATE temp VIEW nm dbnm AS select",
+ /*  97 */ "cmd ::= DROP VIEW fullname",
+ /*  98 */ "cmd ::= select",
+ /*  99 */ "select ::= oneselect",
+ /* 100 */ "select ::= select multiselect_op oneselect",
+ /* 101 */ "multiselect_op ::= UNION",
+ /* 102 */ "multiselect_op ::= UNION ALL",
+ /* 103 */ "multiselect_op ::= INTERSECT",
+ /* 104 */ "multiselect_op ::= EXCEPT",
+ /* 105 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
+ /* 106 */ "distinct ::= DISTINCT",
+ /* 107 */ "distinct ::= ALL",
+ /* 108 */ "distinct ::=",
+ /* 109 */ "sclp ::= selcollist COMMA",
+ /* 110 */ "sclp ::=",
+ /* 111 */ "selcollist ::= sclp expr as",
+ /* 112 */ "selcollist ::= sclp STAR",
+ /* 113 */ "selcollist ::= sclp nm DOT STAR",
+ /* 114 */ "as ::= AS nm",
+ /* 115 */ "as ::= ids",
+ /* 116 */ "as ::=",
+ /* 117 */ "from ::=",
+ /* 118 */ "from ::= FROM seltablist",
+ /* 119 */ "stl_prefix ::= seltablist joinop",
+ /* 120 */ "stl_prefix ::=",
+ /* 121 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt",
+ /* 122 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt",
+ /* 123 */ "seltablist_paren ::= select",
+ /* 124 */ "seltablist_paren ::= seltablist",
+ /* 125 */ "dbnm ::=",
+ /* 126 */ "dbnm ::= DOT nm",
+ /* 127 */ "fullname ::= nm dbnm",
+ /* 128 */ "joinop ::= COMMA",
+ /* 129 */ "joinop ::= JOIN",
+ /* 130 */ "joinop ::= JOIN_KW JOIN",
+ /* 131 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 132 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 133 */ "on_opt ::= ON expr",
+ /* 134 */ "on_opt ::=",
+ /* 135 */ "using_opt ::= USING LP inscollist RP",
+ /* 136 */ "using_opt ::=",
+ /* 137 */ "orderby_opt ::=",
+ /* 138 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 139 */ "sortlist ::= sortlist COMMA sortitem collate sortorder",
+ /* 140 */ "sortlist ::= sortitem collate sortorder",
+ /* 141 */ "sortitem ::= expr",
+ /* 142 */ "sortorder ::= ASC",
+ /* 143 */ "sortorder ::= DESC",
+ /* 144 */ "sortorder ::=",
+ /* 145 */ "collate ::=",
+ /* 146 */ "collate ::= COLLATE id",
+ /* 147 */ "groupby_opt ::=",
+ /* 148 */ "groupby_opt ::= GROUP BY exprlist",
+ /* 149 */ "having_opt ::=",
+ /* 150 */ "having_opt ::= HAVING expr",
+ /* 151 */ "limit_opt ::=",
+ /* 152 */ "limit_opt ::= LIMIT expr",
+ /* 153 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 154 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 155 */ "cmd ::= DELETE FROM fullname where_opt",
+ /* 156 */ "where_opt ::=",
+ /* 157 */ "where_opt ::= WHERE expr",
+ /* 158 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt",
+ /* 159 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 160 */ "setlist ::= nm EQ expr",
+ /* 161 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
+ /* 162 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
+ /* 163 */ "insert_cmd ::= INSERT orconf",
+ /* 164 */ "insert_cmd ::= REPLACE",
+ /* 165 */ "itemlist ::= itemlist COMMA expr",
+ /* 166 */ "itemlist ::= expr",
+ /* 167 */ "inscollist_opt ::=",
+ /* 168 */ "inscollist_opt ::= LP inscollist RP",
+ /* 169 */ "inscollist ::= inscollist COMMA nm",
+ /* 170 */ "inscollist ::= nm",
+ /* 171 */ "expr ::= term",
+ /* 172 */ "expr ::= LP expr RP",
+ /* 173 */ "term ::= NULL",
+ /* 174 */ "expr ::= ID",
+ /* 175 */ "expr ::= JOIN_KW",
+ /* 176 */ "expr ::= nm DOT nm",
+ /* 177 */ "expr ::= nm DOT nm DOT nm",
+ /* 178 */ "term ::= INTEGER",
+ /* 179 */ "term ::= FLOAT",
+ /* 180 */ "term ::= STRING",
+ /* 181 */ "expr ::= BLOB",
+ /* 182 */ "expr ::= REGISTER",
+ /* 183 */ "expr ::= VARIABLE",
+ /* 184 */ "expr ::= ID LP exprlist RP",
+ /* 185 */ "expr ::= ID LP STAR RP",
+ /* 186 */ "term ::= CTIME",
+ /* 187 */ "term ::= CDATE",
+ /* 188 */ "term ::= CTIMESTAMP",
+ /* 189 */ "expr ::= expr AND expr",
+ /* 190 */ "expr ::= expr OR expr",
+ /* 191 */ "expr ::= expr LT expr",
+ /* 192 */ "expr ::= expr GT expr",
+ /* 193 */ "expr ::= expr LE expr",
+ /* 194 */ "expr ::= expr GE expr",
+ /* 195 */ "expr ::= expr NE expr",
+ /* 196 */ "expr ::= expr EQ expr",
+ /* 197 */ "expr ::= expr BITAND expr",
+ /* 198 */ "expr ::= expr BITOR expr",
+ /* 199 */ "expr ::= expr LSHIFT expr",
+ /* 200 */ "expr ::= expr RSHIFT expr",
+ /* 201 */ "expr ::= expr PLUS expr",
+ /* 202 */ "expr ::= expr MINUS expr",
+ /* 203 */ "expr ::= expr STAR expr",
+ /* 204 */ "expr ::= expr SLASH expr",
+ /* 205 */ "expr ::= expr REM expr",
+ /* 206 */ "expr ::= expr CONCAT expr",
+ /* 207 */ "likeop ::= LIKE",
+ /* 208 */ "likeop ::= GLOB",
+ /* 209 */ "likeop ::= NOT LIKE",
+ /* 210 */ "likeop ::= NOT GLOB",
+ /* 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 ::= ALTER TABLE fullname RENAME TO nm",
 };
 #endif /* NDEBUG */
 
@@ -1226,63 +1305,72 @@ 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 146:
-    case 176:
-    case 193:
-#line 303 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3SelectDelete((yypminor->yy107));}
-#line 1236 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-      break;
-    case 161:
-    case 181:
-    case 183:
-    case 191:
-    case 197:
-    case 210:
-#line 552 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3ExprDelete((yypminor->yy258));}
-#line 1246 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+    case 157:
+    case 189:
+    case 206:
+#line 325 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3SelectDelete((yypminor->yy331));}
+#line 1315 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
       break;
-    case 162:
     case 170:
-    case 179:
-    case 182:
-    case 184:
-    case 186:
+    case 174:
+    case 194:
     case 196:
-    case 199:
-    case 200:
-    case 203:
-    case 208:
-#line 744 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3ExprListDelete((yypminor->yy210));}
-#line 1261 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+    case 204:
+    case 210:
+    case 224:
+#line 584 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3ExprDelete((yypminor->yy454));}
+#line 1326 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
       break;
     case 175:
-    case 180:
-    case 188:
-    case 189:
-#line 428 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3SrcListDelete((yypminor->yy259));}
-#line 1269 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-      break;
+    case 183:
     case 192:
     case 195:
+    case 197:
+    case 199:
+    case 209:
+    case 212:
+    case 213:
+    case 216:
+    case 222:
+#line 796 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3ExprListDelete((yypminor->yy266));}
+#line 1341 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+      break;
+    case 188:
+    case 193:
+    case 201:
     case 202:
-#line 446 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 454 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3SrcListDelete((yypminor->yy427));}
+#line 1349 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+      break;
+    case 198:
+#line 516 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+  sqlite3ExprDelete((yypminor->yy348).pLimit);
+  sqlite3ExprDelete((yypminor->yy348).pOffset);
+}
+#line 1357 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+      break;
+    case 205:
+    case 208:
+    case 215:
+#line 472 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {sqlite3IdListDelete((yypminor->yy272));}
-#line 1276 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1364 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
       break;
-    case 216:
-    case 221:
-#line 833 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DeleteTriggerStep((yypminor->yy91));}
-#line 1282 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+    case 230:
+    case 235:
+#line 889 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3DeleteTriggerStep((yypminor->yy455));}
+#line 1370 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
       break;
-    case 218:
-#line 817 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3IdListDelete((yypminor->yy146).b);}
-#line 1287 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+    case 232:
+#line 873 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3IdListDelete((yypminor->yy62).b);}
+#line 1375 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
       break;
     default:  break;   /* If no destructor action specified: do nothing */
   }
@@ -1458,298 +1546,311 @@ 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[] = {
-  { 131, 1 },
-  { 132, 2 },
-  { 132, 1 },
-  { 133, 3 },
-  { 133, 1 },
-  { 135, 1 },
-  { 134, 1 },
-  { 134, 0 },
-  { 136, 3 },
-  { 138, 0 },
-  { 138, 1 },
-  { 138, 2 },
-  { 137, 0 },
-  { 137, 1 },
-  { 137, 1 },
-  { 137, 1 },
-  { 136, 2 },
-  { 136, 2 },
-  { 136, 2 },
-  { 136, 2 },
-  { 140, 5 },
   { 142, 1 },
-  { 142, 0 },
-  { 141, 4 },
-  { 141, 2 },
-  { 144, 3 },
+  { 143, 2 },
+  { 143, 1 },
+  { 145, 1 },
   { 144, 1 },
-  { 147, 3 },
-  { 148, 1 },
-  { 151, 1 },
-  { 152, 1 },
-  { 152, 1 },
-  { 139, 1 },
-  { 139, 1 },
-  { 139, 1 },
+  { 144, 3 },
+  { 147, 0 },
+  { 147, 1 },
+  { 146, 3 },
   { 149, 0 },
   { 149, 1 },
-  { 149, 4 },
-  { 149, 6 },
+  { 149, 2 },
+  { 148, 0 },
+  { 148, 1 },
+  { 148, 1 },
+  { 148, 1 },
+  { 146, 2 },
+  { 146, 2 },
+  { 146, 2 },
+  { 146, 2 },
+  { 151, 5 },
   { 153, 1 },
-  { 153, 2 },
-  { 154, 1 },
-  { 154, 1 },
-  { 150, 2 },
-  { 150, 0 },
-  { 157, 3 },
-  { 157, 1 },
-  { 157, 2 },
-  { 157, 2 },
-  { 157, 2 },
-  { 157, 2 },
-  { 158, 2 },
+  { 153, 0 },
+  { 152, 4 },
+  { 152, 2 },
+  { 155, 3 },
+  { 155, 1 },
   { 158, 3 },
-  { 158, 4 },
-  { 158, 2 },
-  { 158, 5 },
-  { 158, 4 },
-  { 158, 1 },
-  { 158, 2 },
-  { 163, 0 },
-  { 163, 2 },
-  { 165, 2 },
-  { 165, 3 },
-  { 165, 3 },
-  { 165, 3 },
-  { 166, 2 },
-  { 166, 2 },
-  { 166, 1 },
-  { 166, 1 },
-  { 164, 3 },
+  { 159, 1 },
+  { 162, 1 },
+  { 163, 1 },
+  { 163, 1 },
+  { 150, 1 },
+  { 150, 1 },
+  { 150, 1 },
+  { 160, 0 },
+  { 160, 1 },
+  { 160, 4 },
+  { 160, 6 },
+  { 164, 1 },
   { 164, 2 },
-  { 167, 0 },
-  { 167, 2 },
-  { 167, 2 },
-  { 145, 0 },
-  { 145, 2 },
+  { 165, 1 },
+  { 165, 1 },
+  { 161, 2 },
+  { 161, 0 },
   { 168, 3 },
-  { 168, 2 },
   { 168, 1 },
+  { 168, 2 },
+  { 168, 3 },
+  { 168, 3 },
+  { 168, 2 },
   { 169, 2 },
-  { 169, 6 },
-  { 169, 5 },
   { 169, 3 },
-  { 169, 10 },
-  { 171, 0 },
-  { 171, 1 },
-  { 159, 0 },
-  { 159, 3 },
-  { 172, 0 },
-  { 172, 2 },
-  { 173, 1 },
-  { 173, 1 },
+  { 169, 5 },
+  { 169, 2 },
+  { 169, 5 },
+  { 169, 4 },
+  { 169, 1 },
+  { 169, 2 },
+  { 173, 0 },
   { 173, 1 },
-  { 136, 3 },
-  { 136, 7 },
-  { 136, 3 },
-  { 136, 1 },
-  { 146, 1 },
-  { 146, 3 },
-  { 177, 1 },
-  { 177, 2 },
-  { 177, 1 },
-  { 177, 1 },
-  { 176, 9 },
-  { 178, 1 },
-  { 178, 1 },
-  { 178, 0 },
-  { 186, 2 },
-  { 186, 0 },
-  { 179, 3 },
+  { 176, 0 },
+  { 176, 2 },
+  { 178, 2 },
+  { 178, 3 },
+  { 178, 3 },
+  { 178, 3 },
   { 179, 2 },
-  { 179, 4 },
-  { 187, 2 },
-  { 187, 1 },
-  { 187, 0 },
+  { 179, 2 },
+  { 179, 1 },
+  { 179, 1 },
+  { 177, 3 },
+  { 177, 2 },
   { 180, 0 },
   { 180, 2 },
-  { 189, 2 },
-  { 189, 0 },
-  { 188, 6 },
-  { 188, 7 },
-  { 193, 1 },
-  { 193, 1 },
-  { 143, 0 },
-  { 143, 2 },
-  { 175, 2 },
-  { 190, 1 },
+  { 180, 2 },
+  { 156, 0 },
+  { 156, 2 },
+  { 181, 3 },
+  { 181, 2 },
+  { 181, 1 },
+  { 182, 2 },
+  { 182, 7 },
+  { 182, 5 },
+  { 182, 3 },
+  { 182, 10 },
+  { 184, 0 },
+  { 184, 1 },
+  { 171, 0 },
+  { 171, 3 },
+  { 185, 0 },
+  { 185, 2 },
+  { 186, 1 },
+  { 186, 1 },
+  { 186, 1 },
+  { 146, 3 },
+  { 146, 7 },
+  { 146, 3 },
+  { 146, 1 },
+  { 157, 1 },
+  { 157, 3 },
   { 190, 1 },
   { 190, 2 },
-  { 190, 3 },
-  { 190, 4 },
-  { 191, 2 },
+  { 190, 1 },
+  { 190, 1 },
+  { 189, 9 },
+  { 191, 1 },
+  { 191, 1 },
   { 191, 0 },
+  { 199, 2 },
+  { 199, 0 },
+  { 192, 3 },
+  { 192, 2 },
   { 192, 4 },
-  { 192, 0 },
-  { 184, 0 },
-  { 184, 3 },
-  { 196, 5 },
-  { 196, 3 },
-  { 197, 1 },
-  { 160, 1 },
-  { 160, 1 },
-  { 160, 0 },
-  { 198, 0 },
-  { 198, 2 },
-  { 182, 0 },
-  { 182, 3 },
-  { 183, 0 },
-  { 183, 2 },
-  { 185, 0 },
-  { 185, 2 },
-  { 185, 4 },
-  { 185, 4 },
-  { 136, 4 },
-  { 181, 0 },
-  { 181, 2 },
-  { 136, 6 },
-  { 200, 5 },
-  { 200, 3 },
-  { 136, 8 },
-  { 136, 5 },
-  { 201, 2 },
-  { 201, 1 },
-  { 203, 3 },
-  { 203, 1 },
+  { 200, 2 },
+  { 200, 1 },
+  { 200, 0 },
+  { 193, 0 },
+  { 193, 2 },
+  { 202, 2 },
   { 202, 0 },
-  { 202, 3 },
-  { 195, 3 },
-  { 195, 1 },
-  { 161, 3 },
-  { 161, 1 },
-  { 161, 1 },
-  { 161, 1 },
-  { 161, 3 },
-  { 161, 5 },
-  { 161, 1 },
-  { 161, 1 },
-  { 161, 1 },
-  { 161, 1 },
-  { 161, 1 },
-  { 161, 4 },
-  { 161, 4 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 161, 3 },
-  { 204, 1 },
-  { 204, 1 },
-  { 204, 2 },
-  { 204, 2 },
-  { 161, 3 },
-  { 161, 2 },
-  { 161, 3 },
-  { 161, 2 },
-  { 161, 3 },
-  { 161, 4 },
-  { 161, 2 },
-  { 161, 2 },
-  { 161, 2 },
-  { 161, 2 },
-  { 161, 3 },
-  { 205, 1 },
-  { 205, 2 },
-  { 161, 5 },
+  { 201, 6 },
+  { 201, 7 },
   { 206, 1 },
-  { 206, 2 },
-  { 161, 5 },
-  { 161, 5 },
-  { 161, 4 },
-  { 161, 5 },
-  { 208, 5 },
-  { 208, 4 },
-  { 209, 2 },
-  { 209, 0 },
-  { 207, 1 },
-  { 207, 0 },
-  { 199, 3 },
-  { 199, 1 },
+  { 206, 1 },
+  { 154, 0 },
+  { 154, 2 },
+  { 188, 2 },
+  { 203, 1 },
+  { 203, 1 },
+  { 203, 2 },
+  { 203, 3 },
+  { 203, 4 },
+  { 204, 2 },
+  { 204, 0 },
+  { 205, 4 },
+  { 205, 0 },
+  { 197, 0 },
+  { 197, 3 },
+  { 209, 5 },
+  { 209, 3 },
   { 210, 1 },
-  { 210, 0 },
-  { 136, 11 },
-  { 211, 1 },
+  { 172, 1 },
+  { 172, 1 },
+  { 172, 0 },
   { 211, 0 },
-  { 162, 0 },
-  { 162, 3 },
-  { 170, 5 },
-  { 170, 3 },
-  { 212, 1 },
-  { 136, 3 },
-  { 136, 1 },
-  { 136, 2 },
-  { 136, 5 },
-  { 136, 5 },
-  { 136, 5 },
-  { 136, 5 },
-  { 136, 6 },
-  { 136, 3 },
-  { 155, 2 },
-  { 156, 2 },
-  { 214, 1 },
+  { 211, 2 },
+  { 195, 0 },
+  { 195, 3 },
+  { 196, 0 },
+  { 196, 2 },
+  { 198, 0 },
+  { 198, 2 },
+  { 198, 4 },
+  { 198, 4 },
+  { 146, 4 },
+  { 194, 0 },
+  { 194, 2 },
+  { 146, 6 },
+  { 213, 5 },
+  { 213, 3 },
+  { 146, 8 },
+  { 146, 5 },
+  { 214, 2 },
   { 214, 1 },
-  { 213, 1 },
-  { 213, 0 },
-  { 136, 5 },
-  { 215, 10 },
-  { 217, 1 },
-  { 217, 1 },
-  { 217, 2 },
-  { 217, 0 },
-  { 218, 1 },
-  { 218, 1 },
-  { 218, 1 },
-  { 218, 3 },
-  { 219, 0 },
-  { 219, 3 },
-  { 219, 3 },
-  { 220, 0 },
-  { 220, 2 },
   { 216, 3 },
-  { 216, 0 },
-  { 221, 6 },
-  { 221, 8 },
-  { 221, 5 },
-  { 221, 4 },
-  { 221, 1 },
-  { 161, 4 },
-  { 161, 6 },
+  { 216, 1 },
+  { 215, 0 },
+  { 215, 3 },
+  { 208, 3 },
+  { 208, 1 },
   { 174, 1 },
+  { 174, 3 },
+  { 170, 1 },
   { 174, 1 },
   { 174, 1 },
-  { 136, 3 },
-  { 136, 6 },
-  { 223, 0 },
-  { 223, 2 },
+  { 174, 3 },
+  { 174, 5 },
+  { 170, 1 },
+  { 170, 1 },
+  { 170, 1 },
+  { 174, 1 },
+  { 174, 1 },
+  { 174, 1 },
+  { 174, 4 },
+  { 174, 4 },
+  { 170, 1 },
+  { 170, 1 },
+  { 170, 1 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 174, 3 },
+  { 217, 1 },
+  { 217, 1 },
+  { 217, 2 },
+  { 217, 2 },
+  { 218, 2 },
+  { 218, 0 },
+  { 174, 4 },
+  { 174, 2 },
+  { 174, 3 },
+  { 174, 2 },
+  { 174, 3 },
+  { 174, 4 },
+  { 174, 2 },
+  { 174, 2 },
+  { 174, 2 },
+  { 174, 2 },
+  { 219, 1 },
+  { 219, 2 },
+  { 174, 5 },
+  { 220, 1 },
+  { 220, 2 },
+  { 174, 5 },
+  { 174, 3 },
+  { 174, 5 },
+  { 174, 4 },
+  { 174, 4 },
+  { 174, 5 },
+  { 222, 5 },
+  { 222, 4 },
   { 223, 2 },
-  { 222, 1 },
-  { 222, 0 },
-  { 136, 3 },
+  { 223, 0 },
+  { 221, 1 },
+  { 221, 0 },
+  { 212, 3 },
+  { 212, 1 },
+  { 224, 1 },
+  { 224, 0 },
+  { 146, 11 },
+  { 225, 1 },
+  { 225, 0 },
+  { 175, 0 },
+  { 175, 3 },
+  { 183, 5 },
+  { 183, 3 },
+  { 226, 1 },
+  { 146, 3 },
+  { 146, 1 },
+  { 146, 2 },
+  { 146, 5 },
+  { 146, 5 },
+  { 146, 5 },
+  { 146, 5 },
+  { 146, 6 },
+  { 146, 3 },
+  { 166, 2 },
+  { 167, 2 },
+  { 228, 1 },
+  { 228, 1 },
+  { 227, 1 },
+  { 227, 0 },
+  { 146, 5 },
+  { 229, 10 },
+  { 231, 1 },
+  { 231, 1 },
+  { 231, 2 },
+  { 231, 0 },
+  { 232, 1 },
+  { 232, 1 },
+  { 232, 1 },
+  { 232, 3 },
+  { 233, 0 },
+  { 233, 3 },
+  { 233, 3 },
+  { 234, 0 },
+  { 234, 2 },
+  { 230, 3 },
+  { 230, 0 },
+  { 235, 6 },
+  { 235, 8 },
+  { 235, 5 },
+  { 235, 4 },
+  { 235, 1 },
+  { 174, 4 },
+  { 174, 6 },
+  { 187, 1 },
+  { 187, 1 },
+  { 187, 1 },
+  { 146, 3 },
+  { 146, 6 },
+  { 237, 0 },
+  { 237, 2 },
+  { 237, 2 },
+  { 236, 1 },
+  { 236, 0 },
+  { 146, 3 },
+  { 146, 1 },
+  { 146, 3 },
+  { 146, 6 },
 };
 
 static void yy_accept(yyParser*);  /* Forward Declaration */
@@ -1786,99 +1887,101 @@ static void yy_reduce(
   **  #line <lineno> <thisfile>
   **     break;
   */
-      case 5:
-#line 86 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 3:
+#line 84 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 { sqlite3FinishCoding(pParse); }
-#line 1794 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1895 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 6:
-#line 87 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ sqlite3BeginParse(pParse, 1); }
-#line 1799 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 87 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ sqlite3BeginParse(pParse, 0); }
+#line 1900 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 7:
-#line 88 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ sqlite3BeginParse(pParse, 0); }
-#line 1804 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 89 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ sqlite3BeginParse(pParse, 1); }
+#line 1905 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 8:
-#line 93 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy284);}
-#line 1809 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 95 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy60);}
+#line 1910 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 12:
-#line 98 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = TK_DEFERRED;}
-#line 1814 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 100 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = TK_DEFERRED;}
+#line 1915 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 13:
       case 14:
       case 15:
-      case 99:
       case 101:
-      case 102:
-#line 99 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = yymsp[0].major;}
-#line 1824 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 103:
+      case 104:
+#line 101 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = yymsp[0].major;}
+#line 1925 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 16:
       case 17:
-#line 102 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 104 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {sqlite3CommitTransaction(pParse);}
-#line 1830 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1931 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 18:
-#line 104 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 106 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {sqlite3RollbackTransaction(pParse);}
-#line 1835 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1936 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 20:
-#line 109 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 111 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-   sqlite3StartTable(pParse,&yymsp[-4].minor.yy0,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98,yymsp[-3].minor.yy284,0);
+   sqlite3StartTable(pParse,&yymsp[-4].minor.yy0,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406,yymsp[-3].minor.yy60,0);
 }
-#line 1842 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1943 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 21:
-      case 72:
-      case 104:
-      case 216:
-      case 219:
-#line 113 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = 1;}
-#line 1851 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 60:
+      case 74:
+      case 106:
+      case 224:
+      case 227:
+#line 115 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = 1;}
+#line 1953 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 22:
-      case 71:
+      case 59:
       case 73:
-      case 84:
-      case 105:
-      case 106:
-      case 215:
-      case 218:
-#line 114 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = 0;}
-#line 1863 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 75:
+      case 86:
+      case 107:
+      case 108:
+      case 223:
+      case 226:
+#line 116 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = 0;}
+#line 1966 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 23:
-#line 115 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 117 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
   sqlite3EndTable(pParse,&yymsp[0].minor.yy0,0);
 }
-#line 1870 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1973 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 24:
-#line 118 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 120 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  sqlite3EndTable(pParse,0,yymsp[0].minor.yy107);
-  sqlite3SelectDelete(yymsp[0].minor.yy107);
+  sqlite3EndTable(pParse,0,yymsp[0].minor.yy331);
+  sqlite3SelectDelete(yymsp[0].minor.yy331);
 }
-#line 1878 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1981 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 28:
-#line 130 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumn(pParse,&yymsp[0].minor.yy98);}
-#line 1883 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 132 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddColumn(pParse,&yymsp[0].minor.yy406);}
+#line 1986 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 29:
       case 30:
@@ -1886,600 +1989,619 @@ static void yy_reduce(
       case 32:
       case 33:
       case 34:
-      case 253:
-      case 254:
-#line 136 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98 = yymsp[0].minor.yy0;}
-#line 1895 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 263:
+      case 264:
+#line 138 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406 = yymsp[0].minor.yy0;}
+#line 1998 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 36:
-#line 185 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy98,&yymsp[0].minor.yy98);}
-#line 1900 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 193 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy406,&yymsp[0].minor.yy406);}
+#line 2003 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 37:
-#line 186 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[-3].minor.yy98,&yymsp[0].minor.yy0);}
-#line 1905 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 194 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddColumnType(pParse,&yymsp[-3].minor.yy406,&yymsp[0].minor.yy0);}
+#line 2008 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 38:
-#line 188 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[-5].minor.yy98,&yymsp[0].minor.yy0);}
-#line 1910 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 196 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddColumnType(pParse,&yymsp[-5].minor.yy406,&yymsp[0].minor.yy0);}
+#line 2013 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 39:
-      case 112:
-      case 113:
-      case 124:
-      case 144:
-      case 241:
+      case 114:
+      case 115:
+      case 126:
+      case 146:
       case 251:
-      case 252:
-#line 190 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98 = yymsp[0].minor.yy98;}
-#line 1922 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 261:
+      case 262:
+#line 198 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406 = yymsp[0].minor.yy406;}
+#line 2025 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 40:
-#line 191 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98.z=yymsp[-1].minor.yy98.z; yygotominor.yy98.n=yymsp[0].minor.yy98.n+(yymsp[0].minor.yy98.z-yymsp[-1].minor.yy98.z);}
-#line 1927 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 199 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406.z=yymsp[-1].minor.yy406.z; yygotominor.yy406.n=yymsp[0].minor.yy406.n+(yymsp[0].minor.yy406.z-yymsp[-1].minor.yy406.z);}
+#line 2030 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 41:
-#line 193 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = atoi(yymsp[0].minor.yy98.z); }
-#line 1932 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 201 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = atoi(yymsp[0].minor.yy406.z); }
+#line 2035 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 42:
-#line 194 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = -atoi(yymsp[0].minor.yy98.z); }
-#line 1937 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 202 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = -atoi(yymsp[0].minor.yy406.z); }
+#line 2040 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 47:
       case 48:
-#line 199 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy98,0);}
-#line 1943 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 207 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454);}
+#line 2046 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 49:
-#line 201 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy98,1);}
-#line 1948 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 209 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+  Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy454, 0, 0);
+  sqlite3AddDefaultValue(pParse,p);
+}
+#line 2054 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 50:
+#line 213 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+  Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy406);
+  sqlite3AddDefaultValue(pParse,p);
+}
+#line 2062 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 52:
-#line 208 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy284);}
-#line 1953 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 222 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy60);}
+#line 2067 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 53:
-#line 209 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddPrimaryKey(pParse,0,yymsp[0].minor.yy284);}
-#line 1958 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 224 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy60,yymsp[0].minor.yy60);}
+#line 2072 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 54:
-#line 210 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy284,0,0);}
-#line 1963 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 225 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy60,0,0);}
+#line 2077 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 56:
-#line 213 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy98,yymsp[-1].minor.yy210,yymsp[0].minor.yy284);}
-#line 1968 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 228 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy406,yymsp[-1].minor.yy266,yymsp[0].minor.yy60);}
+#line 2082 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 57:
-#line 214 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy284);}
-#line 1973 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 229 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy60);}
+#line 2087 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 58:
-#line 215 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddCollateType(pParse, yymsp[0].minor.yy98.z, yymsp[0].minor.yy98.n);}
-#line 1978 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 59:
-#line 223 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = OE_Restrict * 0x010101; }
-#line 1983 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 60:
-#line 224 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = (yymsp[-1].minor.yy284 & yymsp[0].minor.yy47.mask) | yymsp[0].minor.yy47.value; }
-#line 1988 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 230 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddCollateType(pParse, yymsp[0].minor.yy406.z, yymsp[0].minor.yy406.n);}
+#line 2092 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 61:
-#line 226 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = 0;     yygotominor.yy47.mask = 0x000000; }
-#line 1993 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 243 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = OE_Restrict * 0x010101; }
+#line 2097 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 62:
-#line 227 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = yymsp[0].minor.yy284;     yygotominor.yy47.mask = 0x0000ff; }
-#line 1998 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 244 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = (yymsp[-1].minor.yy60 & yymsp[0].minor.yy243.mask) | yymsp[0].minor.yy243.value; }
+#line 2102 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 63:
-#line 228 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = yymsp[0].minor.yy284<<8;  yygotominor.yy47.mask = 0x00ff00; }
-#line 2003 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 246 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy243.value = 0;     yygotominor.yy243.mask = 0x000000; }
+#line 2107 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 64:
-#line 229 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = yymsp[0].minor.yy284<<16; yygotominor.yy47.mask = 0xff0000; }
-#line 2008 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 247 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy243.value = yymsp[0].minor.yy60;     yygotominor.yy243.mask = 0x0000ff; }
+#line 2112 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 65:
-#line 231 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = OE_SetNull; }
-#line 2013 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 248 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy243.value = yymsp[0].minor.yy60<<8;  yygotominor.yy243.mask = 0x00ff00; }
+#line 2117 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 66:
-#line 232 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = OE_SetDflt; }
-#line 2018 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 249 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy243.value = yymsp[0].minor.yy60<<16; yygotominor.yy243.mask = 0xff0000; }
+#line 2122 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 67:
-#line 233 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = OE_Cascade; }
-#line 2023 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 251 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = OE_SetNull; }
+#line 2127 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 68:
-#line 234 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = OE_Restrict; }
-#line 2028 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 252 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = OE_SetDflt; }
+#line 2132 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 69:
+#line 253 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = OE_Cascade; }
+#line 2137 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
       case 70:
-      case 85:
+#line 254 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = OE_Restrict; }
+#line 2142 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 71:
+      case 72:
       case 87:
       case 89:
-      case 90:
-      case 161:
-#line 236 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = yymsp[0].minor.yy284;}
-#line 2039 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 80:
-#line 253 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddPrimaryKey(pParse,yymsp[-2].minor.yy210,yymsp[0].minor.yy284);}
-#line 2044 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 91:
+      case 92:
+      case 163:
+#line 256 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = yymsp[0].minor.yy60;}
+#line 2153 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 81:
-#line 255 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy210,yymsp[0].minor.yy284,0,0);}
-#line 2049 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 82:
+#line 273 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy266,yymsp[0].minor.yy60,yymsp[-2].minor.yy60);}
+#line 2158 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 83:
-#line 258 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 275 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy266,yymsp[0].minor.yy60,0,0);}
+#line 2163 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 85:
+#line 278 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy210, &yymsp[-3].minor.yy98, yymsp[-2].minor.yy210, yymsp[-1].minor.yy284);
-    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy284);
+    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy266, &yymsp[-3].minor.yy406, yymsp[-2].minor.yy266, yymsp[-1].minor.yy60);
+    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy60);
 }
-#line 2057 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2171 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 86:
       case 88:
-#line 272 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Default;}
-#line 2063 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 91:
-#line 277 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Ignore;}
-#line 2068 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 92:
-      case 162:
-#line 278 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Replace;}
-#line 2074 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 90:
+#line 292 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Default;}
+#line 2177 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 93:
-#line 282 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
-  sqlite3DropTable(pParse, yymsp[0].minor.yy259, 0);
-}
-#line 2081 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 297 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Ignore;}
+#line 2182 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 94:
-#line 288 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
-  sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy98, &yymsp[-2].minor.yy98, yymsp[0].minor.yy107, yymsp[-5].minor.yy284);
-}
-#line 2088 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 164:
+#line 298 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Replace;}
+#line 2188 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 95:
-#line 291 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 302 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  sqlite3DropTable(pParse, yymsp[0].minor.yy259, 1);
+  sqlite3DropTable(pParse, yymsp[0].minor.yy427, 0);
 }
-#line 2095 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2195 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 96:
-#line 297 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 309 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  sqlite3Select(pParse, yymsp[0].minor.yy107, SRT_Callback, 0, 0, 0, 0, 0);
-  sqlite3SelectDelete(yymsp[0].minor.yy107);
+  sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy406, &yymsp[-2].minor.yy406, yymsp[0].minor.yy331, yymsp[-5].minor.yy60);
 }
-#line 2103 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2202 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 97:
-      case 121:
-#line 307 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy107 = yymsp[0].minor.yy107;}
-#line 2109 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 312 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+  sqlite3DropTable(pParse, yymsp[0].minor.yy427, 1);
+}
+#line 2209 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 98:
-#line 308 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 319 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  if( yymsp[0].minor.yy107 ){
-    yymsp[0].minor.yy107->op = yymsp[-1].minor.yy284;
-    yymsp[0].minor.yy107->pPrior = yymsp[-2].minor.yy107;
-  }
-  yygotominor.yy107 = yymsp[0].minor.yy107;
+  sqlite3Select(pParse, yymsp[0].minor.yy331, SRT_Callback, 0, 0, 0, 0, 0);
+  sqlite3SelectDelete(yymsp[0].minor.yy331);
 }
-#line 2120 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2217 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 100:
-#line 317 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = TK_ALL;}
-#line 2125 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 99:
+      case 123:
+#line 329 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy331 = yymsp[0].minor.yy331;}
+#line 2223 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 103:
-#line 321 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 100:
+#line 331 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy107 = sqlite3SelectNew(yymsp[-6].minor.yy210,yymsp[-5].minor.yy259,yymsp[-4].minor.yy258,yymsp[-3].minor.yy210,yymsp[-2].minor.yy258,yymsp[-1].minor.yy210,yymsp[-7].minor.yy284,yymsp[0].minor.yy404.limit,yymsp[0].minor.yy404.offset);
+  if( yymsp[0].minor.yy331 ){
+    yymsp[0].minor.yy331->op = yymsp[-1].minor.yy60;
+    yymsp[0].minor.yy331->pPrior = yymsp[-2].minor.yy331;
+  }
+  yygotominor.yy331 = yymsp[0].minor.yy331;
 }
-#line 2132 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2234 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 107:
-      case 238:
-#line 342 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = yymsp[-1].minor.yy210;}
-#line 2138 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 102:
+#line 340 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = TK_ALL;}
+#line 2239 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 108:
-      case 135:
-      case 145:
-      case 237:
-#line 343 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = 0;}
-#line 2146 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 105:
+#line 345 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+  yygotominor.yy331 = sqlite3SelectNew(yymsp[-6].minor.yy266,yymsp[-5].minor.yy427,yymsp[-4].minor.yy454,yymsp[-3].minor.yy266,yymsp[-2].minor.yy454,yymsp[-1].minor.yy266,yymsp[-7].minor.yy60,yymsp[0].minor.yy348.pLimit,yymsp[0].minor.yy348.pOffset);
+}
+#line 2246 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 109:
-#line 344 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 248:
+#line 366 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = yymsp[-1].minor.yy266;}
+#line 2252 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 110:
+      case 137:
+      case 147:
+      case 247:
+#line 367 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = 0;}
+#line 2260 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 111:
+#line 368 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-   yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-2].minor.yy210,yymsp[-1].minor.yy258,yymsp[0].minor.yy98.n?&yymsp[0].minor.yy98:0);
+   yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-2].minor.yy266,yymsp[-1].minor.yy454,yymsp[0].minor.yy406.n?&yymsp[0].minor.yy406:0);
 }
-#line 2153 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2267 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 110:
-#line 347 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 112:
+#line 371 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-1].minor.yy210, sqlite3Expr(TK_ALL, 0, 0, 0), 0);
+  yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-1].minor.yy266, sqlite3Expr(TK_ALL, 0, 0, 0), 0);
 }
-#line 2160 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2274 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 111:
-#line 350 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 113:
+#line 374 "/home/wez/php5-HEAD/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.yy98);
-  yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-3].minor.yy210, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0);
+  Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy406);
+  yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-3].minor.yy266, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0);
 }
-#line 2169 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 114:
-#line 362 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98.n = 0;}
-#line 2174 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 115:
-#line 374 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy259 = sqliteMalloc(sizeof(*yygotominor.yy259));}
-#line 2179 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2283 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 116:
-#line 375 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy259 = yymsp[0].minor.yy259;}
-#line 2184 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 386 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406.n = 0;}
+#line 2288 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 117:
-#line 380 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
-   yygotominor.yy259 = yymsp[-1].minor.yy259;
-   if( yygotominor.yy259 && yygotominor.yy259->nSrc>0 ) yygotominor.yy259->a[yygotominor.yy259->nSrc-1].jointype = yymsp[0].minor.yy284;
-}
-#line 2192 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 398 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy427 = sqliteMalloc(sizeof(*yygotominor.yy427));}
+#line 2293 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 118:
-#line 384 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy259 = 0;}
-#line 2197 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 399 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy427 = yymsp[0].minor.yy427;}
+#line 2298 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 119:
-#line 385 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 404 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy259 = sqlite3SrcListAppend(yymsp[-5].minor.yy259,&yymsp[-4].minor.yy98,&yymsp[-3].minor.yy98);
-  if( yymsp[-2].minor.yy98.n ) sqlite3SrcListAddAlias(yygotominor.yy259,&yymsp[-2].minor.yy98);
-  if( yymsp[-1].minor.yy258 ){
-    if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pOn = yymsp[-1].minor.yy258; }
-    else { sqlite3ExprDelete(yymsp[-1].minor.yy258); }
-  }
-  if( yymsp[0].minor.yy272 ){
-    if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pUsing = yymsp[0].minor.yy272; }
-    else { sqlite3IdListDelete(yymsp[0].minor.yy272); }
-  }
+   yygotominor.yy427 = yymsp[-1].minor.yy427;
+   if( yygotominor.yy427 && yygotominor.yy427->nSrc>0 ) yygotominor.yy427->a[yygotominor.yy427->nSrc-1].jointype = yymsp[0].minor.yy60;
 }
-#line 2213 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2306 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 120:
-#line 398 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 408 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy427 = 0;}
+#line 2311 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 121:
+#line 409 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy259 = sqlite3SrcListAppend(yymsp[-6].minor.yy259,0,0);
-  yygotominor.yy259->a[yygotominor.yy259->nSrc-1].pSelect = yymsp[-4].minor.yy107;
-  if( yymsp[-2].minor.yy98.n ) sqlite3SrcListAddAlias(yygotominor.yy259,&yymsp[-2].minor.yy98);
-  if( yymsp[-1].minor.yy258 ){
-    if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pOn = yymsp[-1].minor.yy258; }
-    else { sqlite3ExprDelete(yymsp[-1].minor.yy258); }
+  yygotominor.yy427 = sqlite3SrcListAppend(yymsp[-5].minor.yy427,&yymsp[-4].minor.yy406,&yymsp[-3].minor.yy406);
+  if( yymsp[-2].minor.yy406.n ) sqlite3SrcListAddAlias(yygotominor.yy427,&yymsp[-2].minor.yy406);
+  if( yymsp[-1].minor.yy454 ){
+    if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pOn = yymsp[-1].minor.yy454; }
+    else { sqlite3ExprDelete(yymsp[-1].minor.yy454); }
   }
   if( yymsp[0].minor.yy272 ){
-    if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pUsing = yymsp[0].minor.yy272; }
+    if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pUsing = yymsp[0].minor.yy272; }
     else { sqlite3IdListDelete(yymsp[0].minor.yy272); }
   }
 }
-#line 2230 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2327 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 122:
-#line 419 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 423 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-   yygotominor.yy107 = sqlite3SelectNew(0,yymsp[0].minor.yy259,0,0,0,0,0,-1,0);
-}
-#line 2237 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+    yygotominor.yy427 = sqlite3SrcListAppend(yymsp[-6].minor.yy427,0,0);
+    yygotominor.yy427->a[yygotominor.yy427->nSrc-1].pSelect = yymsp[-4].minor.yy331;
+    if( yymsp[-2].minor.yy406.n ) sqlite3SrcListAddAlias(yygotominor.yy427,&yymsp[-2].minor.yy406);
+    if( yymsp[-1].minor.yy454 ){
+      if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pOn = yymsp[-1].minor.yy454; }
+      else { sqlite3ExprDelete(yymsp[-1].minor.yy454); }
+    }
+    if( yymsp[0].minor.yy272 ){
+      if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pUsing = yymsp[0].minor.yy272; }
+      else { sqlite3IdListDelete(yymsp[0].minor.yy272); }
+    }
+  }
+#line 2344 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 123:
-#line 424 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98.z=0; yygotominor.yy98.n=0;}
-#line 2242 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 124:
+#line 444 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+     yygotominor.yy331 = sqlite3SelectNew(0,yymsp[0].minor.yy427,0,0,0,0,0,0,0);
+  }
+#line 2351 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 125:
-#line 429 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy259 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98);}
-#line 2247 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 450 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406.z=0; yygotominor.yy406.n=0;}
+#line 2356 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 126:
       case 127:
-#line 433 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = JT_INNER; }
-#line 2253 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 455 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy427 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406);}
+#line 2361 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 128:
-#line 435 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
-#line 2258 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 129:
-#line 436 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy98,0); }
-#line 2263 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 459 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = JT_INNER; }
+#line 2367 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 130:
-#line 438 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy98,&yymsp[-1].minor.yy98); }
-#line 2268 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 461 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+#line 2372 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 131:
-      case 139:
-      case 148:
-      case 155:
-      case 226:
-      case 228:
-      case 232:
-#line 442 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = yymsp[0].minor.yy258;}
-#line 2279 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 462 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy406,0); }
+#line 2377 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 132:
-      case 147:
-      case 154:
-      case 227:
-      case 229:
-      case 233:
-#line 443 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = 0;}
-#line 2289 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 464 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy406,&yymsp[-1].minor.yy406); }
+#line 2382 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 133:
-      case 166:
-#line 447 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy272 = yymsp[-1].minor.yy272;}
-#line 2295 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 141:
+      case 150:
+      case 157:
+      case 171:
+      case 211:
+      case 236:
+      case 238:
+      case 242:
+#line 468 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = yymsp[0].minor.yy454;}
+#line 2395 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 134:
-      case 165:
-#line 448 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy272 = 0;}
-#line 2301 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 149:
+      case 156:
+      case 212:
+      case 237:
+      case 239:
+      case 243:
+#line 469 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = 0;}
+#line 2406 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 135:
+      case 168:
+#line 473 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy272 = yymsp[-1].minor.yy272;}
+#line 2412 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 136:
-      case 146:
-#line 459 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = yymsp[0].minor.yy210;}
-#line 2307 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 167:
+#line 474 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy272 = 0;}
+#line 2418 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 137:
-#line 460 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 138:
+      case 148:
+#line 485 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = yymsp[0].minor.yy266;}
+#line 2424 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 139:
+#line 486 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210,yymsp[-2].minor.yy258,yymsp[-1].minor.yy98.n>0?&yymsp[-1].minor.yy98:0);
-  if( yygotominor.yy210 ) yygotominor.yy210->a[yygotominor.yy210->nExpr-1].sortOrder = yymsp[0].minor.yy284;
+  yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266,yymsp[-2].minor.yy454,yymsp[-1].minor.yy406.n>0?&yymsp[-1].minor.yy406:0);
+  if( yygotominor.yy266 ) yygotominor.yy266->a[yygotominor.yy266->nExpr-1].sortOrder = yymsp[0].minor.yy60;
 }
-#line 2315 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2432 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 138:
-#line 464 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 140:
+#line 490 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy210 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy258,yymsp[-1].minor.yy98.n>0?&yymsp[-1].minor.yy98:0);
-  if( yygotominor.yy210 && yygotominor.yy210->a ) yygotominor.yy210->a[0].sortOrder = yymsp[0].minor.yy284;
+  yygotominor.yy266 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy454,yymsp[-1].minor.yy406.n>0?&yymsp[-1].minor.yy406:0);
+  if( yygotominor.yy266 && yygotominor.yy266->a ) yygotominor.yy266->a[0].sortOrder = yymsp[0].minor.yy60;
 }
-#line 2323 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2440 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 140:
       case 142:
-#line 473 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = SQLITE_SO_ASC;}
-#line 2329 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 141:
-#line 474 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = SQLITE_SO_DESC;}
-#line 2334 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 144:
+#line 499 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = SQLITE_SO_ASC;}
+#line 2446 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 143:
-#line 476 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98.z = 0; yygotominor.yy98.n = 0;}
-#line 2339 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 149:
-#line 490 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy404.limit = -1; yygotominor.yy404.offset = 0;}
-#line 2344 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 500 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = SQLITE_SO_DESC;}
+#line 2451 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 150:
-#line 491 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy404.limit = yymsp[0].minor.yy284; yygotominor.yy404.offset = 0;}
-#line 2349 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 145:
+#line 502 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406.z = 0; yygotominor.yy406.n = 0;}
+#line 2456 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 151:
-#line 493 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy404.limit = yymsp[-2].minor.yy284; yygotominor.yy404.offset = yymsp[0].minor.yy284;}
-#line 2354 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 520 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy348.pLimit = 0; yygotominor.yy348.pOffset = 0;}
+#line 2461 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 152:
-#line 495 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy404.limit = yymsp[0].minor.yy284; yygotominor.yy404.offset = yymsp[-2].minor.yy284;}
-#line 2359 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 521 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy348.pLimit = yymsp[0].minor.yy454; yygotominor.yy348.pOffset = 0;}
+#line 2466 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 153:
-#line 499 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy259,yymsp[0].minor.yy258);}
-#line 2364 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 523 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy348.pLimit = yymsp[-2].minor.yy454; yygotominor.yy348.pOffset = yymsp[0].minor.yy454;}
+#line 2471 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 156:
-#line 513 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Update(pParse,yymsp[-3].minor.yy259,yymsp[-1].minor.yy210,yymsp[0].minor.yy258,yymsp[-4].minor.yy284);}
-#line 2369 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 154:
+#line 525 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy348.pOffset = yymsp[-2].minor.yy454; yygotominor.yy348.pLimit = yymsp[0].minor.yy454;}
+#line 2476 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 157:
-#line 516 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210,yymsp[0].minor.yy258,&yymsp[-2].minor.yy98);}
-#line 2374 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 155:
+#line 529 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy427,yymsp[0].minor.yy454);}
+#line 2481 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 158:
-#line 517 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = sqlite3ExprListAppend(0,yymsp[0].minor.yy258,&yymsp[-2].minor.yy98);}
-#line 2379 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 543 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Update(pParse,yymsp[-3].minor.yy427,yymsp[-1].minor.yy266,yymsp[0].minor.yy454,yymsp[-4].minor.yy60);}
+#line 2486 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 159:
-#line 523 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Insert(pParse, yymsp[-5].minor.yy259, yymsp[-1].minor.yy210, 0, yymsp[-4].minor.yy272, yymsp[-7].minor.yy284);}
-#line 2384 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 546 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266,yymsp[0].minor.yy454,&yymsp[-2].minor.yy406);}
+#line 2491 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 160:
-#line 525 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Insert(pParse, yymsp[-2].minor.yy259, 0, yymsp[0].minor.yy107, yymsp[-1].minor.yy272, yymsp[-4].minor.yy284);}
-#line 2389 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 547 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = sqlite3ExprListAppend(0,yymsp[0].minor.yy454,&yymsp[-2].minor.yy406);}
+#line 2496 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 163:
-      case 230:
-#line 535 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-2].minor.yy210,yymsp[0].minor.yy258,0);}
-#line 2395 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 161:
+#line 553 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Insert(pParse, yymsp[-5].minor.yy427, yymsp[-1].minor.yy266, 0, yymsp[-4].minor.yy272, yymsp[-7].minor.yy60);}
+#line 2501 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 164:
-      case 231:
-#line 536 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = sqlite3ExprListAppend(0,yymsp[0].minor.yy258,0);}
-#line 2401 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 162:
+#line 555 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Insert(pParse, yymsp[-2].minor.yy427, 0, yymsp[0].minor.yy331, yymsp[-1].minor.yy272, yymsp[-4].minor.yy60);}
+#line 2506 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 167:
-#line 545 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy272 = sqlite3IdListAppend(yymsp[-2].minor.yy272,&yymsp[0].minor.yy98);}
-#line 2406 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 165:
+      case 240:
+#line 565 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-2].minor.yy266,yymsp[0].minor.yy454,0);}
+#line 2512 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 168:
-#line 546 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy272 = sqlite3IdListAppend(0,&yymsp[0].minor.yy98);}
-#line 2411 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 166:
+      case 241:
+#line 566 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = sqlite3ExprListAppend(0,yymsp[0].minor.yy454,0);}
+#line 2518 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 169:
-#line 554 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = yymsp[-1].minor.yy258; sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
-#line 2416 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 575 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy272 = sqlite3IdListAppend(yymsp[-2].minor.yy272,&yymsp[0].minor.yy406);}
+#line 2523 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 170:
-      case 175:
-      case 176:
-      case 177:
-      case 178:
-#line 555 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
-#line 2425 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 576 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy272 = sqlite3IdListAppend(0,&yymsp[0].minor.yy406);}
+#line 2528 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 171:
       case 172:
-#line 556 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
-#line 2431 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 587 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = yymsp[-1].minor.yy454; sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
+#line 2533 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 173:
-#line 558 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 178:
+      case 179:
+      case 180:
+      case 181:
+#line 588 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
+#line 2542 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 174:
+      case 175:
+#line 589 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
+#line 2548 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 176:
+#line 591 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy98);
-  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy98);
-  yygotominor.yy258 = sqlite3Expr(TK_DOT, temp1, temp2, 0);
+  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy406);
+  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy406);
+  yygotominor.yy454 = sqlite3Expr(TK_DOT, temp1, temp2, 0);
 }
-#line 2440 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2557 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 174:
-#line 563 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 177:
+#line 596 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy98);
-  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy98);
-  Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy98);
+  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy406);
+  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy406);
+  Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy406);
   Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
-  yygotominor.yy258 = sqlite3Expr(TK_DOT, temp1, temp4, 0);
+  yygotominor.yy454 = sqlite3Expr(TK_DOT, temp1, temp4, 0);
 }
-#line 2451 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2568 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 179:
-#line 574 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 182:
+#line 607 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
+#line 2573 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 183:
+#line 608 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
   Token *pToken = &yymsp[0].minor.yy0;
-  Expr *pExpr = yygotominor.yy258 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
+  Expr *pExpr = yygotominor.yy454 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
   sqlite3ExprAssignVarNumber(pParse, pExpr);
 }
-#line 2460 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2582 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 180:
-#line 579 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 184:
+#line 613 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3ExprFunction(yymsp[-1].minor.yy210, &yymsp[-3].minor.yy0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+  yygotominor.yy454 = sqlite3ExprFunction(yymsp[-1].minor.yy266, &yymsp[-3].minor.yy0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
 }
-#line 2468 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2590 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 181:
-#line 583 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 185:
+#line 617 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+  yygotominor.yy454 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
 }
-#line 2476 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2598 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 182:
-      case 183:
-      case 184:
-      case 185:
       case 186:
       case 187:
       case 188:
+#line 621 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = sqlite3Expr(yymsp[0].major,0,0,0);}
+#line 2605 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
       case 189:
       case 190:
       case 191:
@@ -2491,435 +2613,473 @@ static void yy_reduce(
       case 197:
       case 198:
       case 199:
-#line 587 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy258, yymsp[0].minor.yy258, 0);}
-#line 2498 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 200:
-#line 606 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy342.opcode = TK_LIKE; yygotominor.yy342.not = 0;}
-#line 2503 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 201:
-#line 607 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy342.opcode = TK_GLOB; yygotominor.yy342.not = 0;}
-#line 2508 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 202:
-#line 608 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy342.opcode = TK_LIKE; yygotominor.yy342.not = 1;}
-#line 2513 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 203:
-#line 609 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy342.opcode = TK_GLOB; yygotominor.yy342.not = 1;}
-#line 2518 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 204:
-#line 610 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
-  ExprList *pList = sqlite3ExprListAppend(0, yymsp[0].minor.yy258, 0);
-  pList = sqlite3ExprListAppend(pList, yymsp[-2].minor.yy258, 0);
-  yygotominor.yy258 = sqlite3ExprFunction(pList, 0);
-  if( yygotominor.yy258 ) yygotominor.yy258->op = yymsp[-1].minor.yy342.opcode;
-  if( yymsp[-1].minor.yy342.not ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258, &yymsp[-2].minor.yy258->span, &yymsp[0].minor.yy258->span);
-}
-#line 2530 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 205:
-#line 618 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
-  yygotominor.yy258 = sqlite3Expr(TK_ISNULL, yymsp[-1].minor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy258->span,&yymsp[0].minor.yy0);
-}
-#line 2538 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 206:
-#line 622 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
-  yygotominor.yy258 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy258->span,&yymsp[0].minor.yy0);
-}
-#line 2546 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 624 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy454, yymsp[0].minor.yy454, 0);}
+#line 2627 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 207:
-#line 626 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
-  yygotominor.yy258 = sqlite3Expr(TK_NOTNULL, yymsp[-1].minor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy258->span,&yymsp[0].minor.yy0);
-}
-#line 2554 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 643 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy258.opcode = TK_LIKE; yygotominor.yy258.not = 0;}
+#line 2632 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 208:
-#line 630 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
-  yygotominor.yy258 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy258->span,&yymsp[0].minor.yy0);
-}
-#line 2562 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 644 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy258.opcode = TK_GLOB; yygotominor.yy258.not = 0;}
+#line 2637 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 209:
-#line 634 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
-  yygotominor.yy258 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy258->span,&yymsp[0].minor.yy0);
-}
-#line 2570 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 645 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy258.opcode = TK_LIKE; yygotominor.yy258.not = 1;}
+#line 2642 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 210:
-      case 211:
-#line 638 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 646 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy258.opcode = TK_GLOB; yygotominor.yy258.not = 1;}
+#line 2647 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 213:
+#line 650 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy258->span);
+  ExprList *pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy454, 0);
+  pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy454, 0);
+  if( yymsp[0].minor.yy454 ){
+    pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy454, 0);
+  }
+  yygotominor.yy454 = sqlite3ExprFunction(pList, 0);
+  if( yygotominor.yy454 ) yygotominor.yy454->op = yymsp[-2].minor.yy258.opcode;
+  if( yymsp[-2].minor.yy258.not ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy454, &yymsp[-3].minor.yy454->span, &yymsp[-1].minor.yy454->span);
 }
-#line 2579 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2662 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 212:
-#line 646 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 214:
+#line 662 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy258->span);
+  yygotominor.yy454 = sqlite3Expr(TK_ISNULL, yymsp[-1].minor.yy454, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy454->span,&yymsp[0].minor.yy0);
 }
-#line 2587 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2670 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 213:
-#line 650 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 215:
+#line 666 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy258->span);
+  yygotominor.yy454 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy454, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy454->span,&yymsp[0].minor.yy0);
 }
-#line 2595 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2678 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 214:
-#line 654 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 216:
+#line 670 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3Expr(TK_SELECT, 0, 0, 0);
-  if( yygotominor.yy258 ) yygotominor.yy258->pSelect = yymsp[-1].minor.yy107;
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+  yygotominor.yy454 = sqlite3Expr(TK_NOTNULL, yymsp[-1].minor.yy454, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy454->span,&yymsp[0].minor.yy0);
 }
-#line 2604 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2686 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 217:
-#line 662 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 674 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+  yygotominor.yy454 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy454, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy454->span,&yymsp[0].minor.yy0);
+}
+#line 2694 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 218:
+#line 678 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy258, 0);
-  pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy258, 0);
-  yygotominor.yy258 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy258, 0, 0);
-  if( yygotominor.yy258 ) yygotominor.yy258->pList = pList;
-  if( yymsp[-3].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-4].minor.yy258->span,&yymsp[0].minor.yy258->span);
+  yygotominor.yy454 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy454, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy454->span,&yymsp[0].minor.yy0);
 }
-#line 2616 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2702 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
+      case 219:
       case 220:
-#line 673 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 682 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy258, 0, 0);
-  if( yygotominor.yy258 ) yygotominor.yy258->pList = yymsp[-1].minor.yy210;
-  if( yymsp[-3].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-4].minor.yy258->span,&yymsp[0].minor.yy0);
+  yygotominor.yy454 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy454, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy454->span);
 }
-#line 2626 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2711 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 221:
-#line 679 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 690 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy258, 0, 0);
-  if( yygotominor.yy258 ) yygotominor.yy258->pSelect = yymsp[-1].minor.yy107;
-  if( yymsp[-3].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-4].minor.yy258->span,&yymsp[0].minor.yy0);
+  yygotominor.yy454 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy454, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy454->span);
 }
-#line 2636 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2719 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 222:
-#line 685 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 694 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98);
-  yygotominor.yy258 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy258, 0, 0);
-  if( yygotominor.yy258 ) yygotominor.yy258->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,-1,0);
-  if( yymsp[-2].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy258->span,yymsp[0].minor.yy98.z?&yymsp[0].minor.yy98:&yymsp[-1].minor.yy98);
+  yygotominor.yy454 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy454, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy454->span);
 }
-#line 2647 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2727 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 223:
-#line 695 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 225:
+#line 701 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy258, yymsp[-1].minor.yy258, 0);
-  if( yygotominor.yy258 ) yygotominor.yy258->pList = yymsp[-2].minor.yy210;
-  sqlite3ExprSpan(yygotominor.yy258, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
+  ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy454, 0);
+  pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy454, 0);
+  yygotominor.yy454 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy454, 0, 0);
+  if( yygotominor.yy454 ) yygotominor.yy454->pList = pList;
+  if( yymsp[-3].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy454,&yymsp[-4].minor.yy454->span,&yymsp[0].minor.yy454->span);
 }
-#line 2656 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2739 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 224:
-#line 702 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 228:
+#line 713 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210, yymsp[-2].minor.yy258, 0);
-  yygotominor.yy210 = sqlite3ExprListAppend(yygotominor.yy210, yymsp[0].minor.yy258, 0);
-}
-#line 2664 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+    yygotominor.yy454 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy454, 0, 0);
+    if( yygotominor.yy454 ) yygotominor.yy454->pList = yymsp[-1].minor.yy266;
+    if( yymsp[-3].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0);
+    sqlite3ExprSpan(yygotominor.yy454,&yymsp[-4].minor.yy454->span,&yymsp[0].minor.yy0);
+  }
+#line 2749 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 225:
-#line 706 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 229:
+#line 719 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+    yygotominor.yy454 = sqlite3Expr(TK_SELECT, 0, 0, 0);
+    if( yygotominor.yy454 ) yygotominor.yy454->pSelect = yymsp[-1].minor.yy331;
+    sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+  }
+#line 2758 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 230:
+#line 724 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+    yygotominor.yy454 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy454, 0, 0);
+    if( yygotominor.yy454 ) yygotominor.yy454->pSelect = yymsp[-1].minor.yy331;
+    if( yymsp[-3].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0);
+    sqlite3ExprSpan(yygotominor.yy454,&yymsp[-4].minor.yy454->span,&yymsp[0].minor.yy0);
+  }
+#line 2768 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 231:
+#line 730 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy210 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy258, 0);
-  yygotominor.yy210 = sqlite3ExprListAppend(yygotominor.yy210, yymsp[0].minor.yy258, 0);
+    SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406);
+    yygotominor.yy454 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy454, 0, 0);
+    if( yygotominor.yy454 ) yygotominor.yy454->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0);
+    if( yymsp[-2].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0);
+    sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy454->span,yymsp[0].minor.yy406.z?&yymsp[0].minor.yy406:&yymsp[-1].minor.yy406);
+  }
+#line 2779 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 232:
+#line 737 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+    Expr *p = yygotominor.yy454 = sqlite3Expr(TK_EXISTS, 0, 0, 0);
+    if( p ){
+      p->pSelect = yymsp[-1].minor.yy331;
+      sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+    }
+  }
+#line 2790 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 233:
+#line 747 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+  yygotominor.yy454 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy454, yymsp[-1].minor.yy454, 0);
+  if( yygotominor.yy454 ) yygotominor.yy454->pList = yymsp[-2].minor.yy266;
+  sqlite3ExprSpan(yygotominor.yy454, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
 }
-#line 2672 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2799 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 234:
-#line 731 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 754 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  if( yymsp[-9].minor.yy284!=OE_None ) yymsp[-9].minor.yy284 = yymsp[0].minor.yy284;
-  if( yymsp[-9].minor.yy284==OE_Default) yymsp[-9].minor.yy284 = OE_Abort;
-  sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy98, &yymsp[-6].minor.yy98, yymsp[-4].minor.yy259, yymsp[-2].minor.yy210, yymsp[-9].minor.yy284, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0);
+  yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266, yymsp[-2].minor.yy454, 0);
+  yygotominor.yy266 = sqlite3ExprListAppend(yygotominor.yy266, yymsp[0].minor.yy454, 0);
 }
-#line 2681 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2807 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
       case 235:
-      case 282:
-#line 738 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Abort;}
-#line 2687 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 758 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+  yygotominor.yy266 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy454, 0);
+  yygotominor.yy266 = sqlite3ExprListAppend(yygotominor.yy266, yymsp[0].minor.yy454, 0);
+}
+#line 2815 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 236:
-#line 739 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_None;}
-#line 2692 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 244:
+#line 783 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+  if( yymsp[-9].minor.yy60!=OE_None ) yymsp[-9].minor.yy60 = yymsp[0].minor.yy60;
+  if( yymsp[-9].minor.yy60==OE_Default) yymsp[-9].minor.yy60 = OE_Abort;
+  sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy406, &yymsp[-6].minor.yy406, sqlite3SrcListAppend(0,&yymsp[-4].minor.yy406,0),yymsp[-2].minor.yy266,yymsp[-9].minor.yy60, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0);
+}
+#line 2824 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 239:
-#line 749 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 245:
+      case 292:
+#line 790 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Abort;}
+#line 2830 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 246:
+#line 791 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_None;}
+#line 2835 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 249:
+#line 801 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
   Expr *p = 0;
-  if( yymsp[-1].minor.yy98.n>0 ){
+  if( yymsp[-1].minor.yy406.n>0 ){
     p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
-    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy98.z, yymsp[-1].minor.yy98.n);
+    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy406.z, yymsp[-1].minor.yy406.n);
   }
-  yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210, p, &yymsp[-2].minor.yy98);
+  yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266, p, &yymsp[-2].minor.yy406);
 }
-#line 2704 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2847 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 240:
-#line 757 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 250:
+#line 809 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
   Expr *p = 0;
-  if( yymsp[-1].minor.yy98.n>0 ){
+  if( yymsp[-1].minor.yy406.n>0 ){
     p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
-    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy98.z, yymsp[-1].minor.yy98.n);
+    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy406.z, yymsp[-1].minor.yy406.n);
   }
-  yygotominor.yy210 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy98);
+  yygotominor.yy266 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy406);
 }
-#line 2716 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2859 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 242:
-#line 770 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy259);}
-#line 2721 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 252:
+#line 822 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy427);}
+#line 2864 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 243:
-      case 244:
-#line 774 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 253:
+      case 254:
+#line 826 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {sqlite3Vacuum(pParse,0);}
-#line 2727 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2870 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 245:
-      case 247:
-#line 779 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-3].minor.yy98,&yymsp[-2].minor.yy98,&yymsp[0].minor.yy98,0);}
-#line 2733 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 255:
+      case 257:
+#line 832 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Pragma(pParse,&yymsp[-3].minor.yy406,&yymsp[-2].minor.yy406,&yymsp[0].minor.yy406,0);}
+#line 2876 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 246:
-#line 780 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-3].minor.yy98,&yymsp[-2].minor.yy98,&yymsp[0].minor.yy0,0);}
-#line 2738 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 256:
+#line 833 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Pragma(pParse,&yymsp[-3].minor.yy406,&yymsp[-2].minor.yy406,&yymsp[0].minor.yy0,0);}
+#line 2881 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 248:
-#line 782 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 258:
+#line 835 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  sqlite3Pragma(pParse,&yymsp[-3].minor.yy98,&yymsp[-2].minor.yy98,&yymsp[0].minor.yy98,1);
+  sqlite3Pragma(pParse,&yymsp[-3].minor.yy406,&yymsp[-2].minor.yy406,&yymsp[0].minor.yy406,1);
 }
-#line 2745 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2888 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 249:
-#line 785 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-4].minor.yy98,&yymsp[-3].minor.yy98,&yymsp[-1].minor.yy98,0);}
-#line 2750 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 259:
+#line 838 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Pragma(pParse,&yymsp[-4].minor.yy406,&yymsp[-3].minor.yy406,&yymsp[-1].minor.yy406,0);}
+#line 2893 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 250:
-#line 786 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98,0,0);}
-#line 2755 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 260:
+#line 839 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Pragma(pParse,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406,0,0);}
+#line 2898 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 257:
-#line 796 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 267:
+#line 852 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
   Token all;
-  all.z = yymsp[-3].minor.yy98.z;
-  all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy98.z) + yymsp[0].minor.yy0.n;
-  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy91, &all);
+  all.z = yymsp[-3].minor.yy406.z;
+  all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy406.z) + yymsp[0].minor.yy0.n;
+  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy455, &all);
 }
-#line 2765 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2908 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 258:
-#line 805 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 268:
+#line 861 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy98, &yymsp[-6].minor.yy98, yymsp[-5].minor.yy284, yymsp[-4].minor.yy146.a, yymsp[-4].minor.yy146.b, yymsp[-2].minor.yy259, yymsp[-1].minor.yy284, yymsp[0].minor.yy258, yymsp[-9].minor.yy284);
-  yygotominor.yy98 = (yymsp[-6].minor.yy98.n==0?yymsp[-7].minor.yy98:yymsp[-6].minor.yy98);
+  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy406, &yymsp[-6].minor.yy406, yymsp[-5].minor.yy60, yymsp[-4].minor.yy62.a, yymsp[-4].minor.yy62.b, yymsp[-2].minor.yy427, yymsp[-1].minor.yy60, yymsp[0].minor.yy454, yymsp[-9].minor.yy60);
+  yygotominor.yy406 = (yymsp[-6].minor.yy406.n==0?yymsp[-7].minor.yy406:yymsp[-6].minor.yy406);
 }
-#line 2773 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2916 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 259:
-      case 262:
-#line 811 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = TK_BEFORE; }
-#line 2779 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 269:
+      case 272:
+#line 867 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = TK_BEFORE; }
+#line 2922 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 260:
-#line 812 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = TK_AFTER;  }
-#line 2784 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 270:
+#line 868 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = TK_AFTER;  }
+#line 2927 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 261:
-#line 813 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = TK_INSTEAD;}
-#line 2789 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 271:
+#line 869 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = TK_INSTEAD;}
+#line 2932 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 263:
-      case 264:
-      case 265:
-#line 818 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy146.a = yymsp[0].major; yygotominor.yy146.b = 0;}
-#line 2796 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 273:
+      case 274:
+      case 275:
+#line 874 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy62.a = yymsp[0].major; yygotominor.yy62.b = 0;}
+#line 2939 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 266:
-#line 821 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy146.a = TK_UPDATE; yygotominor.yy146.b = yymsp[0].minor.yy272;}
-#line 2801 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 276:
+#line 877 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy62.a = TK_UPDATE; yygotominor.yy62.b = yymsp[0].minor.yy272;}
+#line 2944 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 267:
-      case 268:
-#line 824 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = TK_ROW; }
-#line 2807 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 277:
+      case 278:
+#line 880 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = TK_ROW; }
+#line 2950 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 269:
-#line 826 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = TK_STATEMENT; }
-#line 2812 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 279:
+#line 882 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = TK_STATEMENT; }
+#line 2955 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 270:
-#line 829 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy258 = 0; }
-#line 2817 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 280:
+#line 885 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy454 = 0; }
+#line 2960 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 271:
-#line 830 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy258 = yymsp[0].minor.yy258; }
-#line 2822 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 281:
+#line 886 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy454 = yymsp[0].minor.yy454; }
+#line 2965 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 272:
-#line 834 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 282:
+#line 890 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yymsp[-2].minor.yy91->pNext = yymsp[0].minor.yy91;
-  yygotominor.yy91 = yymsp[-2].minor.yy91;
+  yymsp[-2].minor.yy455->pNext = yymsp[0].minor.yy455;
+  yygotominor.yy455 = yymsp[-2].minor.yy455;
 }
-#line 2830 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2973 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 273:
-#line 838 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy91 = 0; }
-#line 2835 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 283:
+#line 894 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy455 = 0; }
+#line 2978 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 274:
-#line 844 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy91 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy98, yymsp[-1].minor.yy210, yymsp[0].minor.yy258, yymsp[-4].minor.yy284); }
-#line 2840 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 284:
+#line 900 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy455 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy406, yymsp[-1].minor.yy266, yymsp[0].minor.yy454, yymsp[-4].minor.yy60); }
+#line 2983 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 275:
-#line 849 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy91 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy98, yymsp[-4].minor.yy272, yymsp[-1].minor.yy210, 0, yymsp[-7].minor.yy284);}
-#line 2845 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 285:
+#line 905 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy455 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy406, yymsp[-4].minor.yy272, yymsp[-1].minor.yy266, 0, yymsp[-7].minor.yy60);}
+#line 2988 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 276:
-#line 852 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy91 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy98, yymsp[-1].minor.yy272, 0, yymsp[0].minor.yy107, yymsp[-4].minor.yy284);}
-#line 2850 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 286:
+#line 908 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy455 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy406, yymsp[-1].minor.yy272, 0, yymsp[0].minor.yy331, yymsp[-4].minor.yy60);}
+#line 2993 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 277:
-#line 856 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy91 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy98, yymsp[0].minor.yy258);}
-#line 2855 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 287:
+#line 912 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy455 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy406, yymsp[0].minor.yy454);}
+#line 2998 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 278:
-#line 859 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy91 = sqlite3TriggerSelectStep(yymsp[0].minor.yy107); }
-#line 2860 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 288:
+#line 915 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy455 = sqlite3TriggerSelectStep(yymsp[0].minor.yy331); }
+#line 3003 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 279:
-#line 862 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 289:
+#line 918 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3Expr(TK_RAISE, 0, 0, 0); 
-  yygotominor.yy258->iColumn = OE_Ignore;
-  sqlite3ExprSpan(yygotominor.yy258, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
+  yygotominor.yy454 = sqlite3Expr(TK_RAISE, 0, 0, 0); 
+  yygotominor.yy454->iColumn = OE_Ignore;
+  sqlite3ExprSpan(yygotominor.yy454, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
 }
-#line 2869 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3012 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 280:
-#line 867 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 290:
+#line 923 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  yygotominor.yy258 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy98); 
-  yygotominor.yy258->iColumn = yymsp[-3].minor.yy284;
-  sqlite3ExprSpan(yygotominor.yy258, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
+  yygotominor.yy454 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy406); 
+  yygotominor.yy454->iColumn = yymsp[-3].minor.yy60;
+  sqlite3ExprSpan(yygotominor.yy454, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
 }
-#line 2878 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3021 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 281:
-#line 873 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Rollback;}
-#line 2883 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 291:
+#line 931 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Rollback;}
+#line 3026 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 283:
-#line 875 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Fail;}
-#line 2888 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 293:
+#line 933 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Fail;}
+#line 3031 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 284:
-#line 879 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 294:
+#line 938 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  sqlite3DropTrigger(pParse,yymsp[0].minor.yy259);
+  sqlite3DropTrigger(pParse,yymsp[0].minor.yy427);
 }
-#line 2895 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3038 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 285:
-#line 884 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 295:
+#line 944 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  sqlite3Attach(pParse, &yymsp[-3].minor.yy98, &yymsp[-1].minor.yy98, yymsp[0].minor.yy292.type, &yymsp[0].minor.yy292.key);
+  sqlite3Attach(pParse, &yymsp[-3].minor.yy406, &yymsp[-1].minor.yy406, yymsp[0].minor.yy40.type, &yymsp[0].minor.yy40.key);
 }
-#line 2902 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3045 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 286:
-#line 888 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy292.type = 0; }
-#line 2907 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 296:
+#line 948 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy40.type = 0; }
+#line 3050 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 287:
-#line 889 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy292.type=1; yygotominor.yy292.key = yymsp[0].minor.yy98; }
-#line 2912 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 297:
+#line 949 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy40.type=1; yygotominor.yy40.key = yymsp[0].minor.yy406; }
+#line 3055 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 288:
-#line 890 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy292.type=2; yygotominor.yy292.key = yymsp[0].minor.yy0; }
-#line 2917 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+      case 298:
+#line 950 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy40.type=2; yygotominor.yy40.key = yymsp[0].minor.yy0; }
+#line 3060 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
-      case 291:
-#line 896 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+      case 301:
+#line 956 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+  sqlite3Detach(pParse, &yymsp[0].minor.yy406);
+}
+#line 3067 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 302:
+#line 962 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Reindex(pParse, 0, 0);}
+#line 3072 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 303:
+#line 963 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Reindex(pParse, &yymsp[-1].minor.yy406, &yymsp[0].minor.yy406);}
+#line 3077 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+        break;
+      case 304:
+#line 968 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 {
-  sqlite3Detach(pParse, &yymsp[0].minor.yy98);
+  sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy427,&yymsp[0].minor.yy406);
 }
-#line 2924 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3084 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
         break;
   };
   yygoto = yyRuleInfo[yyruleno].lhs;
@@ -2961,7 +3121,7 @@ static void yy_syntax_error(
 ){
   sqlite3ParserARG_FETCH;
 #define TOKEN (yyminor.yy0)
-#line 23 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 23 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
 
   if( pParse->zErrMsg==0 ){
     if( TOKEN.z[0] ){
@@ -2970,7 +3130,7 @@ static void yy_syntax_error(
       sqlite3ErrorMsg(pParse, "incomplete SQL statement");
     }
   }
-#line 2976 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3136 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
   sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
 }
 
index 547319ed705f0cb3a48b37ea236e5c1225416a26..e50789a834aad587ac6b179d47df5fe2b5a178e7 100644 (file)
 #define TK_TRIGGER                        55
 #define TK_VACUUM                         56
 #define TK_VIEW                           57
-#define TK_OR                             58
-#define TK_AND                            59
-#define TK_NOT                            60
-#define TK_IS                             61
-#define TK_BETWEEN                        62
-#define TK_IN                             63
-#define TK_ISNULL                         64
-#define TK_NOTNULL                        65
-#define TK_NE                             66
-#define TK_EQ                             67
-#define TK_GT                             68
-#define TK_LE                             69
-#define TK_LT                             70
-#define TK_GE                             71
-#define TK_BITAND                         72
-#define TK_BITOR                          73
-#define TK_LSHIFT                         74
-#define TK_RSHIFT                         75
-#define TK_PLUS                           76
-#define TK_MINUS                          77
-#define TK_STAR                           78
-#define TK_SLASH                          79
-#define TK_REM                            80
-#define TK_CONCAT                         81
-#define TK_UMINUS                         82
-#define TK_UPLUS                          83
-#define TK_BITNOT                         84
-#define TK_STRING                         85
-#define TK_JOIN_KW                        86
-#define TK_CONSTRAINT                     87
-#define TK_DEFAULT                        88
-#define TK_NULL                           89
-#define TK_PRIMARY                        90
-#define TK_UNIQUE                         91
-#define TK_CHECK                          92
-#define TK_REFERENCES                     93
-#define TK_COLLATE                        94
-#define TK_ON                             95
-#define TK_DELETE                         96
-#define TK_UPDATE                         97
-#define TK_INSERT                         98
-#define TK_SET                            99
-#define TK_DEFERRABLE                     100
-#define TK_FOREIGN                        101
-#define TK_DROP                           102
-#define TK_UNION                          103
-#define TK_ALL                            104
-#define TK_INTERSECT                      105
-#define TK_EXCEPT                         106
-#define TK_SELECT                         107
-#define TK_DISTINCT                       108
-#define TK_DOT                            109
-#define TK_FROM                           110
-#define TK_JOIN                           111
-#define TK_USING                          112
-#define TK_ORDER                          113
-#define TK_BY                             114
-#define TK_GROUP                          115
-#define TK_HAVING                         116
-#define TK_LIMIT                          117
-#define TK_WHERE                          118
-#define TK_INTO                           119
-#define TK_VALUES                         120
-#define TK_INTEGER                        121
-#define TK_FLOAT                          122
-#define TK_BLOB                           123
-#define TK_VARIABLE                       124
-#define TK_CASE                           125
-#define TK_WHEN                           126
-#define TK_THEN                           127
-#define TK_ELSE                           128
-#define TK_INDEX                          129
+#define TK_REINDEX                        58
+#define TK_RENAME                         59
+#define TK_CDATE                          60
+#define TK_CTIME                          61
+#define TK_CTIMESTAMP                     62
+#define TK_ALTER                          63
+#define TK_OR                             64
+#define TK_AND                            65
+#define TK_NOT                            66
+#define TK_IS                             67
+#define TK_BETWEEN                        68
+#define TK_IN                             69
+#define TK_ISNULL                         70
+#define TK_NOTNULL                        71
+#define TK_NE                             72
+#define TK_EQ                             73
+#define TK_GT                             74
+#define TK_LE                             75
+#define TK_LT                             76
+#define TK_GE                             77
+#define TK_ESCAPE                         78
+#define TK_BITAND                         79
+#define TK_BITOR                          80
+#define TK_LSHIFT                         81
+#define TK_RSHIFT                         82
+#define TK_PLUS                           83
+#define TK_MINUS                          84
+#define TK_STAR                           85
+#define TK_SLASH                          86
+#define TK_REM                            87
+#define TK_CONCAT                         88
+#define TK_UMINUS                         89
+#define TK_UPLUS                          90
+#define TK_BITNOT                         91
+#define TK_STRING                         92
+#define TK_JOIN_KW                        93
+#define TK_CONSTRAINT                     94
+#define TK_DEFAULT                        95
+#define TK_NULL                           96
+#define TK_PRIMARY                        97
+#define TK_UNIQUE                         98
+#define TK_CHECK                          99
+#define TK_REFERENCES                     100
+#define TK_COLLATE                        101
+#define TK_AUTOINCR                       102
+#define TK_ON                             103
+#define TK_DELETE                         104
+#define TK_UPDATE                         105
+#define TK_INSERT                         106
+#define TK_SET                            107
+#define TK_DEFERRABLE                     108
+#define TK_FOREIGN                        109
+#define TK_DROP                           110
+#define TK_UNION                          111
+#define TK_ALL                            112
+#define TK_INTERSECT                      113
+#define TK_EXCEPT                         114
+#define TK_SELECT                         115
+#define TK_DISTINCT                       116
+#define TK_DOT                            117
+#define TK_FROM                           118
+#define TK_JOIN                           119
+#define TK_USING                          120
+#define TK_ORDER                          121
+#define TK_BY                             122
+#define TK_GROUP                          123
+#define TK_HAVING                         124
+#define TK_LIMIT                          125
+#define TK_WHERE                          126
+#define TK_INTO                           127
+#define TK_VALUES                         128
+#define TK_INTEGER                        129
+#define TK_FLOAT                          130
+#define TK_BLOB                           131
+#define TK_REGISTER                       132
+#define TK_VARIABLE                       133
+#define TK_EXISTS                         134
+#define TK_CASE                           135
+#define TK_WHEN                           136
+#define TK_THEN                           137
+#define TK_ELSE                           138
+#define TK_INDEX                          139
+#define TK_TO                             140
index 59dd563a6c992d95f713603b92f03753a3ff0105..66398ac4f1d59079d1f9ea8fedbde82e1a4ff365 100644 (file)
@@ -39,8 +39,8 @@
 ** LIMIT clause of a SELECT statement.
 */
 struct LimitVal {
-  int limit;    /* The LIMIT value.  -1 if there is no limit */
-  int offset;   /* The OFFSET.  0 if there is none */
+  Expr *pLimit;    /* The LIMIT expression.  NULL if there is no limit */
+  Expr *pOffset;   /* The OFFSET expression.  NULL if there is none */
 };
 
 /*
@@ -81,11 +81,13 @@ struct AttachKey { int type;  Token key; };
 input ::= cmdlist.
 cmdlist ::= cmdlist ecmd.
 cmdlist ::= ecmd.
-ecmd ::= explain cmdx SEMI.
-ecmd ::= SEMI.
 cmdx ::= cmd.           { sqlite3FinishCoding(pParse); }
-explain ::= EXPLAIN.    { sqlite3BeginParse(pParse, 1); }
+ecmd ::= SEMI.
+ecmd ::= explain cmdx SEMI.
 explain ::= .           { sqlite3BeginParse(pParse, 0); }
+%ifndef SQLITE_OMIT_EXPLAIN
+explain ::= EXPLAIN.    { sqlite3BeginParse(pParse, 1); }
+%endif
 
 ///////////////////// Begin and end transactions. ////////////////////////////
 //
@@ -144,7 +146,12 @@ id(A) ::= ID(X).         {A = X;}
   DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
   GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY
   OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
-  TEMP TRIGGER VACUUM VIEW.
+  TEMP TRIGGER VACUUM VIEW
+%ifdef SQLITE_OMIT_COMPOUND_SELECT
+  EXCEPT INTERSECT UNION
+%endif
+  REINDEX RENAME CDATE CTIME CTIMESTAMP ALTER
+  .
 
 // Define operator precedence early so that this is the first occurance
 // of the operator tokens in the grammer.  Keeping the operators together
@@ -162,6 +169,7 @@ id(A) ::= ID(X).         {A = X;}
 %right NOT.
 %left IS LIKE GLOB BETWEEN IN ISNULL NOTNULL NE EQ.
 %left GT LE LT GE.
+%right ESCAPE.
 %left BITAND BITOR LSHIFT RSHIFT.
 %left PLUS MINUS.
 %left STAR SLASH REM.
@@ -196,17 +204,24 @@ carglist ::= carglist carg.
 carglist ::= .
 carg ::= CONSTRAINT nm ccons.
 carg ::= ccons.
-carg ::= DEFAULT ids(X).             {sqlite3AddDefaultValue(pParse,&X,0);}
-carg ::= DEFAULT plus_num(X).        {sqlite3AddDefaultValue(pParse,&X,0);}
-carg ::= DEFAULT minus_num(X).       {sqlite3AddDefaultValue(pParse,&X,1);}
-carg ::= DEFAULT NULL. 
+carg ::= DEFAULT term(X).            {sqlite3AddDefaultValue(pParse,X);}
+carg ::= DEFAULT PLUS term(X).       {sqlite3AddDefaultValue(pParse,X);}
+carg ::= DEFAULT MINUS term(X).      {
+  Expr *p = sqlite3Expr(TK_UMINUS, X, 0, 0);
+  sqlite3AddDefaultValue(pParse,p);
+}
+carg ::= DEFAULT id(X).              {
+  Expr *p = sqlite3Expr(TK_STRING, 0, 0, &X);
+  sqlite3AddDefaultValue(pParse,p);
+}
 
 // In addition to the type name, we also care about the primary key and
 // UNIQUE constraints.
 //
 ccons ::= NULL onconf.
 ccons ::= NOT NULL onconf(R).               {sqlite3AddNotNull(pParse, R);}
-ccons ::= PRIMARY KEY sortorder onconf(R).  {sqlite3AddPrimaryKey(pParse,0,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 RP onconf.
 ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
@@ -214,6 +229,11 @@ ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
 ccons ::= defer_subclause(D).   {sqlite3DeferForeignKey(pParse,D);}
 ccons ::= COLLATE id(C).  {sqlite3AddCollateType(pParse, C.z, C.n);}
 
+// The optional AUTOINCREMENT keyword
+%type autoinc {int}
+autoinc(X) ::= .          {X = 0;}
+autoinc(X) ::= AUTOINCR.  {X = 1;}
+
 // The next group of rules parses the arguments to a REFERENCES clause
 // that determine if the referential integrity checking is deferred or
 // or immediate and which determine what action to take if a ref-integ
@@ -249,8 +269,8 @@ conslist ::= conslist COMMA tcons.
 conslist ::= conslist tcons.
 conslist ::= tcons.
 tcons ::= CONSTRAINT nm.
-tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R).
-                                             {sqlite3AddPrimaryKey(pParse,X,R);}
+tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R).
+                                         {sqlite3AddPrimaryKey(pParse,X,R,I);}
 tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
                                        {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0);}
 tcons ::= CHECK expr onconf.
@@ -285,12 +305,14 @@ cmd ::= DROP TABLE fullname(X). {
 
 ///////////////////// The CREATE VIEW statement /////////////////////////////
 //
+%ifndef SQLITE_OMIT_VIEW
 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);
 }
+%endif // SQLITE_OMIT_VIEW
 
 //////////////////////// The SELECT statement /////////////////////////////////
 //
@@ -305,6 +327,7 @@ cmd ::= select(X).  {
 %destructor oneselect {sqlite3SelectDelete($$);}
 
 select(A) ::= oneselect(X).                      {A = X;}
+%ifndef SQLITE_OMIT_COMPOUND_SELECT
 select(A) ::= select(X) multiselect_op(Y) oneselect(Z).  {
   if( Z ){
     Z->op = Y;
@@ -317,9 +340,10 @@ 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;}
+%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). {
-  A = sqlite3SelectNew(W,X,Y,P,Q,Z,D,L.limit,L.offset);
+  A = sqlite3SelectNew(W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset);
 }
 
 // The "distinct" nonterminal is true (1) if the DISTINCT keyword is
@@ -394,31 +418,33 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). {
     else { sqlite3IdListDelete(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( Z.n ) sqlite3SrcListAddAlias(A,&Z);
-  if( N ){
-    if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; }
-    else { sqlite3ExprDelete(N); }
+%ifndef SQLITE_OMIT_SUBQUERY
+  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( Z.n ) sqlite3SrcListAddAlias(A,&Z);
+    if( N ){
+      if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; }
+      else { sqlite3ExprDelete(N); }
+    }
+    if( U ){
+      if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pUsing = U; }
+      else { sqlite3IdListDelete(U); }
+    }
   }
-  if( U ){
-    if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pUsing = U; }
-    else { sqlite3IdListDelete(U); }
+  
+ // 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.
+  //
+  %type seltablist_paren {Select*}
+  %destructor seltablist_paren {sqlite3SelectDelete($$);}
+  seltablist_paren(A) ::= select(S).      {A = S;}
+  seltablist_paren(A) ::= seltablist(F).  {
+     A = sqlite3SelectNew(0,F,0,0,0,0,0,0,0);
   }
-}
-
-// 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.
-//
-%type seltablist_paren {Select*}
-%destructor seltablist_paren {sqlite3SelectDelete($$);}
-seltablist_paren(A) ::= select(S).      {A = S;}
-seltablist_paren(A) ::= seltablist(F).  {
-   A = sqlite3SelectNew(0,F,0,0,0,0,0,-1,0);
-}
+%endif // SQLITE_OMIT_SUBQUERY
 
 %type dbnm {Token}
 dbnm(A) ::= .          {A.z=0; A.n=0;}
@@ -487,12 +513,16 @@ having_opt(A) ::= .                {A = 0;}
 having_opt(A) ::= HAVING expr(X).  {A = X;}
 
 %type limit_opt {struct LimitVal}
-limit_opt(A) ::= .                     {A.limit = -1; A.offset = 0;}
-limit_opt(A) ::= LIMIT signed(X).      {A.limit = X; A.offset = 0;}
-limit_opt(A) ::= LIMIT signed(X) OFFSET signed(Y). 
-                                       {A.limit = X; A.offset = Y;}
-limit_opt(A) ::= LIMIT signed(X) COMMA signed(Y). 
-                                       {A.limit = Y; A.offset = X;}
+%destructor limit_opt {
+  sqlite3ExprDelete($$.pLimit);
+  sqlite3ExprDelete($$.pOffset);
+}
+limit_opt(A) ::= .                     {A.pLimit = 0; A.pOffset = 0;}
+limit_opt(A) ::= LIMIT expr(X).        {A.pLimit = X; A.pOffset = 0;}
+limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). 
+                                       {A.pLimit = X; A.pOffset = Y;}
+limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). 
+                                       {A.pOffset = X; A.pLimit = Y;}
 
 /////////////////////////// The DELETE statement /////////////////////////////
 //
@@ -550,9 +580,12 @@ inscollist(A) ::= nm(Y).                      {A = sqlite3IdListAppend(0,&Y);}
 
 %type expr {Expr*}
 %destructor expr {sqlite3ExprDelete($$);}
+%type term {Expr*}
+%destructor term {sqlite3ExprDelete($$);}
 
+expr(A) ::= term(X).             {A = X;}
 expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); }
-expr(A) ::= NULL(X).             {A = sqlite3Expr(@X, 0, 0, &X);}
+term(A) ::= NULL(X).             {A = sqlite3Expr(@X, 0, 0, &X);}
 expr(A) ::= ID(X).               {A = sqlite3Expr(TK_ID, 0, 0, &X);}
 expr(A) ::= JOIN_KW(X).          {A = sqlite3Expr(TK_ID, 0, 0, &X);}
 expr(A) ::= nm(X) DOT nm(Y). {
@@ -567,10 +600,11 @@ 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);
 }
-expr(A) ::= INTEGER(X).      {A = sqlite3Expr(@X, 0, 0, &X);}
-expr(A) ::= FLOAT(X).        {A = sqlite3Expr(@X, 0, 0, &X);}
-expr(A) ::= STRING(X).       {A = sqlite3Expr(@X, 0, 0, &X);}
+term(A) ::= INTEGER(X).      {A = sqlite3Expr(@X, 0, 0, &X);}
+term(A) ::= FLOAT(X).        {A = sqlite3Expr(@X, 0, 0, &X);}
+term(A) ::= STRING(X).       {A = sqlite3Expr(@X, 0, 0, &X);}
 expr(A) ::= BLOB(X).         {A = sqlite3Expr(@X, 0, 0, &X);}
+expr(A) ::= REGISTER(X).     {A = sqlite3RegisterExpr(pParse, &X);}
 expr(A) ::= VARIABLE(X).     {
   Token *pToken = &X;
   Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
@@ -584,6 +618,9 @@ expr(A) ::= ID(X) LP STAR RP(E). {
   A = sqlite3ExprFunction(0, &X);
   sqlite3ExprSpan(A,&X,&E);
 }
+term(A) ::= CTIME(OP).                  {A = sqlite3Expr(@OP,0,0,0);}
+term(A) ::= CDATE(OP).                  {A = sqlite3Expr(@OP,0,0,0);}
+term(A) ::= CTIMESTAMP(OP).             {A = sqlite3Expr(@OP,0,0,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(OP) expr(Y).     {A = sqlite3Expr(@OP, X, Y, 0);}
@@ -607,14 +644,21 @@ likeop(A) ::= LIKE.     {A.opcode = TK_LIKE; A.not = 0;}
 likeop(A) ::= GLOB.     {A.opcode = TK_GLOB; A.not = 0;}
 likeop(A) ::= NOT LIKE. {A.opcode = TK_LIKE; A.not = 1;}
 likeop(A) ::= NOT GLOB. {A.opcode = TK_GLOB; A.not = 1;}
-expr(A) ::= expr(X) likeop(OP) expr(Y).  [LIKE]  {
+%type escape {Expr*}
+escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;}
+escape(X) ::= .               [ESCAPE] {X = 0;}
+expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E).  [LIKE]  {
   ExprList *pList = sqlite3ExprListAppend(0, Y, 0);
   pList = sqlite3ExprListAppend(pList, X, 0);
+  if( E ){
+    pList = sqlite3ExprListAppend(pList, E, 0);
+  }
   A = sqlite3ExprFunction(pList, 0);
   if( A ) A->op = OP.opcode;
   if( OP.not ) A = sqlite3Expr(TK_NOT, A, 0, 0);
   sqlite3ExprSpan(A, &X->span, &Y->span);
 }
+
 expr(A) ::= expr(X) ISNULL(E). {
   A = sqlite3Expr(TK_ISNULL, X, 0, 0);
   sqlite3ExprSpan(A,&X->span,&E);
@@ -651,11 +695,6 @@ expr(A) ::= PLUS(B) expr(X). [UPLUS] {
   A = sqlite3Expr(TK_UPLUS, X, 0, 0);
   sqlite3ExprSpan(A,&B,&X->span);
 }
-expr(A) ::= LP(B) select(X) RP(E). {
-  A = sqlite3Expr(TK_SELECT, 0, 0, 0);
-  if( A ) A->pSelect = X;
-  sqlite3ExprSpan(A,&B,&E);
-}
 %type between_op {int}
 between_op(A) ::= BETWEEN.     {A = 0;}
 between_op(A) ::= NOT BETWEEN. {A = 1;}
@@ -667,29 +706,42 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
   if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
   sqlite3ExprSpan(A,&W->span,&Y->span);
 }
-%type in_op {int}
-in_op(A) ::= IN.      {A = 0;}
-in_op(A) ::= NOT IN.  {A = 1;}
-expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] {
-  A = sqlite3Expr(TK_IN, X, 0, 0);
-  if( A ) A->pList = Y;
-  if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
-  sqlite3ExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E).  [IN] {
-  A = sqlite3Expr(TK_IN, X, 0, 0);
-  if( A ) A->pSelect = Y;
-  if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
-  sqlite3ExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
-  SrcList *pSrc = sqlite3SrcListAppend(0,&Y,&Z);
-  A = sqlite3Expr(TK_IN, X, 0, 0);
-  if( A ) A->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,-1,0);
-  if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
-  sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y);
-}
-
+%ifndef SQLITE_OMIT_SUBQUERY
+  %type in_op {int}
+  in_op(A) ::= IN.      {A = 0;}
+  in_op(A) ::= NOT IN.  {A = 1;}
+  expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] {
+    A = sqlite3Expr(TK_IN, X, 0, 0);
+    if( A ) A->pList = Y;
+    if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
+    sqlite3ExprSpan(A,&X->span,&E);
+  }
+  expr(A) ::= LP(B) select(X) RP(E). {
+    A = sqlite3Expr(TK_SELECT, 0, 0, 0);
+    if( A ) A->pSelect = X;
+    sqlite3ExprSpan(A,&B,&E);
+  }
+  expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E).  [IN] {
+    A = sqlite3Expr(TK_IN, X, 0, 0);
+    if( A ) A->pSelect = Y;
+    if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
+    sqlite3ExprSpan(A,&X->span,&E);
+  }
+  expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
+    SrcList *pSrc = sqlite3SrcListAppend(0,&Y,&Z);
+    A = sqlite3Expr(TK_IN, X, 0, 0);
+    if( A ) A->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0);
+    if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
+    sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y);
+  }
+  expr(A) ::= EXISTS(B) LP select(Y) RP(E). {
+    Expr *p = A = sqlite3Expr(TK_EXISTS, 0, 0, 0);
+    if( p ){
+      p->pSelect = Y;
+      sqlite3ExprSpan(p,&B,&E);
+    }
+  }
+%endif // SQLITE_OMIT_SUBQUERY
 
 /* CASE expressions */
 expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
@@ -728,10 +780,10 @@ expritem(A) ::= .                       {A = 0;}
 ///////////////////////////// The CREATE INDEX command ///////////////////////
 //
 cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X) dbnm(D)
-        ON fullname(Y) LP idxlist(Z) RP(E) onconf(R). {
+        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, Y, Z, U, &S, &E);
+  sqlite3CreateIndex(pParse, &X, &D, sqlite3SrcListAppend(0,&Y,0),Z,U, &S, &E);
 }
 
 %type uniqueflag {int}
@@ -776,6 +828,7 @@ cmd ::= VACUUM nm.             {sqlite3Vacuum(pParse,0);}
 
 ///////////////////////////// The PRAGMA command /////////////////////////////
 //
+%ifndef SQLITE_OMIT_PRAGMA
 cmd ::= PRAGMA nm(X) dbnm(Z) EQ nm(Y).  {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
 cmd ::= PRAGMA nm(X) dbnm(Z) EQ ON(Y).  {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
 cmd ::= PRAGMA nm(X) dbnm(Z) EQ plus_num(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
@@ -784,6 +837,7 @@ cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y). {
 }
 cmd ::= PRAGMA nm(X) dbnm(Z) LP nm(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
 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;}
@@ -793,6 +847,8 @@ plus_opt ::= .
 
 //////////////////////////// The CREATE TRIGGER command /////////////////////
 
+%ifndef SQLITE_OMIT_TRIGGER
+
 cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). {
   Token all;
   all.z = A.z;
@@ -869,6 +925,8 @@ expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y).  {
   A->iColumn = T;
   sqlite3ExprSpan(A, &X, &Y);
 }
+%endif // !SQLITE_OMIT_TRIGGER
+
 %type raisetype {int}
 raisetype(A) ::= ROLLBACK.  {A = OE_Rollback;}
 raisetype(A) ::= ABORT.     {A = OE_Abort;}
@@ -876,9 +934,11 @@ raisetype(A) ::= FAIL.      {A = OE_Fail;}
 
 
 ////////////////////////  DROP TRIGGER statement //////////////////////////////
+%ifndef SQLITE_OMIT_TRIGGER
 cmd ::= DROP TRIGGER fullname(X). {
   sqlite3DropTrigger(pParse,X);
 }
+%endif // !SQLITE_OMIT_TRIGGER
 
 //////////////////////// ATTACH DATABASE file AS name /////////////////////////
 cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). {
@@ -896,3 +956,16 @@ database_kw_opt ::= .
 cmd ::= DETACH database_kw_opt nm(D). {
   sqlite3Detach(pParse, &D);
 }
+
+////////////////////////// REINDEX collation //////////////////////////////////
+%ifndef SQLITE_OMIT_REINDEX
+cmd ::= REINDEX.                {sqlite3Reindex(pParse, 0, 0);}
+cmd ::= REINDEX nm(X) dbnm(Y).  {sqlite3Reindex(pParse, &X, &Y);}
+%endif
+
+//////////////////////// ALTER TABLE table ... ////////////////////////////////
+%ifndef SQLITE_OMIT_ALTERTABLE
+cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
+  sqlite3AlterRenameTable(pParse,X,&Z);
+}
+%endif
index 94a218632aab104f7a5fe82a824700cdffb1940a..3c09a4b196dca87c943e605ca6e57c43fd391396 100644 (file)
 ** $Id$
 */
 #include "sqliteInt.h"
+#include "os.h"
 #include <ctype.h>
 
+/* Ignore this whole file if pragmas are disabled
+*/
+#ifndef SQLITE_OMIT_PRAGMA
+
 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
 # include "pager.h"
 # include "btree.h"
 #endif
 
-/*
-** Interpret the given string as a boolean value.
-*/
-static int getBoolean(const u8 *z){
-  static const u8 *azTrue[] = { "yes", "on", "true" };
-  int i;
-  if( z[0]==0 ) return 0;
-  if( sqlite3IsNumber(z, 0, SQLITE_UTF8) ){
-    return atoi(z);
-  }
-  for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){
-    if( sqlite3StrICmp(z,azTrue[i])==0 ) return 1;
-  }
-  return 0;
-}
-
 /*
 ** Interpret the given string as a safety level.  Return 0 for OFF,
 ** 1 for ON or NORMAL and 2 for FULL.  Return 1 for an empty or 
@@ -47,30 +36,33 @@ static int getBoolean(const u8 *z){
 ** 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(u8 *z){
-  static const struct {
-    const u8 *zWord;
-    int val;
-  } aKey[] = {
-    { "no",    0 },
-    { "off",   0 },
-    { "false", 0 },
-    { "yes",   1 },
-    { "on",    1 },
-    { "true",  1 },
-    { "full",  2 },
-  };
-  int i;
-  if( z[0]==0 ) return 1;
-  if( sqlite3IsNumber(z, 0, SQLITE_UTF8) ){
+static int getSafetyLevel(const u8 *z){
+                             /* 123456789 123456789 */
+  static const char zText[] = "onoffalseyestruefull";
+  static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
+  static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4};
+  static const u8 iValue[] =  {1, 0, 0, 0, 1, 1, 2};
+  int i, n;
+  if( isdigit(*z) ){
     return atoi(z);
   }
-  for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){
-    if( sqlite3StrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val;
+  n = strlen(z);
+  for(i=0; i<sizeof(iLength); i++){
+    if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){
+      return iValue[i];
+    }
   }
   return 1;
 }
 
+/*
+** Interpret the given string as a boolean value.
+*/
+static int getBoolean(const u8 *z){
+  return getSafetyLevel(z)&1;
+}
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
 /*
 ** Interpret the given string as a temp db location. Return 1 for file
 ** backed temporary databases, 2 for the Red-Black tree in memory database
@@ -89,14 +81,11 @@ static int getTempStore(const char *z){
 }
 
 /*
-** If the TEMP database is open, close it and mark the database schema
-** as needing reloading.  This must be done when using the TEMP_STORE
-** or DEFAULT_TEMP_STORE pragmas.
+** Invalidate temp storage, either when the temp storage is changed
+** from default, or when 'file' and the temp_store_directory has changed
 */
-static int changeTempStorage(Parse *pParse, const char *zStorageType){
-  int ts = getTempStore(zStorageType);
+static int invalidateTempStorage(Parse *pParse){
   sqlite3 *db = pParse->db;
-  if( db->temp_store==ts ) return SQLITE_OK;
   if( db->aDb[1].pBt!=0 ){
     if( db->flags & SQLITE_InTrans ){
       sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
@@ -107,9 +96,25 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
     db->aDb[1].pBt = 0;
     sqlite3ResetInternalSchema(db, 0);
   }
+  return SQLITE_OK;
+}
+
+/*
+** If the TEMP database is open, close it and mark the database schema
+** as needing reloading.  This must be done when using the TEMP_STORE
+** or DEFAULT_TEMP_STORE pragmas.
+*/
+static int changeTempStorage(Parse *pParse, const char *zStorageType){
+  int ts = getTempStore(zStorageType);
+  sqlite3 *db = pParse->db;
+  if( db->temp_store==ts ) return SQLITE_OK;
+  if( invalidateTempStorage( pParse ) != SQLITE_OK ){
+    return SQLITE_ERROR;
+  }
   db->temp_store = ts;
   return SQLITE_OK;
 }
+#endif
 
 /*
 ** Generate code to return a single integer value.
@@ -130,35 +135,42 @@ static void returnSingleInt(Parse *pParse, const char *zLabel, int value){
 ** Also, implement the pragma.
 */
 static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
-  static const struct {
+  static const struct sPragmaType {
     const char *zName;  /* Name of the pragma */
     int mask;           /* Mask for the db->flags value */
   } aPragma[] = {
     { "vdbe_trace",               SQLITE_VdbeTrace     },
     { "sql_trace",                SQLITE_SqlTrace      },
     { "vdbe_listing",             SQLITE_VdbeListing   },
-#if 1  /* FIX ME:  Remove the following pragmas */
     { "full_column_names",        SQLITE_FullColNames  },
     { "short_column_names",       SQLITE_ShortColNames },
     { "count_changes",            SQLITE_CountRows     },
     { "empty_result_callbacks",   SQLITE_NullCallback  },
-#endif
+    /* The following is VERY experimental */
+    { "writable_schema",          SQLITE_WriteSchema   },
+    { "omit_readlock",            SQLITE_NoReadlock    },
   };
   int i;
-  for(i=0; i<sizeof(aPragma)/sizeof(aPragma[0]); i++){
-    if( sqlite3StrICmp(zLeft, aPragma[i].zName)==0 ){
+  const struct sPragmaType *p;
+  for(i=0, p=aPragma; i<sizeof(aPragma)/sizeof(aPragma[0]); i++, p++){
+    if( sqlite3StrICmp(zLeft, p->zName)==0 ){
       sqlite3 *db = pParse->db;
       Vdbe *v;
-      if( zRight==0 ){
-        v = sqlite3GetVdbe(pParse);
-        if( v ){
-          returnSingleInt(pParse,
-               aPragma[i].zName, (db->flags&aPragma[i].mask)!=0);
+      v = sqlite3GetVdbe(pParse);
+      if( v ){
+        if( zRight==0 ){
+          returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 );
+        }else{
+          if( getBoolean(zRight) ){
+            db->flags |= p->mask;
+          }else{
+            db->flags &= ~p->mask;
+          }
         }
-      }else if( getBoolean(zRight) ){
-        db->flags |= aPragma[i].mask;
-      }else{
-        db->flags &= ~aPragma[i].mask;
+        /* If one of these pragmas is executed, any prepared statements
+        ** need to be recompiled.
+        */
+        sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
       }
       return 1;
     }
@@ -217,6 +229,7 @@ void sqlite3Pragma(
     goto pragma_out;
   }
  
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
   /*
   **  PRAGMA [database.]default_cache_size
   **  PRAGMA [database.]default_cache_size=N
@@ -281,10 +294,31 @@ void sqlite3Pragma(
       int size = pBt ? sqlite3BtreeGetPageSize(pBt) : 0;
       returnSingleInt(pParse, "page_size", size);
     }else{
-      sqlite3BtreeSetPageSize(pBt, atoi(zRight), sqlite3BtreeGetReserve(pBt));
+      sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1);
     }
   }else
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
 
+  /*
+  **  PRAGMA [database.]auto_vacuum
+  **  PRAGMA [database.]auto_vacuum=N
+  **
+  ** Get or set the (boolean) value of the database 'auto-vacuum' parameter.
+  */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){
+    Btree *pBt = pDb->pBt;
+    if( !zRight ){
+      int auto_vacuum = 
+          pBt ? sqlite3BtreeGetAutoVacuum(pBt) : SQLITE_DEFAULT_AUTOVACUUM;
+      returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
+    }else{
+      sqlite3BtreeSetAutoVacuum(pBt, getBoolean(zRight));
+    }
+  }else
+#endif
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
   /*
   **  PRAGMA [database.]cache_size
   **  PRAGMA [database.]cache_size=N
@@ -330,6 +364,45 @@ void sqlite3Pragma(
     }
   }else
 
+  /*
+  **   PRAGMA temp_store_directory
+  **   PRAGMA temp_store_directory = ""|"directory_name"
+  **
+  ** Return or set the local value of the temp_store_directory flag.  Changing
+  ** the value sets a specific directory to be used for temporary files.
+  ** Setting to a null string reverts to the default temporary directory search.
+  ** If temporary directory is changed, then invalidateTempStorage.
+  **
+  */
+  if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){
+    if( !zRight ){
+      if( sqlite3_temp_directory ){
+        sqlite3VdbeSetNumCols(v, 1);
+        sqlite3VdbeSetColName(v, 0, "temp_store_directory", P3_STATIC);
+        sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3_temp_directory, 0);
+        sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
+      }
+    }else{
+      if( zRight[0] && !sqlite3OsIsDirWritable(zRight) ){
+        sqlite3ErrorMsg(pParse, "not a writable directory");
+        goto pragma_out;
+      }
+      if( TEMP_STORE==0
+       || (TEMP_STORE==1 && db->temp_store<=1)
+       || (TEMP_STORE==2 && db->temp_store==1)
+      ){
+        invalidateTempStorage(pParse);
+      }
+      sqliteFree(sqlite3_temp_directory);
+      if( zRight[0] ){
+        sqlite3_temp_directory = zRight;
+        zRight = 0;
+      }else{
+        sqlite3_temp_directory = 0;
+      }
+    }
+  }else
+
   /*
   **   PRAGMA [database.]synchronous
   **   PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL
@@ -353,22 +426,14 @@ void sqlite3Pragma(
       }
     }
   }else
-
-#if 0  /* Used once during development.  No longer needed */
-  if( sqlite3StrICmp(zLeft, "trigger_overhead_test")==0 ){
-    if( getBoolean(zRight) ){
-      sqlite3_always_code_trigger_setup = 1;
-    }else{
-      sqlite3_always_code_trigger_setup = 0;
-    }
-  }else
-#endif
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
 
   if( flagPragma(pParse, zLeft, zRight) ){
     /* The flagPragma() subroutine also generates any necessary code
     ** there is nothing more to do here */
   }else
 
+#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
   /*
   **   PRAGMA table_info(<table>)
   **
@@ -401,8 +466,7 @@ void sqlite3Pragma(
         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);
-        sqlite3VdbeOp3(v, OP_String8, 0, 0,
-           pTab->aCol[i].zDflt, P3_STATIC);
+        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
         sqlite3VdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0);
         sqlite3VdbeAddOp(v, OP_Callback, 6, 0);
       }
@@ -458,6 +522,40 @@ void sqlite3Pragma(
     }
   }else
 
+  if( sqlite3StrICmp(zLeft, "database_list")==0 ){
+    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);
+    for(i=0; i<db->nDb; i++){
+      if( db->aDb[i].pBt==0 ) continue;
+      assert( db->aDb[i].zName!=0 );
+      sqlite3VdbeAddOp(v, OP_Integer, i, 0);
+      sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, 0);
+      sqlite3VdbeOp3(v, OP_String8, 0, 0,
+           sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
+      sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
+    }
+  }else
+
+  if( sqlite3StrICmp(zLeft, "collation_list")==0 ){
+    int i = 0;
+    HashElem *p;
+    sqlite3VdbeSetNumCols(v, 2);
+    sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC);
+    sqlite3VdbeSetColName(v, 1, "name", P3_STATIC);
+    for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
+      CollSeq *pColl = (CollSeq *)sqliteHashData(p);
+      sqlite3VdbeAddOp(v, OP_Integer, i++, 0);
+      sqlite3VdbeOp3(v, OP_String8, 0, 0, pColl->zName, 0);
+      sqlite3VdbeAddOp(v, OP_Callback, 2, 0);
+    }
+  }else
+#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */
+
+#ifndef SQLITE_OMIT_FOREIGN_KEY
   if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){
     FKey *pFK;
     Table *pTab;
@@ -491,24 +589,7 @@ void sqlite3Pragma(
       }
     }
   }else
-
-  if( sqlite3StrICmp(zLeft, "database_list")==0 ){
-    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);
-    for(i=0; i<db->nDb; i++){
-      if( db->aDb[i].pBt==0 ) continue;
-      assert( db->aDb[i].zName!=0 );
-      sqlite3VdbeAddOp(v, OP_Integer, i, 0);
-      sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, 0);
-      sqlite3VdbeOp3(v, OP_String8, 0, 0,
-           sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
-      sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
-    }
-  }else
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
 
 #ifndef NDEBUG
   if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
@@ -521,6 +602,7 @@ void sqlite3Pragma(
   }else
 #endif
 
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
   if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
     int i, j, addr;
 
@@ -645,6 +727,9 @@ void sqlite3Pragma(
     addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
     sqlite3VdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
   }else
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+
+#ifndef SQLITE_OMIT_UTF16
   /*
   **   PRAGMA encoding
   **   PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be"
@@ -715,6 +800,69 @@ void sqlite3Pragma(
       }
     }
   }else
+#endif /* SQLITE_OMIT_UTF16 */
+
+#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+  /*
+  **   PRAGMA [database.]schema_version
+  **   PRAGMA [database.]schema_version = <integer>
+  **
+  **   PRAGMA [database.]user_version
+  **   PRAGMA [database.]user_version = <integer>
+  **
+  ** The pragma's schema_version and user_version are used to set or get
+  ** the value of the schema-version and user-version, respectively. Both
+  ** the schema-version and the user-version are 32-bit signed integers
+  ** stored in the database header.
+  **
+  ** The schema-cookie is usually only manipulated internally by SQLite. It
+  ** is incremented by SQLite whenever the database schema is modified (by
+  ** creating or dropping a table or index). The schema version is used by
+  ** SQLite each time a query is executed to ensure that the internal cache
+  ** of the schema used when compiling the SQL query matches the schema of
+  ** the database against which the compiled query is actually executed.
+  ** Subverting this mechanism by using "PRAGMA schema_version" to modify
+  ** the schema-version is potentially dangerous and may lead to program
+  ** crashes or database corruption. Use with caution!
+  **
+  ** The user-version is not used internally by SQLite. It may be used by
+  ** applications for any purpose.
+  */
+  if( sqlite3StrICmp(zLeft, "schema_version")==0 ||
+      sqlite3StrICmp(zLeft, "user_version")==0 ){
+
+    int iCookie;   /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */
+    if( zLeft[0]=='s' || zLeft[0]=='S' ){
+      iCookie = 0;
+    }else{
+      iCookie = 5;
+    }
+
+    if( zRight ){
+      /* Write the specified cookie value */
+      static const VdbeOpList setCookie[] = {
+        { OP_Transaction,    0,  1,  0},    /* 0 */
+        { OP_Integer,        0,  0,  0},    /* 1 */
+        { OP_SetCookie,      0,  0,  0},    /* 2 */
+      };
+      int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie);
+      sqlite3VdbeChangeP1(v, addr, iDb);
+      sqlite3VdbeChangeP1(v, addr+1, atoi(zRight));
+      sqlite3VdbeChangeP1(v, addr+2, iDb);
+      sqlite3VdbeChangeP2(v, addr+2, iCookie);
+    }else{
+      /* Read the specified cookie value */
+      static const VdbeOpList readCookie[] = {
+        { OP_ReadCookie,      0,  0,  0},    /* 0 */
+        { OP_Callback,        1,  0,  0}
+      };
+      int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie);
+      sqlite3VdbeChangeP1(v, addr, iDb);
+      sqlite3VdbeChangeP2(v, addr, iCookie);
+      sqlite3VdbeSetNumCols(v, 1);
+    }
+  }
+#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
 
 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
   /*
@@ -748,7 +896,17 @@ void sqlite3Pragma(
 #endif
 
   {}
+
+  if( v ){
+    /* Code an OP_Expire at the end of each PRAGMA program to cause
+    ** the VDBE implementing the pragma to expire. Most (all?) pragmas
+    ** are only valid for a single execution.
+    */
+    sqlite3VdbeAddOp(v, OP_Expire, 1, 0);
+  }
 pragma_out:
   sqliteFree(zLeft);
   sqliteFree(zRight);
 }
+
+#endif /* SQLITE_OMIT_PRAGMA */
index 43e12863721072cb31f498e050a187dd0a884921..6e700771b4ba2e34ef6129d67a1748abc47bde2d 100644 (file)
@@ -99,6 +99,7 @@ typedef struct et_info {   /* Information about each format field */
 */
 #define FLAG_SIGNED  1     /* True if the value to convert is signed */
 #define FLAG_INTERN  2     /* True if for internal use only */
+#define FLAG_STRING  4     /* Allow infinity precision */
 
 
 /*
@@ -109,10 +110,10 @@ static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
 static const char aPrefix[] = "-x0\000X0";
 static const et_info fmtinfo[] = {
   {  'd', 10, 1, etRADIX,      0,  0 },
-  {  's',  0, 0, etSTRING,     0,  0 },
-  {  'z',  0, 2, etDYNSTRING,  0,  0 },
-  {  'q',  0, 0, etSQLESCAPE,  0,  0 },
-  {  'Q',  0, 0, etSQLESCAPE2, 0,  0 },
+  {  's',  0, 4, etSTRING,     0,  0 },
+  {  'z',  0, 6, etDYNSTRING,  0,  0 },
+  {  'q',  0, 4, etSQLESCAPE,  0,  0 },
+  {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
   {  'c',  0, 0, etCHARX,      0,  0 },
   {  'o',  8, 0, etRADIX,      0,  2 },
   {  'u', 10, 0, etRADIX,      0,  0 },
@@ -296,8 +297,6 @@ static int vxprintf(
           c = *++fmt;
         }
       }
-      /* Limit the precision to prevent overflowing buf[] during conversion */
-      if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40;
     }else{
       precision = -1;
     }
@@ -328,6 +327,11 @@ static int vxprintf(
     }
     zExtra = 0;
 
+    /* Limit the precision to prevent overflowing buf[] during conversion */
+    if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){
+      precision = etBUFSIZE-40;
+    }
+
     /*
     ** At this point, variables are initialized as follows:
     **
@@ -563,13 +567,15 @@ static int vxprintf(
       case etSQLESCAPE2:
         {
           int i, j, n, c, 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++;
           }
-          n += i + 1 + ((!isnull && xtype==etSQLESCAPE2) ? 2 : 0);
+          needQuote = !isnull && xtype==etSQLESCAPE2;
+          n += i + 1 + needQuote*2;
           if( n>etBUFSIZE ){
             bufpt = zExtra = sqliteMalloc( n );
             if( bufpt==0 ) return -1;
@@ -577,12 +583,12 @@ static int vxprintf(
             bufpt = buf;
           }
           j = 0;
-          if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
+          if( needQuote ) bufpt[j++] = '\'';
           for(i=0; (c=arg[i])!=0; i++){
             bufpt[j++] = c;
             if( c=='\'' ) bufpt[j++] = c;
           }
-          if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
+          if( needQuote ) bufpt[j++] = '\'';
           bufpt[j] = 0;
           length = j;
           if( precision>=0 && precision<length ) length = precision;
index 8bee789773ed94f9899ce38642fa68a211cf9713..646134df2e68a10aa0206124957b64acf93466c5 100644 (file)
@@ -29,11 +29,12 @@ Select *sqlite3SelectNew(
   Expr *pHaving,        /* the HAVING clause */
   ExprList *pOrderBy,   /* the ORDER BY clause */
   int isDistinct,       /* true if the DISTINCT keyword is present */
-  int nLimit,           /* LIMIT value.  -1 means not used */
-  int nOffset           /* OFFSET value.  0 means no offset */
+  Expr *pLimit,         /* LIMIT value.  NULL means not used */
+  Expr *pOffset         /* OFFSET value.  NULL means no offset */
 ){
   Select *pNew;
   pNew = sqliteMalloc( sizeof(*pNew) );
+  assert( !pOffset || pLimit );   /* Can't have OFFSET without LIMIT. */
   if( pNew==0 ){
     sqlite3ExprListDelete(pEList);
     sqlite3SrcListDelete(pSrc);
@@ -41,6 +42,8 @@ Select *sqlite3SelectNew(
     sqlite3ExprListDelete(pGroupBy);
     sqlite3ExprDelete(pHaving);
     sqlite3ExprListDelete(pOrderBy);
+    sqlite3ExprDelete(pLimit);
+    sqlite3ExprDelete(pOffset);
   }else{
     if( pEList==0 ){
       pEList = sqlite3ExprListAppend(0, sqlite3Expr(TK_ALL,0,0,0), 0);
@@ -53,8 +56,8 @@ Select *sqlite3SelectNew(
     pNew->pOrderBy = pOrderBy;
     pNew->isDistinct = isDistinct;
     pNew->op = TK_SELECT;
-    pNew->nLimit = nLimit;
-    pNew->nOffset = nOffset;
+    pNew->pLimit = pLimit;
+    pNew->pOffset = pOffset;
     pNew->iLimit = -1;
     pNew->iOffset = -1;
   }
@@ -160,7 +163,9 @@ static void setToken(Token *p, const char *z){
 static void addWhereTerm(
   const char *zCol,        /* Name of the column */
   const Table *pTab1,      /* First table */
+  const char *zAlias1,     /* Alias for first table.  May be NULL */
   const Table *pTab2,      /* Second table */
+  const char *zAlias2,     /* Alias for second table.  May be NULL */
   Expr **ppExpr            /* Add the equality term to this expression */
 ){
   Token dummy;
@@ -171,9 +176,15 @@ static void addWhereTerm(
   setToken(&dummy, zCol);
   pE1a = sqlite3Expr(TK_ID, 0, 0, &dummy);
   pE2a = sqlite3Expr(TK_ID, 0, 0, &dummy);
-  setToken(&dummy, pTab1->zName);
+  if( zAlias1==0 ){
+    zAlias1 = pTab1->zName;
+  }
+  setToken(&dummy, zAlias1);
   pE1b = sqlite3Expr(TK_ID, 0, 0, &dummy);
-  setToken(&dummy, pTab2->zName);
+  if( zAlias2==0 ){
+    zAlias2 = pTab2->zName;
+  }
+  setToken(&dummy, zAlias2);
   pE2b = sqlite3Expr(TK_ID, 0, 0, &dummy);
   pE1c = sqlite3Expr(TK_DOT, pE1b, pE1a, 0);
   pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0);
@@ -241,7 +252,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
       for(j=0; j<pLeftTab->nCol; j++){
         char *zName = pLeftTab->aCol[j].zName;
         if( columnIndex(pRightTab, zName)>=0 ){
-          addWhereTerm(zName, pLeftTab, pRightTab, &p->pWhere);
+          addWhereTerm(zName, pLeftTab, pLeft->zAlias, 
+                              pRightTab, pRight->zAlias, &p->pWhere);
         }
       }
     }
@@ -279,7 +291,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
             "not present in both tables", zName);
           return 1;
         }
-        addWhereTerm(zName, pLeftTab, pRightTab, &p->pWhere);
+        addWhereTerm(zName, pLeftTab, pLeft->zAlias, 
+                            pRightTab, pRight->zAlias, &p->pWhere);
       }
     }
   }
@@ -298,20 +311,11 @@ void sqlite3SelectDelete(Select *p){
   sqlite3ExprDelete(p->pHaving);
   sqlite3ExprListDelete(p->pOrderBy);
   sqlite3SelectDelete(p->pPrior);
-  sqliteFree(p->zSelect);
+  sqlite3ExprDelete(p->pLimit);
+  sqlite3ExprDelete(p->pOffset);
   sqliteFree(p);
 }
 
-/*
-** Delete the aggregate information from the parse structure.
-*/
-static void sqliteAggregateInfoReset(Parse *pParse){
-  sqliteFree(pParse->aAgg);
-  pParse->aAgg = 0;
-  pParse->nAgg = 0;
-  pParse->useAgg = 0;
-}
-
 /*
 ** Insert code into "v" that will push the record on the top of the
 ** stack into the sorter.
@@ -336,9 +340,10 @@ static void codeLimiter(
   int nPop          /* Number of times to pop stack when jumping */
 ){
   if( p->iOffset>=0 ){
-    int addr = sqlite3VdbeCurrentAddr(v) + 2;
+    int addr = sqlite3VdbeCurrentAddr(v) + 3;
     if( nPop>0 ) addr++;
-    sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, addr);
+    sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, 0);
+    sqlite3VdbeAddOp(v, OP_IfMemPos, p->iOffset, addr);
     if( nPop>0 ){
       sqlite3VdbeAddOp(v, OP_Pop, nPop, 0);
     }
@@ -425,6 +430,7 @@ static int selectInnerLoop(
   }
 
   switch( eDest ){
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
     /* In this mode, write each query result to the key of the temporary
     ** table iParm.
     */
@@ -436,6 +442,20 @@ static int selectInnerLoop(
       break;
     }
 
+    /* Construct a record from the query result, but instead of
+    ** saving that record, use it as a key to delete elements from
+    ** the temporary table iParm.
+    */
+    case SRT_Except: {
+      int addr;
+      addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
+      sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
+      sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3);
+      sqlite3VdbeAddOp(v, OP_Delete, iParm, 0);
+      break;
+    }
+#endif
+
     /* Store the result as data using a unique key.
     */
     case SRT_Table:
@@ -451,19 +471,7 @@ static int selectInnerLoop(
       break;
     }
 
-    /* Construct a record from the query result, but instead of
-    ** saving that record, use it as a key to delete elements from
-    ** the temporary table iParm.
-    */
-    case SRT_Except: {
-      int addr;
-      addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
-      sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
-      sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3);
-      sqlite3VdbeAddOp(v, OP_Delete, iParm, 0);
-      break;
-    }
-
+#ifndef SQLITE_OMIT_SUBQUERY
     /* If we are creating a set for an "expr IN (SELECT ...)" construct,
     ** then there should be a single item on the stack.  Write this
     ** item into the set table with bogus data.
@@ -493,6 +501,7 @@ static int selectInnerLoop(
     ** 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 ){
@@ -503,6 +512,7 @@ static int selectInnerLoop(
       }
       break;
     }
+#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
 
     /* Send the data to the callback function.
     */
@@ -531,6 +541,7 @@ static int selectInnerLoop(
       break;
     }
 
+#if !defined(SQLITE_OMIT_TRIGGER)
     /* Discard the results.  This is used for SELECT statements inside
     ** the body of a TRIGGER.  The purpose of such selects is to call
     ** user-defined functions that have side effects.  We do not care
@@ -541,6 +552,7 @@ static int selectInnerLoop(
       sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
       break;
     }
+#endif
   }
   return 0;
 }
@@ -596,6 +608,7 @@ static void generateSortTail(
       sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0);
       break;
     }
+#ifndef SQLITE_OMIT_SUBQUERY
     case SRT_Set: {
       assert( nColumn==1 );
       sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
@@ -606,12 +619,14 @@ static void generateSortTail(
       sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
       break;
     }
+    case SRT_Exists:
     case SRT_Mem: {
       assert( nColumn==1 );
       sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
       sqlite3VdbeAddOp(v, OP_Goto, 0, end1);
       break;
     }
+#endif
     case SRT_Callback:
     case SRT_Subroutine: {
       int i;
@@ -650,18 +665,31 @@ static void generateSortTail(
 ** The declaration type for an expression is either TEXT, NUMERIC or ANY.
 ** The declaration type for a ROWID field is INTEGER.
 */
-static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){
+static const char *columnType(NameContext *pNC, Expr *pExpr){
   char const *zType;
   int j;
-  if( pExpr==0 || pTabList==0 ) return 0;
+  if( pExpr==0 || pNC->pSrcList==0 ) return 0;
+
+  /* The TK_AS operator can only occur in ORDER BY, GROUP BY, HAVING,
+  ** and LIMIT clauses.  But pExpr originates in the result set of a
+  ** SELECT.  So pExpr can never contain an AS operator.
+  */
+  assert( pExpr->op!=TK_AS );
 
   switch( pExpr->op ){
     case TK_COLUMN: {
-      Table *pTab;
+      Table *pTab = 0;
       int iCol = pExpr->iColumn;
-      for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable; j++){}
-      assert( j<pTabList->nSrc );
-      pTab = pTabList->a[j].pTab;
+      while( pNC && !pTab ){
+        SrcList *pTabList = pNC->pSrcList;
+        for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
+        if( j<pTabList->nSrc ){
+          pTab = pTabList->a[j].pTab;
+        }else{
+          pNC = pNC->pNext;
+        }
+      }
+      assert( pTab );
       if( iCol<0 ) iCol = pTab->iPKey;
       assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
       if( iCol<0 ){
@@ -671,14 +699,16 @@ static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){
       }
       break;
     }
-    case TK_AS:
-      zType = columnType(pParse, pTabList, pExpr->pLeft); 
-      break;
+#ifndef SQLITE_OMIT_SUBQUERY
     case TK_SELECT: {
+      NameContext sNC;
       Select *pS = pExpr->pSelect;
-      zType = columnType(pParse, pS->pSrc, pS->pEList->a[0].pExpr); 
+      sNC.pSrcList = pExpr->pSelect->pSrc;
+      sNC.pNext = pNC;
+      zType = columnType(&sNC, pS->pEList->a[0].pExpr); 
       break;
     }
+#endif
     default:
       zType = 0;
   }
@@ -697,9 +727,11 @@ static void generateColumnTypes(
 ){
   Vdbe *v = pParse->pVdbe;
   int i;
+  NameContext sNC;
+  sNC.pSrcList = pTabList;
   for(i=0; i<pEList->nExpr; i++){
     Expr *p = pEList->a[i].pExpr;
-    const char *zType = columnType(pParse, pTabList, p);
+    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.
@@ -723,10 +755,12 @@ static void generateColumnNames(
   sqlite3 *db = pParse->db;
   int fullNames, shortNames;
 
+#ifndef SQLITE_OMIT_EXPLAIN
   /* If this is an EXPLAIN, skip this step */
   if( pParse->explain ){
     return;
   }
+#endif
 
   assert( v!=0 );
   if( pParse->colNamesSet || v==0 || sqlite3_malloc_failed ) return;
@@ -753,7 +787,7 @@ static void generateColumnNames(
       if( iCol<0 ) iCol = pTab->iPKey;
       assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
       if( iCol<0 ){
-        zCol = "_ROWID_";
+        zCol = "rowid";
       }else{
         zCol = pTab->aCol[iCol].zName;
       }
@@ -768,7 +802,7 @@ static void generateColumnNames(
         sqlite3SetString(&zName, zTab, ".", zCol, 0);
         sqlite3VdbeSetColName(v, i, zName, P3_DYNAMIC);
       }else{
-        sqlite3VdbeSetColName(v, i, zCol, 0);
+        sqlite3VdbeSetColName(v, i, zCol, strlen(zCol));
       }
     }else if( p->span.z && p->span.z[0] ){
       sqlite3VdbeSetColName(v, i, p->span.z, p->span.n);
@@ -783,6 +817,7 @@ static void generateColumnNames(
   generateColumnTypes(pParse, pTabList, pEList);
 }
 
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
 /*
 ** Name of the connection operator, used for error messages.
 */
@@ -796,11 +831,12 @@ static const char *selectOpName(int id){
   }
   return z;
 }
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
 
 /*
 ** Forward declaration
 */
-static int fillInColumnList(Parse*, Select*);
+static int prepSelectStmt(Parse*, Select*);
 
 /*
 ** Given a SELECT statement, generate a Table structure that describes
@@ -812,7 +848,10 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
   ExprList *pEList;
   Column *aCol, *pCol;
 
-  if( fillInColumnList(pParse, pSelect) ){
+  if( prepSelectStmt(pParse, pSelect) ){
+    return 0;
+  }
+  if( sqlite3SelectResolve(pParse, pSelect, 0) ){
     return 0;
   }
   pTab = sqliteMalloc( sizeof(Table) );
@@ -825,38 +864,55 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
   assert( pTab->nCol>0 );
   pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
   for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
-    Expr *pR;
+    Expr *p, *pR;
     char *zType;
     char *zName;
-    Expr *p = pEList->a[i].pExpr;
+    char *zBasename;
+    int cnt;
+    NameContext sNC;
+    
+    /* Get an appropriate name for the column
+    */
+    p = pEList->a[i].pExpr;
     assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 );
     if( (zName = pEList->a[i].zName)!=0 ){
+      /* If the column contains an "AS <name>" phrase, use <name> as the name */
       zName = sqliteStrDup(zName);
     }else if( p->op==TK_DOT 
-               && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
-      int cnt;
+              && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
+      /* For columns of the from A.B use B as the name */
       zName = sqlite3MPrintf("%T", &pR->token);
-      for(j=cnt=0; j<i; j++){
-        if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
-          sqliteFree(zName);
-          zName = sqlite3MPrintf("%T_%d", &pR->token, ++cnt);
-          j = -1;
-        }
-      }
     }else if( p->span.z && p->span.z[0] ){
+      /* Use the original text of the column expression as its name */
       zName = sqlite3MPrintf("%T", &p->span);
     }else{
+      /* If all else fails, make up a name */
       zName = sqlite3MPrintf("column%d", i+1);
     }
     sqlite3Dequote(zName);
+
+    /* Make sure the column name is unique.  If the name is not unique,
+    ** append a integer to the name so that it becomes unique.
+    */
+    zBasename = zName;
+    for(j=cnt=0; j<i; j++){
+      if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
+        zName = sqlite3MPrintf("%s:%d", zBasename, ++cnt);
+        j = -1;
+      }
+    }
+    if( zBasename!=zName ){
+      sqliteFree(zBasename);
+    }
     pCol->zName = zName;
 
-    zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p));
+    /* Get the typename, type affinity, and collating sequence for the
+    ** column.
+    */
+    sNC.pSrcList = pSelect->pSrc;
+    zType = sqliteStrDup(columnType(&sNC, p));
     pCol->zType = zType;
-    pCol->affinity = SQLITE_AFF_NUMERIC;
-    if( zType ){
-      pCol->affinity = sqlite3AffinityType(zType, strlen(zType));
-    }
+    pCol->affinity = sqlite3ExprAffinity(p);
     pCol->pColl = sqlite3ExprCollSeq(pParse, p);
     if( !pCol->pColl ){
       pCol->pColl = pParse->db->pDfltColl;
@@ -867,20 +923,24 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
 }
 
 /*
-** For the given SELECT statement, do three things.
+** Prepare a SELECT statement for processing by doing the following
+** things:
+**
+**    (1)  Make sure VDBE cursor numbers have been assigned to every
+**         element of the FROM clause.
 **
-**    (1)  Fill in the pTabList->a[].pTab fields in the SrcList that 
-**         defines the set of tables that should be scanned.  For views,
+**    (2)  Fill in the pTabList->a[].pTab fields in the SrcList that 
+**         defines FROM clause.  When views appear in the FROM clause,
 **         fill pTabList->a[].pSelect with a copy of the SELECT statement
 **         that implements the view.  A copy is made of the view's SELECT
 **         statement so that we can freely modify or delete that statement
 **         without worrying about messing up the presistent representation
 **         of the view.
 **
-**    (2)  Add terms to the WHERE clause to accomodate the NATURAL keyword
+**    (3)  Add terms to the WHERE clause to accomodate the NATURAL keyword
 **         on joins and the ON and USING clause of joins.
 **
-**    (3)  Scan the list of columns in the result set (pEList) looking
+**    (4)  Scan the list of columns in the result set (pEList) looking
 **         for instances of the "*" operator or the TABLE.* operator.
 **         If found, expand each "*" to be every column in every table
 **         and TABLE.* to be every column in TABLE.
@@ -888,7 +948,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
 ** Return 0 on success.  If there are problems, leave an error message
 ** in pParse and return non-zero.
 */
-static int fillInColumnList(Parse *pParse, Select *p){
+static int prepSelectStmt(Parse *pParse, Select *p){
   int i, j, k, rc;
   SrcList *pTabList;
   ExprList *pEList;
@@ -899,14 +959,24 @@ static int fillInColumnList(Parse *pParse, Select *p){
   pTabList = p->pSrc;
   pEList = p->pEList;
 
-  /* Look up every table in the table list.
+  /* Make sure cursor numbers have been assigned to all entries in
+  ** the FROM clause of the SELECT statement.
+  */
+  sqlite3SrcListAssignCursors(pParse, p->pSrc);
+
+  /* Look up every table named in the FROM clause of the select.  If
+  ** an entry of the FROM clause is a subquery instead of a table or view,
+  ** then create a transient table structure to describe the subquery.
   */
   for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
-    if( pFrom->pTab ){
-      /* This routine has run before!  No need to continue */
+    if( pFrom->pTab!=0 ){
+      /* This statement has already been prepared.  There is no need
+      ** to go further. */
+      assert( i==0 );
       return 0;
     }
     if( pFrom->zName==0 ){
+#ifndef SQLITE_OMIT_SUBQUERY
       /* A sub-query in the FROM clause of a SELECT */
       assert( pFrom->pSelect!=0 );
       if( pFrom->zAlias==0 ){
@@ -923,6 +993,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
       ** pTab is not pointing to a persistent table structure that defines
       ** part of the schema. */
       pTab->isTransient = 1;
+#endif
     }else{
       /* An ordinary table or view name in the FROM clause */
       pFrom->pTab = pTab = 
@@ -930,6 +1001,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
       if( pTab==0 ){
         return 1;
       }
+#ifndef SQLITE_OMIT_VIEW
       if( pTab->pSelect ){
         /* We reach here if the named table is a really a view */
         if( sqlite3ViewGetColumnNames(pParse, pTab) ){
@@ -944,6 +1016,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
           pFrom->pSelect = sqlite3SelectDup(pTab->pSelect);
         }
       }
+#endif
     }
   }
 
@@ -1042,7 +1115,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
               pExpr = pRight;
               pExpr->span = pExpr->token;
             }
-            pNew = sqlite3ExprListAppend(pNew, pExpr, 0);
+            pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token);
           }
         }
         if( !tableSeen ){
@@ -1075,6 +1148,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
 ** will be left pointing to a deallocated Table structure after the
 ** DROP and a coredump will occur the next time the VIEW is used.
 */
+#if 0
 void sqlite3SelectUnbind(Select *p){
   int i;
   SrcList *pSrc = p->pSrc;
@@ -1093,7 +1167,9 @@ void sqlite3SelectUnbind(Select *p){
     }
   }
 }
+#endif
 
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
 /*
 ** This routine associates entries in an ORDER BY expression list with
 ** columns in a result.  For each ORDER BY expression, the opcode of
@@ -1122,7 +1198,7 @@ static int matchOrderbyToColumn(
   if( mustComplete ){
     for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; }
   }
-  if( fillInColumnList(pParse, pSelect) ){
+  if( prepSelectStmt(pParse, pSelect) ){
     return 1;
   }
   if( pSelect->pPrior ){
@@ -1165,6 +1241,7 @@ static int matchOrderbyToColumn(
       pE->op = TK_COLUMN;
       pE->iColumn = iCol;
       pE->iTable = iTable;
+      pE->iAgg = -1;
       pOrderBy->a[i].done = 1;
     }
     if( iCol<0 && mustComplete ){
@@ -1176,6 +1253,7 @@ static int matchOrderbyToColumn(
   }
   return nErr;  
 }
+#endif /* #ifndef SQLITE_OMIT_COMPOUND_SELECT */
 
 /*
 ** Get a VDBE for the given parser context.  Create a new one if necessary.
@@ -1191,12 +1269,12 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
 
 /*
 ** Compute the iLimit and iOffset fields of the SELECT based on the
-** nLimit and nOffset fields.  nLimit and nOffset hold the integers
+** pLimit and pOffset expressions.  nLimit and nOffset hold the expressions
 ** that appear in the original SQL statement after the LIMIT and OFFSET
-** keywords.  Or that hold -1 and 0 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.
+** 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
@@ -1209,28 +1287,29 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
 */
 static void computeLimitRegisters(Parse *pParse, Select *p){
   /* 
-  ** If the comparison is p->nLimit>0 then "LIMIT 0" shows
-  ** all rows.  It is the same as no limit. If the comparision is
-  ** p->nLimit>=0 then "LIMIT 0" show no rows at all.
   ** "LIMIT -1" always shows all rows.  There is some
   ** contraversy about what the correct behavior should be.
   ** The current implementation interprets "LIMIT 0" to mean
   ** no rows.
   */
-  if( p->nLimit>=0 ){
+  if( p->pLimit ){
     int iMem = pParse->nMem++;
     Vdbe *v = sqlite3GetVdbe(pParse);
     if( v==0 ) return;
-    sqlite3VdbeAddOp(v, OP_Integer, -p->nLimit, 0);
+    sqlite3ExprCode(pParse, p->pLimit);
+    sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
+    sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
     sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1);
     VdbeComment((v, "# LIMIT counter"));
     p->iLimit = iMem;
   }
-  if( p->nOffset>0 ){
+  if( p->pOffset ){
     int iMem = pParse->nMem++;
     Vdbe *v = sqlite3GetVdbe(pParse);
     if( v==0 ) return;
-    sqlite3VdbeAddOp(v, OP_Integer, -p->nOffset, 0);
+    sqlite3ExprCode(pParse, p->pOffset);
+    sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
+    sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
     sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1);
     VdbeComment((v, "# OFFSET counter"));
     p->iOffset = iMem;
@@ -1260,7 +1339,7 @@ static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){
   Vdbe *v = pParse->pVdbe;
   int addr;
 
-  if( fillInColumnList(pParse, p) ){
+  if( prepSelectStmt(pParse, p) ){
     return 0;
   }
   nColumn = p->pEList->nExpr;
@@ -1282,6 +1361,7 @@ static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){
   return addr;
 }
 
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
 /*
 ** Add the address "addr" to the set of all OpenTemp opcode addresses
 ** that are being accumulated in p->ppOpenTemp.
@@ -1294,7 +1374,9 @@ static int multiSelectOpenTempAddr(Select *p, int addr){
   pList->a[pList->nId-1].idx = addr;
   return SQLITE_OK;
 }
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
 
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
 /*
 ** Return the appropriate collating sequence for the iCol-th column of
 ** the result set for the compound-select statement "p".  Return NULL if
@@ -1315,7 +1397,9 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
   }
   return pRet;
 }
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
 
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
 /*
 ** This routine is called to process a query that is really the union
 ** or intersection of two or more separate queries.
@@ -1375,7 +1459,7 @@ static int multiSelect(
     rc = 1;
     goto multi_select_end;
   }
-  if( pPrior->nLimit>=0 || pPrior->nOffset>0 ){
+  if( pPrior->pLimit ){
     sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before",
       selectOpName(p->op));
     rc = 1;
@@ -1416,8 +1500,9 @@ static int multiSelect(
   switch( p->op ){
     case TK_ALL: {
       if( p->pOrderBy==0 ){
-        pPrior->nLimit = p->nLimit;
-        pPrior->nOffset = p->nOffset;
+        assert( !pPrior->pLimit );
+        pPrior->pLimit = p->pLimit;
+        pPrior->pOffset = p->pOffset;
         rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff);
         if( rc ){
           goto multi_select_end;
@@ -1425,8 +1510,8 @@ static int multiSelect(
         p->pPrior = 0;
         p->iLimit = pPrior->iLimit;
         p->iOffset = pPrior->iOffset;
-        p->nLimit = -1;
-        p->nOffset = 0;
+        p->pLimit = 0;
+        p->pOffset = 0;
         rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff);
         p->pPrior = pPrior;
         if( rc ){
@@ -1441,12 +1526,12 @@ static int multiSelect(
       int unionTab;    /* Cursor number of the temporary table holding result */
       int op = 0;      /* One of the SRT_ operations to apply to self */
       int priorOp;     /* The SRT_ operation to apply to prior selects */
-      int nLimit, nOffset; /* Saved values of p->nLimit and p->nOffset */
-      ExprList *pOrderBy;  /* The ORDER BY clause for the right SELECT */
+      Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */
+      ExprList *pOrderBy;     /* The ORDER BY clause for the right SELECT */
       int addr;
 
       priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union;
-      if( eDest==priorOp && p->pOrderBy==0 && p->nLimit<0 && p->nOffset==0 ){
+      if( eDest==priorOp && p->pOrderBy==0 && !p->pLimit && !p->pOffset ){
         /* We can reuse a temporary table generated by a SELECT to our
         ** right.
         */
@@ -1476,6 +1561,7 @@ static int multiSelect(
 
       /* Code the SELECT statements to our left
       */
+      assert( !pPrior->pOrderBy );
       rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff);
       if( rc ){
         goto multi_select_end;
@@ -1491,15 +1577,18 @@ static int multiSelect(
       p->pPrior = 0;
       pOrderBy = p->pOrderBy;
       p->pOrderBy = 0;
-      nLimit = p->nLimit;
-      p->nLimit = -1;
-      nOffset = p->nOffset;
-      p->nOffset = 0;
+      pLimit = p->pLimit;
+      p->pLimit = 0;
+      pOffset = p->pOffset;
+      p->pOffset = 0;
       rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff);
       p->pPrior = pPrior;
       p->pOrderBy = pOrderBy;
-      p->nLimit = nLimit;
-      p->nOffset = nOffset;
+      sqlite3ExprDelete(p->pLimit);
+      p->pLimit = pLimit;
+      p->pOffset = pOffset;
+      p->iLimit = -1;
+      p->iOffset = -1;
       if( rc ){
         goto multi_select_end;
       }
@@ -1536,7 +1625,7 @@ static int multiSelect(
     case TK_INTERSECT: {
       int tab1, tab2;
       int iCont, iBreak, iStart;
-      int nLimit, nOffset;
+      Expr *pLimit, *pOffset;
       int addr;
 
       /* INTERSECT is different from the others since it requires
@@ -1578,14 +1667,15 @@ static int multiSelect(
       assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) );
       aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab2, 0);
       p->pPrior = 0;
-      nLimit = p->nLimit;
-      p->nLimit = -1;
-      nOffset = p->nOffset;
-      p->nOffset = 0;
+      pLimit = p->pLimit;
+      p->pLimit = 0;
+      pOffset = p->pOffset;
+      p->pOffset = 0;
       rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff);
       p->pPrior = pPrior;
-      p->nLimit = nLimit;
-      p->nOffset = nOffset;
+      sqlite3ExprDelete(p->pLimit);
+      p->pLimit = pLimit;
+      p->pOffset = pOffset;
       if( rc ){
         goto multi_select_end;
       }
@@ -1681,7 +1771,7 @@ static int multiSelect(
         Expr *pExpr = pOrderByTerm->pExpr;
         char *zName = pOrderByTerm->zName;
         assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol );
-        assert( !pExpr->pColl );
+        /* assert( !pExpr->pColl ); */
         if( zName ){
           pExpr->pColl = sqlite3LocateCollSeq(pParse, zName, -1);
         }else{
@@ -1704,7 +1794,9 @@ multi_select_end:
   p->ppOpenTemp = 0;
   return rc;
 }
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
 
+#ifndef SQLITE_OMIT_VIEW
 /*
 ** Scan through the expression pExpr.  Replace every reference to
 ** a column in table number iTable with a copy of the iColumn-th
@@ -1719,6 +1811,7 @@ multi_select_end:
 ** of the subquery rather the result set of the subquery.
 */
 static void substExprList(ExprList*,int,ExprList*);  /* Forward Decl */
+static void substSelect(Select *, int, ExprList *);  /* Forward Decl */
 static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
   if( pExpr==0 ) return;
   if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
@@ -1742,22 +1835,34 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
       pExpr->iAgg = pNew->iAgg;
       sqlite3TokenCopy(&pExpr->token, &pNew->token);
       sqlite3TokenCopy(&pExpr->span, &pNew->span);
+      pExpr->pSelect = sqlite3SelectDup(pNew->pSelect);
+      pExpr->flags = pNew->flags;
     }
   }else{
     substExpr(pExpr->pLeft, iTable, pEList);
     substExpr(pExpr->pRight, iTable, pEList);
+    substSelect(pExpr->pSelect, iTable, pEList);
     substExprList(pExpr->pList, iTable, pEList);
   }
 }
-static void 
-substExprList(ExprList *pList, int iTable, ExprList *pEList){
+static void substExprList(ExprList *pList, int iTable, ExprList *pEList){
   int i;
   if( pList==0 ) return;
   for(i=0; i<pList->nExpr; i++){
     substExpr(pList->a[i].pExpr, iTable, pEList);
   }
 }
+static void substSelect(Select *p, int iTable, ExprList *pEList){
+  if( !p ) return;
+  substExprList(p->pEList, iTable, pEList);
+  substExprList(p->pGroupBy, iTable, pEList);
+  substExprList(p->pOrderBy, iTable, pEList);
+  substExpr(p->pHaving, iTable, pEList);
+  substExpr(p->pWhere, iTable, pEList);
+}
+#endif /* !defined(SQLITE_OMIT_VIEW) */
 
+#ifndef SQLITE_OMIT_VIEW
 /*
 ** This routine attempts to flatten subqueries in order to speed
 ** execution.  It returns 1 if it makes changes and 0 if no flattening
@@ -1855,11 +1960,13 @@ static int flattenSubquery(
   if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;
   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 || pSub->nLimit>=0) &&  (pSrc->nSrc>1 || isAgg) ){
+  if( pSub->isDistinct && (pSrc->nSrc>1 || isAgg) ){
      return 0;
   }
-  if( (p->isDistinct || p->nLimit>=0) && subqueryIsAgg ) return 0;
+  if( p->isDistinct && subqueryIsAgg ) return 0;
   if( p->pOrderBy && pSub->pOrderBy ) return 0;
 
   /* Restriction 3:  If the subquery is a join, make sure the subquery is 
@@ -1991,17 +2098,13 @@ static int flattenSubquery(
   */
   p->isDistinct = p->isDistinct || pSub->isDistinct;
 
-  /* Transfer the limit expression from the subquery to the outer
-  ** query.
+  /*
+  ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
   */
-  if( pSub->nLimit>=0 ){
-    if( p->nLimit<0 ){
-      p->nLimit = pSub->nLimit;
-    }else if( p->nLimit+p->nOffset > pSub->nLimit+pSub->nOffset ){
-      p->nLimit = pSub->nLimit + pSub->nOffset - p->nOffset;
-    }
+  if( pSub->pLimit ){
+    p->pLimit = pSub->pLimit;
+    pSub->pLimit = 0;
   }
-  p->nOffset += pSub->nOffset;
 
   /* Finially, delete what is left of the subquery and return
   ** success.
@@ -2009,6 +2112,7 @@ static int flattenSubquery(
   sqlite3SelectDelete(pSub);
   return 1;
 }
+#endif /* SQLITE_OMIT_VIEW */
 
 /*
 ** Analyze the SELECT statement passed in as an argument to see if it
@@ -2042,7 +2146,6 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
   ExprList *pEList, *pList, eList;
   struct ExprList_item eListItem;
   SrcList *pSrc;
-  
 
   /* Check to see if this query is a simple min() or max() query.  Return
   ** zero if it is  not.
@@ -2115,17 +2218,25 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
   if( pIdx==0 ){
     sqlite3VdbeAddOp(v, seekOp, base, 0);
   }else{
+    /* Even though the cursor used to open the index here is closed
+    ** as soon as a single value has been read from it, allocate it
+    ** using (pParse->nTab++) to prevent the cursor id from being 
+    ** reused. This is important for statements of the form 
+    ** "INSERT INTO x SELECT max() FROM x".
+    */
+    int iIdx;
+    iIdx = pParse->nTab++;
     sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
-    sqlite3VdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum,
+    sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum,
                    (char*)&pIdx->keyInfo, P3_KEYINFO);
     if( seekOp==OP_Rewind ){
       sqlite3VdbeAddOp(v, OP_String, 0, 0);
       sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0);
       seekOp = OP_MoveGt;
     }
-    sqlite3VdbeAddOp(v, seekOp, base+1, 0);
-    sqlite3VdbeAddOp(v, OP_IdxRecno, base+1, 0);
-    sqlite3VdbeAddOp(v, OP_Close, base+1, 0);
+    sqlite3VdbeAddOp(v, seekOp, iIdx, 0);
+    sqlite3VdbeAddOp(v, OP_IdxRecno, iIdx, 0);
+    sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
     sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
   }
   eList.nExpr = 1;
@@ -2148,41 +2259,193 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
 ** corresponding entry in the result set.
 */
 static int processOrderGroupBy(
-  Parse *pParse,        /* Parsing context */
+  NameContext *pNC,     /* Name context of the SELECT statement. */
   ExprList *pOrderBy,   /* The ORDER BY or GROUP BY clause to be processed */
-  SrcList *pTabList,    /* The FROM clause */
-  ExprList *pEList,     /* The result set */
-  int isAgg,            /* True if aggregate functions are involved */
   const char *zType     /* Either "ORDER" or "GROUP", as appropriate */
 ){
   int i;
+  ExprList *pEList = pNC->pEList;     /* The result set of the SELECT */
+  Parse *pParse = pNC->pParse;     /* The result set of the SELECT */
+  assert( pEList );
+
   if( pOrderBy==0 ) return 0;
   for(i=0; i<pOrderBy->nExpr; i++){
     int iCol;
     Expr *pE = pOrderBy->a[i].pExpr;
-    if( sqlite3ExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){
-      sqlite3ExprDelete(pE);
-      pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr);
-    }
-    if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pE, isAgg, 0) ){
-      return 1;
-    }
-    if( sqlite3ExprIsConstant(pE) ){
-      if( sqlite3ExprIsInteger(pE, &iCol)==0 ){
-        sqlite3ErrorMsg(pParse,
-          "%s BY terms must not be non-integer constants", zType);
-        return 1;
-      }else if( iCol<=0 || iCol>pEList->nExpr ){
+    if( sqlite3ExprIsInteger(pE, &iCol) ){
+      if( iCol>0 && iCol<=pEList->nExpr ){
+        sqlite3ExprDelete(pE);
+        pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr);
+      }else{
         sqlite3ErrorMsg(pParse, 
            "%s BY column number %d out of range - should be "
            "between 1 and %d", zType, iCol, pEList->nExpr);
         return 1;
       }
     }
+    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;
 }
 
+/*
+** This routine resolves any names used in the result set of the
+** supplied SELECT statement. If the SELECT statement being resolved
+** is a sub-select, then pOuterNC is a pointer to the NameContext 
+** of the parent SELECT.
+*/
+int sqlite3SelectResolve(
+  Parse *pParse,         /* The parser context */
+  Select *p,             /* The SELECT statement being coded. */
+  NameContext *pOuterNC  /* The outer name context. May be NULL. */
+){
+  ExprList *pEList;          /* Result set. */
+  int i;                     /* For-loop variable used in multiple places */
+  NameContext sNC;           /* Local name-context */
+
+  /* If this routine has run before, return immediately. */
+  if( p->isResolved ){
+    assert( !pOuterNC );
+    return SQLITE_OK;
+  }
+  p->isResolved = 1;
+
+  /* If there have already been errors, do nothing. */
+  if( pParse->nErr>0 ){
+    return SQLITE_ERROR;
+  }
+
+  /* Prepare the select statement. This call will allocate all cursors
+  ** required to handle the tables and subqueries in the FROM clause.
+  */
+  if( prepSelectStmt(pParse, p) ){
+    return SQLITE_ERROR;
+  }
+
+  /* Resolve the expressions in the LIMIT and OFFSET clauses. These
+  ** are not allowed to refer to any names, so pass an empty NameContext.
+  */
+  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;
+  }
+
+  /* Set up the local name-context to pass to ExprResolveNames() to
+  ** resolve the expression-list.
+  */
+  sNC.allowAgg = 1;
+  sNC.pSrcList = p->pSrc;
+  sNC.pNext = pOuterNC;
+
+  /* NameContext.nDepth stores the depth of recursion for this query. For
+  ** an outer query (e.g. SELECT * FROM sqlite_master) this is 1. For
+  ** a subquery it is 2. For a subquery of a subquery, 3. And so on. 
+  ** Parse.nMaxDepth is the maximum depth for any subquery resolved so
+  ** far. This is used to determine the number of aggregate contexts
+  ** required at runtime.
+  */
+  sNC.nDepth = (pOuterNC?pOuterNC->nDepth+1:1);
+  if( sNC.nDepth>pParse->nMaxDepth ){
+    pParse->nMaxDepth = sNC.nDepth;
+  }
+
+  /* Resolve names in the result set. */
+  pEList = p->pEList;
+  if( !pEList ) return SQLITE_ERROR;
+  for(i=0; i<pEList->nExpr; i++){
+    Expr *pX = pEList->a[i].pExpr;
+    if( sqlite3ExprResolveNames(&sNC, pX) ){
+      return SQLITE_ERROR;
+    }
+  }
+
+  /* If there are no aggregate functions in the result-set, and no GROUP BY 
+  ** expression, do not allow aggregates in any of the other expressions.
+  */
+  assert( !p->isAgg );
+  if( p->pGroupBy || sNC.hasAgg ){
+    p->isAgg = 1;
+  }else{
+    sNC.allowAgg = 0;
+  }
+
+  /* If a HAVING clause is present, then there must be a GROUP BY clause.
+  */
+  if( p->pHaving && !p->pGroupBy ){
+    sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
+    return SQLITE_ERROR;
+  }
+
+  /* Add the expression list to the name-context before parsing the
+  ** other expressions in the SELECT statement. This is so that
+  ** expressions in the WHERE clause (etc.) can refer to expressions by
+  ** aliases in the result set.
+  **
+  ** Minor point: If this is the case, then the expression will be
+  ** re-evaluated for each reference to it.
+  */
+  sNC.pEList = p->pEList;
+  if( sqlite3ExprResolveNames(&sNC, p->pWhere) ||
+      sqlite3ExprResolveNames(&sNC, p->pHaving) ||
+      processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") ||
+      processOrderGroupBy(&sNC, p->pGroupBy, "GROUP")
+  ){
+    return SQLITE_ERROR;
+  }
+
+  return SQLITE_OK;
+}
+
+/*
+** An instance of the following struct is used by sqlite3Select()
+** to save aggregate related information from the Parse object
+** at the start of each call and to restore it at the end. See
+** saveAggregateInfo() and restoreAggregateInfo().
+*/ 
+struct AggregateInfo {
+  int nAgg;
+  AggExpr *aAgg;
+};
+typedef struct AggregateInfo AggregateInfo;
+
+/* 
+** Copy aggregate related information from the Parse structure
+** into the AggregateInfo structure. Zero the aggregate related
+** values in the Parse struct.
+*/
+static void saveAggregateInfo(Parse *pParse, AggregateInfo *pInfo){
+  pInfo->aAgg = pParse->aAgg;
+  pInfo->nAgg = pParse->nAgg;
+  pParse->aAgg = 0;
+  pParse->nAgg = 0;
+}
+
+/*
+** Copy aggregate related information from the AggregateInfo struct
+** back into the Parse structure. The aggregate related information
+** currently stored in the Parse structure is deleted.
+*/
+static void restoreAggregateInfo(Parse *pParse, AggregateInfo *pInfo){
+  sqliteFree(pParse->aAgg);
+  pParse->aAgg = pInfo->aAgg;
+  pParse->nAgg = pInfo->nAgg;
+}
+  
 /*
 ** Generate code for the given SELECT statement.
 **
@@ -2248,7 +2511,7 @@ int sqlite3Select(
   int i;
   WhereInfo *pWInfo;
   Vdbe *v;
-  int isAgg = 0;         /* True for select lists like "count(*)" */
+  int isAgg;             /* True for select lists like "count(*)" */
   ExprList *pEList;      /* List of columns to extract. */
   SrcList *pTabList;     /* List of tables to select from */
   Expr *pWhere;          /* The WHERE clause.  May be NULL */
@@ -2258,28 +2521,39 @@ 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 */
+  AggregateInfo sAggInfo;
 
   if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1;
   if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
 
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
   /* If there is are a sequence of queries, do the earlier ones first.
   */
   if( p->pPrior ){
     return multiSelect(pParse, p, eDest, iParm, aff);
   }
+#endif
+
+  saveAggregateInfo(pParse, &sAggInfo);
+  pOrderBy = p->pOrderBy;
+  if( eDest==SRT_Union || eDest==SRT_Except || eDest==SRT_Discard ){
+    p->pOrderBy = 0;
+  }
+  if( sqlite3SelectResolve(pParse, p, 0) ){
+    goto select_end;
+  }
+  p->pOrderBy = pOrderBy;
 
   /* Make local copies of the parameters for this query.
   */
   pTabList = p->pSrc;
   pWhere = p->pWhere;
-  pOrderBy = p->pOrderBy;
   pGroupBy = p->pGroupBy;
   pHaving = p->pHaving;
+  isAgg = p->isAgg;
   isDistinct = p->isDistinct;
-
-  /* Allocate VDBE cursors for each table in the FROM clause
-  */
-  sqlite3SrcListAssignCursors(pParse, pTabList);
+  pEList = p->pEList;
+  if( pEList==0 ) goto select_end;
 
   /* 
   ** Do not even attempt to generate any code if we have already seen
@@ -2287,25 +2561,17 @@ int sqlite3Select(
   */
   if( pParse->nErr>0 ) goto select_end;
 
-  /* Expand any "*" terms in the result set.  (For example the "*" in
-  ** "SELECT * FROM t1")  The fillInColumnlist() routine also does some
-  ** other housekeeping - see the header comment for details.
-  */
-  if( fillInColumnList(pParse, p) ){
-    goto select_end;
-  }
-  pWhere = p->pWhere;
-  pEList = p->pEList;
-  if( pEList==0 ) goto select_end;
-
   /* 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 "
        "a SELECT that is part of an expression");
     goto select_end;
   }
+#endif
 
   /* ORDER BY is ignored for some destinations.
   */
@@ -2319,35 +2585,6 @@ int sqlite3Select(
       break;
   }
 
-  /* At this point, we should have allocated all the cursors that we
-  ** need to handle subquerys and temporary tables.  
-  **
-  ** Resolve the column names and do a semantics check on all the expressions.
-  */
-  for(i=0; i<pEList->nExpr; i++){
-    if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pEList->a[i].pExpr,
-                                    1, &isAgg) ){
-      goto select_end;
-    }
-  }
-  if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pWhere, 0, 0) ){
-    goto select_end;
-  }
-  if( pHaving ){
-    if( pGroupBy==0 ){
-      sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
-      goto select_end;
-    }
-    if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList,pHaving,1,&isAgg) ){
-      goto select_end;
-    }
-  }
-  if( processOrderGroupBy(pParse, pOrderBy, pTabList, pEList, isAgg, "ORDER")
-   || processOrderGroupBy(pParse, pGroupBy, pTabList, pEList, isAgg, "GROUP")
-  ){
-    goto select_end;
-  }
-
   /* Begin generating code.
   */
   v = sqlite3GetVdbe(pParse);
@@ -2362,6 +2599,7 @@ int sqlite3Select(
 
   /* Generate code for all sub-queries in the FROM clause
   */
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
   for(i=0; i<pTabList->nSrc; i++){
     const char *zSavedAuthContext = 0;
     int needRestoreContext;
@@ -2388,6 +2626,7 @@ int sqlite3Select(
     pHaving = p->pHaving;
     isDistinct = p->isDistinct;
   }
+#endif
 
   /* Check for the special case of a min() or max() function by itself
   ** in the result set.
@@ -2400,11 +2639,13 @@ int sqlite3Select(
   /* Check to see if this is a subquery that can be "flattened" into its parent.
   ** If flattening is a possiblity, do so and return immediately.  
   */
+#ifndef SQLITE_OMIT_VIEW
   if( pParent && pParentAgg &&
       flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){
     if( isAgg ) *pParentAgg = 1;
-    return rc;
+    goto select_end;
   }
+#endif
 
   /* If there is an ORDER BY clause, resolve any collation sequences
   ** names that have been explicitly specified.
@@ -2434,28 +2675,32 @@ int sqlite3Select(
 
   /* Do an analysis of aggregate expressions.
   */
-  sqliteAggregateInfoReset(pParse);
   if( isAgg || pGroupBy ){
+    NameContext sNC;
+    memset(&sNC, 0, sizeof(sNC));
+    sNC.pParse = pParse;
+    sNC.pSrcList = pTabList;
+
     assert( pParse->nAgg==0 );
     isAgg = 1;
     for(i=0; i<pEList->nExpr; i++){
-      if( sqlite3ExprAnalyzeAggregates(pParse, pEList->a[i].pExpr) ){
+      if( sqlite3ExprAnalyzeAggregates(&sNC, pEList->a[i].pExpr) ){
         goto select_end;
       }
     }
     if( pGroupBy ){
       for(i=0; i<pGroupBy->nExpr; i++){
-        if( sqlite3ExprAnalyzeAggregates(pParse, pGroupBy->a[i].pExpr) ){
+        if( sqlite3ExprAnalyzeAggregates(&sNC, pGroupBy->a[i].pExpr) ){
           goto select_end;
         }
       }
     }
-    if( pHaving && sqlite3ExprAnalyzeAggregates(pParse, pHaving) ){
+    if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){
       goto select_end;
     }
     if( pOrderBy ){
       for(i=0; i<pOrderBy->nExpr; i++){
-        if( sqlite3ExprAnalyzeAggregates(pParse, pOrderBy->a[i].pExpr) ){
+        if( sqlite3ExprAnalyzeAggregates(&sNC, pOrderBy->a[i].pExpr) ){
           goto select_end;
         }
       }
@@ -2490,10 +2735,10 @@ int sqlite3Select(
     }
   }
 
-  /* Initialize the memory cell to NULL
+  /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists
   */
-  if( eDest==SRT_Mem ){
-    sqlite3VdbeAddOp(v, OP_String8, 0, 0);
+  if( eDest==SRT_Mem || eDest==SRT_Exists ){
+    sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_String8 : OP_Integer, 0, 0);
     sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
   }
 
@@ -2508,8 +2753,8 @@ int sqlite3Select(
 
   /* Begin the database scan
   */
-  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 
-                            pGroupBy ? 0 : &pOrderBy);
+  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,
+                             pGroupBy ? 0 : &pOrderBy, p->pFetch);
   if( pWInfo==0 ) goto select_end;
 
   /* Use the standard inner loop if we are not dealing with
@@ -2527,8 +2772,9 @@ int sqlite3Select(
   */
   else{
     AggExpr *pAgg;
+    int lbl1 = 0;
+    pParse->fillAgg = 1;
     if( pGroupBy ){
-      int lbl1;
       for(i=0; i<pGroupBy->nExpr; i++){
         sqlite3ExprCode(pParse, pGroupBy->a[i].pExpr);
       }
@@ -2537,11 +2783,14 @@ int sqlite3Select(
       sqlite3VdbeAddOp(v, OP_MakeRecord, pGroupBy->nExpr, 0);
       lbl1 = sqlite3VdbeMakeLabel(v);
       sqlite3VdbeAddOp(v, OP_AggFocus, 0, lbl1);
-      for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
-        if( pAgg->isAgg ) continue;
-        sqlite3ExprCode(pParse, pAgg->pExpr);
-        sqlite3VdbeAddOp(v, OP_AggSet, 0, i);
-      }
+    }
+    for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
+      if( pAgg->isAgg ) continue;
+      sqlite3ExprCode(pParse, pAgg->pExpr);
+      sqlite3VdbeAddOp(v, OP_AggSet, 0, i);
+    }
+    pParse->fillAgg = 0;
+    if( lbl1<0 ){
       sqlite3VdbeResolveLabel(v, lbl1);
     }
     for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
@@ -2581,7 +2830,6 @@ int sqlite3Select(
     int endagg = sqlite3VdbeMakeLabel(v);
     int startagg;
     startagg = sqlite3VdbeAddOp(v, OP_AggNext, 0, endagg);
-    pParse->useAgg = 1;
     if( pHaving ){
       sqlite3ExprIfFalse(pParse, pHaving, startagg, 1);
     }
@@ -2592,7 +2840,6 @@ int sqlite3Select(
     sqlite3VdbeAddOp(v, OP_Goto, 0, startagg);
     sqlite3VdbeResolveLabel(v, endagg);
     sqlite3VdbeAddOp(v, OP_Noop, 0, 0);
-    pParse->useAgg = 0;
   }
 
   /* If there is an ORDER BY clause, then we need to sort the results
@@ -2602,6 +2849,7 @@ int sqlite3Select(
     generateSortTail(pParse, p, v, pEList->nExpr, eDest, iParm);
   }
 
+#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
@@ -2613,6 +2861,7 @@ int sqlite3Select(
     sqlite3SelectDelete(p);
     pParent->pSrc->a[parentTab].pSelect = 0;
   }
+#endif
 
   /* The SELECT was successfully coded.   Set the return code to 0
   ** to indicate no errors.
@@ -2623,6 +2872,6 @@ int sqlite3Select(
   ** successful coding of the SELECT.
   */
 select_end:
-  sqliteAggregateInfoReset(pParse);
+  restoreAggregateInfo(pParse, &sAggInfo);
   return rc;
 }
index bdd13cc93144f4c252f3e5f94a8dd6cf719edb85..2b369a210e1ae0d9090ca2c83d57c7f2d04ec220 100644 (file)
@@ -196,7 +196,9 @@ static char *one_input_line(const char *zPrior, FILE *in){
     zPrompt = mainPrompt;
   }
   zResult = readline(zPrompt);
+#if defined(HAVE_READLINE) && HAVE_READLINE==1
   if( zResult ) add_history(zResult);
+#endif
   return zResult;
 }
 
@@ -360,6 +362,7 @@ static void output_csv(struct callback_data *p, const char *z, int bSep){
   }
 }
 
+#ifdef SIGINT
 /*
 ** This routine runs when the user presses Ctrl-C
 */
@@ -367,6 +370,7 @@ static void interrupt_handler(int NotUsed){
   seenInterrupt = 1;
   if( db ) sqlite3_interrupt(db);
 }
+#endif
 
 /*
 ** This is the callback routine that the SQLite library
@@ -652,7 +656,11 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
   zType = azArg[1];
   zSql = azArg[2];
   
-  fprintf(p->out, "%s;\n", zSql);
+  if( strcasecmp(zTable,"sqlite_sequence")!=0 ){
+    fprintf(p->out, "%s;\n", zSql);
+  }else{
+    fprintf(p->out, "DELETE FROM sqlite_sequence;\n");
+  }
 
   if( strcmp(zType, "table")==0 ){
     sqlite3_stmt *pTableInfo = 0;
@@ -746,7 +754,7 @@ 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"
-  ".mode MODE ?TABLE?     Set output mode where MODE is on of:\n"
+  ".mode MODE ?TABLE?     Set output mode where MODE is one of:\n"
   "                         csv      Comma-separated values\n"
   "                         column   Left-aligned columns.  (See .width)\n"
   "                         html     HTML <table> code\n"
@@ -882,6 +890,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
     data.colWidth[0] = 3;
     data.colWidth[1] = 15;
     data.colWidth[2] = 58;
+    data.cnt = 0;
     sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
     if( zErrMsg ){
       fprintf(stderr,"Error: %s\n", zErrMsg);
@@ -1677,7 +1686,11 @@ int main(int argc, char **argv){
   if( i<argc ){
     data.zDbFilename = argv[i++];
   }else{
+#ifndef SQLITE_OMIT_MEMORYDB
     data.zDbFilename = ":memory:";
+#else
+    data.zDbFilename = 0;
+#endif
   }
   if( i<argc ){
     zFirstCmd = argv[i++];
@@ -1770,7 +1783,9 @@ int main(int argc, char **argv){
       if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){
         sprintf(zHistory,"%s/.sqlite_history", zHome);
       }
+#if defined(HAVE_READLINE) && HAVE_READLINE==1
       if( zHistory ) read_history(zHistory);
+#endif
       process_input(&data, 0);
       if( zHistory ){
         stifle_history(100);
index 2dd97ed8cd4e52ceb53f05d3233ec5e0a8edf70a..daffc25c62769c6c8507b627a76c7c8081d0170e 100644 (file)
@@ -30,9 +30,25 @@ extern "C" {
 */
 #ifdef SQLITE_VERSION
 # undef SQLITE_VERSION
-#else
-# define SQLITE_VERSION         "--VERS--"
 #endif
+#define SQLITE_VERSION         "--VERS--"
+
+/*
+** The format of the version string is "X.Y.Z<trailing string>", where
+** X is the major version number, Y is the minor version number and Z
+** is the release number. The trailing string is often "alpha" or "beta".
+** For example "3.1.1beta".
+**
+** The SQLITE_VERSION_NUMBER is an integer with the value 
+** (X*100000 + Y*1000 + Z). For example, for version "3.1.1beta", 
+** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using 
+** version 3.1.1 or greater at compile time, programs may use the test 
+** (SQLITE_VERSION_NUMBER>=3001001).
+*/
+#ifdef SQLITE_VERSION_NUMBER
+# undef SQLITE_VERSION_NUMBER
+#endif
+#define SQLITE_VERSION_NUMBER --VERSION-NUMBER--
 
 /*
 ** The version string is also compiled into the library so that a program
@@ -44,6 +60,12 @@ extern "C" {
 extern const char sqlite3_version[];
 const char *sqlite3_libversion(void);
 
+/*
+** Return the value of the SQLITE_VERSION_NUMBER macro when the
+** library was compiled.
+*/
+int sqlite3_libversion_number(void);
+
 /*
 ** Each open sqlite database is represented by an instance of the
 ** following opaque structure.
@@ -309,7 +331,7 @@ int sqlite3_busy_timeout(sqlite3*, int ms);
 ** pass the result data pointer to sqlite3_free_table() in order to 
 ** release the memory that was malloc-ed.  Because of the way the 
 ** malloc() happens, the calling function must not try to call 
-** malloc() directly.  Only sqlite3_free_table() is able to release 
+** free() directly.  Only sqlite3_free_table() is able to release 
 ** the memory properly and safely.
 **
 ** The return value of this routine is the same as from sqlite3_exec().
@@ -428,6 +450,8 @@ int sqlite3_set_authorizer(
 #define SQLITE_UPDATE               23   /* Table Name      Column Name     */
 #define SQLITE_ATTACH               24   /* Filename        NULL            */
 #define SQLITE_DETACH               25   /* Database Name   NULL            */
+#define SQLITE_ALTER_TABLE          26   /* Database Name   Table Name      */
+#define SQLITE_REINDEX              27   /* Index Name      NULL            */
 
 
 /*
@@ -448,8 +472,8 @@ void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
 /*
 ** This routine configures a callback function - the progress callback - that
 ** is invoked periodically during long running calls to sqlite3_exec(),
-** sqlite3_step() and sqlite3_get_table(). An example use for this API is to keep
-** a GUI updated during a large query.
+** sqlite3_step() and sqlite3_get_table(). An example use for this API is to 
+** keep a GUI updated during a large query.
 **
 ** The progress callback is invoked once for every N virtual machine opcodes,
 ** where N is the second argument to this function. The progress callback
@@ -606,14 +630,19 @@ typedef struct Mem sqlite3_value;
 
 /*
 ** In the SQL strings input to sqlite3_prepare() and sqlite3_prepare16(),
-** one or more literals can be replace by a wildcard "?" or ":N:" where
-** N is an integer.  These value of these wildcard literals can be set
-** using the routines listed below.
+** one or more literals can be replace by parameters "?" or ":AAA" or
+** "$VVV" where AAA is an identifer and VVV is a variable name according
+** to the syntax rules of the TCL programming language.
+** The value of these parameters (also called "host parameter names") can
+** be set using the routines listed below.
 **
 ** In every case, the first parameter is a pointer to the sqlite3_stmt
 ** structure returned from sqlite3_prepare().  The second parameter is the
-** index of the wildcard.  The first "?" has an index of 1.  ":N:" wildcards
-** use the index N.
+** index of the parameter.  The first parameter as an index of 1.  For
+** named parameters (":AAA" or "$VVV") you can use 
+** sqlite3_bind_parameter_index() to get the correct index value given
+** the parameters name.  If the same named parameter occurs more than
+** once, it is assigned the same index each time.
 **
 ** The fifth parameter to sqlite3_bind_blob(), sqlite3_bind_text(), and
 ** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
@@ -624,8 +653,8 @@ typedef struct Mem sqlite3_value;
 ** own private copy of the data.
 **
 ** The sqlite3_bind_* routine must be called before sqlite3_step() after
-** an sqlite3_prepare() or sqlite3_reset().  Unbound wildcards are interpreted
-** as NULL.
+** an sqlite3_prepare() or sqlite3_reset().  Unbound parameterss are
+** interpreted as NULL.
 */
 int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
 int sqlite3_bind_double(sqlite3_stmt*, int, double);
@@ -637,16 +666,16 @@ int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
 int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
 
 /*
-** Return the number of wildcards in a compiled SQL statement.  This
+** Return the number of parameters in a compiled SQL statement.  This
 ** routine was added to support DBD::SQLite.
 */
 int sqlite3_bind_parameter_count(sqlite3_stmt*);
 
 /*
-** Return the name of the i-th parameter.  Ordinary wildcards "?" are
-** nameless and a NULL is returned.  For wildcards of the form :N or
-** $vvvv the complete text of the wildcard is returned.
-** NULL is returned if the index is out of range.
+** Return the name of the i-th parameter.  Ordinary parameters "?" are
+** nameless and a NULL is returned.  For parameters of the form :AAA or
+** $VVV the complete text of the parameter name is returned, including
+** the initial ":" or "$".  NULL is returned if the index is out of range.
 */
 const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
 
@@ -657,6 +686,13 @@ const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
 */
 int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
 
+/*
+** Set all the parameters in the compiled SQL statement to NULL.
+**
+******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
+*/
+int sqlite3_clear_bindings(sqlite3_stmt*);
+
 /*
 ** Return the number of columns in the result set returned by the compiled
 ** SQL statement. This routine returns 0 if pStmt is an SQL statement
@@ -1148,17 +1184,41 @@ int sqlite3_rekey(
 );
 
 /*
-** If the following global variable is made to point to a constant
+** Sleep for a little while. The second parameter is the number of
+** miliseconds to sleep for. 
+**
+** If the operating system does not support sleep requests with 
+** milisecond time resolution, then the time will be rounded up to 
+** the nearest second. The number of miliseconds of sleep actually 
+** requested from the operating system is returned.
+**
+******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
+*/
+int sqlite3_sleep(int);
+
+/*
+** Return TRUE (non-zero) of the statement supplied as an argument needs
+** to be recompiled.  A statement needs to be recompiled whenever the
+** execution environment changes in a way that would alter the program
+** that sqlite3_prepare() generates.  For example, if new functions or
+** collating sequences are registered or if an authorizer function is
+** added or changed.
+**
+******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
+*/
+int sqlite3_expired(sqlite3_stmt*);
+
+/*
+** If the following global variable is made to point to a
 ** string which is the name of a directory, then all temporary files
 ** created by SQLite will be placed in that directory.  If this variable
 ** is NULL pointer, then SQLite does a search for an appropriate temporary
 ** file directory.
 **
-** This variable should only be changed when there are no open databases.
-** Once sqlite3_open() has been called, this variable should not be changed
-** until all database connections are closed.
+** Once sqlite3_open() has been called, changing this variable will invalidate the
+** current temporary database, if any.
 */
-extern const char *sqlite3_temp_directory;
+extern char *sqlite3_temp_directory;
 
 #ifdef __cplusplus
 }  /* End of the 'extern "C"' block */
index b4fa474ba9715f8e450fe114fb4f2541827e99c8..a9dde13186cf8d87e104d83e3a3771d5dced74bc 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <stddef.h>
 
 /*
 ** The maximum number of in-memory pages to use for the main database
-** table and for temporary tables.
+** table and for temporary tables. Internally, the MAX_PAGES and 
+** TEMP_PAGES macros are used. To override the default values at
+** compilation time, the SQLITE_DEFAULT_CACHE_SIZE and 
+** SQLITE_DEFAULT_TEMP_CACHE_SIZE macros should be set.
 */
-#define MAX_PAGES   2000
-#define TEMP_PAGES   500
+#ifdef SQLITE_DEFAULT_CACHE_SIZE
+# define MAX_PAGES SQLITE_DEFAULT_CACHE_SIZE
+#else
+# define MAX_PAGES   2000
+#endif
+#ifdef SQLITE_DEFAULT_TEMP_CACHE_SIZE
+# define TEMP_PAGES SQLITE_DEFAULT_TEMP_CACHE_SIZE
+#else
+# define TEMP_PAGES   500
+#endif
 
 /*
 ** If the following macro is set to 1, then NULL values are considered
 ** a minimum.
 */
 /* #define SQLITE_OMIT_AUTHORIZATION  1 */
-/* #define SQLITE_OMIT_INMEMORYDB     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 */
+
+/*
+** Provide a default value for TEMP_STORE in case it is not specified
+** on the command-line
+*/
+#ifndef TEMP_STORE
+# define TEMP_STORE 1
+#endif
+
+/*
+** GCC does not define the offsetof() macro so we'll have to do it
+** ourselves.
+*/
+#ifndef offsetof
+#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
 
 /*
 ** Integers of known sizes.  These typedefs might change for architectures
@@ -213,7 +243,7 @@ struct BusyHandler {
 ** each malloc() and free().  This output can be analyzed
 ** by an AWK script to determine if there are any leaks.
 */
-#ifdef SQLITE_DEBUG
+#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__)
@@ -239,10 +269,11 @@ extern int sqlite3_malloc_failed;
 ** The following global variables are used for testing and debugging
 ** only.  They only work if SQLITE_DEBUG is defined.
 */
-#ifdef SQLITE_DEBUG
-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 */
+#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 */
 #endif
 
 /*
@@ -296,6 +327,8 @@ typedef struct AuthContext AuthContext;
 typedef struct KeyClass KeyClass;
 typedef struct CollSeq CollSeq;
 typedef struct KeyInfo KeyInfo;
+typedef struct NameContext NameContext;
+typedef struct Fetch Fetch;
 
 /*
 ** Each database file to be accessed by the system is an instance
@@ -316,7 +349,8 @@ struct Db {
   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 */
-  void *pAux;          /* Auxiliary data.  Usually NULL */
+  Table *pSeqTab;      /* The sqlite_sequence table used by AUTOINCREMENT */
+  void *pAux;               /* Auxiliary data.  Usually NULL */
   void (*xFreeAux)(void*);  /* Routine to free pAux */
 };
 
@@ -408,7 +442,6 @@ struct sqlite3 {
   void *pProgressArg;           /* Argument to the progress callback */
   int nProgressOps;             /* Number of opcodes for progress callback */
 #endif
-
   int errCode;                  /* Most recent error code (SQLITE_*) */
   u8 enc;                       /* Text encoding for this database. */
   u8 autoCommit;                /* The auto-commit flag. */
@@ -417,9 +450,8 @@ struct sqlite3 {
   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-8 encoded) */
+  char *zErrMsg16;              /* Most recent error message (UTF-16 encoded) */
 };
 
 /*
@@ -443,6 +475,9 @@ struct sqlite3 {
                                           /*   result set is empty */
 #define SQLITE_SqlTrace       0x00000200  /* Debug print SQL as it executes */
 #define SQLITE_VdbeListing    0x00000400  /* Debug listings of VDBE programs */
+#define SQLITE_WriteSchema    0x00000800  /* OK to update SQLITE_MASTER */
+#define SQLITE_NoReadlock     0x00001000  /* Readlocks are omitted when 
+                                          ** accessing read-only databases */
 
 /*
 ** Possible values for the sqlite.magic field.
@@ -478,7 +513,7 @@ struct FuncDef {
 */
 struct Column {
   char *zName;     /* Name of this column */
-  char *zDflt;     /* Default value 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 */
   u8 notNull;      /* True if there is a NOT NULL constraint */
@@ -572,6 +607,7 @@ struct 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 */
   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 */
@@ -759,6 +795,12 @@ struct Token {
 ** marker (a question mark character '?' in the original SQL) then the
 ** Expr.iTable holds the index number for that variable.
 **
+** If the expression is a subquery then Expr.iColumn holds an integer
+** register number containing the result of the subquery.  If the
+** subquery gives a constant result, then iTable is -1.  If the subquery
+** gives a different answer at different times during statement processing
+** then iTable is the address of a subroutine that computes the subquery.
+**
 ** The Expr.pSelect field points to a SELECT statement.  The SELECT might
 ** be the right operand of an IN operator.  Or, if a scalar SELECT appears
 ** in an expression the opcode is TK_SELECT and Expr.pSelect is the only
@@ -777,8 +819,9 @@ struct Expr {
   Token span;            /* Complete text of the expression */
   int iTable, iColumn;   /* When op==TK_COLUMN, then this expr node means the
                          ** iColumn-th field of the iTable-th table. */
-  int iAgg;              /* When op==TK_COLUMN and pParse->useAgg==TRUE, pull
+  int iAgg;              /* When op==TK_COLUMN and pParse->fillAgg==FALSE, pull
                          ** result from the iAgg-th element of the aggregator */
+  int iAggCtx;           /* The value to pass as P1 of OP_AggGet. */
   Select *pSelect;       /* When the expression is a sub-select.  Also the
                          ** right side of "<expr> IN (<select>)" */
 };
@@ -787,6 +830,11 @@ struct Expr {
 ** The following are the meanings of bits in the Expr.flags field.
 */
 #define EP_FromJoin     0x0001  /* Originated in ON or USING clause of a join */
+#define EP_Agg          0x0002  /* Contains one or more aggregate functions */
+#define EP_Resolved     0x0004  /* IDs have been resolved to COLUMNs */
+#define EP_Error        0x0008  /* Expression contains one or more errors */
+#define EP_Not          0x0010  /* Operator preceeded by NOT */
+#define EP_VarSelect    0x0020  /* pSelect is correlated, not constant */
 
 /*
 ** These macros can be used to test, set, or clear bits in the 
@@ -841,6 +889,11 @@ struct IdList {
   } *a;
 };
 
+/*
+** The bitmask datatype defined below is used for various optimizations.
+*/
+typedef unsigned int Bitmask;
+
 /*
 ** The following structure describes the FROM clause of a SELECT statement.
 ** Each table or subquery in the FROM clause is a separate element of
@@ -865,6 +918,7 @@ struct SrcList {
     int iCursor;      /* The VDBE cursor number used to access this table */
     Expr *pOn;        /* The ON clause of a join */
     IdList *pUsing;   /* The USING clause of a join */
+    Bitmask colUsed;  /* Bit N (1<<N) set if column N or pTab is used */
   } a[1];             /* One entry for each identifier on the list */
 };
 
@@ -886,9 +940,10 @@ struct SrcList {
 */
 struct WhereLevel {
   int iMem;            /* Memory cell used by this level */
-  Index *pIdx;         /* Index used */
-  int iCur;            /* Cursor number used for this index */
-  int score;           /* How well this indexed scored */
+  Index *pIdx;         /* Index used.  NULL if no index */
+  int iTabCur;         /* The VDBE cursor used to access the table */
+  int iIdxCur;         /* The VDBE cursor used to acesss pIdx */
+  int score;           /* How well this index scored */
   int brk;             /* Jump here to break out of the loop */
   int cont;            /* Jump here to continue with the next loop cycle */
   int op, p1, p2;      /* Opcode used to terminate the loop */
@@ -908,24 +963,50 @@ struct WhereLevel {
 struct WhereInfo {
   Parse *pParse;
   SrcList *pTabList;   /* List of tables in the join */
+  int iTop;            /* The very beginning of the WHERE loop */
   int iContinue;       /* Jump here to continue with next record */
   int iBreak;          /* Jump here to break out of the loop */
   int nLevel;          /* Number of nested loop */
   WhereLevel a[1];     /* Information about each nest loop in the WHERE */
 };
 
+/*
+** A NameContext defines a context in which to resolve table and column
+** names.  The context consists of a list of tables (the pSrcList) field and
+** a list of named expression (pEList).  The named expression list may
+** be NULL.  The pSrc corresponds to the FROM clause of a SELECT or
+** to the table being operated on by INSERT, UPDATE, or DELETE.  The
+** pEList corresponds to the result set of a SELECT and is NULL for
+** other statements.
+**
+** NameContexts can be nested.  When resolving names, the inner-most 
+** context is searched first.  If no match is found, the next outer
+** context is checked.  If there is still no match, the next context
+** is checked.  This process continues until either a match is found
+** or all contexts are check.  When a match is found, the nRef member of
+** the context containing the match is incremented. 
+**
+** Each subquery gets a new NameContext.  The pNext field points to the
+** NameContext in the parent query.  Thus the process of scanning the
+** NameContext list corresponds to searching through successively outer
+** subqueries looking for a match.
+*/
+struct NameContext {
+  Parse *pParse;       /* The parser */
+  SrcList *pSrcList;   /* One or more tables used to resolve names */
+  ExprList *pEList;    /* Optional list of named expressions */
+  int nRef;            /* Number of names resolved by this context */
+  int nErr;            /* Number of errors encountered while resolving names */
+  u8 allowAgg;         /* Aggregate functions allowed here */
+  u8 hasAgg;
+  int nDepth;          /* Depth of subquery recursion. 1 for no recursion */
+  NameContext *pNext;  /* Next outer name context.  NULL for outermost */
+};
+
 /*
 ** An instance of the following structure contains all information
 ** needed to generate code for a single SELECT statement.
 **
-** The zSelect field is used when the Select structure must be persistent.
-** Normally, the expression tree points to tokens in the original input
-** string that encodes the select.  But if the Select structure must live
-** longer than its input string (for example when it is used to describe
-** a VIEW) we have to make a copy of the input string so that the nodes
-** of the expression tree will have something to point to.  zSelect is used
-** to hold that copy.
-**
 ** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
 ** If there is a LIMIT clause, the parser sets nLimit to the value of the
 ** limit and nOffset to the value of the offset (or 0 if there is not
@@ -942,10 +1023,13 @@ struct Select {
   Expr *pHaving;         /* The HAVING clause */
   ExprList *pOrderBy;    /* The ORDER BY clause */
   Select *pPrior;        /* Prior select in a compound select statement */
-  int nLimit, nOffset;   /* LIMIT and OFFSET values.  -1 means not used */
+  Expr *pLimit;          /* LIMIT expression. NULL means not used. */
+  Expr *pOffset;         /* OFFSET expression. NULL means not used. */
   int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
-  char *zSelect;         /* Complete text of the SELECT command */
   IdList **ppOpenTemp;   /* OP_OpenTemp addresses used by multi-selects */
+  Fetch *pFetch;         /* If this stmt is part of a FETCH command */
+  u8 isResolved;         /* True once sqlite3SelectResolve() has run. */
+  u8 isAgg;              /* True if this is an aggregate query */
 };
 
 /*
@@ -961,6 +1045,7 @@ struct Select {
 #define SRT_Discard      9  /* Do not save the results anywhere */
 #define SRT_Sorter      10  /* Store results in the sorter */
 #define SRT_Subroutine  11  /* Call a subroutine to handle results */
+#define SRT_Exists      12  /* Put 0 or 1 in a memory cell */
 
 /*
 ** When a SELECT uses aggregate functions (like "count(*)" or "avg(f1)")
@@ -991,41 +1076,51 @@ struct AggExpr {
 ** An SQL parser context.  A copy of this structure is passed through
 ** the parser and down into all the parser action routine in order to
 ** carry around information that is global to the entire parse.
+**
+** The structure is divided into two parts.  When the parser and code
+** generate call themselves recursively, the first part of the structure
+** is constant but the second part is reset at the beginning and end of
+** each recursion.
 */
 struct Parse {
   sqlite3 *db;         /* The main database structure */
   int rc;              /* Return code from execution */
   char *zErrMsg;       /* An error message */
-  Token sErrToken;     /* The token at which the error occurred */
-  Token sNameToken;    /* Token with unqualified schema object name */
-  Token sLastToken;    /* The last token parsed */
-  const char *zSql;    /* All SQL text */
-  const char *zTail;   /* All SQL text past the last semicolon parsed */
-  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
   Vdbe *pVdbe;         /* An engine for executing database bytecode */
   u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */
-  u8 explain;          /* True if the EXPLAIN flag is found on the query */
   u8 nameClash;        /* A permanent table name clashes with temp table name */
-  u8 useAgg;           /* If true, extract field values from the aggregator
-                       ** while generating expressions.  Normally false */
   u8 checkSchema;      /* Causes schema cookie check after an error */
+  u8 nested;           /* Number of nested calls to the parser/code generator */
   int nErr;            /* Number of errors seen */
   int nTab;            /* Number of previously allocated VDBE cursors */
   int nMem;            /* Number of memory cells used so far */
   int nSet;            /* Number of sets used so far */
-  int nAgg;            /* Number of aggregate expressions */
+  u32 cookieMask;      /* Bitmask of schema verified databases */
+  int cookieValue[MAX_ATTACHED+2];  /* Values of cookies to verify */
+  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
+  u32 writeMask;       /* Start a write transaction on these databases */
+  u8 fillAgg;          /* If true, ignore the Expr.iAgg field. Normally false */
+
+  /* Above is constant between recursions.  Below is reset before and after
+  ** each recursion */
+
   int nVar;            /* Number of '?' variables seen in the SQL so far */
   int nVarExpr;        /* Number of used slots in apVarExpr[] */
   int nVarExprAlloc;   /* Number of allocated slots in apVarExpr[] */
   Expr **apVarExpr;    /* Pointers to :aaa and $aaaa wildcard expressions */
-  AggExpr *aAgg;       /* An array of aggregate expressions */
-  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
+  u8 explain;          /* True if the EXPLAIN flag is found on the query */
+  Token sErrToken;     /* The token at which the error occurred */
+  Token sNameToken;    /* Token with unqualified schema object name */
+  Token sLastToken;    /* The last token parsed */
+  const char *zSql;    /* All SQL text */
+  const char *zTail;   /* All SQL text past the last semicolon parsed */
+  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
   Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
   TriggerStack *trigStack;  /* Trigger actions being coded */
-  u32 cookieMask;      /* Bitmask of schema verified databases */
-  int cookieValue[MAX_ATTACHED+2];  /* Values of cookies to verify */
-  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
-  u32 writeMask;       /* Start a write transaction on these databases */
+  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
+  int nAgg;            /* Number of aggregate expressions */
+  AggExpr *aAgg;       /* An array of aggregate expressions */
+  int nMaxDepth;       /* Maximum depth of subquery recursion */
 };
 
 /*
@@ -1064,7 +1159,7 @@ struct Trigger {
   u8 iDb;                 /* Database containing this trigger               */
   u8 iTabDb;              /* Database containing Trigger.table              */
   u8 op;                  /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */
-  u8 tr_tm;               /* One of TK_BEFORE, TK_AFTER */
+  u8 tr_tm;               /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
   Expr *pWhen;            /* The WHEN clause of the expresion (may be NULL) */
   IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
                              the <column-list> is stored here */
@@ -1075,6 +1170,16 @@ struct Trigger {
   Trigger *pNext;         /* Next trigger associated with the table */
 };
 
+/*
+** A trigger is either a BEFORE or an AFTER trigger.  The following constants
+** determine which. 
+**
+** If there are multiple triggers, you might of some BEFORE and some AFTER.
+** In that cases, the constants below can be ORed together.
+*/
+#define TRIGGER_BEFORE  1
+#define TRIGGER_AFTER   2
+
 /*
  * An instance of struct TriggerStep is used to store a single SQL statement
  * that is a part of a trigger-program. 
@@ -1188,7 +1293,6 @@ typedef struct {
   char **pzErrMsg;    /* Error message stored here */
 } InitData;
 
-
 /*
  * This global flag is set for performance testing of triggers. When it is set
  * SQLite will perform the overhead of building new and old trigger references 
@@ -1206,7 +1310,7 @@ int sqlite3IsNumber(const char*, int*, u8);
 int sqlite3Compare(const char *, const char *);
 int sqlite3SortCompare(const char *, const char *);
 void sqlite3RealToSortable(double r, char *);
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
   void *sqlite3Malloc_(int,int,char*,int);
   void sqlite3Free_(void*,char*,int);
   void *sqlite3Realloc_(void*,int,char*,int);
@@ -1233,7 +1337,8 @@ void sqlite3Dequote(char*);
 int sqlite3KeywordCode(const char*, int);
 int sqlite3RunParser(Parse*, const char*, char **);
 void sqlite3FinishCoding(Parse*);
-Expr *sqlite3Expr(int, Expr*, Expr*, Token*);
+Expr *sqlite3Expr(int, Expr*, Expr*, const Token*);
+Expr *sqlite3RegisterExpr(Parse*,Token*);
 Expr *sqlite3ExprAnd(Expr*, Expr*);
 void sqlite3ExprSpan(Expr*,Token*,Token*);
 Expr *sqlite3ExprFunction(ExprList*, Token*);
@@ -1253,13 +1358,19 @@ void sqlite3OpenMasterTable(Vdbe *v, int);
 void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int);
 void sqlite3AddColumn(Parse*,Token*);
 void sqlite3AddNotNull(Parse*, int);
-void sqlite3AddPrimaryKey(Parse*, ExprList*, int);
+void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int);
 void sqlite3AddColumnType(Parse*,Token*,Token*);
-void sqlite3AddDefaultValue(Parse*,Token*,int);
+void sqlite3AddDefaultValue(Parse*,Expr*);
 void sqlite3AddCollateType(Parse*, const char*, int);
 void sqlite3EndTable(Parse*,Token*,Select*);
-void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int);
-int sqlite3ViewGetColumnNames(Parse*,Table*);
+
+#ifndef SQLITE_OMIT_VIEW
+  void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int);
+  int sqlite3ViewGetColumnNames(Parse*,Table*);
+#else
+# define sqlite3ViewGetColumnNames(A,B) 0
+#endif
+
 void sqlite3DropTable(Parse*, SrcList*, int);
 void sqlite3DeleteTable(sqlite3*, Table*);
 void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
@@ -1277,35 +1388,36 @@ void sqlite3AddKeyType(Vdbe*, ExprList*);
 void sqlite3AddIdxKeyType(Vdbe*, Index*);
 int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff);
 Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*,
-                        int,int,int);
+                        int,Expr*,Expr*);
 void sqlite3SelectDelete(Select*);
 void sqlite3SelectUnbind(Select*);
 Table *sqlite3SrcListLookup(Parse*, SrcList*);
 int sqlite3IsReadOnly(Parse*, Table*, int);
 void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*);
+void sqlite3OpenTable(Vdbe*, int iCur, Table*, int);
 void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
 void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
-WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, int, ExprList**);
+WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, Fetch*);
 void sqlite3WhereEnd(WhereInfo*);
 void sqlite3ExprCode(Parse*, Expr*);
+void sqlite3ExprCodeAndCache(Parse*, Expr*);
 int sqlite3ExprCodeExprList(Parse*, ExprList*);
 void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
 void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
+void sqlite3NextedParse(Parse*, const char*, ...);
 Table *sqlite3FindTable(sqlite3*,const char*, const char*);
 Table *sqlite3LocateTable(Parse*,const char*, const char*);
 Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
 void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
 void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
-void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
 void sqlite3Vacuum(Parse*, Token*);
 int sqlite3RunVacuum(char**, sqlite3*);
 char *sqlite3NameFromToken(Token*);
 int sqlite3ExprCheck(Parse*, Expr*, int, int*);
 int sqlite3ExprCompare(Expr*, Expr*);
 int sqliteFuncId(Token*);
-int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*);
-int sqlite3ExprResolveAndCheck(Parse*,SrcList*,ExprList*,Expr*,int,int*);
-int sqlite3ExprAnalyzeAggregates(Parse*, Expr*);
+int sqlite3ExprResolveNames(NameContext *, Expr *);
+int sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
 Vdbe *sqlite3GetVdbe(Parse*);
 void sqlite3Randomness(int, void*);
 void sqlite3RollbackAll(sqlite3*);
@@ -1336,21 +1448,32 @@ int sqlite3SafetyOn(sqlite3*);
 int sqlite3SafetyOff(sqlite3*);
 int sqlite3SafetyCheck(sqlite3*);
 void sqlite3ChangeCookie(sqlite3*, Vdbe*, int);
-void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
-                         int,Expr*,int);
-void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
-void sqlite3DropTrigger(Parse*, SrcList*);
-void sqlite3DropTriggerPtr(Parse*, Trigger*, int);
-int sqlite3TriggersExist(Parse* , Trigger* , int , int , int, ExprList*);
-int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, 
-                         int, int);
-void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
-void sqlite3DeleteTriggerStep(TriggerStep*);
-TriggerStep *sqlite3TriggerSelectStep(Select*);
-TriggerStep *sqlite3TriggerInsertStep(Token*, IdList*, ExprList*, Select*, int);
-TriggerStep *sqlite3TriggerUpdateStep(Token*, ExprList*, Expr*, int);
-TriggerStep *sqlite3TriggerDeleteStep(Token*, Expr*);
-void sqlite3DeleteTrigger(Trigger*);
+
+#ifndef SQLITE_OMIT_TRIGGER
+  void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
+                           int,Expr*,int);
+  void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
+  void sqlite3DropTrigger(Parse*, SrcList*);
+  void sqlite3DropTriggerPtr(Parse*, Trigger*, int);
+  int sqlite3TriggersExist(Parse*, Table*, int, ExprList*);
+  int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, 
+                           int, int);
+  void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
+  void sqlite3DeleteTriggerStep(TriggerStep*);
+  TriggerStep *sqlite3TriggerSelectStep(Select*);
+  TriggerStep *sqlite3TriggerInsertStep(Token*, IdList*, ExprList*,Select*,int);
+  TriggerStep *sqlite3TriggerUpdateStep(Token*, ExprList*, Expr*, int);
+  TriggerStep *sqlite3TriggerDeleteStep(Token*, Expr*);
+  void sqlite3DeleteTrigger(Trigger*);
+  void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
+#else
+# define sqlite3TriggersExist(A,B,C,D,E,F) 0
+# define sqlite3DeleteTrigger(A)
+# define sqlite3DropTriggerPtr(A,B,C)
+# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
+# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) 0
+#endif
+
 int sqlite3JoinType(Parse*, Token*, Token*, Token*);
 void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
 void sqlite3DeferForeignKey(Parse*, int);
@@ -1386,7 +1509,6 @@ int sqlite3PutVarint(unsigned char *, u64);
 int sqlite3GetVarint(const unsigned char *, u64 *);
 int sqlite3GetVarint32(const unsigned char *, u32 *);
 int sqlite3VarintLen(u64 v);
-char sqlite3AffinityType(const char *, int);
 void sqlite3IndexAffinityStr(Vdbe *, Index *);
 void sqlite3TableAffinityStr(Vdbe *, Table *);
 char sqlite3CompareAffinity(Expr *pExpr, char aff2);
@@ -1415,5 +1537,14 @@ void sqlite3ValueFree(sqlite3_value*);
 sqlite3_value *sqlite3ValueNew();
 sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
 extern const unsigned char sqlite3UpperToLower[];
+void sqlite3RootPageMoved(Db*, int, int);
+void sqlite3Reindex(Parse*, Token*, Token*);
+void sqlite3AlterFunctions(sqlite3*);
+void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
+int sqlite3GetToken(const unsigned char *, int *);
+void sqlite3NestedParse(Parse*, const char*, ...);
+void sqlite3ExpirePreparedStatements(sqlite3*);
+void sqlite3CodeSubselect(Parse *, Expr *);
+int sqlite3SelectResolve(Parse *, Select *, NameContext *);
 
 #endif
index 5e37945b7039e92c4c770b608fc0ffab12d030cd..7f1aba3c7e9dfd7d00f5e3082b341e61527b3b41 100644 (file)
@@ -22,6 +22,9 @@
 #include <string.h>
 #include <assert.h>
 
+#define NUM_PREPARED_STMTS 10
+#define MAX_PREPARED_STMTS 100
+
 /*
 ** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we
 ** have to do a translation when going between the two.  Set the 
@@ -54,6 +57,19 @@ struct SqlCollate {
   SqlCollate *pNext;       /* Next function on the list of them all */
 };
 
+/*
+** Prepared statements are cached for faster execution.  Each prepared
+** statement is described by an instance of the following structure.
+*/
+typedef struct SqlPreparedStmt SqlPreparedStmt;
+struct SqlPreparedStmt {
+  SqlPreparedStmt *pNext;  /* Next in linked list */
+  SqlPreparedStmt *pPrev;  /* Previous on the list */
+  sqlite3_stmt *pStmt;     /* The prepared statement */
+  int nSql;                /* chars in zSql[] */
+  char zSql[1];            /* Text of the SQL statement */
+};
+
 /*
 ** There is one instance of this structure for each SQLite database
 ** that has been opened by the SQLite TCL interface.
@@ -71,14 +87,35 @@ struct SqliteDb {
   SqlCollate *pCollate; /* List of SQL collation functions */
   int rc;               /* Return code of most recent sqlite3_exec() */
   Tcl_Obj *pCollateNeeded;  /* Collation needed script */
+  SqlPreparedStmt *stmtList; /* List of prepared statements*/
+  SqlPreparedStmt *stmtLast; /* Last statement in the list */
+  int maxStmt;               /* The next maximum number of stmtList */
+  int nStmt;                 /* Number of statements in stmtList */
 };
 
+/*
+** Finalize and free a list of prepared statements
+*/
+static void flushStmtCache( SqliteDb *pDb ){
+  SqlPreparedStmt *pPreStmt;
+
+  while(  pDb->stmtList ){
+    sqlite3_finalize( pDb->stmtList->pStmt );
+    pPreStmt = pDb->stmtList;
+    pDb->stmtList = pDb->stmtList->pNext;
+    Tcl_Free( (char*)pPreStmt );
+  }
+  pDb->nStmt = 0;
+  pDb->stmtLast = 0;
+}
+
 /*
 ** TCL calls this procedure when an sqlite3 database command is
 ** deleted.
 */
 static void DbDeleteCmd(void *db){
   SqliteDb *pDb = (SqliteDb*)db;
+  flushStmtCache(pDb);
   sqlite3_close(pDb->db);
   while( pDb->pFunc ){
     SqlFunc *pFunc = pDb->pFunc;
@@ -215,7 +252,7 @@ static int tclSqlCollate(
 ** This routine is called to evaluate an SQL function implemented
 ** using TCL script.
 */
-static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
   SqlFunc *p = sqlite3_user_data(context);
   Tcl_DString cmd;
   int i;
@@ -287,6 +324,8 @@ static int auth_callback(
     case SQLITE_UPDATE            : zCode="SQLITE_UPDATE"; break;
     case SQLITE_ATTACH            : zCode="SQLITE_ATTACH"; break;
     case SQLITE_DETACH            : zCode="SQLITE_DETACH"; break;
+    case SQLITE_ALTER_TABLE       : zCode="SQLITE_ALTER_TABLE"; break;
+    case SQLITE_REINDEX           : zCode="SQLITE_REINDEX"; break;
     default                       : zCode="????"; break;
   }
   Tcl_DStringInit(&str);
@@ -332,6 +371,54 @@ static Tcl_Obj *dbTextToObj(char const *zText){
   return pVal;
 }
 
+/*
+** This routine reads a line of text from FILE in, stores
+** the text in memory obtained from malloc() and returns a pointer
+** to the text.  NULL is returned at end of file, or if malloc()
+** fails.
+**
+** The interface is like "readline" but no command-line editing
+** is done.
+**
+** copied from shell.c from '.import' command
+*/
+static char *local_getline(char *zPrompt, FILE *in){
+  char *zLine;
+  int nLine;
+  int n;
+  int eol;
+
+  nLine = 100;
+  zLine = malloc( nLine );
+  if( zLine==0 ) return 0;
+  n = 0;
+  eol = 0;
+  while( !eol ){
+    if( n+100>nLine ){
+      nLine = nLine*2 + 100;
+      zLine = realloc(zLine, nLine);
+      if( zLine==0 ) return 0;
+    }
+    if( fgets(&zLine[n], nLine - n, in)==0 ){
+      if( n==0 ){
+        free(zLine);
+        return 0;
+      }
+      zLine[n] = 0;
+      eol = 1;
+      break;
+    }
+    while( zLine[n] ){ n++; }
+    if( n>0 && zLine[n-1]=='\n' ){
+      n--;
+      zLine[n] = 0;
+      eol = 1;
+    }
+  }
+  zLine = realloc( zLine, n+1 );
+  return zLine;
+}
+
 /*
 ** The "sqlite" command below creates a new Tcl command for each
 ** connection it opens to an SQLite database.  This routine is invoked
@@ -350,22 +437,25 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
   int choice;
   int rc = TCL_OK;
   static const char *DB_strs[] = {
-    "authorizer",         "busy",              "changes",
-    "close",              "collate",           "collation_needed",
-    "commit_hook",        "complete",          "errorcode",
-    "eval",               "function",          "last_insert_rowid",
-    "onecolumn",          "progress",          "rekey",
-    "timeout",            "total_changes",     "trace",
+    "authorizer",         "busy",              "cache",
+    "changes",            "close",             "collate",
+    "collation_needed",   "commit_hook",       "complete",
+    "copy",               "errorcode",         "eval",
+    "function",           "last_insert_rowid", "onecolumn",
+    "progress",           "rekey",             "timeout",
+    "total_changes",      "trace",             "version",
     0                    
   };
   enum DB_enum {
-    DB_AUTHORIZER,        DB_BUSY,             DB_CHANGES,
-    DB_CLOSE,             DB_COLLATE,          DB_COLLATION_NEEDED,
-    DB_COMMIT_HOOK,       DB_COMPLETE,         DB_ERRORCODE,
-    DB_EVAL,              DB_FUNCTION,         DB_LAST_INSERT_ROWID,
-    DB_ONECOLUMN,         DB_PROGRESS,         DB_REKEY,
-    DB_TIMEOUT,           DB_TOTAL_CHANGES,    DB_TRACE,
+    DB_AUTHORIZER,        DB_BUSY,             DB_CACHE,
+    DB_CHANGES,           DB_CLOSE,            DB_COLLATE,
+    DB_COLLATION_NEEDED,  DB_COMMIT_HOOK,      DB_COMPLETE,
+    DB_COPY,              DB_ERRORCODE,        DB_EVAL,
+    DB_FUNCTION,          DB_LAST_INSERT_ROWID,DB_ONECOLUMN,
+    DB_PROGRESS,          DB_REKEY,            DB_TIMEOUT,
+    DB_TOTAL_CHANGES,     DB_TRACE,            DB_VERSION
   };
+  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
 
   if( objc<2 ){
     Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
@@ -467,6 +557,55 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     break;
   }
 
+  /*     $db cache flush
+  **     $db cache size n
+  **
+  ** Flush the prepared statement cache, or set the maximum number of
+  ** cached statements.
+  */
+  case DB_CACHE: {
+    char *subCmd;
+    int n;
+
+    if( objc<=2 ){
+      Tcl_WrongNumArgs(interp, 1, objv, "cache option ?arg?");
+      return TCL_ERROR;
+    }
+    subCmd = Tcl_GetStringFromObj( objv[2], 0 );
+    if( *subCmd=='f' && strcmp(subCmd,"flush")==0 ){
+      if( objc!=3 ){
+        Tcl_WrongNumArgs(interp, 2, objv, "flush");
+        return TCL_ERROR;
+      }else{
+        flushStmtCache( pDb );
+      }
+    }else if( *subCmd=='s' && strcmp(subCmd,"size")==0 ){
+      if( objc!=4 ){
+        Tcl_WrongNumArgs(interp, 2, objv, "size n");
+        return TCL_ERROR;
+      }else{
+        if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){
+          Tcl_AppendResult( interp, "cannot convert \"", 
+               Tcl_GetStringFromObj(objv[3],0), "\" to integer", 0);
+          return TCL_ERROR;
+        }else{
+          if( n<0 ){
+            flushStmtCache( pDb );
+            n = 0;
+          }else if( n>MAX_PREPARED_STMTS ){
+            n = MAX_PREPARED_STMTS;
+          }
+          pDb->maxStmt = n;
+        }
+      }
+    }else{
+      Tcl_AppendResult( interp, "bad option \"", 
+          Tcl_GetStringFromObj(objv[0],0), "\": must be flush or size", 0);
+      return TCL_ERROR;
+    }
+    break;
+  }
+
   /*     $db changes
   **
   ** Return the number of rows that were modified, inserted, or deleted by
@@ -557,6 +696,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     strcpy(pCollate->zScript, zScript);
     if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8, 
         pCollate, tclSqlCollate) ){
+      Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
       return TCL_ERROR;
     }
     break;
@@ -636,6 +776,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     int nParm;             /* Number of entries used in apParm[] */
     Tcl_Obj *aParm[10];    /* Static space for apParm[] in the common case */
     Tcl_Obj *pRet;         /* Value to be returned */
+    SqlPreparedStmt *pPreStmt;  /* Pointer to a prepared statement */
+    int rc2;
 
     if( choice==DB_ONECOLUMN ){
       if( objc!=3 ){
@@ -665,29 +807,78 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     Tcl_IncrRefCount(objv[2]);
     zSql = Tcl_GetStringFromObj(objv[2], 0);
     while( rc==TCL_OK && zSql[0] ){
-      int i;      /* Loop counter */
-      int nVar;   /* Number of wildcards in the SQL */
-      int nCol;   /* Number of columns in the result set */
+      int i;                     /* Loop counter */
+      int nVar;                  /* Number of bind parameters in the pStmt */
+      int nCol;                  /* Number of columns in the result set */
       Tcl_Obj **apColName = 0;   /* Array of column names */
+      int len;                   /* String length of zSql */
   
-      /* Compile a single SQL statement */
-      if( SQLITE_OK!=sqlite3_prepare(pDb->db, zSql, -1, &pStmt, &zLeft) ){
-        Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
-        rc = TCL_ERROR;
-        break;
+      /* Try to find a SQL statement that has already been compiled and
+      ** which matches the next sequence of SQL.
+      */
+      pStmt = 0;
+      pPreStmt = pDb->stmtList;
+      len = strlen(zSql);
+      if( pPreStmt && sqlite3_expired(pPreStmt->pStmt) ){
+        flushStmtCache(pDb);
+        pPreStmt = 0;
+      }
+      for(; pPreStmt; pPreStmt=pPreStmt->pNext){
+        int n = pPreStmt->nSql;
+        if( len>=n 
+            && memcmp(pPreStmt->zSql, zSql, n)==0
+            && (zSql[n]==0 || zSql[n-1]==';')
+        ){
+          pStmt = pPreStmt->pStmt;
+          zLeft = &zSql[pPreStmt->nSql];
+
+          /* When a prepared statement is found, unlink it from the
+          ** cache list.  It will later be added back to the beginning
+          ** of the cache list in order to implement LRU replacement.
+          */
+          if( pPreStmt->pPrev ){
+            pPreStmt->pPrev->pNext = pPreStmt->pNext;
+          }else{
+            pDb->stmtList = pPreStmt->pNext;
+          }
+          if( pPreStmt->pNext ){
+            pPreStmt->pNext->pPrev = pPreStmt->pPrev;
+          }else{
+            pDb->stmtLast = pPreStmt->pPrev;
+          }
+          pDb->nStmt--;
+          break;
+        }
       }
+  
+      /* If no prepared statement was found.  Compile the SQL text
+      */
       if( pStmt==0 ){
-        if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
+        if( SQLITE_OK!=sqlite3_prepare(pDb->db, zSql, -1, &pStmt, &zLeft) ){
           Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
           rc = TCL_ERROR;
           break;
-        }else{
-          zSql = zLeft;
-          continue;
         }
+        if( pStmt==0 ){
+          if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
+            /* A compile-time error in the statement
+            */
+            Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
+            rc = TCL_ERROR;
+            break;
+          }else{
+            /* The statement was a no-op.  Continue to the next statement
+            ** in the SQL string.
+            */
+            zSql = zLeft;
+            continue;
+          }
+        }
+        assert( pPreStmt==0 );
       }
 
-      /* Bind values to wildcards that begin with $ or : */  
+      /* Bind values to parameters that begin with $ or :
+      */  
       nVar = sqlite3_bind_parameter_count(pStmt);
       nParm = 0;
       if( nVar>sizeof(aParm)/sizeof(aParm[0]) ){
@@ -697,7 +888,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
       }
       for(i=1; i<=nVar; i++){
         const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
-        if( zVar[0]=='$' || zVar[0]==':' ){
+        if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':') ){
           Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
           if( pVar ){
             int n;
@@ -723,6 +914,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
               Tcl_IncrRefCount(pVar);
               apParm[nParm++] = pVar;
             }
+          }else{
+            sqlite3_bind_null( pStmt, i );
           }
         }
       }
@@ -827,19 +1020,75 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
         Tcl_Free((char*)apParm);
       }
 
-      /* Finalize the statement.  If the result code is SQLITE_SCHEMA, then
-      ** try again to execute the same statement
+      /* Reset the statement.  If the result code is SQLITE_SCHEMA, then
+      ** flush the statement cache and try the statement again.
       */
-      if( SQLITE_SCHEMA==sqlite3_finalize(pStmt) ){
+      rc2 = sqlite3_reset(pStmt);
+      if( SQLITE_SCHEMA==rc2 ){
+        /* After a schema change, flush the cache and try to run the
+        ** statement again
+        */
+        flushStmtCache( pDb );
+        sqlite3_finalize(pStmt);
+        if( pPreStmt ) Tcl_Free((char*)pPreStmt);
         continue;
-      }
-  
-      if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
+      }else if( SQLITE_OK!=rc2 ){
+        /* If a run-time error occurs, report the error and stop reading
+        ** the SQL
+        */
         Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
+        sqlite3_finalize(pStmt);
         rc = TCL_ERROR;
+        if( pPreStmt ) Tcl_Free((char*)pPreStmt);
         break;
+      }else if( pDb->maxStmt<=0 ){
+        /* If the cache is turned off, deallocated the statement */
+        if( pPreStmt ) Tcl_Free((char*)pPreStmt);
+        sqlite3_finalize(pStmt);
+      }else{
+        /* Everything worked and the cache is operational.
+        ** Create a new SqlPreparedStmt structure if we need one.
+        ** (If we already have one we can just reuse it.)
+        */
+        if( pPreStmt==0 ){
+          len = zLeft - zSql;
+          pPreStmt = (SqlPreparedStmt*)Tcl_Alloc( sizeof(*pPreStmt) + len );
+          if( pPreStmt==0 ) return TCL_ERROR;
+          pPreStmt->pStmt = pStmt;
+          pPreStmt->nSql = len;
+          memcpy(pPreStmt->zSql, zSql, len);
+          pPreStmt->zSql[len] = 0;
+        }
+
+        /* Add the prepared statement to the beginning of the cache list
+        */
+        pPreStmt->pNext = pDb->stmtList;
+        pPreStmt->pPrev = 0;
+        if( pDb->stmtList ){
+         pDb->stmtList->pPrev = pPreStmt;
+        }
+        pDb->stmtList = pPreStmt;
+        if( pDb->stmtLast==0 ){
+          assert( pDb->nStmt==0 );
+          pDb->stmtLast = pPreStmt;
+        }else{
+          assert( pDb->nStmt>0 );
+        }
+        pDb->nStmt++;
+   
+        /* If we have too many statement in cache, remove the surplus from the
+        ** end of the cache list.
+        */
+        while( pDb->nStmt>pDb->maxStmt ){
+          sqlite3_finalize(pDb->stmtLast->pStmt);
+          pDb->stmtLast = pDb->stmtLast->pPrev;
+          Tcl_Free((char*)pDb->stmtLast->pNext);
+          pDb->stmtLast->pNext = 0;
+          pDb->nStmt--;
+        }
       }
 
+      /* Proceed to the next statement */
       zSql = zLeft;
     }
     Tcl_DecrRefCount(objv[2]);
@@ -879,7 +1128,13 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     strcpy(pFunc->zScript, zScript);
     rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8,
         pFunc, tclSqlFunc, 0, 0);
-    if( rc!=SQLITE_OK ) rc = TCL_ERROR;
+    if( rc!=SQLITE_OK ){
+      rc = TCL_ERROR;
+      Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
+    }else{
+      /* Must flush any cached statements */
+      flushStmtCache( pDb );
+    }
     break;
   }
 
@@ -1040,6 +1295,202 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     break;
   }
 
+  /*    $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
+  **
+  ** Copy data into table from filename, optionally using SEPARATOR
+  ** as column separators.  If a column contains a null string, or the
+  ** value of NULLINDICATOR, a NULL is inserted for the column.
+  ** conflict-algorithm is one of the sqlite conflict algorithms:
+  **    rollback, abort, fail, ignore, replace
+  ** On success, return the number of lines processed, not necessarily same
+  ** as 'db changes' due to conflict-algorithm selected.
+  **
+  ** This code is basically an implementation/enhancement of
+  ** the sqlite3 shell.c ".import" command.
+  **
+  ** This command usage is equivalent to the sqlite2.x COPY statement,
+  ** which imports file data into a table using the PostgreSQL COPY file format:
+  **   $db copy $conflit_algo $table_name $filename \t \\N
+  */
+  case DB_COPY: {
+    char *zTable;               /* Insert data into this table */
+    char *zFile;                /* The file from which to extract data */
+    char *zConflict;            /* The conflict algorithm to use */
+    sqlite3_stmt *pStmt;        /* A statement */
+    int rc;                     /* Result code */
+    int nCol;                   /* Number of columns in the table */
+    int nByte;                  /* Number of bytes in an SQL string */
+    int i, j;                   /* Loop counters */
+    int nSep;                   /* Number of bytes in zSep[] */
+    int nNull;                  /* Number of bytes in zNull[] */
+    char *zSql;                 /* An SQL statement */
+    char *zLine;                /* A single line of input from the file */
+    char **azCol;               /* zLine[] broken up into columns */
+    char *zCommit;              /* How to commit changes */
+    FILE *in;                   /* The input file */
+    int lineno = 0;             /* Line number of input file */
+    char zLineNum[80];          /* Line number print buffer */
+    Tcl_Obj *pResult;           /* interp result */
+
+    char *zSep;
+    char *zNull;
+    if( objc<5 || objc>7 ){
+      Tcl_WrongNumArgs(interp, 2, objv, 
+         "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?");
+      return TCL_ERROR;
+    }
+    if( objc>=6 ){
+      zSep = Tcl_GetStringFromObj(objv[5], 0);
+    }else{
+      zSep = "\t";
+    }
+    if( objc>=7 ){
+      zNull = Tcl_GetStringFromObj(objv[6], 0);
+    }else{
+      zNull = "";
+    }
+    zConflict = Tcl_GetStringFromObj(objv[2], 0);
+    zTable = Tcl_GetStringFromObj(objv[3], 0);
+    zFile = Tcl_GetStringFromObj(objv[4], 0);
+    nSep = strlen(zSep);
+    nNull = strlen(zNull);
+    if( nSep==0 ){
+      Tcl_AppendResult(interp, "Error: non-null separator required for copy", 0);
+      return TCL_ERROR;
+    }
+    if(sqlite3StrICmp(zConflict, "rollback") != 0 &&
+       sqlite3StrICmp(zConflict, "abort"   ) != 0 &&
+       sqlite3StrICmp(zConflict, "fail"    ) != 0 &&
+       sqlite3StrICmp(zConflict, "ignore"  ) != 0 &&
+       sqlite3StrICmp(zConflict, "replace" ) != 0 ) {
+      Tcl_AppendResult(interp, "Error: \"", zConflict, 
+            "\", conflict-algorithm must be one of: rollback, "
+            "abort, fail, ignore, or replace", 0);
+      return TCL_ERROR;
+    }
+    zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
+    if( zSql==0 ){
+      Tcl_AppendResult(interp, "Error: no such table: ", zTable, 0);
+      return TCL_ERROR;
+    }
+    nByte = strlen(zSql);
+    rc = sqlite3_prepare(pDb->db, zSql, 0, &pStmt, 0);
+    sqlite3_free(zSql);
+    if( rc ){
+      Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
+      nCol = 0;
+    }else{
+      nCol = sqlite3_column_count(pStmt);
+    }
+    sqlite3_finalize(pStmt);
+    if( nCol==0 ) {
+      return TCL_ERROR;
+    }
+    zSql = malloc( nByte + 50 + nCol*2 );
+    if( zSql==0 ) {
+      Tcl_AppendResult(interp, "Error: can't malloc()", 0);
+      return TCL_ERROR;
+    }
+    sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",
+         zConflict, zTable);
+    j = strlen(zSql);
+    for(i=1; i<nCol; i++){
+      zSql[j++] = ',';
+      zSql[j++] = '?';
+    }
+    zSql[j++] = ')';
+    zSql[j] = 0;
+    rc = sqlite3_prepare(pDb->db, zSql, 0, &pStmt, 0);
+    free(zSql);
+    if( rc ){
+      Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
+      sqlite3_finalize(pStmt);
+      return TCL_ERROR;
+    }
+    in = fopen(zFile, "rb");
+    if( in==0 ){
+      Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, NULL);
+      sqlite3_finalize(pStmt);
+      return TCL_ERROR;
+    }
+    azCol = malloc( sizeof(azCol[0])*(nCol+1) );
+    if( azCol==0 ) {
+      Tcl_AppendResult(interp, "Error: can't malloc()", 0);
+      return TCL_ERROR;
+    }
+    sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0);
+    zCommit = "COMMIT";
+    while( (zLine = local_getline(0, in))!=0 ){
+      char *z;
+      i = 0;
+      lineno++;
+      azCol[0] = zLine;
+      for(i=0, z=zLine; *z; z++){
+        if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){
+          *z = 0;
+          i++;
+          if( i<nCol ){
+            azCol[i] = &z[nSep];
+            z += nSep-1;
+          }
+        }
+      }
+      if( i+1!=nCol ){
+        char *zErr;
+        zErr = malloc(200 + strlen(zFile));
+        sprintf(zErr,"Error: %s line %d: expected %d columns of data but found %d",
+           zFile, lineno, nCol, i+1);
+        Tcl_AppendResult(interp, zErr, 0);
+        free(zErr);
+        zCommit = "ROLLBACK";
+        break;
+      }
+      for(i=0; i<nCol; i++){
+        /* check for null data, if so, bind as null */
+        if ((nNull>0 && strcmp(azCol[i], zNull)==0) || strlen(azCol[i])==0) {
+          sqlite3_bind_null(pStmt, i+1);
+        }else{
+          sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
+        }
+      }
+      sqlite3_step(pStmt);
+      rc = sqlite3_reset(pStmt);
+      free(zLine);
+      if( rc!=SQLITE_OK ){
+        Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), 0);
+        zCommit = "ROLLBACK";
+        break;
+      }
+    }
+    free(azCol);
+    fclose(in);
+    sqlite3_finalize(pStmt);
+    sqlite3_exec(pDb->db, zCommit, 0, 0, 0);
+
+    if( zCommit[0] == 'C' ){
+      /* success, set result as number of lines processed */
+      pResult = Tcl_GetObjResult(interp);
+      Tcl_SetIntObj(pResult, lineno);
+      rc = TCL_OK;
+    }else{
+      /* failure, append lineno where failed */
+      sprintf(zLineNum,"%d",lineno);
+      Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,0);
+      rc = TCL_ERROR;
+    }
+    break;
+  }
+
+  /*    $db version
+  **
+  ** Return the version string for this database.
+  */
+  case DB_VERSION: {
+    Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC);
+    break;
+  }
+
+
   } /* End of the SWITCH statement */
   return rc;
 }
@@ -1146,6 +1597,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     free(zErrMsg);
     return TCL_ERROR;
   }
+  p->maxStmt = NUM_PREPARED_STMTS;
   zArg = Tcl_GetStringFromObj(objv[1], 0);
   Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);
 
@@ -1163,12 +1615,12 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
 #ifdef SQLITE_TEST
   {
     extern void Md5_Register(sqlite3*);
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
     int mallocfail = sqlite3_iMallocFail;
     sqlite3_iMallocFail = 0;
 #endif
     Md5_Register(p->db);
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
     sqlite3_iMallocFail = mallocfail;
 #endif
    }
@@ -1199,20 +1651,20 @@ int Sqlite3_Init(Tcl_Interp *interp){
   Tcl_InitStubs(interp, "8.4", 0);
   Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
   Tcl_PkgProvide(interp, "sqlite3", "3.0");
+  Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
+  Tcl_PkgProvide(interp, "sqlite", "3.0");
   return TCL_OK;
 }
-int Tclsqlite3_Init(Tcl_Interp *interp){
-  Tcl_InitStubs(interp, "8.4", 0);
-  Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
-  Tcl_PkgProvide(interp, "sqlite3", "3.0");
-  return TCL_OK;
-}
-int Sqlite3_SafeInit(Tcl_Interp *interp){
-  return TCL_OK;
-}
-int Tclsqlite3_SafeInit(Tcl_Interp *interp){
-  return TCL_OK;
-}
+int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
+int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+
+#ifndef SQLITE_3_SUFFIX_ONLY
+int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
+int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
+int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+#endif
 
 #ifdef TCLSH
 /*****************************************************************************
@@ -1285,7 +1737,7 @@ int TCLSH_MAIN(int argc, char **argv){
     int i;
     Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
     Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
-    for(i=2; i<argc; i++){
+    for(i=3-TCLSH; i<argc; i++){
       Tcl_SetVar(interp, "argv", argv[i],
           TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
     }
index ba4e440eba288ce0eb64b18cbc36120bf77db958..7a96c378b53d01648af2582f568e51cfcae1e758 100644 (file)
@@ -478,21 +478,22 @@ static int test_create_function(
 ){
   int rc;
   sqlite3 *db;
-  sqlite3_value *pVal;
   extern void Md5_Register(sqlite3*);
 
   if( argc!=2 ){
     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
-       " FILENAME\"", 0);
+       " DB\"", 0);
     return TCL_ERROR;
   }
   if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
   rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0, 
         ifnullFunc, 0, 0);
 
+#ifndef SQLITE_OMIT_UTF16
   /* Use the sqlite3_create_function16() API here. Mainly for fun, but also 
   ** because it is not tested anywhere else. */
   if( rc==SQLITE_OK ){
+    sqlite3_value *pVal;
     pVal = sqlite3ValueNew();
     sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
     rc = sqlite3_create_function16(db, 
@@ -500,7 +501,10 @@ static int test_create_function(
               1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
     sqlite3ValueFree(pVal);
   }
+#endif
+
   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
+  Tcl_SetResult(interp, (char *)errorName(rc), 0);
   return TCL_OK;
 }
 
@@ -743,12 +747,17 @@ static int sqlite3_mprintf_stronly(
 }
 
 /*
-** Usage: sqlite_malloc_fail N
+** Usage: sqlite_malloc_fail N  ?REPEAT-INTERVAL?
+**
+** Rig sqliteMalloc() to fail on the N-th call and every REPEAT-INTERVAL call
+** after that.  If REPEAT-INTERVAL is 0 or is omitted, then only a single
+** malloc will fail.  If REPEAT-INTERVAL is 1 then all mallocs after the
+** first failure will continue to fail on every call.  If REPEAT-INTERVAL is
+** 2 then every other malloc will fail.  And so forth.
 **
-** Rig sqliteMalloc() to fail on the N-th call.  Turn off this mechanism
-** and reset the sqlite3_malloc_failed variable is N==0.
+** Turn off this mechanism and reset the sqlite3_malloc_failed variable is N==0.
 */
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
 static int sqlite_malloc_fail(
   void *NotUsed,
   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
@@ -756,12 +765,19 @@ static int sqlite_malloc_fail(
   char **argv            /* Text of each argument */
 ){
   int n;
-  if( argc!=2 ){
+  int rep;
+  if( argc!=2 && argc!=3 ){
     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
+  if( argc==3 ){
+    if( Tcl_GetInt(interp, argv[2], &rep) ) return TCL_ERROR;
+  }else{
+    rep = 0;
+  }
   sqlite3_iMallocFail = n;
+  sqlite3_iMallocReset = rep;
   sqlite3_malloc_failed = 0;
   return TCL_OK;
 }
@@ -772,7 +788,7 @@ static int sqlite_malloc_fail(
 **
 ** Return the number of prior calls to sqliteMalloc() and sqliteFree().
 */
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
 static int sqlite_malloc_stat(
   void *NotUsed,
   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
@@ -892,10 +908,12 @@ static int test_finalize(
 
   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
 
-  db = StmtToDb(pStmt);
+  if( pStmt ){
+    db = StmtToDb(pStmt);
+  }
   rc = sqlite3_finalize(pStmt);
   Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
-  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
+  if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
   return TCL_OK;
 }
 
@@ -922,13 +940,37 @@ static int test_reset(
   if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
 
   rc = sqlite3_reset(pStmt);
-  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
+  if( pStmt && 
+      sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
+  Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
   if( rc ){
     return TCL_ERROR;
   }
   return TCL_OK;
 }
 
+/*
+** Usage:  sqlite3_expired STMT 
+**
+** Return TRUE if a recompilation of the statement is recommended.
+*/
+static int test_expired(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  sqlite3_stmt *pStmt;
+  if( objc!=2 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"",
+        Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
+    return TCL_ERROR;
+  }
+  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
+  Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
+  return TCL_OK;
+}
+
 /*
 ** Usage:  sqlite3_changes DB
 **
@@ -1005,7 +1047,7 @@ static int test_bind(
   return TCL_OK;
 }
 
-
+#ifndef SQLITE_OMIT_UTF16
 /*
 ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
 **
@@ -1148,6 +1190,7 @@ bad_args:
   Tcl_WrongNumArgs(interp, 1, objv, "DB");
   return TCL_ERROR;
 }
+#endif /* SQLITE_OMIT_UTF16 */
 
 /*
 ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
@@ -1174,6 +1217,7 @@ bad_args:
 ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
 ** prefers UTF-16BE.
 */
+#ifndef SQLITE_OMIT_UTF16
 static void test_function_utf8(
   sqlite3_context *pCtx, 
   int nArg,
@@ -1243,12 +1287,14 @@ static void test_function_utf16be(
       -1, SQLITE_TRANSIENT);
   sqlite3ValueFree(pVal);
 }
+#endif /* SQLITE_OMIT_UTF16 */
 static int test_function(
   void * clientData,
   Tcl_Interp *interp,
   int objc,
   Tcl_Obj *CONST objv[]
 ){
+#ifndef SQLITE_OMIT_UTF16
   sqlite3 *db;
   int val;
 
@@ -1275,6 +1321,7 @@ static int test_function(
 bad_args:
   Tcl_AppendResult(interp, "wrong # args: should be \"",
       Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
+#endif /* SQLITE_OMIT_UTF16 */
   return TCL_ERROR;
 }
 
@@ -1553,6 +1600,7 @@ static int test_bind_text16(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
+#ifndef SQLITE_OMIT_UTF16
   sqlite3_stmt *pStmt;
   int idx;
   int bytes;
@@ -1576,6 +1624,7 @@ static int test_bind_text16(
     return TCL_ERROR;
   }
 
+#endif /* SQLITE_OMIT_UTF16 */
   return TCL_OK;
 }
 
@@ -1695,6 +1744,29 @@ static int test_bind_parameter_index(
   return TCL_OK;
 }
 
+/*
+** Usage:   sqlite3_clear_bindings STMT
+**
+*/
+#if 0
+static int test_clear_bindings(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  sqlite3_stmt *pStmt;
+
+  if( objc!=2 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "STMT");
+    return TCL_ERROR;
+  }
+  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
+  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
+  return TCL_OK;
+}
+#endif
+
 /*
 ** Usage: sqlite3_errcode DB
 **
@@ -1760,6 +1832,7 @@ static int test_errmsg16(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
+#ifndef SQLITE_OMIT_UTF16
   sqlite3 *db;
   const void *zErr;
   int bytes;
@@ -1774,6 +1847,7 @@ static int test_errmsg16(
   zErr = sqlite3_errmsg16(db);
   bytes = sqlite3utf16ByteLen(zErr, -1);
   Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
+#endif /* SQLITE_OMIT_UTF16 */
   return TCL_OK;
 }
 
@@ -1844,6 +1918,7 @@ static int test_prepare16(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
+#ifndef SQLITE_OMIT_UTF16
   sqlite3 *db;
   const void *zSql;
   const void *zTail = 0;
@@ -1883,6 +1958,7 @@ static int test_prepare16(
     if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
   }
   Tcl_AppendResult(interp, zBuf, 0);
+#endif /* SQLITE_OMIT_UTF16 */
   return TCL_OK;
 }
 
@@ -1923,6 +1999,7 @@ static int test_open16(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
+#ifndef SQLITE_OMIT_UTF16
   const void *zFilename;
   sqlite3 *db;
   int rc;
@@ -1939,6 +2016,7 @@ static int test_open16(
   
   if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
   Tcl_AppendResult(interp, zBuf, 0);
+#endif /* SQLITE_OMIT_UTF16 */
   return TCL_OK;
 }
 
@@ -1954,6 +2032,7 @@ static int test_complete16(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
+#ifndef SQLITE_OMIT_UTF16
   char *zBuf;
 
   if( objc!=2 ){
@@ -1963,6 +2042,7 @@ static int test_complete16(
 
   zBuf = Tcl_GetByteArrayFromObj(objv[1], 0);
   Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
+#endif /* SQLITE_OMIT_UTF16 */
   return TCL_OK;
 }
 
@@ -2227,6 +2307,7 @@ static int test_stmt_utf16(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
+#ifndef SQLITE_OMIT_UTF16
   sqlite3_stmt *pStmt;
   int col;
   Tcl_Obj *pRet;
@@ -2247,6 +2328,7 @@ static int test_stmt_utf16(
     pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
     Tcl_SetObjResult(interp, pRet);
   }
+#endif /* SQLITE_OMIT_UTF16 */
 
   return TCL_OK;
 }
@@ -2442,6 +2524,133 @@ static int test_sqlite3OsTempFileName(
   return TCL_OK;
 }
 
+/*
+** Usage:  sqlite_set_magic  DB  MAGIC-NUMBER
+**
+** Set the db->magic value.  This is used to test error recovery logic.
+*/
+static int sqlite_set_magic(
+  void * clientData,
+  Tcl_Interp *interp,
+  int argc,
+  char **argv
+){
+  sqlite3 *db;
+  if( argc!=3 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+         " DB MAGIC", 0);
+    return TCL_ERROR;
+  }
+  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
+  if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
+    db->magic = SQLITE_MAGIC_OPEN;
+  }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
+    db->magic = SQLITE_MAGIC_CLOSED;
+  }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
+    db->magic = SQLITE_MAGIC_BUSY;
+  }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
+    db->magic = SQLITE_MAGIC_ERROR;
+  }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){
+    return TCL_ERROR;
+  }
+  return TCL_OK;
+}
+
+/*
+** Usage:  sqlite3_interrupt  DB 
+**
+** Trigger an interrupt on DB
+*/
+static int test_interrupt(
+  void * clientData,
+  Tcl_Interp *interp,
+  int argc,
+  char **argv
+){
+  sqlite3 *db;
+  if( argc!=2 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
+    return TCL_ERROR;
+  }
+  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
+  sqlite3_interrupt(db);
+  return TCL_OK;
+}
+
+/*
+** Usage:  sqlite3_sleep ms 
+**
+** Sleep for the specified number of ms.
+*/
+#if 0
+static int test_sleep(
+  void * clientData,
+  Tcl_Interp *interp,
+  int argc,
+  char **argv
+){
+  sqlite3 *db;
+  if( argc!=2 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ms", 0);
+    return TCL_ERROR;
+  }
+  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(atoi(argv[1]))));
+  return TCL_OK;
+}
+#endif
+
+/*
+** Usage: sqlite_delete_function DB function-name
+**
+** Delete the user function 'function-name' from database handle DB. It
+** is assumed that the user function was created as UTF8, any number of
+** arguments (the way the TCL interface does it).
+*/
+static int delete_function(
+  void * clientData,
+  Tcl_Interp *interp,
+  int argc,
+  char **argv
+){
+  int rc;
+  sqlite3 *db;
+  if( argc!=3 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
+        " DB function-name", 0);
+    return TCL_ERROR;
+  }
+  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
+  rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
+  Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
+  return TCL_OK;
+}
+
+/*
+** Usage: sqlite_delete_collation DB collation-name
+**
+** Delete the collation sequence 'collation-name' from database handle 
+** DB. It is assumed that the collation sequence was created as UTF8 (the 
+** way the TCL interface does it).
+*/
+static int delete_collation(
+  void * clientData,
+  Tcl_Interp *interp,
+  int argc,
+  char **argv
+){
+  int rc;
+  sqlite3 *db;
+  if( argc!=3 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
+        " DB function-name", 0);
+    return TCL_ERROR;
+  }
+  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
+  rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
+  Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
+  return TCL_OK;
+}
+
 /*
 ** Usage:  tcl_variable_type VARIABLENAME
 **
@@ -2467,6 +2676,181 @@ static int tcl_variable_type(
   return TCL_OK;
 }
 
+/*
+** This routine sets entries in the global ::sqlite_options() array variable
+** according to the compile-time configuration of the database.  Test
+** procedures use this to determine when tests should be omitted.
+*/
+static void set_options(Tcl_Interp *interp){
+#ifdef SQLITE_32BIT_ROWID
+  Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_ALTERTABLE
+  Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_AUTHORIZATION
+  Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_AUTOINCREMENT
+  Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_AUTOVACUUM
+  Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
+#endif /* SQLITE_OMIT_AUTOVACUUM */
+#if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0
+  Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_BLOB_LITERAL
+  Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_COMPOUND_SELECT
+  Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
+  Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_DATETIME_FUNCS
+  Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_EXPLAIN
+  Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_FLOATING_POINT
+  Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_FOREIGN_KEY
+  Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_INTEGRITY_CHECK
+  Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_MEMORYDB
+  Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_PAGER_PRAGMAS
+  Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_PRAGMA
+  Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
+  Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
+  Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_REINDEX
+  Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
+  Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+  Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_SUBQUERY
+  Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_TCL_VARIABLE
+  Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#if defined(THREADSAFE) && THREADSAFE
+  Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_TRIGGER
+  Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_UTF16
+  Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_VACUUM
+  Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_VIEW
+  Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
+#endif
+}
+
 /*
 ** Register commands with the TCL interpreter.
 */
@@ -2474,6 +2858,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
   extern int sqlite3_search_count;
   extern int sqlite3_interrupt_count;
   extern int sqlite3_open_file_count;
+  extern int sqlite3_sort_count;
   extern int sqlite3_current_time;
   static struct {
      char *zName;
@@ -2494,7 +2879,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite3_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },
      { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    },
      { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          },
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
      { "sqlite_malloc_fail",            (Tcl_CmdProc*)sqlite_malloc_fail    },
      { "sqlite_malloc_stat",            (Tcl_CmdProc*)sqlite_malloc_stat    },
 #endif
@@ -2502,6 +2887,13 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },
      { "sqlite3_key",                   (Tcl_CmdProc*)test_key              },
      { "sqlite3_rekey",                 (Tcl_CmdProc*)test_rekey            },
+     { "sqlite_set_magic",              (Tcl_CmdProc*)sqlite_set_magic      },
+     { "sqlite3_interrupt",             (Tcl_CmdProc*)test_interrupt        },
+#if 0
+     { "sqlite3_sleep",                 (Tcl_CmdProc*)test_sleep            },
+#endif
+     { "sqlite_delete_function",       (Tcl_CmdProc*)delete_function        },
+     { "sqlite_delete_collation",      (Tcl_CmdProc*)delete_collation       }
   };
   static struct {
      char *zName;
@@ -2518,6 +2910,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0},
      { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0},
      { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0},
+#if 0
+     { "sqlite3_clear_bindings",        test_clear_bindings, 0},
+#endif
      { "sqlite3_errcode",               test_errcode       ,0 },
      { "sqlite3_errmsg",                test_errmsg        ,0 },
      { "sqlite3_errmsg16",              test_errmsg16      ,0 },
@@ -2529,6 +2924,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite3_prepare16",             test_prepare16     ,0 },
      { "sqlite3_finalize",              test_finalize      ,0 },
      { "sqlite3_reset",                 test_reset         ,0 },
+     { "sqlite3_expired",               test_expired       ,0 },
      { "sqlite3_changes",               test_changes       ,0 },
      { "sqlite3_step",                  test_step          ,0 },
 
@@ -2539,15 +2935,17 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite3_column_blob",           test_column_blob   ,0 },
      { "sqlite3_column_double",         test_column_double ,0 },
      { "sqlite3_column_int64",          test_column_int64  ,0 },
-     { "sqlite3_column_int",        test_stmt_int,   sqlite3_column_int       },
-     { "sqlite3_column_bytes",      test_stmt_int,   sqlite3_column_bytes     },
-     { "sqlite3_column_bytes16",    test_stmt_int,   sqlite3_column_bytes16   },
      { "sqlite3_column_text",       test_stmt_utf8,  sqlite3_column_text      },
      { "sqlite3_column_decltype",   test_stmt_utf8,  sqlite3_column_decltype  },
      { "sqlite3_column_name",       test_stmt_utf8,  sqlite3_column_name      },
+     { "sqlite3_column_int",        test_stmt_int,   sqlite3_column_int       },
+     { "sqlite3_column_bytes",      test_stmt_int,   sqlite3_column_bytes     },
+#ifndef SQLITE_OMIT_UTF16
+     { "sqlite3_column_bytes16",    test_stmt_int,   sqlite3_column_bytes16   },
      { "sqlite3_column_text16",     test_stmt_utf16, sqlite3_column_text16    },
      { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
      { "sqlite3_column_name16",     test_stmt_utf16, sqlite3_column_name16    },
+#endif
 
      /* Functions from os.h */
      { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
@@ -2557,16 +2955,19 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
    
      /* Custom test interfaces */
      { "sqlite3OsUnlock",         test_sqlite3OsUnlock, 0    },
+#ifndef SQLITE_OMIT_UTF16
      { "add_test_collate",        test_collate, 0            },
      { "add_test_collate_needed", test_collate_needed, 0     },
      { "add_test_function",       test_function, 0           },
+#endif
      { "sqlite3_crashparams",     sqlite3_crashparams, 0     },
      { "sqlite3_test_errstr",     test_errstr, 0             },
      { "tcl_variable_type",       tcl_variable_type, 0       },
-
   };
+  static int bitmask_size = sizeof(Bitmask)*8;
   int i;
   extern int sqlite3_os_trace;
 
   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
     Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
@@ -2577,6 +2978,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
   }
   Tcl_LinkVar(interp, "sqlite_search_count", 
       (char*)&sqlite3_search_count, TCL_LINK_INT);
+  Tcl_LinkVar(interp, "sqlite_sort_count", 
+      (char*)&sqlite3_sort_count, TCL_LINK_INT);
   Tcl_LinkVar(interp, "sqlite_interrupt_count", 
       (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
   Tcl_LinkVar(interp, "sqlite_open_file_count", 
@@ -2589,5 +2992,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
       (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
   Tcl_LinkVar(interp, "sqlite_temp_directory",
       (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
+  Tcl_LinkVar(interp, "bitmask_size",
+      (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
+  set_options(interp);
   return TCL_OK;
 }
index a3706c1a78e7001f50b84a4c7e07a37be618a9ef..2f8cdf4846cda33c110789035a105e49852cf3b6 100644 (file)
@@ -81,7 +81,7 @@ static int pager_open(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
-  rc = sqlite3pager_open(&pPager, argv[1], 0, 1);
+  rc = sqlite3pager_open(&pPager, argv[1], 0, 0);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -376,6 +376,34 @@ static int page_lookup(
   return TCL_OK;
 }
 
+/*
+** Usage:   pager_truncate ID PGNO
+*/
+static int pager_truncate(
+  void *NotUsed,
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int argc,              /* Number of arguments */
+  const char **argv      /* Text of each argument */
+){
+  Pager *pPager;
+  int rc;
+  int pgno;
+  if( argc!=3 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+       " ID PGNO\"", 0);
+    return TCL_ERROR;
+  }
+  pPager = sqlite3TextToPtr(argv[1]);
+  if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
+  rc = sqlite3pager_truncate(pPager, pgno);
+  if( rc!=SQLITE_OK ){
+    Tcl_AppendResult(interp, errorName(rc), 0);
+    return TCL_ERROR;
+  }
+  return TCL_OK;
+}
+
+
 /*
 ** Usage:   page_unref PAGE
 **
@@ -553,6 +581,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
     { "page_read",               (Tcl_CmdProc*)page_read           },
     { "page_write",              (Tcl_CmdProc*)page_write          },
     { "page_number",             (Tcl_CmdProc*)page_number         },
+    { "pager_truncate",          (Tcl_CmdProc*)pager_truncate      },
     { "fake_big_file",           (Tcl_CmdProc*)fake_big_file       },
   };
   int i;
index 8824029f89c3afb51b5d303ca53567d662fff2fa..a3edd8740c4c38ef782ccc033e865b2589f8e504 100644 (file)
@@ -44,6 +44,7 @@ static char *errorName(int rc){
     case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
     case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
     case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
+    case SQLITE_LOCKED:     zName = "SQLITE_LOCKED";      break;
     default:                zName = "SQLITE_Unknown";     break;
   }
   return zName;
@@ -315,6 +316,7 @@ static int btree_drop_table(
   Btree *pBt;
   int iTable;
   int rc;
+  int notUsed1;
   if( argc!=3 ){
     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        " ID TABLENUM\"", 0);
@@ -322,7 +324,7 @@ static int btree_drop_table(
   }
   pBt = sqlite3TextToPtr(argv[1]);
   if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
-  rc = sqlite3BtreeDropTable(pBt, iTable);
+  rc = sqlite3BtreeDropTable(pBt, iTable, &notUsed1);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -512,10 +514,10 @@ static int btree_pager_stats(
   }
   pBt = sqlite3TextToPtr(argv[1]);
   a = sqlite3pager_stats(sqlite3BtreePager(pBt));
-  for(i=0; i<9; i++){
+  for(i=0; i<11; i++){
     static char *zName[] = {
       "ref", "page", "max", "size", "state", "err",
-      "hit", "miss", "ovfl",
+      "hit", "miss", "ovfl", "read", "write"
     };
     char zBuf[100];
     Tcl_AppendElement(interp, zName[i]);
@@ -544,7 +546,9 @@ static int btree_pager_ref_dump(
     return TCL_ERROR;
   }
   pBt = sqlite3TextToPtr(argv[1]);
+#ifdef SQLITE_DEBUG
   sqlite3pager_refdump(sqlite3BtreePager(pBt));
+#endif
   return TCL_OK;
 }
 
@@ -562,10 +566,10 @@ static int btree_integrity_check(
   const char **argv      /* Text of each argument */
 ){
   Btree *pBt;
-  char *zResult;
   int nRoot;
   int *aRoot;
   int i;
+  char *zResult;
 
   if( argc<3 ){
     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
@@ -578,7 +582,11 @@ static int btree_integrity_check(
   for(i=0; i<argc-2; i++){
     if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
   }
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
   zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot);
+#else
+  zResult = 0;
+#endif
   if( zResult ){
     Tcl_AppendResult(interp, zResult, 0);
     sqliteFree(zResult); 
@@ -1014,7 +1022,7 @@ static int btree_key(
 }
 
 /*
-** Usage:   btree_data ID
+** Usage:   btree_data ID ?N?
 **
 ** Return the data for the entry at which the cursor is pointing.
 */
@@ -1029,13 +1037,17 @@ static int btree_data(
   u32 n;
   char *zBuf;
 
-  if( argc!=2 ){
+  if( argc!=2 && argc!=3 ){
     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        " ID\"", 0);
     return TCL_ERROR;
   }
   pCur = sqlite3TextToPtr(argv[1]);
-  sqlite3BtreeDataSize(pCur, &n);
+  if( argc==2 ){
+    sqlite3BtreeDataSize(pCur, &n);
+  }else{
+    n = atoi(argv[2]);
+  }
   zBuf = malloc( n+1 );
   rc = sqlite3BtreeData(pCur, 0, n, zBuf);
   if( rc ){
@@ -1314,6 +1326,72 @@ static int btree_varint_test(
   return TCL_OK;
 }
 
+/*
+** usage:   btree_from_db  DB-HANDLE
+**
+** This command returns the btree handle for the main database associated
+** with the database-handle passed as the argument. Example usage:
+**
+** sqlite3 db test.db
+** set bt [btree_from_db db]
+*/
+static int btree_from_db(
+  void *NotUsed,
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int argc,              /* Number of arguments */
+  const char **argv      /* Text of each argument */
+){
+  char zBuf[100];
+  Tcl_CmdInfo info;
+  sqlite3 *db;
+  Btree *pBt;
+
+  if( argc!=2 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+       " DB-HANDLE\"", 0);
+    return TCL_ERROR;
+  }
+
+  if( 1!=Tcl_GetCommandInfo(interp, argv[1], &info) ){
+    Tcl_AppendResult(interp, "No such db-handle: \"", argv[1], "\"", 0);
+    return TCL_ERROR;
+  }
+  db = *((sqlite3 **)info.objClientData);
+  assert( db );
+
+  pBt = db->aDb[0].pBt;
+  sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", pBt);
+  Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
+  return TCL_OK;
+}
+
+
+/*
+** usage:   btree_set_cache_size ID NCACHE
+**
+** Set the size of the cache used by btree $ID.
+*/
+static int btree_set_cache_size(
+  void *NotUsed,
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int argc,              /* Number of arguments */
+  const char **argv      /* Text of each argument */
+){
+  int nCache;
+  Btree *pBt;
+
+  if( argc!=3 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+       " BT NCACHE\"", 0);
+    return TCL_ERROR;
+  }
+  pBt = sqlite3TextToPtr(argv[1]);
+  if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
+  sqlite3BtreeSetCacheSize(pBt, nCache);
+  return TCL_OK;
+}
+
+
 /*
 ** Register commands with the TCL interpreter.
 */
@@ -1360,6 +1438,8 @@ int Sqlitetest3_Init(Tcl_Interp *interp){
      { "btree_begin_statement",    (Tcl_CmdProc*)btree_begin_statement    },
      { "btree_commit_statement",   (Tcl_CmdProc*)btree_commit_statement   },
      { "btree_rollback_statement", (Tcl_CmdProc*)btree_rollback_statement },
+     { "btree_from_db",            (Tcl_CmdProc*)btree_from_db            },
+     { "btree_set_cache_size",     (Tcl_CmdProc*)btree_set_cache_size     },
   };
   int i;
 
index 4de72696422b5bf948dcb2e38764b187fb101942..28f546f608f170b683255fd41ae5e6a49f02252f 100644 (file)
@@ -190,7 +190,9 @@ static int test_translate_selftest(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
+#ifndef SQLITE_OMIT_UTF16
   sqlite3utfSelfTest();
+#endif
   return SQLITE_OK;
 }
 
@@ -214,4 +216,3 @@ int Sqlitetest5_Init(Tcl_Interp *interp){
   }
   return SQLITE_OK;
 }
-
index 061e5b9a455598b7eef864c0fdb02fdfb2bb0bd8..fb1f6674dfde1e09b688e6856af1ff49d954910a 100644 (file)
 #include <stdlib.h>
 
 /*
-** This function looks up an identifier to determine if it is a
-** keyword.  If it is a keyword, the token code of that keyword is 
+** The sqlite3KeywordCode function looks up an identifier to determine if
+** it is a keyword.  If it is a keyword, the token code of that keyword is 
 ** returned.  If the input is not a keyword, TK_ID is returned.
 **
 ** The implementation of this routine was generated by a program,
-** mkkeywordhash.c, located in the tool subdirectory of the distribution.
-** The output of the mkkeywordhash.c program was manually cut and pasted
-** into this file.  When the set of keywords for SQLite changes, you
-** must modify the mkkeywordhash.c program (to add or remove keywords from
-** the data tables) then rerun that program to regenerate this function.
+** mkkeywordhash.h, located in the tool subdirectory of the distribution.
+** The output of the mkkeywordhash.c program is written into a file
+** named keywordhash.h and then included into this source file by
+** the #include below.
 */
-int sqlite3KeywordCode(const char *z, int n){
-  static const char zText[519] =
-    "ABORTAFTERALLANDASCATTACHBEFOREBEGINBETWEENBYCASCADECASECHECK"
-    "COLLATECOMMITCONFLICTCONSTRAINTCREATECROSSDATABASEDEFAULTDEFERRABLE"
-    "DEFERREDDELETEDESCDETACHDISTINCTDROPEACHELSEENDEXCEPTEXCLUSIVE"
-    "EXPLAINFAILFOREIGNFROMFULLGLOBGROUPHAVINGIGNOREIMMEDIATEINDEX"
-    "INITIALLYINNERINSERTINSTEADINTERSECTINTOISNULLJOINKEYLEFTLIKE"
-    "LIMITMATCHNATURALNOTNULLNULLOFFSETONORDEROUTERPRAGMAPRIMARYRAISE"
-    "REFERENCESREPLACERESTRICTRIGHTROLLBACKROWSELECTSETSTATEMENTTABLE"
-    "TEMPORARYTHENTRANSACTIONTRIGGERUNIONUNIQUEUPDATEUSINGVACUUMVALUES"
-    "VIEWWHENWHERE";
-  static const unsigned char aHash[154] = {
-       0,  75,  82,   0,   0,  97,  80,   0,  83,   0,   0,   0,   0,
-       0,   0,   6,   0,  95,   4,   0,   0,   0,   0,   0,   0,   0,
-       0,  96,  86,   8,   0,  26,  13,   7,  19,  15,   0,   0,  32,
-      25,   0,  21,  31,  41,   0,   0,   0,  34,  27,   0,   0,  30,
-       0,   0,   0,   9,   0,  10,   0,   0,   0,   0,  51,   0,  44,
-      43,   0,  45,  40,   0,  29,  39,  35,   0,   0,  20,   0,  59,
-       0,  16,   0,  17,   0,  18,   0,  55,  42,  72,   0,  33,   0,
-       0,  61,  66,  56,   0,   0,   0,   0,   0,   0,   0,  54,   0,
-       0,   0,   0,   0,  74,  50,  76,  64,  52,   0,   0,   0,   0,
-      68,  84,   0,  47,   0,  58,  60,  92,   0,   0,  48,   0,  93,
-       0,  63,  71,  98,   0,   0,   0,   0,   0,  67,   0,   0,   0,
-       0,  87,   0,   0,   0,   0,   0,  90,  88,   0,  94,
-  };
-  static const unsigned char aNext[98] = {
-       0,   0,   0,   0,   2,   0,   0,   0,   0,   0,   0,   0,   0,
-       0,  12,   0,   0,   0,   0,   0,   0,  11,   0,   0,   0,   0,
-       0,   0,   0,  14,   3,  24,   0,   0,   0,   1,  22,   0,   0,
-      36,  23,  28,   0,   0,   0,   0,   0,   0,   0,   0,   5,   0,
-       0,  49,  37,   0,   0,   0,  38,   0,  53,   0,  57,  62,   0,
-       0,   0,   0,   0,   0,  70,  46,   0,  65,   0,   0,   0,   0,
-      69,  73,   0,  77,   0,   0,   0,   0,   0,   0,  81,  85,   0,
-      91,  79,  78,   0,   0,  89,   0,
-  };
-  static const unsigned char aLen[98] = {
-       5,   5,   3,   3,   2,   3,   6,   6,   5,   7,   2,   7,   4,
-       5,   7,   6,   8,  10,   6,   5,   8,   7,  10,   8,   6,   4,
-       6,   8,   4,   4,   4,   3,   6,   9,   7,   4,   3,   7,   4,
-       4,   4,   5,   6,   6,   9,   2,   5,   9,   5,   6,   7,   9,
-       4,   2,   6,   4,   3,   4,   4,   5,   5,   7,   3,   7,   4,
-       2,   6,   2,   2,   5,   5,   6,   7,   5,  10,   7,   8,   5,
-       8,   3,   6,   3,   9,   5,   4,   9,   4,  11,   7,   5,   6,
-       6,   5,   6,   6,   4,   4,   5,
-  };
-  static const unsigned short int aOffset[98] = {
-       0,   5,  10,  13,  16,  16,  19,  25,  31,  36,  43,  45,  52,
-      56,  61,  68,  74,  82,  92,  98, 103, 111, 118, 128, 136, 142,
-     146, 152, 160, 164, 168, 172, 175, 181, 190, 197, 201, 201, 208,
-     212, 216, 220, 225, 231, 237, 246, 246, 251, 260, 265, 271, 278,
-     287, 291, 291, 297, 301, 304, 308, 312, 317, 322, 329, 329, 336,
-     340, 340, 346, 348, 348, 353, 358, 364, 371, 376, 386, 393, 401,
-     406, 414, 417, 423, 426, 435, 440, 440, 449, 453, 464, 471, 476,
-     482, 488, 493, 499, 505, 509, 513,
-  };
-  static const unsigned char aCode[98] = {
-    TK_ABORT,      TK_AFTER,      TK_ALL,        TK_AND,        TK_AS,         
-    TK_ASC,        TK_ATTACH,     TK_BEFORE,     TK_BEGIN,      TK_BETWEEN,    
-    TK_BY,         TK_CASCADE,    TK_CASE,       TK_CHECK,      TK_COLLATE,    
-    TK_COMMIT,     TK_CONFLICT,   TK_CONSTRAINT, TK_CREATE,     TK_JOIN_KW,    
-    TK_DATABASE,   TK_DEFAULT,    TK_DEFERRABLE, TK_DEFERRED,   TK_DELETE,     
-    TK_DESC,       TK_DETACH,     TK_DISTINCT,   TK_DROP,       TK_EACH,       
-    TK_ELSE,       TK_END,        TK_EXCEPT,     TK_EXCLUSIVE,  TK_EXPLAIN,    
-    TK_FAIL,       TK_FOR,        TK_FOREIGN,    TK_FROM,       TK_JOIN_KW,    
-    TK_GLOB,       TK_GROUP,      TK_HAVING,     TK_IGNORE,     TK_IMMEDIATE,  
-    TK_IN,         TK_INDEX,      TK_INITIALLY,  TK_JOIN_KW,    TK_INSERT,     
-    TK_INSTEAD,    TK_INTERSECT,  TK_INTO,       TK_IS,         TK_ISNULL,     
-    TK_JOIN,       TK_KEY,        TK_JOIN_KW,    TK_LIKE,       TK_LIMIT,      
-    TK_MATCH,      TK_JOIN_KW,    TK_NOT,        TK_NOTNULL,    TK_NULL,       
-    TK_OF,         TK_OFFSET,     TK_ON,         TK_OR,         TK_ORDER,      
-    TK_JOIN_KW,    TK_PRAGMA,     TK_PRIMARY,    TK_RAISE,      TK_REFERENCES, 
-    TK_REPLACE,    TK_RESTRICT,   TK_JOIN_KW,    TK_ROLLBACK,   TK_ROW,        
-    TK_SELECT,     TK_SET,        TK_STATEMENT,  TK_TABLE,      TK_TEMP,       
-    TK_TEMP,       TK_THEN,       TK_TRANSACTION,TK_TRIGGER,    TK_UNION,      
-    TK_UNIQUE,     TK_UPDATE,     TK_USING,      TK_VACUUM,     TK_VALUES,     
-    TK_VIEW,       TK_WHEN,       TK_WHERE,      
-  };
-  int h, i;
-  if( n<2 ) return TK_ID;
-  h = (sqlite3UpperToLower[((unsigned char*)z)[0]]*5 + 
-      sqlite3UpperToLower[((unsigned char*)z)[n-1]]*3 +
-      n) % 154;
-  for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){
-    if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){
-      return aCode[i];
-    }
-  }
-  return TK_ID;
-}
+#include "keywordhash.h"
+
 
 /*
 ** If X is a character that can be used in an identifier and
@@ -137,9 +49,15 @@ int sqlite3KeywordCode(const char *z, int n){
 ** with the high-order bit set.  The latter rule means that
 ** any sequence of UTF-8 characters or characters taken from
 ** an extended ISO8859 character set can form an identifier.
+**
+** Ticket #1066.  the SQL standard does not allow '$' in the
+** middle of identfiers.  But many SQL implementations do. 
+** SQLite will allow '$' in identifiers for compatibility.
+** But the feature is undocumented.
 */
 static const char isIdChar[] = {
 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+    0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */
     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */
@@ -147,13 +65,13 @@ static const char isIdChar[] = {
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,  /* 7x */
 };
 
-#define IdChar(C)  (((c=C)&0x80)!=0 || (c>0x2f && isIdChar[c-0x30]))
+#define IdChar(C)  (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20]))
 
 /*
 ** Return the length of the token that begins at z[0]. 
 ** Store the token type in *tokenType before returning.
 */
-static int sqliteGetToken(const unsigned char *z, int *tokenType){
+static int getToken(const unsigned char *z, int *tokenType){
   int i, c;
   switch( *z ){
     case ' ': case '\t': case '\n': case '\f': case '\r': {
@@ -265,6 +183,11 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
       *tokenType = TK_BITNOT;
       return 1;
     }
+    case '#': {
+      for(i=1; isdigit(z[i]) || (i==1 && z[1]=='-'); i++){}
+      *tokenType = TK_REGISTER;
+      return i;
+    }
     case '\'': case '"': {
       int delim = z[0];
       for(i=1; (c=z[i])!=0; i++){
@@ -288,6 +211,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
     case '5': case '6': case '7': case '8': case '9': {
       *tokenType = TK_INTEGER;
       for(i=1; isdigit(z[i]); i++){}
+#ifndef SQLITE_OMIT_FLOATING_POINT
       if( z[i]=='.' && isdigit(z[i+1]) ){
         i += 2;
         while( isdigit(z[i]) ){ i++; }
@@ -302,6 +226,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
         while( isdigit(z[i]) ){ i++; }
         *tokenType = TK_FLOAT;
       }
+#endif
       return i;
     }
     case '[': {
@@ -319,6 +244,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
       *tokenType = i>1 ? TK_VARIABLE : TK_ILLEGAL;
       return i;
     }
+#ifndef SQLITE_OMIT_TCL_VARIABLE
     case '$': {
       *tokenType = TK_VARIABLE;
       if( z[1]=='{' ){
@@ -355,7 +281,9 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
         if( n==0 ) *tokenType = TK_ILLEGAL;
       }
       return i;
-    } 
+    }
+#endif
+#ifndef SQLITE_OMIT_BLOB_LITERAL
     case 'x': case 'X': {
       if( (c=z[1])=='\'' || c=='"' ){
         int delim = c;
@@ -375,18 +303,22 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
       }
       /* Otherwise fall through to the next case */
     }
+#endif
     default: {
       if( !IdChar(*z) ){
         break;
       }
       for(i=1; IdChar(z[i]); i++){}
-      *tokenType = sqlite3KeywordCode((char*)z, i);
+      *tokenType = keywordCode((char*)z, i);
       return i;
     }
   }
   *tokenType = TK_ILLEGAL;
   return 1;
 }
+int sqlite3GetToken(const unsigned char *z, int *tokenType){
+  return getToken(z, tokenType);
+}
 
 /*
 ** Run the parser on the given SQL string.  The parser structure is
@@ -426,7 +358,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
     assert( i>=0 );
     pParse->sLastToken.z = &zSql[i];
     assert( pParse->sLastToken.dyn==0 );
-    pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType);
+    pParse->sLastToken.n = getToken((unsigned char*)&zSql[i],&tokenType);
     i += pParse->sLastToken.n;
     switch( tokenType ){
       case TK_SPACE:
@@ -486,7 +418,7 @@ abort_parse:
     pParse->zErrMsg = 0;
     if( !nErr ) nErr++;
   }
-  if( pParse->pVdbe && pParse->nErr>0 ){
+  if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
     sqlite3VdbeDelete(pParse->pVdbe);
     pParse->pVdbe = 0;
   }
@@ -503,14 +435,14 @@ abort_parse:
 ** Token types used by the sqlite3_complete() routine.  See the header
 ** comments on that procedure for additional information.
 */
-#define tkEXPLAIN 0
-#define tkCREATE  1
-#define tkTEMP    2
-#define tkTRIGGER 3
-#define tkEND     4
-#define tkSEMI    5
-#define tkWS      6
-#define tkOTHER   7
+#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.
@@ -525,16 +457,16 @@ abort_parse:
 **                 returns 1 if it ends in the START state and 0 if it ends
 **                 in any other state.
 **
-**   (1) EXPLAIN   The keyword EXPLAIN has been seen at the beginning of 
+**   (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.
 **
-**   (2) CREATE    The keyword CREATE has been seen at the beginning of a
+**   (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
 **
-**   (3) NORMAL    We are in the middle of statement which ends with a single
-**                 semicolon.
-**
 **   (4) TRIGGER   We are in the middle of a trigger definition that must be
 **                 ended by a semicolon, the keyword END, and another semicolon.
 **
@@ -547,36 +479,51 @@ abort_parse:
 ** Transitions between states above are determined by tokens extracted
 ** from the input.  The following tokens are significant:
 **
-**   (0) tkEXPLAIN   The "explain" keyword.
-**   (1) tkCREATE    The "create" keyword.
-**   (2) tkTEMP      The "temp" or "temporary" keyword.
-**   (3) tkTRIGGER   The "trigger" keyword.
-**   (4) tkEND       The "end" keyword.
-**   (5) tkSEMI      A semicolon.
-**   (6) tkWS        Whitespace
-**   (7) tkOTHER     Any other SQL token.
+**   (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 */
 
-  /* The following matrix defines the transition from one state to another
-  ** according to what token is seen.  trans[state][token] returns the
-  ** next state.
+#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:       **  EXPLAIN  CREATE  TEMP  TRIGGER  END  SEMI  WS  OTHER */
-     /* 0   START: */ {       1,      2,    3,       3,   3,    0,  0,     3, },
-     /* 1 EXPLAIN: */ {       3,      2,    3,       3,   3,    0,  1,     3, },
-     /* 2  CREATE: */ {       3,      3,    2,       4,   3,    0,  2,     3, },
-     /* 3  NORMAL: */ {       3,      3,    3,       3,   3,    0,  3,     3, },
-     /* 4 TRIGGER: */ {       4,      4,    4,       4,   4,    5,  4,     4, },
-     /* 5    SEMI: */ {       4,      4,    4,       4,   6,    5,  5,     4, },
-     /* 6     END: */ {       4,      4,    4,       4,   4,    0,  6,     4, },
+     /* 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 ){
@@ -636,6 +583,9 @@ int sqlite3_complete(const char *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 ){
@@ -660,9 +610,13 @@ int sqlite3_complete(const char *zSql){
             case 'e':  case 'E': {
               if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
                 token = tkEND;
-              }else if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
+              }else
+#ifndef SQLITE_OMIT_EXPLAIN
+              if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
                 token = tkEXPLAIN;
-              }else{
+              }else
+#endif
+              {
                 token = tkOTHER;
               }
               break;
@@ -672,6 +626,7 @@ int sqlite3_complete(const char *zSql){
               break;
             }
           }
+#endif /* SQLITE_OMIT_TRIGGER */
           zSql += nId-1;
         }else{
           /* Operators and special symbols */
@@ -686,6 +641,7 @@ int sqlite3_complete(const char *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
@@ -705,3 +661,4 @@ int sqlite3_complete16(const void *zSql){
   sqlite3ValueFree(pVal);
   return rc;
 }
+#endif /* SQLITE_OMIT_UTF16 */
index bbb526f802a55e985065b51844e173d91953daf7..eccc810e9be328832bd4c1e74f1b6ce12b326018 100644 (file)
@@ -12,6 +12,7 @@
 */
 #include "sqliteInt.h"
 
+#ifndef SQLITE_OMIT_TRIGGER
 /*
 ** Delete a linked list of TriggerStep structures.
 */
@@ -110,9 +111,7 @@ void sqlite3BeginTrigger(
   }
 
   /* Do not create a trigger on a system table */
-  if( (iDb!=1 && sqlite3StrICmp(pTab->zName, MASTER_NAME)==0) || 
-      (iDb==1 && sqlite3StrICmp(pTab->zName, TEMP_MASTER_NAME)==0) 
-  ){
+  if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
     sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
     pParse->nErr++;
     goto trigger_cleanup;
@@ -166,7 +165,7 @@ void sqlite3BeginTrigger(
   pTrigger->iDb = iDb;
   pTrigger->iTabDb = pTab->iDb;
   pTrigger->op = op;
-  pTrigger->tr_tm = tr_tm;
+  pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
   pTrigger->pWhen = sqlite3ExprDup(pWhen);
   pTrigger->pColumns = sqlite3IdListDup(pColumns);
   pTrigger->foreach = foreach;
@@ -190,20 +189,20 @@ void sqlite3FinishTrigger(
   TriggerStep *pStepList, /* The triggered program */
   Token *pAll             /* Token that describes the complete CREATE TRIGGER */
 ){
-  Trigger *nt = 0;          /* The trigger whose construction is finishing up */
+  Trigger *pTrig = 0;     /* The trigger whose construction is finishing up */
   sqlite3 *db = pParse->db;  /* The database */
   DbFixer sFix;
 
   if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
-  nt = pParse->pNewTrigger;
+  pTrig = pParse->pNewTrigger;
   pParse->pNewTrigger = 0;
-  nt->step_list = pStepList;
+  pTrig->step_list = pStepList;
   while( pStepList ){
-    pStepList->pTrig = nt;
+    pStepList->pTrig = pTrig;
     pStepList = pStepList->pNext;
   }
-  if( sqlite3FixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken) 
-          && sqlite3FixTriggerStep(&sFix, nt->step_list) ){
+  if( sqlite3FixInit(&sFix, pParse, pTrig->iDb, "trigger", &pTrig->nameToken) 
+          && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
     goto triggerfinish_cleanup;
   }
 
@@ -229,35 +228,32 @@ void sqlite3FinishTrigger(
     /* Make an entry in the sqlite_master table */
     v = sqlite3GetVdbe(pParse);
     if( v==0 ) goto triggerfinish_cleanup;
-    sqlite3BeginWriteOperation(pParse, 0, nt->iDb);
-    sqlite3OpenMasterTable(v, nt->iDb);
+    sqlite3BeginWriteOperation(pParse, 0, pTrig->iDb);
+    sqlite3OpenMasterTable(v, pTrig->iDb);
     addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
-    sqlite3VdbeChangeP3(v, addr+2, nt->name, 0); 
-    sqlite3VdbeChangeP3(v, addr+3, nt->table, 0); 
+    sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); 
+    sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); 
     sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n);
-    if( nt->iDb!=0 ){
-      sqlite3ChangeCookie(db, v, nt->iDb);
-    }
+    sqlite3ChangeCookie(db, v, pTrig->iDb);
     sqlite3VdbeAddOp(v, OP_Close, 0, 0);
-    sqlite3VdbeOp3(v, OP_ParseSchema, nt->iDb, 0, 
-       sqlite3MPrintf("type='trigger' AND name='%q'", nt->name), P3_DYNAMIC);
+    sqlite3VdbeOp3(v, OP_ParseSchema, pTrig->iDb, 0, 
+       sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC);
   }
 
   if( db->init.busy ){
     Table *pTab;
-    sqlite3HashInsert(&db->aDb[nt->iDb].trigHash, 
-                     nt->name, strlen(nt->name)+1, nt);
-    pTab = sqlite3LocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName);
+    sqlite3HashInsert(&db->aDb[pTrig->iDb].trigHash, 
+                     pTrig->name, strlen(pTrig->name)+1, pTrig);
+    pTab = sqlite3LocateTable(pParse,pTrig->table,db->aDb[pTrig->iTabDb].zName);
     assert( pTab!=0 );
-    nt->pNext = pTab->pTrigger;
-    pTab->pTrigger = nt;
-    nt = 0;
+    pTrig->pNext = pTab->pTrigger;
+    pTab->pTrigger = pTrig;
+    pTrig = 0;
   }
 
 triggerfinish_cleanup:
-  sqlite3DeleteTrigger(nt);
-  sqlite3DeleteTrigger(pParse->pNewTrigger);
-  pParse->pNewTrigger = 0;
+  sqlite3DeleteTrigger(pTrig);
+  assert( !pParse->pNewTrigger );
   sqlite3DeleteTriggerStep(pStepList);
 }
 
@@ -555,52 +551,38 @@ static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
   return 0; 
 }
 
-/* A global variable that is TRUE if we should always set up temp tables for
- * for triggers, even if there are no triggers to code. This is used to test 
- * how much overhead the triggers algorithm is causing.
- *
- * This flag can be set or cleared using the "trigger_overhead_test" pragma.
- * The pragma is not documented since it is not really part of the interface
- * to SQLite, just the test procedure.
-*/
-int sqlite3_always_code_trigger_setup = 0;
-
 /*
- * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
- * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
- * found in the list specified as pTrigger.
- */
+** Return a bit vector to indicate what kind of triggers exist for operation
+** "op" on table pTab.  If pChanges is not NULL then it is a list of columns
+** that are being updated.  Triggers only match if the ON clause of the
+** trigger definition overlaps the set of columns being updated.
+**
+** The returned bit vector is some combination of TRIGGER_BEFORE and
+** TRIGGER_AFTER.
+*/
 int sqlite3TriggersExist(
   Parse *pParse,          /* Used to check for recursive triggers */
-  Trigger *pTrigger,      /* A list of triggers associated with a table */
+  Table *pTab,            /* The table the contains the triggers */
   int op,                 /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
-  int tr_tm,              /* one of TK_BEFORE, TK_AFTER */
-  int foreach,            /* one of TK_ROW or TK_STATEMENT */
   ExprList *pChanges      /* Columns that change in an UPDATE statement */
 ){
-  Trigger * pTriggerCursor;
+  Trigger *pTrigger = pTab->pTrigger;
+  int mask = 0;
 
-  if( sqlite3_always_code_trigger_setup ){
-    return 1;
-  }
-
-  pTriggerCursor = pTrigger;
-  while( pTriggerCursor ){
-    if( pTriggerCursor->op == op && 
-       pTriggerCursor->tr_tm == tr_tm && 
-       pTriggerCursor->foreach == foreach &&
-       checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
-      TriggerStack * ss;
+  while( pTrigger ){
+    if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){
+      TriggerStack *ss;
       ss = pParse->trigStack;
-      while( ss && ss->pTrigger != pTrigger ){
+      while( ss && ss->pTrigger!=pTab->pTrigger ){
        ss = ss->pNext;
       }
-      if( !ss )return 1;
+      if( ss==0 ){
+        mask |= pTrigger->tr_tm;
+      }
     }
-    pTriggerCursor = pTriggerCursor->pNext;
+    pTrigger = pTrigger->pNext;
   }
-
-  return 0;
+  return mask;
 }
 
 /*
@@ -658,6 +640,7 @@ static int codeTriggerProgram(
        Select * ss = sqlite3SelectDup(pTriggerStep->pSelect);            
        assert(ss);
        assert(ss->pSrc);
+        sqlite3SelectResolve(pParse, ss, 0);
        sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
        sqlite3SelectDelete(ss);
        break;
@@ -726,7 +709,7 @@ int sqlite3CodeRowTrigger(
   Parse *pParse,       /* Parse context */
   int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
   ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */
-  int tr_tm,           /* One of TK_BEFORE, TK_AFTER */
+  int tr_tm,           /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
   Table *pTab,         /* The table to code triggers from */
   int newIdx,          /* The indice of the "new" row to access */
   int oldIdx,          /* The indice of the "old" row to access */
@@ -738,7 +721,7 @@ int sqlite3CodeRowTrigger(
   TriggerStack trigStackEntry;
 
   assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
-  assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER );
+  assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER );
 
   assert(newIdx != -1 || oldIdx != -1);
 
@@ -747,8 +730,7 @@ int sqlite3CodeRowTrigger(
     int fire_this = 0;
 
     /* determine whether we should code this trigger */
-    if( pTrigger->op == op && pTrigger->tr_tm == tr_tm && 
-        pTrigger->foreach == TK_ROW ){
+    if( pTrigger->op == op && pTrigger->tr_tm == tr_tm ){
       fire_this = 1;
       for(pStack=pParse->trigStack; pStack; pStack=pStack->pNext){
         if( pStack->pTrigger==pTrigger ){
@@ -763,11 +745,12 @@ int sqlite3CodeRowTrigger(
  
     if( fire_this ){
       int endTrigger;
-      SrcList dummyTablist;
       Expr * whenExpr;
       AuthContext sContext;
+      NameContext sNC;
 
-      dummyTablist.nSrc = 0;
+      memset(&sNC, 0, sizeof(sNC));
+      sNC.pParse = pParse;
 
       /* Push an entry on to the trigger stack */
       trigStackEntry.pTrigger = pTrigger;
@@ -782,7 +765,7 @@ int sqlite3CodeRowTrigger(
       /* code the WHEN clause */
       endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
       whenExpr = sqlite3ExprDup(pTrigger->pWhen);
-      if( sqlite3ExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){
+      if( sqlite3ExprResolveNames(&sNC, whenExpr) ){
         pParse->trigStack = trigStackEntry.pNext;
         sqlite3ExprDelete(whenExpr);
         return 1;
@@ -802,3 +785,4 @@ int sqlite3CodeRowTrigger(
   }
   return 0;
 }
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
index 08c7987c6f8ad3642021b5162b06138f0c1fbbf5..29ac02a646eab5f755f24be5f9203706aa5d2376 100644 (file)
@@ -48,12 +48,13 @@ void sqlite3Update(
   int chngRecno;         /* True if the record number is being changed */
   Expr *pRecnoExpr = 0;  /* Expression defining the new record number */
   int openAll = 0;       /* True if all indices need to be opened */
-  int isView;            /* Trying to update a view */
   AuthContext sContext;  /* The authorization context */
+  NameContext sNC;       /* The name-context to resolve expressions in */
 
-  int before_triggers;         /* True if there are any BEFORE triggers */
-  int after_triggers;          /* True if there are any AFTER triggers */
-  int row_triggers_exist = 0;  /* True if any row triggers exist */
+#ifndef SQLITE_OMIT_TRIGGER
+  int isView;                  /* Trying to update a view */
+  int triggers_exist = 0;      /* True if any row triggers exist */
+#endif
 
   int newIdx      = -1;  /* index of trigger "new" temp table       */
   int oldIdx      = -1;  /* index of trigger "old" temp table       */
@@ -67,13 +68,23 @@ void sqlite3Update(
   */
   pTab = sqlite3SrcListLookup(pParse, pTabList);
   if( pTab==0 ) goto update_cleanup;
-  before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
-            TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);
-  after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, 
-            TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
-  row_triggers_exist = before_triggers || after_triggers;
+
+  /* Figure out if we have any triggers and if the table being
+  ** updated is a view
+  */
+#ifndef SQLITE_OMIT_TRIGGER
+  triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges);
   isView = pTab->pSelect!=0;
-  if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
+#else
+# define triggers_exist 0
+# define isView 0
+#endif
+#ifdef SQLITE_OMIT_VIEW
+# undef isView
+# define isView 0
+#endif
+
+  if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
     goto update_cleanup;
   }
   if( isView ){
@@ -88,7 +99,7 @@ void sqlite3Update(
   /* If there are FOR EACH ROW triggers, allocate cursors for the
   ** special OLD and NEW tables
   */
-  if( row_triggers_exist ){
+  if( triggers_exist ){
     newIdx = pParse->nTab++;
     oldIdx = pParse->nTab++;
   }
@@ -103,6 +114,11 @@ void sqlite3Update(
     pParse->nTab++;
   }
 
+  /* Initialize the name-context */
+  memset(&sNC, 0, sizeof(sNC));
+  sNC.pParse = pParse;
+  sNC.pSrcList = pTabList;
+
   /* Resolve the column names in all the expressions of the
   ** of the UPDATE statement.  Also find the column index
   ** for each column to be updated in the pChanges array.  For each
@@ -111,8 +127,7 @@ void sqlite3Update(
   */
   chngRecno = 0;
   for(i=0; i<pChanges->nExpr; i++){
-    if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0,
-             pChanges->a[i].pExpr, 0, 0) ){
+    if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
       goto update_cleanup;
     }
     for(j=0; j<pTab->nCol; j++){
@@ -188,7 +203,7 @@ void sqlite3Update(
   /* Resolve the column names in all the expressions in the
   ** WHERE clause.
   */
-  if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){
+  if( sqlite3ExprResolveNames(&sNC, pWhere) ){
     goto update_cleanup;
   }
 
@@ -202,7 +217,7 @@ void sqlite3Update(
   */
   v = sqlite3GetVdbe(pParse);
   if( v==0 ) goto update_cleanup;
-  sqlite3VdbeCountChanges(v);
+  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
   sqlite3BeginWriteOperation(pParse, 1, pTab->iDb);
 
   /* If we are trying to update a view, construct that view into
@@ -217,11 +232,12 @@ void sqlite3Update(
 
   /* Begin the database scan
   */
-  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0);
+  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
   if( pWInfo==0 ) goto update_cleanup;
 
   /* Remember the index of every item to be updated.
   */
+  sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
   sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
 
   /* End the database scan loop.
@@ -234,7 +250,7 @@ void sqlite3Update(
     sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
   }
 
-  if( row_triggers_exist ){
+  if( triggers_exist ){
     /* Create pseudo-tables for NEW and OLD
     */
     sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
@@ -266,11 +282,11 @@ void sqlite3Update(
     /* Generate the NEW table
     */
     if( chngRecno ){
-      sqlite3ExprCode(pParse, pRecnoExpr);
+      sqlite3ExprCodeAndCache(pParse, pRecnoExpr);
     }else{
       sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
     }
-    for(i=0; i<pTab->nCol; i++){ /* TODO: Factor out this loop as common code */
+    for(i=0; i<pTab->nCol; i++){
       if( i==pTab->iPKey ){
         sqlite3VdbeAddOp(v, OP_String8, 0, 0);
         continue;
@@ -279,7 +295,7 @@ void sqlite3Update(
       if( j<0 ){
         sqlite3VdbeAddOp(v, OP_Column, iCur, i);
       }else{
-        sqlite3ExprCode(pParse, pChanges->a[j].pExpr);
+        sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr);
       }
     }
     sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
@@ -294,7 +310,7 @@ void sqlite3Update(
 
     /* Fire the BEFORE and INSTEAD OF triggers
     */
-    if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab, 
+    if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab,
           newIdx, oldIdx, onError, addr) ){
       goto update_cleanup;
     }
@@ -336,7 +352,7 @@ void sqlite3Update(
     ** Also, the old data is needed to delete the old index entires.
     ** So make the cursor point at the old record.
     */
-    if( !row_triggers_exist ){
+    if( !triggers_exist ){
       sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
       addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0);
       sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
@@ -396,7 +412,7 @@ void sqlite3Update(
   /* If there are triggers, close all the cursors after each iteration
   ** through the loop.  The fire the after triggers.
   */
-  if( row_triggers_exist ){
+  if( triggers_exist ){
     if( !isView ){
       for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
         if( openAll || aIdxUsed[i] )
@@ -404,7 +420,7 @@ void sqlite3Update(
       }
       sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
     }
-    if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, 
+    if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab, 
           newIdx, oldIdx, onError, addr) ){
       goto update_cleanup;
     }
@@ -418,7 +434,7 @@ void sqlite3Update(
   sqlite3VdbeAddOp(v, OP_ListReset, 0, 0);
 
   /* Close all tables if there were no FOR EACH ROW triggers */
-  if( !row_triggers_exist ){
+  if( !triggers_exist ){
     for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
       if( openAll || aIdxUsed[i] ){
         sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
@@ -431,9 +447,11 @@ void sqlite3Update(
   }
 
   /*
-  ** Return the number of rows that were changed.
+  ** Return the number of rows that were changed. If this routine is 
+  ** generating code because of a call to sqlite3NestedParse(), do not
+  ** invoke the callback function.
   */
-  if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
+  if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){
     sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
     sqlite3VdbeSetNumCols(v, 1);
     sqlite3VdbeSetColName(v, 0, "rows updated", P3_STATIC);
index 58b1a972d7c9f1cc4ffae08fc6344e8406a57721..a96b36c6db98addfc170f68b0239e6e4fd87590a 100644 (file)
@@ -58,8 +58,8 @@
 ** sqlite3utf8LikeCompare()  - Do a LIKE match given two UTF8 char* strings.
 **
 */
-#include <assert.h>
 #include "sqliteInt.h"
+#include <assert.h>
 #include "vdbeInt.h"
 
 /*
@@ -232,6 +232,7 @@ int sqlite3ReadUtf8(const unsigned char *z){
 */ 
 /* #define TRANSLATE_TRACE 1 */
 
+#ifndef SQLITE_OMIT_UTF16
 /*
 ** This routine transforms the internal text encoding used by pMem to
 ** desiredEnc. It is an error if the string is already of the desired
@@ -251,7 +252,7 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
   assert( pMem->enc!=0 );
   assert( pMem->n>=0 );
 
-#ifdef TRANSLATE_TRACE
+#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
   {
     char zBuf[100];
     sqlite3VdbeMemPrettyPrint(pMem, zBuf, 100);
@@ -367,7 +368,7 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
   pMem->z = zOut;
 
 translate_out:
-#ifdef TRANSLATE_TRACE
+#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
   {
     char zBuf[100];
     sqlite3VdbeMemPrettyPrint(pMem, zBuf, 100);
@@ -423,6 +424,7 @@ int sqlite3VdbeMemHandleBom(Mem *pMem){
   }
   return rc;
 }
+#endif /* SQLITE_OMIT_UTF16 */
 
 /*
 ** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
@@ -447,6 +449,7 @@ int sqlite3utf8CharLen(const char *z, int nByte){
   return r;
 }
 
+#ifndef SQLITE_OMIT_UTF16
 /*
 ** pZ is a UTF-16 encoded unicode string. If nChar is less than zero,
 ** return the number of bytes up to (but not including), the first pair
@@ -563,4 +566,5 @@ void sqlite3utfSelfTest(){
     assert( (z-zBuf)==n );
   }
 }
-#endif
+#endif /* SQLITE_TEST */
+#endif /* SQLITE_OMIT_UTF16 */
index 74ec89795febe6389c2f01ef6e810585493ffaee..bcbfe2493ea417872239044a9be8d3278b793075 100644 (file)
 #include <stdarg.h>
 #include <ctype.h>
 
-#if SQLITE_DEBUG>2 && defined(__GLIBC__)
+#if SQLITE_MEMDEBUG>2 && defined(__GLIBC__)
 #include <execinfo.h>
 void print_stack_trace(){
   void *bt[30];
   int i;
   int n = backtrace(bt, 30);
 
-  sqlite3DebugPrintf("STACK: ");
+  fprintf(stderr, "STACK: ");
   for(i=0; i<n;i++){
-    sqlite3DebugPrintf("%p ", bt[i]);
+    fprintf(stderr, "%p ", bt[i]);
   }
-  sqlite3DebugPrintf("\n");
+  fprintf(stderr, "\n");
 }
 #else
 #define print_stack_trace()
@@ -44,19 +44,23 @@ void print_stack_trace(){
 int sqlite3_malloc_failed = 0;
 
 /*
-** If SQLITE_DEBUG is defined, then use versions of malloc() and
+** If SQLITE_MEMDEBUG is defined, then use versions of malloc() and
 ** free() that track memory usage and check for buffer overruns.
 */
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
 
 /*
 ** For keeping track of the number of mallocs and frees.   This
-** is used to check for memory leaks.
+** is used to check for memory leaks.  The iMallocFail and iMallocReset
+** values are used to simulate malloc() failures during testing in 
+** order to verify that the library correctly handles an out-of-memory
+** condition.
 */
 int sqlite3_nMalloc;         /* Number of sqliteMalloc() calls */
 int sqlite3_nFree;           /* Number of sqliteFree() calls */
 int sqlite3_iMallocFail;     /* Fail sqliteMalloc() after this many calls */
-#if SQLITE_DEBUG>1
+int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */
+#if SQLITE_MEMDEBUG>1
 static int memcnt = 0;
 #endif
 
@@ -77,11 +81,11 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
     sqlite3_iMallocFail--;
     if( sqlite3_iMallocFail==0 ){
       sqlite3_malloc_failed++;
-#if SQLITE_DEBUG>1
+#if SQLITE_MEMDEBUG>1
       fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n",
               n, zFile,line);
 #endif
-      sqlite3_iMallocFail--;
+      sqlite3_iMallocFail = sqlite3_iMallocReset;
       return 0;
     }
   }
@@ -89,7 +93,7 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
   k = (n+sizeof(int)-1)/sizeof(int);
   pi = malloc( (N_GUARD*2+1+k)*sizeof(int));
   if( pi==0 ){
-    sqlite3_malloc_failed++;
+    if( n>0 ) sqlite3_malloc_failed++;
     return 0;
   }
   sqlite3_nMalloc++;
@@ -98,7 +102,7 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
   for(i=0; i<N_GUARD; i++) pi[k+1+N_GUARD+i] = 0xdead3344;
   p = &pi[N_GUARD+1];
   memset(p, bZero==0, n);
-#if SQLITE_DEBUG>1
+#if SQLITE_MEMDEBUG>1
   print_stack_trace();
   fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n",
       ++memcnt, n, (int)p, zFile,line);
@@ -152,7 +156,7 @@ void sqlite3Free_(void *p, char *zFile, int line){
       }
     }
     memset(pi, 0xff, (k+N_GUARD*2+1)*sizeof(int));
-#if SQLITE_DEBUG>1
+#if SQLITE_MEMDEBUG>1
     fprintf(stderr,"%06d free %d bytes at 0x%x from %s:%d\n",
          ++memcnt, n, (int)p, zFile,line);
 #endif
@@ -193,7 +197,7 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
   k = (n + sizeof(int) - 1)/sizeof(int);
   pi = malloc( (k+N_GUARD*2+1)*sizeof(int) );
   if( pi==0 ){
-    sqlite3_malloc_failed++;
+    if( n>0 ) sqlite3_malloc_failed++;
     return 0;
   }
   for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122;
@@ -206,7 +210,7 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
   }
   memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int));
   free(oldPi);
-#if SQLITE_DEBUG>1
+#if SQLITE_MEMDEBUG>1
   print_stack_trace();
   fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n",
     ++memcnt, oldN, n, (int)oldP, (int)p, zFile, line);
@@ -241,13 +245,13 @@ char *sqlite3StrNDup_(const char *z, int n, char *zFile, int line){
 void sqlite3FreeX(void *p){
   sqliteFree(p);
 }
-#endif /* SQLITE_DEBUG */
+#endif /* SQLITE_MEMDEBUG */
 
 /*
 ** The following versions of malloc() and free() are for use in a
 ** normal build.
 */
-#if !defined(SQLITE_DEBUG)
+#if !defined(SQLITE_MEMDEBUG)
 
 /*
 ** Allocate new memory and set it to zero.  Return NULL if
@@ -300,7 +304,7 @@ void *sqlite3Realloc(void *p, int n){
   }
   p2 = realloc(p, n);
   if( p2==0 ){
-    sqlite3_malloc_failed++;
+    if( n>0 ) sqlite3_malloc_failed++;
   }
   return p2;
 }
@@ -325,7 +329,7 @@ char *sqlite3StrNDup(const char *z, int n){
   }
   return zNew;
 }
-#endif /* !defined(SQLITE_DEBUG) */
+#endif /* !defined(SQLITE_MEMDEBUG) */
 
 /*
 ** Create a string from the 2nd and subsequent arguments (up to the
@@ -488,20 +492,6 @@ const unsigned char sqlite3UpperToLower[] = {
 };
 #define UpperToLower sqlite3UpperToLower
 
-/*
-** This function computes a hash on the name of a keyword.
-** Case is not significant.
-*/
-int sqlite3HashNoCase(const char *z, int n){
-  int h = 0;
-  if( n<=0 ) n = strlen(z);
-  while( n > 0  ){
-    h = (h<<3) ^ h ^ UpperToLower[(unsigned char)*z++];
-    n--;
-  }
-  return h & 0x7fffffff;
-}
-
 /*
 ** Some systems have stricmp().  Others have strcasecmp().  Because
 ** there is no consistency, we will define our own.
@@ -796,7 +786,7 @@ int sqlite3SafetyCheck(sqlite3 *db){
 int sqlite3PutVarint(unsigned char *p, u64 v){
   int i, j, n;
   u8 buf[10];
-  if( v & 0xff00000000000000 ){
+  if( v & (((u64)0xff000000)<<32) ){
     p[8] = v;
     v >>= 8;
     for(i=7; i>=0; i--){
@@ -868,6 +858,7 @@ int sqlite3GetVarint32(const unsigned char *p, u32 *v){
   u32 x;
   int n;
   unsigned char c;
+#if 0
   if( ((c = p[0]) & 0x80)==0 ){
     *v = c;
     return 1;
@@ -878,6 +869,18 @@ int sqlite3GetVarint32(const unsigned char *p, u32 *v){
     return 2;
   }
   x = (x<<7) | (c & 0x7f);
+#else
+  if( ((signed char*)p)[0]>=0 ){
+    *v = p[0];
+    return 1;
+  }
+  x = p[0] & 0x7f;
+  if( ((signed char*)p)[1]>=0 ){
+    *v = (x<<7) | p[1];
+    return 2;
+  }
+  x = (x<<7) | (p[1] & 0x7f);
+#endif
   n = 2;
   do{
     x = (x<<7) | ((c = p[n++])&0x7f);
@@ -899,6 +902,8 @@ int sqlite3VarintLen(u64 v){
   return i;
 }
 
+#if (!defined(SQLITE_OMIT_BLOB_LITERAL) && !defined(SQLITE_HAS_CODEC)) \
+    || defined(SQLITE_TEST)
 /*
 ** Translate a single byte of Hex into an integer.
 */
@@ -907,13 +912,14 @@ static int hexToInt(int h){
     return h - '0';
   }else if( h>='a' && h<='f' ){
     return h - 'a' + 10;
-  }else if( h>='A' && h<='F' ){
-    return h - 'A' + 10;
   }else{
-    return 0;
+    assert( h>='A' && h<='F' );
+    return h - 'A' + 10;
   }
 }
+#endif /* (!SQLITE_OMIT_BLOB_LITERAL && !SQLITE_HAS_CODEC) || SQLITE_TEST */
 
+#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
 /*
 ** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
 ** value.  Return a pointer to its binary value.  Space to hold the
@@ -932,6 +938,7 @@ void *sqlite3HexToBlob(const char *z){
   }
   return zBlob;
 }
+#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
 
 #if defined(SQLITE_TEST)
 /*
index 371a855770ee988cde2dc93699cabb1759f2643b..ed418b0ff6fe32a156d7650e218e9eae2fe2cec0 100644 (file)
@@ -19,7 +19,7 @@
 #include "sqliteInt.h"
 #include "os.h"
 
-#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
+#ifndef SQLITE_OMIT_VACUUM
 /*
 ** Generate a random name of 20 character in length.
 */
@@ -93,11 +93,10 @@ void sqlite3Vacuum(Parse *pParse, Token *pTableName){
 */
 int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
   int rc = SQLITE_OK;     /* Return code from service routines */
-#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
+#ifndef SQLITE_OMIT_VACUUM
   const char *zFilename;  /* full pathname of the database file */
   int nFilename;          /* number of characters  in zFilename[] */
   char *zTemp = 0;        /* a temporary file in same directory as zFilename */
-  int i;                  /* Loop counter */
   Btree *pMain;           /* The database being vacuumed */
   Btree *pTemp;
   char *zSql = 0;
@@ -129,11 +128,19 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
     goto end_of_vacuum;
   }
   strcpy(zTemp, zFilename);
-  i = 0;
+
+  /* The randomName() procedure in the following loop uses an excellent
+  ** source of randomness to generate a name from a space of 1.3e+31 
+  ** possibilities.  So unless the directory already contains on the order
+  ** of 1.3e+31 files, the probability that the following loop will
+  ** run more than once or twice is vanishingly small.  We are certain
+  ** enough that this loop will always terminate (and terminate quickly)
+  ** that we don't even bother to set a maximum loop count.
+  */
   do {
     zTemp[nFilename] = '-';
     randomName((unsigned char*)&zTemp[nFilename+1]);
-  } while( i<10 && sqlite3OsFileExists(zTemp) );
+  } while( sqlite3OsFileExists(zTemp) );
 
   /* Attach the temporary database as 'vacuum_db'. The synchronous pragma
   ** can be set to 'off' for this file, as it is not recovered if a crash
@@ -159,6 +166,10 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
   assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) );
   execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
 
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  sqlite3BtreeSetAutoVacuum(pTemp, sqlite3BtreeGetAutoVacuum(pMain));
+#endif
+
   /* Begin a transaction */
   rc = execSql(db, "BEGIN;");
   if( rc!=SQLITE_OK ) goto end_of_vacuum;
@@ -168,14 +179,17 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
   */
   rc = execExecSql(db, 
       "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) "
-      "  FROM sqlite_master WHERE type='table' "
-      "UNION ALL "
-      "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000) "
-      "  FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "
-      "UNION ALL "
+      "  FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'");
+  if( rc!=SQLITE_OK ) goto end_of_vacuum;
+  rc = execExecSql(db, 
+      "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000)"
+      "  FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
+  if( rc!=SQLITE_OK ) goto end_of_vacuum;
+  rc = execExecSql(db, 
       "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) "
-      "  FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"
-      "UNION ALL "
+      "  FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
+  if( rc!=SQLITE_OK ) goto end_of_vacuum;
+  rc = execExecSql(db, 
       "SELECT 'CREATE VIEW vacuum_db.' || substr(sql,13,100000000) "
       "  FROM sqlite_master WHERE type='view'"
   );
@@ -189,9 +203,24 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
       "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
       "|| ' SELECT * FROM ' || quote(name) || ';'"
       "FROM sqlite_master "
-      "WHERE type = 'table';"
+      "WHERE type = 'table' AND name!='sqlite_sequence';"
+  );
+  if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
+  /* Copy over the sequence table
+  */
+  rc = execExecSql(db, 
+      "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
+      "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
   );
   if( rc!=SQLITE_OK ) goto end_of_vacuum;
+  rc = execExecSql(db, 
+      "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
+      "|| ' SELECT * FROM ' || quote(name) || ';' "
+      "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
+  );
+  if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
 
   /* Copy the triggers from the main database to the temporary database.
   ** This was deferred before in case the triggers interfered with copying
@@ -215,22 +244,31 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
   */
   if( sqlite3BtreeIsInTrans(pTemp) ){
     u32 meta;
+    int i;
+
+    /* This array determines which meta meta values are preserved in the
+    ** vacuum.  Even entries are the meta value number and odd entries
+    ** are an increment to apply to the meta value after the vacuum.
+    ** The increment is used to increase the schema cookie so that other
+    ** connections to the same database will know to reread the schema.
+    */
+    static const unsigned char aCopy[] = {
+       1, 1,    /* Add one to the old schema cookie */
+       3, 0,    /* Preserve the default page cache size */
+       5, 0,    /* Preserve the default text encoding */
+       6, 0,    /* Preserve the user version */
+    };
 
     assert( 0==sqlite3BtreeIsInTrans(pMain) );
     rc = sqlite3BtreeBeginTrans(pMain, 1);
     if( rc!=SQLITE_OK ) goto end_of_vacuum;
 
-    /* Copy Btree meta values 3 and 4. These correspond to SQL layer meta 
-    ** values 2 and 3, the default values of a couple of pragmas.
-    */
-    rc = sqlite3BtreeGetMeta(pMain, 3, &meta);
-    if( rc!=SQLITE_OK ) goto end_of_vacuum;
-    rc = sqlite3BtreeUpdateMeta(pTemp, 3, meta);
-    if( rc!=SQLITE_OK ) goto end_of_vacuum;
-    rc = sqlite3BtreeGetMeta(pMain, 4, &meta);
-    if( rc!=SQLITE_OK ) goto end_of_vacuum;
-    rc = sqlite3BtreeUpdateMeta(pTemp, 4, meta);
-    if( rc!=SQLITE_OK ) goto end_of_vacuum;
+    /* Copy Btree meta values */
+    for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){
+      rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
+      if( rc!=SQLITE_OK ) goto end_of_vacuum;
+      rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
+    }
 
     rc = sqlite3BtreeCopyFile(pMain, pTemp);
     if( rc!=SQLITE_OK ) goto end_of_vacuum;
index 58f8c73109eaad807d8a081d9ab9a3f9b64a5f2f..485788820cc6d9e0cd62c59e4b2132270d277d50 100644 (file)
@@ -69,6 +69,15 @@ int sqlite3_search_count = 0;
 */
 int sqlite3_interrupt_count = 0;
 
+/*
+** The next global variable is incremented each type the OP_Sort opcode
+** is executed.  The test procedures use this information to make sure that
+** sorting is occurring or not occuring at appropriate times.   This variable
+** has no function other than to help verify the correct operation of the
+** library.
+*/
+int sqlite3_sort_count = 0;
+
 /*
 ** Release the memory associated with the given stack level.  This
 ** leaves the Mem.flags field in an inconsistent state.
@@ -294,7 +303,7 @@ static void applyAffinity(Mem *pRec, char affinity, u8 enc){
   }
 }
 
-#ifndef NDEBUG
+#ifdef SQLITE_DEBUG
 /*
 ** Write a nice string representation of the contents of cell pMem
 ** into buffer zBuf, length nBuf.
@@ -371,7 +380,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf){
 #ifdef VDBE_PROFILE
 /*
 ** The following routine only works on pentium-class processors.
-** It uses the RDTSC opcode to read cycle count value out of the
+** It uses the RDTSC opcode to read the cycle count value out of the
 ** processor and returns that value.  This can be used for high-res
 ** profiling.
 */
@@ -468,9 +477,9 @@ int sqlite3VdbeExec(
 #endif
     pOp = &p->aOp[pc];
 
-    /* Only allow tracing if NDEBUG is not defined.
+    /* Only allow tracing if SQLITE_DEBUG is defined.
     */
-#ifndef NDEBUG
+#ifdef SQLITE_DEBUG
     if( p->trace ){
       if( pc==0 ){
         printf("VDBE Execution Trace:\n");
@@ -478,8 +487,6 @@ int sqlite3VdbeExec(
       }
       sqlite3VdbePrintOp(p->trace, pc, pOp);
     }
-#endif
-#ifdef SQLITE_TEST
     if( p->trace==0 && pc==0 && sqlite3OsFileExists("vdbe_sqltrace") ){
       sqlite3VdbePrintSql(p);
     }
@@ -618,11 +625,10 @@ case OP_Halt: {
     sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0);
   }
   rc = sqlite3VdbeHalt(p);
+  assert( rc==SQLITE_BUSY || rc==SQLITE_OK );
   if( rc==SQLITE_BUSY ){
     p->rc = SQLITE_BUSY;
     return SQLITE_BUSY;
-  }else if( rc!=SQLITE_OK ){
-    p->rc = rc;
   }
   return p->rc ? SQLITE_ERROR : SQLITE_DONE;
 }
@@ -632,6 +638,9 @@ case OP_Halt: {
 ** The integer value P1 is pushed onto the stack.  If P3 is not zero
 ** then it is assumed to be a string representation of the same integer.
 ** If P1 is zero and P3 is not zero, then the value is derived from P3.
+**
+** If the value cannot be represented as a 32-bits then its value
+** will be in P3.
 */
 case OP_Integer: {
   pTos++;
@@ -671,6 +680,7 @@ case OP_Real: {            /* same as TK_FLOAT */
 ** into an OP_String before it is executed for the first time.
 */
 case OP_String8: {         /* same as TK_STRING */
+#ifndef SQLITE_OMIT_UTF16
   pOp->opcode = OP_String;
 
   if( db->enc!=SQLITE_UTF8 && pOp->p3 ){
@@ -687,6 +697,7 @@ case OP_String8: {         /* same as TK_STRING */
     pOp->p3 = pTos->z;
     break;
   }
+#endif
   /* Otherwise fall through to the next case, OP_String */
 }
   
@@ -701,11 +712,16 @@ case OP_String: {
   if( pOp->p3 ){
     pTos->flags = MEM_Str|MEM_Static|MEM_Term;
     pTos->z = pOp->p3;
+#ifndef SQLITE_OMIT_UTF16
     if( db->enc==SQLITE_UTF8 ){
       pTos->n = strlen(pTos->z);
     }else{
       pTos->n  = sqlite3utf16ByteLen(pTos->z, -1);
     }
+#else
+    assert( db->enc==SQLITE_UTF8 );
+    pTos->n = strlen(pTos->z);
+#endif
     pTos->enc = db->enc;
   }else{
     pTos->flags = MEM_Null;
@@ -713,6 +729,7 @@ case OP_String: {
   break;
 }
 
+#ifndef SQLITE_OMIT_BLOB_LITERAL
 /* Opcode: HexBlob * * P3
 **
 ** P3 is an UTF-8 SQL hex encoding of a blob. The blob is pushed onto the
@@ -750,13 +767,14 @@ case OP_HexBlob: {            /* same as TK_BLOB */
 ** by the compiler. Instead, the compiler layer specifies
 ** an OP_HexBlob opcode, with the hex string representation of
 ** the blob as P3. This opcode is transformed to an OP_Blob
-** before execution (within the sqlite3_prepare() function).
+** the first time it is executed.
 */
 case OP_Blob: {
   pTos++;
   sqlite3VdbeMemSetStr(pTos, pOp->p3, pOp->p1, 0, 0);
   break;
 }
+#endif /* SQLITE_OMIT_BLOB_LITERAL */
 
 /* Opcode: Variable P1 * *
 **
@@ -1084,7 +1102,7 @@ divide_by_zero:
 ** P3 is a pointer to a CollSeq struct. If the next call to a user function
 ** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
 ** be returned. This is used by the built-in min(), max() and nullif()
-** built-in functions.
+** functions.
 **
 ** The interface used by the implementation of the aforementioned functions
 ** to retrieve the collation sequence set by this opcode is not available
@@ -1140,7 +1158,6 @@ case OP_Function: {
   ctx.s.z = 0;
   ctx.s.xDel = 0;
   ctx.isError = 0;
-  ctx.isStep = 0;
   if( ctx.pFunc->needCollSeq ){
     assert( pOp>p->aOp );
     assert( pOp[-1].p3type==P3_COLLSEQ );
@@ -1643,25 +1660,30 @@ case OP_NotNull: {            /* same as TK_NOTNULL */
 ** opcode must be called to set the number of fields in the table.
 **
 ** This opcode sets the number of columns for cursor P1 to P2.
+**
+** If OP_KeyAsData is to be applied to cursor P1, it must be executed
+** before this op-code.
 */
 case OP_SetNumColumns: {
+  Cursor *pC;
   assert( (pOp->p1)<p->nCursor );
   assert( p->apCsr[pOp->p1]!=0 );
-  p->apCsr[pOp->p1]->nField = pOp->p2;
+  pC = p->apCsr[pOp->p1];
+  pC->nField = pOp->p2;
+  if( (!pC->keyAsData && pC->zeroData) || (pC->keyAsData && pC->intKey) ){
+    rc = SQLITE_CORRUPT;
+    goto abort_due_to_error;
+  }
   break;
 }
 
-/* Opcode: IdxColumn P1 * *
-**
-** P1 is a cursor opened on an index. Push the first field from the
-** current index key onto the stack.
-*/
 /* Opcode: Column P1 P2 *
 **
 ** Interpret the data that cursor P1 points to as a structure built using
 ** the MakeRecord instruction.  (See the MakeRecord opcode for additional
 ** information about the format of the data.) Push onto the stack the value
-** of the P2-th column contained in the data.
+** of the P2-th column contained in the data. If there are less that (P2+1) 
+** values in the record, push a NULL onto the stack.
 **
 ** If the KeyAsData opcode has previously executed on this cursor, then the
 ** field might be extracted from the key rather than the data.
@@ -1673,7 +1695,6 @@ case OP_SetNumColumns: {
 ** stack.  The column value is not copied. The number of columns in the
 ** record is stored on the stack just above the record itself.
 */
-case OP_IdxColumn:
 case OP_Column: {
   u32 payloadSize;   /* Number of bytes in the record */
   int p1 = pOp->p1;  /* P1 value of the opcode */
@@ -1727,7 +1748,8 @@ case OP_Column: {
     pCrsr = 0;
   }else if( (pC = p->apCsr[p1])->pCursor!=0 ){
     /* The record is stored in a B-Tree */
-    sqlite3VdbeCursorMoveto(pC);
+    rc = sqlite3VdbeCursorMoveto(pC);
+    if( rc ) goto abort_due_to_error;
     zRec = 0;
     pCrsr = pC->pCursor;
     if( pC->nullRow ){
@@ -1743,6 +1765,7 @@ case OP_Column: {
       sqlite3BtreeDataSize(pCrsr, &payloadSize);
     }
     nField = pC->nField;
+#ifndef SQLITE_OMIT_TRIGGER
   }else if( pC->pseudoTable ){
     /* The record is the sole entry of a pseudo-table */
     payloadSize = pC->nData;
@@ -1751,6 +1774,7 @@ case OP_Column: {
     assert( payloadSize==0 || zRec!=0 );
     nField = pC->nField;
     pCrsr = 0;
+#endif
   }else{
     zRec = 0;
     payloadSize = 0;
@@ -1816,7 +1840,7 @@ case OP_Column: {
     if( !zRec && avail<szHdr ){
       rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->keyAsData, &sMem);
       if( rc!=SQLITE_OK ){
-        goto abort_due_to_error;
+        goto op_column_out;
       }
       zData = sMem.z;
     }
@@ -1827,6 +1851,7 @@ case OP_Column: {
     ** of the record to the start of the data for the i-th column
     */
     offset = szHdr;
+    assert( offset>0 );
     i = 0;
     while( idx<szHdr && i<nField && offset<=payloadSize ){
       aOffset[i] = offset;
@@ -1837,15 +1862,23 @@ case OP_Column: {
     Release(&sMem);
     sMem.flags = MEM_Null;
 
+    /* If i is less that nField, then there are less fields in this
+    ** record than SetNumColumns indicated there are columns in the
+    ** table. Set the offset for any extra columns not present in
+    ** the record to 0. This tells code below to push a NULL onto the
+    ** stack instead of deserializing a value from the record.
+    */
+    while( i<nField ){
+      aOffset[i++] = 0;
+    }
+
     /* The header should end at the start of data and the data should
     ** end at last byte of the record. If this is not the case then
     ** we are dealing with a malformed record.
     */
     if( idx!=szHdr || offset!=payloadSize ){
-      sqliteFree(aType);
-      if( pC ) pC->aType = 0;
       rc = SQLITE_CORRUPT;
-      break;
+      goto op_column_out;
     }
 
     /* Remember all aType and aColumn information if we have a cursor
@@ -1858,20 +1891,28 @@ case OP_Column: {
     }
   }
 
-  /* Get the column information.
+  /* Get the column information. If aOffset[p2] is non-zero, then 
+  ** deserialize the value from the record. If aOffset[p2] is zero,
+  ** then there are not enough fields in the record to satisfy the
+  ** request. The value is NULL in this case.
   */
-  if( rc!=SQLITE_OK ){
-    goto abort_due_to_error;
-  }
-  if( zRec ){
-    zData = &zRec[aOffset[p2]];
+  if( aOffset[p2] ){
+    assert( rc==SQLITE_OK );
+    if( zRec ){
+      zData = &zRec[aOffset[p2]];
+    }else{
+      len = sqlite3VdbeSerialTypeLen(aType[p2]);
+      rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len,pC->keyAsData,&sMem);
+      if( rc!=SQLITE_OK ){
+        goto op_column_out;
+      }
+      zData = sMem.z;
+    }
+    sqlite3VdbeSerialGet(zData, aType[p2], pTos);
+    pTos->enc = db->enc;
   }else{
-    len = sqlite3VdbeSerialTypeLen(aType[p2]);
-    sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->keyAsData, &sMem);
-    zData = sMem.z;
+    pTos->flags = MEM_Null;
   }
-  sqlite3VdbeSerialGet(zData, aType[p2], pTos);
-  pTos->enc = db->enc;
 
   /* If we dynamically allocated space to hold the data (in the
   ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
@@ -1891,14 +1932,15 @@ case OP_Column: {
   ** can abandon sMem */
   rc = sqlite3VdbeMemMakeWriteable(pTos);
 
+op_column_out:
   /* Release the aType[] memory if we are not dealing with cursor */
-  if( !pC ){
+  if( !pC || !pC->aType ){
     sqliteFree(aType);
   }
   break;
 }
 
-/* Opcode MakeRecord P1 P2 P3
+/* Opcode: MakeRecord P1 P2 P3
 **
 ** Convert the top abs(P1) entries of the stack into a single entry
 ** suitable for use as a data record in a database table or as a key
@@ -1923,12 +1965,11 @@ case OP_Column: {
 ** field of the index key (i.e. the first character of P3 corresponds to the
 ** lowest element on the stack).
 **
-**  Character      Column affinity
-**  ------------------------------
-**  'n'            NUMERIC
-**  'i'            INTEGER
-**  't'            TEXT
-**  'o'            NONE
+** The mapping from character to affinity is as follows:
+**    'n' = NUMERIC.
+**    'i' = INTEGER.
+**    't' = TEXT.
+**    'o' = NONE.
 **
 ** If P3 is NULL then all index fields have the affinity NONE.
 */
@@ -2034,15 +2075,7 @@ case OP_MakeRecord: {
   if( addRowid ){
     zCsr += sqlite3VdbeSerialPut(zCsr, pRowid);
   }
-
-  /* If zCsr has not been advanced exactly nByte bytes, then one
-  ** of the sqlite3PutVarint() or sqlite3VdbeSerialPut() calls above
-  ** failed. This indicates a corrupted memory cell or code bug.
-  */
-  if( zCsr!=(zNewRecord+nByte) ){
-    rc = SQLITE_INTERNAL;
-    goto abort_due_to_error;
-  }
+  assert( zCsr==(zNewRecord+nByte) );
 
   /* Pop entries off the stack if required. Push the new record on. */
   if( !leaveOnStack ){
@@ -2448,6 +2481,7 @@ case OP_OpenTemp: {
   break;
 }
 
+#ifndef SQLITE_OMIT_TRIGGER
 /* Opcode: OpenPseudo P1 * *
 **
 ** Open a new cursor that points to a fake table that contains a single
@@ -2469,6 +2503,7 @@ case OP_OpenPseudo: {
   pCx->pIncrKey = &pCx->bogusIncrKey;
   break;
 }
+#endif
 
 /* Opcode: Close P1 * *
 **
@@ -2542,7 +2577,6 @@ case OP_MoveGt: {
     *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
     if( pC->intKey ){
       i64 iKey;
-      assert( !pOp->p3 );
       Integerify(pTos);
       iKey = intToKey(pTos->i);
       if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){
@@ -2552,12 +2586,18 @@ case OP_MoveGt: {
         pTos--;
         break;
       }
-      sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res);
+      rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res);
+      if( rc!=SQLITE_OK ){
+        goto abort_due_to_error;
+      }
       pC->lastRecno = pTos->i;
       pC->recnoIsValid = res==0;
     }else{
       Stringify(pTos, db->enc);
-      sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
+      rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
+      if( rc!=SQLITE_OK ){
+        goto abort_due_to_error;
+      }
       pC->recnoIsValid = 0;
     }
     pC->deferredMoveto = 0;
@@ -2566,7 +2606,8 @@ case OP_MoveGt: {
     sqlite3_search_count++;
     if( oc==OP_MoveGe || oc==OP_MoveGt ){
       if( res<0 ){
-        sqlite3BtreeNext(pC->pCursor, &res);
+        rc = sqlite3BtreeNext(pC->pCursor, &res);
+        if( rc!=SQLITE_OK ) goto abort_due_to_error;
         pC->recnoIsValid = 0;
       }else{
         res = 0;
@@ -2574,7 +2615,8 @@ case OP_MoveGt: {
     }else{
       assert( oc==OP_MoveLt || oc==OP_MoveLe );
       if( res>=0 ){
-        sqlite3BtreePrevious(pC->pCursor, &res);
+        rc = sqlite3BtreePrevious(pC->pCursor, &res);
+        if( rc!=SQLITE_OK ) goto abort_due_to_error;
         pC->recnoIsValid = 0;
       }else{
         /* res might be negative because the table is empty.  Check to
@@ -2782,17 +2824,17 @@ case OP_NotExists: {
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
-    int res, rx;
+    int res;
     u64 iKey;
     assert( pTos->flags & MEM_Int );
     assert( p->apCsr[i]->intKey );
     iKey = intToKey(pTos->i);
-    rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
+    rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
     pC->lastRecno = pTos->i;
     pC->recnoIsValid = res==0;
     pC->nullRow = 0;
     pC->cacheValid = 0;
-    if( rx!=SQLITE_OK || res!=0 ){
+    if( res!=0 ){
       pc = pOp->p2 - 1;
       pC->recnoIsValid = 0;
     }
@@ -2802,12 +2844,19 @@ case OP_NotExists: {
   break;
 }
 
-/* Opcode: NewRecno P1 * *
+/* Opcode: NewRecno P1 P2 *
 **
 ** Get a new integer record number used as the key to a table.
 ** The record number is not previously used as a key in the database
 ** table that cursor P1 points to.  The new record number is pushed 
 ** onto the stack.
+**
+** If P2>0 then P2 is a memory cell that holds the largest previously
+** generated record number.  No new record numbers are allowed to be less
+** than this value.  When this value reaches its maximum, a SQLITE_FULL
+** error is generated.  The P2 memory cell is updated with the generated
+** record number.  This P2 mechanism is used to help implement the
+** AUTOINCREMENT feature.
 */
 case OP_NewRecno: {
   int i = pOp->p1;
@@ -2852,8 +2901,24 @@ case OP_NewRecno: {
     int res, rx=SQLITE_OK, cnt;
     i64 x;
     cnt = 0;
+    if( (sqlite3BtreeFlags(pC->pCursor)&(BTREE_INTKEY|BTREE_ZERODATA)) !=
+          BTREE_INTKEY ){
+      rc = SQLITE_CORRUPT;
+      goto abort_due_to_error;
+    }
     assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_INTKEY)!=0 );
     assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_ZERODATA)==0 );
+
+#ifdef SQLITE_32BIT_ROWID
+#   define MAX_ROWID 0x7fffffff
+#else
+    /* Some compilers complain about constants of the form 0x7fffffffffffffff.
+    ** Others complain about 0x7ffffffffffffffffLL.  The following macro seems
+    ** to provide the constant while making all compilers happy.
+    */
+#   define MAX_ROWID  ( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
+#endif
+
     if( !pC->useRandomRowid ){
       if( pC->nextRowidValid ){
         v = pC->nextRowid;
@@ -2864,14 +2929,33 @@ case OP_NewRecno: {
         }else{
           sqlite3BtreeKeySize(pC->pCursor, &v);
           v = keyToInt(v);
-          if( v==0x7fffffffffffffff ){
+          if( v==MAX_ROWID ){
             pC->useRandomRowid = 1;
           }else{
             v++;
           }
         }
       }
-      if( v<0x7fffffffffffffff ){
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+      if( pOp->p2 ){
+        Mem *pMem;
+        assert( pOp->p2>0 && pOp->p2<p->nMem );  /* P2 is a valid memory cell */
+        pMem = &p->aMem[pOp->p2];
+        Integerify(pMem);
+        assert( (pMem->flags & MEM_Int)!=0 );  /* mem(P2) holds an integer */
+        if( pMem->i==MAX_ROWID || pC->useRandomRowid ){
+          rc = SQLITE_FULL;
+          goto abort_due_to_error;
+        }
+        if( v<pMem->i+1 ){
+          v = pMem->i + 1;
+        }
+        pMem->i = v;
+      }
+#endif
+
+      if( v<MAX_ROWID ){
         pC->nextRowidValid = 1;
         pC->nextRowid = v+1;
       }else{
@@ -2879,6 +2963,7 @@ case OP_NewRecno: {
       }
     }
     if( pC->useRandomRowid ){
+      assert( pOp->p2==0 );  /* SQLITE_FULL must have occurred prior to this */
       v = db->priorNewRowid;
       cnt = 0;
       do{
@@ -2979,6 +3064,7 @@ case OP_PutStrKey: {
     }else{
       assert( pTos->flags & (MEM_Blob|MEM_Str) );
     }
+#ifndef SQLITE_OMIT_TRIGGER
     if( pC->pseudoTable ){
       /* PutStrKey does not work for pseudo-tables.
       ** The following assert makes sure we are not trying to use
@@ -3000,8 +3086,12 @@ case OP_PutStrKey: {
       }
       pC->nullRow = 0;
     }else{
+#endif
       rc = sqlite3BtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
+#ifndef SQLITE_OMIT_TRIGGER
     }
+#endif
+    
     pC->recnoIsValid = 0;
     pC->deferredMoveto = 0;
     pC->cacheValid = 0;
@@ -3031,7 +3121,8 @@ case OP_Delete: {
   pC = p->apCsr[i];
   assert( pC!=0 );
   if( pC->pCursor!=0 ){
-    sqlite3VdbeCursorMoveto(pC);
+    rc = sqlite3VdbeCursorMoveto(pC);
+    if( rc ) goto abort_due_to_error;
     rc = sqlite3BtreeDelete(pC->pCursor);
     pC->nextRowidValid = 0;
     pC->cacheValid = 0;
@@ -3104,7 +3195,8 @@ case OP_RowData: {
     pTos->flags = MEM_Null;
   }else if( pC->pCursor!=0 ){
     BtCursor *pCrsr = pC->pCursor;
-    sqlite3VdbeCursorMoveto(pC);
+    rc = sqlite3VdbeCursorMoveto(pC);
+    if( rc ) goto abort_due_to_error;
     if( pC->nullRow ){
       pTos->flags = MEM_Null;
       break;
@@ -3132,10 +3224,12 @@ case OP_RowData: {
     }else{
       sqlite3BtreeData(pCrsr, 0, n, pTos->z);
     }
+#ifndef SQLITE_OMIT_TRIGGER
   }else if( pC->pseudoTable ){
     pTos->n = pC->nData;
     pTos->z = pC->pData;
     pTos->flags = MEM_Blob|MEM_Ephem;
+#endif
   }else{
     pTos->flags = MEM_Null;
   }
@@ -3157,7 +3251,8 @@ case OP_Recno: {
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
   assert( pC!=0 );
-  sqlite3VdbeCursorMoveto(pC);
+  rc = sqlite3VdbeCursorMoveto(pC);
+  if( rc ) goto abort_due_to_error;
   pTos++;
   if( pC->recnoIsValid ){
     v = pC->lastRecno;
@@ -3176,6 +3271,7 @@ case OP_Recno: {
   break;
 }
 
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
 /* Opcode: FullKey P1 * *
 **
 ** Extract the complete key from the record that cursor P1 is currently
@@ -3202,7 +3298,8 @@ case OP_FullKey: {
     i64 amt;
     char *z;
 
-    sqlite3VdbeCursorMoveto(pC);
+    rc = sqlite3VdbeCursorMoveto(pC);
+    if( rc ) goto abort_due_to_error;
     assert( pC->intKey==0 );
     sqlite3BtreeKeySize(pCrsr, &amt);
     if( amt<=0 ){
@@ -3224,6 +3321,7 @@ case OP_FullKey: {
   }
   break;
 }
+#endif
 
 /* Opcode: NullRow P1 * *
 **
@@ -3441,7 +3539,7 @@ case OP_IdxDelete: {
 /* Opcode: IdxRecno P1 * *
 **
 ** Push onto the stack an integer which is the varint located at the
-** end of the index key pointed to by cursor P1.  These integer should be
+** end of the index key pointed to by cursor P1.  This integer should be
 ** the record number of the table entry to which this index entry points.
 **
 ** See also: Recno, MakeIdxKey.
@@ -3596,10 +3694,33 @@ case OP_IdxIsNull: {
 ** P2==1 then the table to be clear is in the auxiliary database file
 ** that is used to store tables create using CREATE TEMPORARY TABLE.
 **
+** If AUTOVACUUM is enabled then it is possible that another root page
+** might be moved into the newly deleted root page in order to keep all
+** root pages contiguous at the beginning of the database.  The former
+** value of the root page that moved - its value before the move occurred -
+** is pushed onto the stack.  If no page movement was required (because
+** the table being dropped was already the last one in the database) then
+** a zero is pushed onto the stack.  If AUTOVACUUM is disabled
+** then a zero is pushed onto the stack.
+**
 ** See also: Clear
 */
 case OP_Destroy: {
-  rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1);
+  int iMoved;
+  if( db->activeVdbeCnt>1 ){
+    rc = SQLITE_LOCKED;
+  }else{
+    assert( db->activeVdbeCnt==1 );
+    rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
+    pTos++;
+    pTos->flags = MEM_Int;
+    pTos->i = iMoved;
+  #ifndef SQLITE_OMIT_AUTOVACUUM
+    if( rc==SQLITE_OK && iMoved!=0 ){
+      sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1);
+    }
+  #endif
+  }
   break;
 }
 
@@ -3735,6 +3856,7 @@ case OP_DropTrigger: {
 }
 
 
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
 /* Opcode: IntegrityCk * P2 *
 **
 ** Do an analysis of the currently open database.  Push onto the
@@ -3786,6 +3908,7 @@ case OP_IntegrityCk: {
   sqliteFree(aRoot);
   break;
 }
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
 
 /* Opcode: ListWrite * * *
 **
@@ -3871,6 +3994,32 @@ case OP_ListReset: {
   break;
 }
 
+#ifndef SQLITE_OMIT_SUBQUERY
+/* Opcode: AggContextPush * * * 
+**
+** Save the state of the current aggregator. It is restored an 
+** AggContextPop opcode.
+** 
+*/
+case OP_AggContextPush: {
+  p->pAgg++;
+  assert( p->pAgg<&p->apAgg[p->nAgg] );
+  break;
+}
+
+/* Opcode: AggContextPop * * *
+**
+** Restore the aggregator to the state it was in when AggContextPush
+** was last called. Any data in the current aggregator is deleted.
+*/
+case OP_AggContextPop: {
+  p->pAgg--;
+  assert( p->pAgg>=p->apAgg );
+  break;
+}
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
 /* Opcode: ContextPush * * * 
 **
 ** Save the current Vdbe context such that it can be restored by a ContextPop
@@ -3911,12 +4060,13 @@ case OP_ContextPop: {
   p->pList = pContext->pList;
   break;
 }
+#endif /* #ifndef SQLITE_OMIT_TRIGGER */
 
 /* Opcode: SortPut * * *
 **
 ** The TOS is the key and the NOS is the data.  Pop both from the stack
 ** and put them on the sorter.  The key and data should have been
-** made using SortMakeKey and SortMakeRec, respectively.
+** made using the MakeRecord opcode.
 */
 case OP_SortPut: {
   Mem *pNos = &pTos[-1];
@@ -3947,6 +4097,7 @@ case OP_Sort: {
   KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3;
   Sorter *pElem;
   Sorter *apSorter[NSORT];
+  sqlite3_sort_count++;
   pKeyInfo->enc = p->db->enc;
   for(i=0; i<NSORT; i++){
     apSorter[i] = 0;
@@ -4048,10 +4199,34 @@ case OP_MemLoad: {
   break;
 }
 
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+/* Opcode: MemMax P1 * *
+**
+** Set the value of memory cell P1 to the maximum of its current value
+** and the value on the top of the stack.  The stack is unchanged.
+**
+** This instruction throws an error if the memory cell is not initially
+** an integer.
+*/
+case OP_MemMax: {
+  int i = pOp->p1;
+  Mem *pMem;
+  assert( pTos>=p->aStack );
+  assert( i>=0 && i<p->nMem );
+  pMem = &p->aMem[i];
+  Integerify(pMem);
+  Integerify(pTos);
+  if( pMem->i<pTos->i){
+    pMem->i = pTos->i;
+  }
+  break;
+}
+#endif /* SQLITE_OMIT_AUTOINCREMENT */
+
 /* Opcode: MemIncr P1 P2 *
 **
 ** Increment the integer valued memory cell P1 by 1.  If P2 is not zero
-** and the result after the increment is greater than zero, then jump
+** and the result after the increment is exactly 1, then jump
 ** to P2.
 **
 ** This instruction throws an error if the memory cell is not initially
@@ -4064,7 +4239,24 @@ case OP_MemIncr: {
   pMem = &p->aMem[i];
   assert( pMem->flags==MEM_Int );
   pMem->i++;
-  if( pOp->p2>0 && pMem->i>0 ){
+  if( pOp->p2>0 && pMem->i==1 ){
+     pc = pOp->p2 - 1;
+  }
+  break;
+}
+
+/* Opcode: IfMemPos P1 P2 *
+**
+** If the value of memory cell P1 is 1 or greater, jump to P2. This
+** opcode assumes that memory cell P1 holds an integer value.
+*/
+case OP_IfMemPos: {
+  int i = pOp->p1;
+  Mem *pMem;
+  assert( i>=0 && i<p->nMem );
+  pMem = &p->aMem[i];
+  assert( pMem->flags==MEM_Int );
+  if( pMem->i>0 ){
      pc = pOp->p2 - 1;
   }
   break;
@@ -4072,8 +4264,8 @@ case OP_MemIncr: {
 
 /* Opcode: AggReset P1 P2 P3
 **
-** Reset the aggregator so that it no longer contains any data.
-** Future aggregator elements will contain P2 values each and be sorted
+** Reset the current aggregator context so that it no longer contains any 
+** data. Future aggregator elements will contain P2 values each and be sorted
 ** using the KeyInfo structure pointed to by P3.
 **
 ** If P1 is non-zero, then only a single aggregator row is available (i.e.
@@ -4083,18 +4275,18 @@ case OP_MemIncr: {
 case OP_AggReset: {
   assert( !pOp->p3 || pOp->p3type==P3_KEYINFO );
   if( pOp->p1 ){
-    rc = sqlite3VdbeAggReset(0, &p->agg, (KeyInfo *)pOp->p3);
-    p->agg.nMem = pOp->p2;    /* Agg.nMem is used by AggInsert() */
-    rc = AggInsert(&p->agg, 0, 0);
+    rc = sqlite3VdbeAggReset(0, p->pAgg, (KeyInfo *)pOp->p3);
+    p->pAgg->nMem = pOp->p2;    /* Agg.nMem is used by AggInsert() */
+    rc = AggInsert(p->pAgg, 0, 0);
   }else{
-    rc = sqlite3VdbeAggReset(db, &p->agg, (KeyInfo *)pOp->p3);
-    p->agg.nMem = pOp->p2;
+    rc = sqlite3VdbeAggReset(db, p->pAgg, (KeyInfo *)pOp->p3);
+    p->pAgg->nMem = pOp->p2;
   }
   if( rc!=SQLITE_OK ){
     goto abort_due_to_error;
   }
-  p->agg.apFunc = sqliteMalloc( p->agg.nMem*sizeof(p->agg.apFunc[0]) );
-  if( p->agg.apFunc==0 ) goto no_mem;
+  p->pAgg->apFunc = sqliteMalloc( p->pAgg->nMem*sizeof(p->pAgg->apFunc[0]) );
+  if( p->pAgg->apFunc==0 ) goto no_mem;
   break;
 }
 
@@ -4106,8 +4298,8 @@ case OP_AggReset: {
 */
 case OP_AggInit: {
   int i = pOp->p2;
-  assert( i>=0 && i<p->agg.nMem );
-  p->agg.apFunc[i] = (FuncDef*)pOp->p3;
+  assert( i>=0 && i<p->pAgg->nMem );
+  p->pAgg->apFunc[i] = (FuncDef*)pOp->p3;
   break;
 }
 
@@ -4142,14 +4334,13 @@ case OP_AggFunc: {
     storeTypeInfo(pRec, db->enc);
   }
   i = pTos->i;
-  assert( i>=0 && i<p->agg.nMem );
+  assert( i>=0 && i<p->pAgg->nMem );
   ctx.pFunc = (FuncDef*)pOp->p3;
-  pMem = &p->agg.pCurrent->aMem[i];
+  pMem = &p->pAgg->pCurrent->aMem[i];
   ctx.s.z = pMem->zShort;  /* Space used for small aggregate contexts */
   ctx.pAgg = pMem->z;
   ctx.cnt = ++pMem->i;
   ctx.isError = 0;
-  ctx.isStep = 1;
   ctx.pColl = 0;
   if( ctx.pFunc->needCollSeq ){
     assert( pOp>p->aOp );
@@ -4189,18 +4380,18 @@ case OP_AggFocus: {
   Stringify(pTos, db->enc);
   zKey = pTos->z;
   nKey = pTos->n;
-  assert( p->agg.pBtree );
-  assert( p->agg.pCsr );
-  rc = sqlite3BtreeMoveto(p->agg.pCsr, zKey, nKey, &res);
+  assert( p->pAgg->pBtree );
+  assert( p->pAgg->pCsr );
+  rc = sqlite3BtreeMoveto(p->pAgg->pCsr, zKey, nKey, &res);
   if( rc!=SQLITE_OK ){
     goto abort_due_to_error;
   }
   if( res==0 ){
-    rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*),
-        (char *)&p->agg.pCurrent);
+    rc = sqlite3BtreeData(p->pAgg->pCsr, 0, sizeof(AggElem*),
+        (char *)&p->pAgg->pCurrent);
     pc = pOp->p2 - 1;
   }else{
-    rc = AggInsert(&p->agg, zKey, nKey);
+    rc = AggInsert(p->pAgg, zKey, nKey);
   }
   if( rc!=SQLITE_OK ){
     goto abort_due_to_error;
@@ -4218,27 +4409,48 @@ case OP_AggFocus: {
 case OP_AggSet: {
   AggElem *pFocus;
   int i = pOp->p2;
-  pFocus = p->agg.pCurrent;
+  pFocus = p->pAgg->pCurrent;
   assert( pTos>=p->aStack );
   if( pFocus==0 ) goto no_mem;
-  assert( i>=0 && i<p->agg.nMem );
+  assert( i>=0 && i<p->pAgg->nMem );
   rc = sqlite3VdbeMemMove(&pFocus->aMem[i], pTos);
   pTos--;
   break;
 }
 
-/* Opcode: AggGet * P2 *
+/* Opcode: AggGet P1 P2 *
 **
 ** Push a new entry onto the stack which is a copy of the P2-th field
 ** of the current aggregate.  Strings are not duplicated so
 ** string values will be ephemeral.
+**
+** If P1 is zero, then the value is pulled out of the current aggregate
+** in the current aggregate context. If P1 is greater than zero, then
+** the value is taken from the P1th outer aggregate context. (i.e. if
+** P1==1 then read from the aggregate context that will be restored
+** by the next OP_AggContextPop opcode).
 */
 case OP_AggGet: {
   AggElem *pFocus;
   int i = pOp->p2;
-  pFocus = p->agg.pCurrent;
-  if( pFocus==0 ) goto no_mem;
-  assert( i>=0 && i<p->agg.nMem );
+  Agg *pAgg = &p->pAgg[-pOp->p1];
+  assert( pAgg>=p->apAgg );
+  pFocus = pAgg->pCurrent;
+  if( pFocus==0 ){
+    int res;
+    if( sqlite3_malloc_failed ) goto no_mem;
+    rc = sqlite3BtreeFirst(pAgg->pCsr, &res);
+    if( rc!=SQLITE_OK ){
+      return rc;
+    }
+    if( res!=0 ){
+      rc = AggInsert(pAgg, "", 1);
+      pFocus = pAgg->pCurrent;
+    }else{
+      rc = sqlite3BtreeData(pAgg->pCsr, 0, 4, (char *)&pFocus);
+    }
+  }
+  assert( i>=0 && i<pAgg->nMem );
   pTos++;
   sqlite3VdbeMemShallowCopy(pTos, &pFocus->aMem[i], MEM_Ephem);
   if( pTos->flags&MEM_Str ){
@@ -4263,16 +4475,16 @@ case OP_AggNext: {
   int res;
   assert( rc==SQLITE_OK );
   CHECK_FOR_INTERRUPT;
-  if( p->agg.searching==0 ){
-    p->agg.searching = 1;
-    if( p->agg.pCsr ){
-      rc = sqlite3BtreeFirst(p->agg.pCsr, &res);
+  if( p->pAgg->searching==0 ){
+    p->pAgg->searching = 1;
+    if( p->pAgg->pCsr ){
+      rc = sqlite3BtreeFirst(p->pAgg->pCsr, &res);
     }else{
       res = 0;
     }
   }else{
-    if( p->agg.pCsr ){
-      rc = sqlite3BtreeNext(p->agg.pCsr, &res);
+    if( p->pAgg->pCsr ){
+      rc = sqlite3BtreeNext(p->pAgg->pCsr, &res);
     }else{
       res = 1;
     }
@@ -4285,21 +4497,20 @@ case OP_AggNext: {
     sqlite3_context ctx;
     Mem *aMem;
 
-    if( p->agg.pCsr ){
-      rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*),
-          (char *)&p->agg.pCurrent);
+    if( p->pAgg->pCsr ){
+      rc = sqlite3BtreeData(p->pAgg->pCsr, 0, sizeof(AggElem*),
+          (char *)&p->pAgg->pCurrent);
       if( rc!=SQLITE_OK ) goto abort_due_to_error;
     }
-    aMem = p->agg.pCurrent->aMem;
-    for(i=0; i<p->agg.nMem; i++){
-      FuncDef *pFunc = p->agg.apFunc[i];
+    aMem = p->pAgg->pCurrent->aMem;
+    for(i=0; i<p->pAgg->nMem; i++){
+      FuncDef *pFunc = p->pAgg->apFunc[i];
       Mem *pMem = &aMem[i];
       if( pFunc==0 || pFunc->xFinalize==0 ) continue;
       ctx.s.flags = MEM_Null;
       ctx.s.z = pMem->zShort;
       ctx.pAgg = (void*)pMem->z;
       ctx.cnt = pMem->i;
-      ctx.isStep = 0;
       ctx.pFunc = pFunc;
       pFunc->xFinalize(&ctx);
       pMem->z = ctx.pAgg;
@@ -4328,6 +4539,25 @@ case OP_Vacuum: {
   break;
 }
 
+/* Opcode: Expire P1 * *
+**
+** Cause precompiled statements to become expired. An expired statement
+** fails with an error code of SQLITE_SCHEMA if it is ever executed 
+** (via sqlite3_step()).
+** 
+** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
+** then only the currently executing statement is affected. 
+*/
+case OP_Expire: {
+  if( !pOp->p1 ){
+    sqlite3ExpirePreparedStatements(db);
+  }else{
+    p->expired = 1;
+  }
+  break;
+}
+
+
 /* An other opcode is illegal...
 */
 default: {
@@ -4371,6 +4601,8 @@ default: {
       sqlite3SetString(&p->zErrMsg, "jump destination out of range", (char*)0);
       rc = SQLITE_INTERNAL;
     }
+#ifdef SQLITE_DEBUG
+    /* Code for tracing the vdbe stack. */
     if( p->trace && pTos>=p->aStack ){
       int i;
       fprintf(p->trace, "Stack:");
@@ -4393,7 +4625,8 @@ default: {
       if( rc!=0 ) fprintf(p->trace," rc=%d",rc);
       fprintf(p->trace,"\n");
     }
-#endif
+#endif  /* SQLITE_DEBUG */
+#endif  /* NDEBUG */
   }  /* The end of the for(;;) loop the loops through opcodes */
 
   /* If we reach this point, it means that execution is finished.
index 490417a422cb0531265951d9a99c8bf9c987c33f..e1b83986f2d213ccdc3f510bce82a731c6d7cacc 100644 (file)
@@ -110,7 +110,7 @@ int sqlite3VdbeFindOp(Vdbe*, int, int, int);
 VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
 int sqlite3VdbeMakeLabel(Vdbe*);
 void sqlite3VdbeDelete(Vdbe*);
-void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int);
+void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int);
 int sqlite3VdbeFinalize(Vdbe*);
 void sqlite3VdbeResolveLabel(Vdbe*, int);
 int sqlite3VdbeCurrentAddr(Vdbe*);
index a929cb95e1a3673b23f82b1f6a8056740776b595..42682d1e25a4e3727f26a63668a648347f391611 100644 (file)
@@ -220,7 +220,6 @@ struct sqlite3_context {
   Mem s;            /* The return value is stored here */
   void *pAgg;       /* Aggregate context */
   u8 isError;       /* Set to true for an error */
-  u8 isStep;        /* Current in the step function */
   int cnt;          /* Number of times that the step function has been called */
   CollSeq *pColl;
 };
@@ -322,7 +321,9 @@ struct Vdbe {
   int magic;              /* Magic number for sanity checking */
   int nMem;               /* Number of memory locations currently allocated */
   Mem *aMem;              /* The memory locations */
-  Agg agg;                /* Aggregate information */
+  int nAgg;               /* Number of elements in apAgg */
+  Agg *apAgg;             /* Array of aggregate contexts */
+  Agg *pAgg;              /* Current aggregate context */
   int nCallback;          /* Number of callbacks invoked so far */
   Keylist *pList;         /* A list of ROWIDs */
   int contextStackTop;    /* Index of top element in the context stack */
@@ -343,6 +344,7 @@ struct Vdbe {
   u8 explain;             /* True if EXPLAIN present on SQL command */
   u8 changeCntOn;         /* True to update the change-counter */
   u8 aborted;             /* True if ROLLBACK in another VM causes an abort */
+  u8 expired;             /* True if the VM needs to be recompiled */
   int nChange;            /* Number of db changes made since last reset */
 };
 
@@ -363,10 +365,12 @@ int sqlite3VdbeAggReset(sqlite3*, Agg *, KeyInfo *);
 void sqlite3VdbeKeylistFree(Keylist*);
 void sqliteVdbePopStack(Vdbe*,int);
 int sqlite3VdbeCursorMoveto(Cursor*);
-#if !defined(NDEBUG) || defined(VDBE_PROFILE)
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
 void sqlite3VdbePrintOp(FILE*, int, Op*);
 #endif
+#ifdef SQLITE_DEBUG
 void sqlite3VdbePrintSql(Vdbe*);
+#endif
 int sqlite3VdbeSerialTypeLen(u32);
 u32 sqlite3VdbeSerialType(Mem*);
 int sqlite3VdbeSerialPut(unsigned char*, Mem*);
index f6047f6fbee2251938c9e426005f2344954b615e..ca1612875ab19612afc3d7a221abcfba06956836 100644 (file)
 #include "sqliteInt.h"
 #include "vdbeInt.h"
 
+/*
+** Return TRUE (non-zero) of the statement supplied as an argument needs
+** to be recompiled.  A statement needs to be recompiled whenever the
+** execution environment changes in a way that would alter the program
+** that sqlite3_prepare() generates.  For example, if new functions or
+** collating sequences are registered or if an authorizer function is
+** added or changed.
+**
+***** EXPERIMENTAL ******
+*/
+int sqlite3_expired(sqlite3_stmt *pStmt){
+  Vdbe *p = (Vdbe*)pStmt;
+  return p==0 || p->expired;
+}
+
 /**************************** sqlite3_value_  *******************************
 ** The following routines extract information from a Mem or sqlite3_value
 ** structure.
@@ -46,6 +61,7 @@ sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
 const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
   return (const char *)sqlite3ValueText(pVal, SQLITE_UTF8);
 }
+#ifndef SQLITE_OMIT_UTF16
 const void *sqlite3_value_text16(sqlite3_value* pVal){
   return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
 }
@@ -55,6 +71,7 @@ const void *sqlite3_value_text16be(sqlite3_value *pVal){
 const void *sqlite3_value_text16le(sqlite3_value *pVal){
   return sqlite3ValueText(pVal, SQLITE_UTF16LE);
 }
+#endif /* SQLITE_OMIT_UTF16 */
 int sqlite3_value_type(sqlite3_value* pVal){
   return pVal->type;
 }
@@ -100,6 +117,7 @@ void sqlite3_result_text(
 ){
   sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, xDel);
 }
+#ifndef SQLITE_OMIT_UTF16
 void sqlite3_result_text16(
   sqlite3_context *pCtx, 
   const void *z, 
@@ -124,6 +142,7 @@ void sqlite3_result_text16le(
 ){
   sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16LE, xDel);
 }
+#endif /* SQLITE_OMIT_UTF16 */
 void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
   sqlite3VdbeMemCopy(&pCtx->s, pValue);
 }
@@ -144,6 +163,12 @@ int sqlite3_step(sqlite3_stmt *pStmt){
   if( p->aborted ){
     return SQLITE_ABORT;
   }
+  if( p->pc<=0 && p->expired ){
+    if( p->rc==SQLITE_OK ){
+      p->rc = SQLITE_SCHEMA;
+    }
+    return SQLITE_ERROR;
+  }
   db = p->db;
   if( sqlite3SafetyOn(db) ){
     p->rc = SQLITE_MISUSE;
@@ -177,9 +202,12 @@ int sqlite3_step(sqlite3_stmt *pStmt){
     db->activeVdbeCnt++;
     p->pc = 0;
   }
+#ifndef SQLITE_OMIT_EXPLAIN
   if( p->explain ){
     rc = sqlite3VdbeList(p);
-  }else{
+  }else
+#endif /* SQLITE_OMIT_EXPLAIN */
+  {
     rc = sqlite3VdbeExec(p);
   }
 
@@ -343,9 +371,11 @@ sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){
 const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
   return sqlite3_value_text( columnMem(pStmt,i) );
 }
+#ifndef SQLITE_OMIT_UTF16
 const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
   return sqlite3_value_text16( columnMem(pStmt,i) );
 }
+#endif /* SQLITE_OMIT_UTF16 */
 int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
   return sqlite3_value_type( columnMem(pStmt,i) );
 }
@@ -383,14 +413,6 @@ const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
   return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 0);
 }
 
-/*
-** Return the name of the 'i'th column of the result set of SQL statement
-** pStmt, encoded as UTF-16.
-*/
-const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
-  return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 0);
-}
-
 /*
 ** Return the column declaration type (if applicable) of the 'i'th column
 ** of the result set of SQL statement pStmt, encoded as UTF-8.
@@ -399,6 +421,15 @@ const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
   return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 1);
 }
 
+#ifndef SQLITE_OMIT_UTF16
+/*
+** Return the name of the 'i'th column of the result set of SQL statement
+** pStmt, encoded as UTF-16.
+*/
+const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
+  return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 0);
+}
+
 /*
 ** Return the column declaration type (if applicable) of the 'i'th column
 ** of the result set of SQL statement pStmt, encoded as UTF-16.
@@ -406,6 +437,7 @@ const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
 const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
   return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 1);
 }
+#endif /* SQLITE_OMIT_UTF16 */
 
 /******************************* sqlite3_bind_  ***************************
 ** 
@@ -513,6 +545,7 @@ int sqlite3_bind_text(
 ){
   return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
 }
+#ifndef SQLITE_OMIT_UTF16
 int sqlite3_bind_text16(
   sqlite3_stmt *pStmt, 
   int i, 
@@ -522,6 +555,7 @@ int sqlite3_bind_text16(
 ){
   return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
 }
+#endif /* SQLITE_OMIT_UTF16 */
 
 /*
 ** Return the number of wildcards that can be potentially bound to.
@@ -578,10 +612,12 @@ int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
     return 0;
   }
   createVarMap(p); 
-  for(i=0; i<p->nVar; i++){
-    const char *z = p->azVar[i];
-    if( z && strcmp(z,zName)==0 ){
-      return i+1;
+  if( zName ){
+    for(i=0; i<p->nVar; i++){
+      const char *z = p->azVar[i];
+      if( z && strcmp(z,zName)==0 ){
+        return i+1;
+      }
     }
   }
   return 0;
index fa9751daabc6fcef9e39795614ccacf16f9e5afa..6d77d725f41335dc8c998c1e3ed26f5ab700e029 100644 (file)
@@ -103,7 +103,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
   pOp->p2 = p2;
   pOp->p3 = 0;
   pOp->p3type = P3_NOTUSED;
-#ifndef NDEBUG
+#ifdef SQLITE_DEBUG
   if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
 #endif
   return i;
@@ -212,7 +212,7 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
       pOut->p2 = p2<0 ? addr + ADDR(p2) : p2;
       pOut->p3 = pIn->p3;
       pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED;
-#ifndef NDEBUG
+#ifdef SQLITE_DEBUG
       if( sqlite3_vdbe_addop_trace ){
         sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
       }
@@ -375,6 +375,8 @@ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
   return &p->aOp[addr];
 }
 
+#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
+     || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
 /*
 ** Compute a string that describes the P3 parameter for an opcode.
 ** Use zTemp for any required temporary buffer space.
@@ -444,9 +446,10 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){
   }
   return zP3;
 }
+#endif
 
 
-#if !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
 /*
 ** Print a single opcode.  This routine is used for debugging only.
 */
@@ -473,6 +476,7 @@ static void releaseMemArray(Mem *p, int N){
   }
 }
 
+#ifndef SQLITE_OMIT_EXPLAIN
 /*
 ** Give a listing of the program in the virtual machine.
 **
@@ -488,6 +492,9 @@ int sqlite3VdbeList(
   int rc = SQLITE_OK;
 
   assert( p->explain );
+  if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
+  assert( db->magic==SQLITE_MAGIC_BUSY );
+  assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
 
   /* Even though this opcode does not put dynamic strings onto the
   ** the stack, they may become dynamic if the user calls
@@ -498,17 +505,14 @@ int sqlite3VdbeList(
   }
   p->resOnStack = 0;
 
+
   i = p->pc++;
   if( i>=p->nOp ){
     p->rc = SQLITE_OK;
     rc = SQLITE_DONE;
   }else if( db->flags & SQLITE_Interrupt ){
     db->flags &= ~SQLITE_Interrupt;
-    if( db->magic!=SQLITE_MAGIC_BUSY ){
-      p->rc = SQLITE_MISUSE;
-    }else{
-      p->rc = SQLITE_INTERRUPT;
-    }
+    p->rc = SQLITE_INTERRUPT;
     rc = SQLITE_ERROR;
     sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0);
   }else{
@@ -549,6 +553,7 @@ int sqlite3VdbeList(
   }
   return rc;
 }
+#endif /* SQLITE_OMIT_EXPLAIN */
 
 /*
 ** Print the SQL that was used to generate a VDBE program.
@@ -581,6 +586,7 @@ void sqlite3VdbeMakeReady(
   int nVar,                      /* Number of '?' see in the SQL statement */
   int nMem,                      /* Number of memory cells to allocate */
   int nCursor,                   /* Number of cursors to allocate */
+  int nAgg,                      /* Number of aggregate contexts required */
   int isExplain                  /* True if the EXPLAIN keywords is present */
 ){
   int n;
@@ -610,6 +616,7 @@ void sqlite3VdbeMakeReady(
       + nVar*sizeof(char*)             /* azVar */
       + nMem*sizeof(Mem)               /* aMem */
       + nCursor*sizeof(Cursor*)        /* apCsr */
+      + nAgg*sizeof(Agg)               /* Aggregate contexts */
     );
     if( !sqlite3_malloc_failed ){
       p->aMem = &p->aStack[n];
@@ -620,15 +627,20 @@ void sqlite3VdbeMakeReady(
       p->apArg = (Mem**)&p->aVar[nVar];
       p->azVar = (char**)&p->apArg[n];
       p->apCsr = (Cursor**)&p->azVar[nVar];
+      if( nAgg>0 ){
+        p->nAgg = nAgg;
+        p->apAgg = (Agg*)&p->apCsr[nCursor];
+      }
       p->nCursor = nCursor;
       for(n=0; n<nVar; n++){
         p->aVar[n].flags = MEM_Null;
       }
-      for(n=0; n<nMem; n++){
-        p->aMem[n].flags = MEM_Null;
-      }
     }
   }
+  p->pAgg = p->apAgg;
+  for(n=0; n<p->nMem; n++){
+    p->aMem[n].flags = MEM_Null;
+  }
 
 #ifdef SQLITE_DEBUG
   if( (p->db->flags & SQLITE_VdbeListing)!=0
@@ -684,7 +696,7 @@ void sqlite3VdbeSorterReset(Vdbe *p){
 ** Free all resources allociated with AggElem pElem, an element of
 ** aggregate pAgg.
 */
-void freeAggElem(AggElem *pElem, Agg *pAgg){
+static void freeAggElem(AggElem *pElem, Agg *pAgg){
   int i;
   for(i=0; i<pAgg->nMem; i++){
     Mem *pMem = &pElem->aMem[i];
@@ -694,9 +706,8 @@ void freeAggElem(AggElem *pElem, Agg *pAgg){
       ctx.s.flags = MEM_Null;
       ctx.pAgg = pMem->z;
       ctx.cnt = pMem->i;
-      ctx.isStep = 0;
       ctx.isError = 0;
-      (*pAgg->apFunc[i]->xFinalize)(&ctx);
+      (*ctx.pFunc->xFinalize)(&ctx);
       pMem->z = ctx.pAgg;
       if( pMem->z!=0 && pMem->z!=pMem->zShort ){
         sqliteFree(pMem->z);
@@ -729,8 +740,10 @@ void freeAggElem(AggElem *pElem, Agg *pAgg){
 */
 int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
   int rc = 0;
-  BtCursor *pCsr = pAgg->pCsr;
+  BtCursor *pCsr;
 
+  if( !pAgg ) return SQLITE_OK;
+  pCsr = pAgg->pCsr;
   assert( (pCsr && pAgg->nTab>0) || (!pCsr && pAgg->nTab==0)
          || sqlite3_malloc_failed );
 
@@ -748,7 +761,7 @@ int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
     while( res==0 && rc==SQLITE_OK ){
       AggElem *pElem;
       rc = sqlite3BtreeData(pCsr, 0, sizeof(AggElem*), (char *)&pElem);
-      if( res!=SQLITE_OK ){
+      if( rc!=SQLITE_OK ){
         return rc;
       }
       assert( pAgg->apFunc!=0 );
@@ -779,7 +792,11 @@ int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
   if( db ){
     if( !pAgg->pBtree ){
       assert( pAgg->nTab==0 );
+#ifndef SQLITE_OMIT_MEMORYDB
       rc = sqlite3BtreeFactory(db, ":memory:", 0, TEMP_PAGES, &pAgg->pBtree);
+#else
+      rc = sqlite3BtreeFactory(db, 0, 0, TEMP_PAGES, &pAgg->pBtree);
+#endif
       if( rc!=SQLITE_OK ) return rc;
       sqlite3BtreeBeginTrans(pAgg->pBtree, 1);
       rc = sqlite3BtreeCreateTable(pAgg->pBtree, &pAgg->nTab, 0);
@@ -878,7 +895,9 @@ static void Cleanup(Vdbe *p){
     sqliteFree(p->contextStack);
   }
   sqlite3VdbeSorterReset(p);
-  sqlite3VdbeAggReset(0, &p->agg, 0);
+  for(i=0; i<p->nAgg; i++){
+    sqlite3VdbeAggReset(0, &p->apAgg[i], 0);
+  }
   p->contextStack = 0;
   p->contextStackDepth = 0;
   p->contextStackTop = 0;
@@ -1026,7 +1045,7 @@ static int vdbeCommit(sqlite3 *db){
     ** master journal file. If an error occurs at this point close
     ** and delete the master journal file. All the individual journal files
     ** still have 'null' as the master journal pointer, so they will roll
-    ** back independantly if a failure occurs.
+    ** back independently if a failure occurs.
     */
     for(i=0; i<db->nDb; i++){ 
       Btree *pBt = db->aDb[i].pBt;
@@ -1050,18 +1069,12 @@ static int vdbeCommit(sqlite3 *db){
     */
     zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
     rc = sqlite3OsOpenDirectory(zMainFile, &master);
-    if( rc!=SQLITE_OK ){
+    if( rc!=SQLITE_OK || (rc = sqlite3OsSync(&master))!=SQLITE_OK ){
       sqlite3OsClose(&master);
       sqlite3OsDelete(zMaster);
       sqliteFree(zMaster);
       return rc;
     }
-    rc = sqlite3OsSync(&master);
-    if( rc!=SQLITE_OK ){
-      sqlite3OsClose(&master);
-      sqliteFree(zMaster);
-      return rc;
-    }
 
     /* Sync all the db files involved in the transaction. The same call
     ** sets the master journal pointer in each individual journal. If
@@ -1103,8 +1116,6 @@ static int vdbeCommit(sqlite3 *db){
       ** master journal exists now or if it will exist after the operating
       ** system crash that may follow the fsync() failure.
       */
-      assert(0);
-      sqliteFree(zMaster);
       return rc;
     }
 
@@ -1193,7 +1204,9 @@ int sqlite3VdbeHalt(Vdbe *p){
   }
   closeAllCursors(p);
   checkActiveVdbeCnt(db);
-  if( db->autoCommit && db->activeVdbeCnt==1 ){
+  if( p->pc<0 ){
+    /* No commit or rollback needed if the program never started */
+  }else if( db->autoCommit && db->activeVdbeCnt==1 ){
     if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
       /* The auto-commit flag is true, there are no other active queries
       ** using this handle and the vdbe program was successful or hit an
@@ -1236,7 +1249,7 @@ int sqlite3VdbeHalt(Vdbe *p){
   }
 
   /* If this was an INSERT, UPDATE or DELETE, set the change counter. */
-  if( p->changeCntOn ){
+  if( p->changeCntOn && p->pc>=0 ){
     if( !xFunc || xFunc==sqlite3BtreeCommitStmt ){
       sqlite3VdbeSetChanges(db, p->nChange);
     }else{
@@ -1285,17 +1298,27 @@ int sqlite3VdbeReset(Vdbe *p){
   */
   sqlite3VdbeHalt(p);
 
-  /* Transfer the error code and error message from the VDBE into the
-  ** main database structure.
+  /* If the VDBE has be run even partially, then transfer the error code
+  ** and error message from the VDBE into the main database structure.  But
+  ** if the VDBE has just been set to run but has not actually executed any
+  ** instructions yet, leave the main database error information unchanged.
   */
-  if( p->zErrMsg ){
-    sqlite3Error(p->db, p->rc, "%s", p->zErrMsg);
-    sqliteFree(p->zErrMsg);
-    p->zErrMsg = 0;
-  }else if( p->rc ){
+  if( p->pc>=0 ){
+    if( p->zErrMsg ){
+      sqlite3Error(p->db, p->rc, "%s", p->zErrMsg);
+      sqliteFree(p->zErrMsg);
+      p->zErrMsg = 0;
+    }else if( p->rc ){
+      sqlite3Error(p->db, p->rc, 0);
+    }else{
+      sqlite3Error(p->db, SQLITE_OK, 0);
+    }
+  }else if( p->rc && p->expired ){
+    /* The expired flag was set on the VDBE before the first call
+    ** to sqlite3_step(). For consistency (since sqlite3_step() was
+    ** called), set the database error in this case as well.
+    */
     sqlite3Error(p->db, p->rc, 0);
-  }else{
-    sqlite3Error(p->db, SQLITE_OK, 0);
   }
 
   /* Reclaim all memory used by the VDBE
@@ -1329,6 +1352,9 @@ int sqlite3VdbeReset(Vdbe *p){
 #endif
   p->magic = VDBE_MAGIC_INIT;
   p->aborted = 0;
+  if( p->rc==SQLITE_SCHEMA ){
+    sqlite3ResetInternalSchema(p->db, 0);
+  }
   return p->rc;
 }
  
@@ -1338,18 +1364,13 @@ int sqlite3VdbeReset(Vdbe *p){
 */
 int sqlite3VdbeFinalize(Vdbe *p){
   int rc = SQLITE_OK;
-  sqlite3 *db = p->db;
 
   if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
     rc = sqlite3VdbeReset(p);
   }else if( p->magic!=VDBE_MAGIC_INIT ){
-    /* sqlite3Error(p->db, SQLITE_MISUSE, 0); */
     return SQLITE_MISUSE;
   }
   sqlite3VdbeDelete(p);
-  if( rc==SQLITE_SCHEMA ){
-    sqlite3ResetInternalSchema(db, 0);
-  }
   return rc;
 }
 
@@ -1418,19 +1439,22 @@ void sqlite3VdbeDelete(Vdbe *p){
 */
 int sqlite3VdbeCursorMoveto(Cursor *p){
   if( p->deferredMoveto ){
-    int res;
+    int res, rc;
     extern int sqlite3_search_count;
     assert( p->intKey );
     if( p->intKey ){
-      sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res);
+      rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res);
     }else{
-      sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget,sizeof(i64),&res);
+      rc = sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget,
+                              sizeof(i64),&res);
     }
+    if( rc ) return rc;
     *p->pIncrKey = 0;
     p->lastRecno = keyToInt(p->movetoTarget);
     p->recnoIsValid = res==0;
     if( res<0 ){
-      sqlite3BtreeNext(p->pCursor, &res);
+      rc = sqlite3BtreeNext(p->pCursor, &res);
+      if( rc ) return rc;
     }
     sqlite3_search_count++;
     p->deferredMoveto = 0;
@@ -1487,13 +1511,15 @@ u32 sqlite3VdbeSerialType(Mem *pMem){
     return 0;
   }
   if( flags&MEM_Int ){
-    /* Figure out whether to use 1, 2, 4 or 8 bytes. */
+    /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
+#   define MAX_6BYTE ((((i64)0x00010000)<<32)-1)
     i64 i = pMem->i;
-    if( i>=-127 && i<=127 ) return 1;
-    if( i>=-32767 && i<=32767 ) return 2;
-    if( i>=-8388607 && i<=8388607 ) return 3;
-    if( i>=-2147483647 && i<=2147483647 ) return 4;
-    if( i>=-140737488355328L && i<=140737488355328L ) return 5;
+    u64 u = i<0 ? -i : i;
+    if( u<=127 ) return 1;
+    if( u<=32767 ) return 2;
+    if( u<=8388607 ) return 3;
+    if( u<=2147483647 ) return 4;
+    if( u<=MAX_6BYTE ) return 5;
     return 6;
   }
   if( flags&MEM_Real ){
@@ -1801,6 +1827,23 @@ void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
 ** Set a flag in the vdbe to update the change counter when it is finalised
 ** or reset.
 */
-void sqlite3VdbeCountChanges(Vdbe *p){
-  p->changeCntOn = 1;
+void sqlite3VdbeCountChanges(Vdbe *v){
+  v->changeCntOn = 1;
+}
+
+/*
+** Mark every prepared statement associated with a database connection
+** as expired.
+**
+** An expired statement means that recompilation of the statement is
+** recommend.  Statements expire when things happen that make their
+** programs obsolete.  Removing user-defined functions or collating
+** sequences, or changing an authorization function are the types of
+** things that make prepared statements obsolete.
+*/
+void sqlite3ExpirePreparedStatements(sqlite3 *db){
+  Vdbe *p;
+  for(p = db->pVdbe; p; p=p->pNext){
+    p->expired = 1;
+  }
 }
index c6cd94e6348430472bbfa409d9a618d374d4de40..23da9ced9e518fea94db8a3e7988b2e6789bf8ba 100644 (file)
 ** between formats.
 */
 int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
+  int rc;
   if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
     return SQLITE_OK;
   }
-  return sqlite3VdbeMemTranslate(pMem, desiredEnc);
+#ifdef SQLITE_OMIT_UTF16
+  return SQLITE_ERROR;
+#else
+  rc = sqlite3VdbeMemTranslate(pMem, desiredEnc);
+  if( rc==SQLITE_NOMEM ){
+    sqlite3VdbeMemRelease(pMem);
+    pMem->flags = MEM_Null;
+    pMem->z = 0;
+  }
+  return rc;
+#endif
 }
 
 /*
@@ -390,6 +401,8 @@ int sqlite3VdbeMemSetStr(
   pMem->type = enc==0 ? SQLITE_BLOB : SQLITE_TEXT;
   pMem->n = n;
 
+  assert( enc==0 || enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE 
+      || enc==SQLITE_UTF16BE );
   switch( enc ){
     case 0:
       pMem->flags |= MEM_Blob;
@@ -403,6 +416,7 @@ int sqlite3VdbeMemSetStr(
       }
       break;
 
+#ifndef SQLITE_OMIT_UTF16
     case SQLITE_UTF16LE:
     case SQLITE_UTF16BE:
       pMem->flags |= MEM_Str;
@@ -413,10 +427,7 @@ int sqlite3VdbeMemSetStr(
       if( sqlite3VdbeMemHandleBom(pMem) ){
         return SQLITE_NOMEM;
       }
-      break;
-
-    default:
-      assert(0);
+#endif /* SQLITE_OMIT_UTF16 */
   }
   if( pMem->flags&MEM_Ephem ){
     return sqlite3VdbeMemMakeWriteable(pMem);
index 08c174e9346450074c5530a8f5c9c6535c3dff42..b2489a4706d07e958270344fe5605cdf80126e40 100644 (file)
 **
 *************************************************************************
 ** This module contains C code that generates VDBE code used to process
-** the WHERE clause of SQL statements.
+** the WHERE clause of SQL statements.  This module is reponsible for
+** generating the code that loops through a table looking for applicable
+** rows.  Indices are selected and used to speed the search when doing
+** so is applicable.  Because this module is responsible for selecting
+** indices, you might also think of this module as the "query optimizer".
 **
 ** $Id$
 */
 ** The query generator uses an array of instances of this structure to
 ** help it analyze the subexpressions of the WHERE clause.  Each WHERE
 ** clause subexpression is separated from the others by an AND operator.
+**
+** The idxLeft and idxRight fields are the VDBE cursor numbers for the
+** table that contains the column that appears on the left-hand and
+** right-hand side of ExprInfo.p.  If either side of ExprInfo.p is
+** something other than a simple column reference, then idxLeft or
+** idxRight are -1.  
+**
+** It is the VDBE cursor number is the value stored in Expr.iTable
+** when Expr.op==TK_COLUMN and the value stored in SrcList.a[].iCursor.
+**
+** prereqLeft, prereqRight, and prereqAll record sets of cursor numbers,
+** but they do so indirectly.  A single ExprMaskSet structure translates
+** cursor number into bits and the translated bit is stored in the prereq
+** fields.  The translation is used in order to maximize the number of
+** bits that will fit in a Bitmask.  The VDBE cursor numbers might be
+** spread out over the non-negative integers.  For example, the cursor
+** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45.  The ExprMaskSet
+** translates these sparse cursor numbers into consecutive integers
+** beginning with 0 in order to make the best possible use of the available
+** bits in the Bitmask.  So, in the example above, the cursor numbers
+** would be mapped into integers 0 through 7.
+**
+** prereqLeft tells us every VDBE cursor that is referenced on the
+** left-hand side of ExprInfo.p.  prereqRight does the same for the
+** right-hand side of the expression.  The following identity always
+** holds:
+**
+**       prereqAll = prereqLeft | prereqRight
+**
+** The ExprInfo.indexable field is true if the ExprInfo.p expression
+** is of a form that might control an index.  Indexable expressions
+** look like this:
+**
+**              <column> <op> <expr>
+**
+** Where <column> is a simple column name and <op> is on of the operators
+** that allowedOp() recognizes.  
 */
 typedef struct ExprInfo ExprInfo;
 struct ExprInfo {
@@ -29,24 +70,41 @@ struct ExprInfo {
                           ** p->pLeft is not the column of any table */
   short int idxRight;     /* p->pRight is a column in this table number. -1 if
                           ** p->pRight is not the column of any table */
-  unsigned prereqLeft;    /* Bitmask of tables referenced by p->pLeft */
-  unsigned prereqRight;   /* Bitmask of tables referenced by p->pRight */
-  unsigned prereqAll;     /* Bitmask of tables referenced by p */
+  Bitmask prereqLeft;     /* Bitmask of tables referenced by p->pLeft */
+  Bitmask prereqRight;    /* Bitmask of tables referenced by p->pRight */
+  Bitmask prereqAll;      /* Bitmask of tables referenced by p */
 };
 
 /*
 ** An instance of the following structure keeps track of a mapping
-** between VDBE cursor numbers and bitmasks.  The VDBE cursor numbers
-** are small integers contained in SrcList_item.iCursor and Expr.iTable
-** fields.  For any given WHERE clause, we want to track which cursors
-** are being used, so we assign a single bit in a 32-bit word to track
-** that cursor.  Then a 32-bit integer is able to show the set of all
-** cursors being used.
+** between VDBE cursor numbers and bits of the bitmasks in ExprInfo.
+**
+** The VDBE cursor numbers are small integers contained in 
+** SrcList_item.iCursor and Expr.iTable fields.  For any given WHERE 
+** clause, the cursor numbers might not begin with 0 and they might
+** contain gaps in the numbering sequence.  But we want to make maximum
+** use of the bits in our bitmasks.  This structure provides a mapping
+** from the sparse cursor numbers into consecutive integers beginning
+** with 0.
+**
+** If ExprMaskSet.ix[A]==B it means that The A-th bit of a Bitmask
+** corresponds VDBE cursor number B.  The A-th bit of a bitmask is 1<<A.
+**
+** For example, if the WHERE clause expression used these VDBE
+** cursors:  4, 5, 8, 29, 57, 73.  Then the  ExprMaskSet structure
+** would map those cursor numbers into bits 0 through 5.
+**
+** Note that the mapping is not necessarily ordered.  In the example
+** above, the mapping might go like this:  4->3, 5->1, 8->2, 29->0,
+** 57->5, 73->4.  Or one of 719 other combinations might be used. It
+** does not really matter.  What is important is that sparse cursor
+** numbers all get mapped into bit numbers that begin with 0 and contain
+** no gaps.
 */
 typedef struct ExprMaskSet ExprMaskSet;
 struct ExprMaskSet {
-  int n;          /* Number of assigned cursor values */
-  int ix[31];     /* Cursor assigned to each bit */
+  int n;                        /* Number of assigned cursor values */
+  int ix[sizeof(Bitmask)*8];    /* Cursor assigned to each bit */
 };
 
 /*
@@ -55,13 +113,21 @@ struct ExprMaskSet {
 #define ARRAYSIZE(X)  (sizeof(X)/sizeof(X[0]))
 
 /*
-** This routine is used to divide the WHERE expression into subexpressions
-** separated by the AND operator.
+** This routine identifies subexpressions in the WHERE clause where
+** each subexpression is separate by the AND operator.  aSlot is 
+** filled with pointers to the subexpressions.  For example:
+**
+**    WHERE  a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22)
+**           \________/     \_______________/     \________________/
+**            slot[0]            slot[1]               slot[2]
+**
+** The original WHERE clause in pExpr is unaltered.  All this routine
+** does is make aSlot[] entries point to substructure within pExpr.
 **
-** aSlot[] is an array of subexpressions structures.
-** There are nSlot spaces left in this array.  This routine attempts to
-** split pExpr into subexpressions and fills aSlot[] with those subexpressions.
-** The return value is the number of slots filled.
+** aSlot[] is an array of subexpressions structures.  There are nSlot
+** spaces left in this array.  This routine finds as many AND-separated
+** subexpressions as it can and puts pointers to those subexpressions
+** into aSlot[] entries.  The return value is the number of slots filled.
 */
 static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){
   int cnt = 0;
@@ -86,22 +152,28 @@ static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){
 #define initMaskSet(P)  memset(P, 0, sizeof(*P))
 
 /*
-** Return the bitmask for the given cursor.  Assign a new bitmask
-** if this is the first time the cursor has been seen.
+** Return the bitmask for the given cursor number.  Return 0 if
+** iCursor is not in the set.
 */
-static int getMask(ExprMaskSet *pMaskSet, int iCursor){
+static Bitmask getMask(ExprMaskSet *pMaskSet, int iCursor){
   int i;
   for(i=0; i<pMaskSet->n; i++){
-    if( pMaskSet->ix[i]==iCursor ) return 1<<i;
-  }
-  if( i==pMaskSet->n && i<ARRAYSIZE(pMaskSet->ix) ){
-    pMaskSet->n++;
-    pMaskSet->ix[i] = iCursor;
-    return 1<<i;
+    if( pMaskSet->ix[i]==iCursor ){
+      return ((Bitmask)1)<<i;
+    }
   }
   return 0;
 }
 
+/*
+** Create a new mask for cursor iCursor.
+*/
+static void createMask(ExprMaskSet *pMaskSet, int iCursor){
+  if( pMaskSet->n<ARRAYSIZE(pMaskSet->ix) ){
+    pMaskSet->ix[pMaskSet->n++] = iCursor;
+  }
+}
+
 /*
 ** Destroy an expression mask set
 */
@@ -113,30 +185,39 @@ static int getMask(ExprMaskSet *pMaskSet, int iCursor){
 ** tree.
 **
 ** In order for this routine to work, the calling function must have
-** previously invoked sqlite3ExprResolveIds() on the expression.  See
+** previously invoked sqlite3ExprResolveNames() on the expression.  See
 ** the header comment on that routine for additional information.
-** The sqlite3ExprResolveIds() routines looks for column names and
+** The sqlite3ExprResolveNames() routines looks for column names and
 ** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
 ** the VDBE cursor number of the table.
 */
-static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
-  unsigned int mask = 0;
+static Bitmask exprListTableUsage(ExprMaskSet *, ExprList *);
+static Bitmask exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
+  Bitmask mask = 0;
   if( p==0 ) return 0;
   if( p->op==TK_COLUMN ){
     mask = getMask(pMaskSet, p->iTable);
-    if( mask==0 ) mask = -1;
     return mask;
   }
-  if( p->pRight ){
-    mask = exprTableUsage(pMaskSet, p->pRight);
+  mask = exprTableUsage(pMaskSet, p->pRight);
+  mask |= exprTableUsage(pMaskSet, p->pLeft);
+  mask |= exprListTableUsage(pMaskSet, p->pList);
+  if( p->pSelect ){
+    Select *pS = p->pSelect;
+    mask |= exprListTableUsage(pMaskSet, pS->pEList);
+    mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
+    mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
+    mask |= exprTableUsage(pMaskSet, pS->pWhere);
+    mask |= exprTableUsage(pMaskSet, pS->pHaving);
   }
-  if( p->pLeft ){
-    mask |= exprTableUsage(pMaskSet, p->pLeft);
-  }
-  if( p->pList ){
-    int i;
-    for(i=0; i<p->pList->nExpr; i++){
-      mask |= exprTableUsage(pMaskSet, p->pList->a[i].pExpr);
+  return mask;
+}
+static Bitmask exprListTableUsage(ExprMaskSet *pMaskSet, ExprList *pList){
+  int i;
+  Bitmask mask = 0;
+  if( pList ){
+    for(i=0; i<pList->nExpr; i++){
+      mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr);
     }
   }
   return mask;
@@ -144,7 +225,7 @@ static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
 
 /*
 ** Return TRUE if the given operator is one of the operators that is
-** allowed for an indexable WHERE clause.  The allowed operators are
+** allowed for an indexable WHERE clause term.  The allowed operators are
 ** "=", "<", ">", "<=", ">=", and "IN".
 */
 static int allowedOp(int op){
@@ -153,7 +234,7 @@ static int allowedOp(int op){
 }
 
 /*
-** Swap two integers.
+** Swap two objects of type T.
 */
 #define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
 
@@ -168,8 +249,9 @@ static int allowedOp(int op){
 */
 static int tableOrder(SrcList *pList, int iCur){
   int i;
-  for(i=0; i<pList->nSrc; i++){
-    if( pList->a[i].iCursor==iCur ) return i;
+  struct SrcList_item *pItem;
+  for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
+    if( pItem->iCursor==iCur ) return i;
   }
   return -1;
 }
@@ -228,98 +310,123 @@ static void exprAnalyze(SrcList *pSrc, ExprMaskSet *pMaskSet, ExprInfo *pInfo){
 }
 
 /*
+** This routine decides if pIdx can be used to satisfy the ORDER BY
+** clause.  If it can, it returns 1.  If pIdx cannot satisfy the
+** ORDER BY clause, this routine returns 0.
+**
 ** pOrderBy is an ORDER BY clause from a SELECT statement.  pTab is the
 ** left-most table in the FROM clause of that same SELECT statement and
-** the table has a cursor number of "base".
-**
-** This routine attempts to find an index for pTab that generates the
-** correct record sequence for the given ORDER BY clause.  The return value
-** is a pointer to an index that does the job.  NULL is returned if the
-** table has no index that will generate the correct sort order.
+** the table has a cursor number of "base".  pIdx is an index on pTab.
 **
-** If there are two or more indices that generate the correct sort order
-** and pPreferredIdx is one of those indices, then return pPreferredIdx.
+** nEqCol is the number of columns of pIdx that are used as equality
+** constraints.  Any of these columns may be missing from the ORDER BY
+** clause and the match can still be a success.
 **
-** nEqCol is the number of columns of pPreferredIdx that are used as
-** equality constraints.  Any index returned must have exactly this same
-** set of columns.  The ORDER BY clause only matches index columns beyond the
-** the first nEqCol columns.
+** If the index is UNIQUE, then the ORDER BY clause is allowed to have
+** additional terms past the end of the index and the match will still
+** be a success.
 **
-** All terms of the ORDER BY clause must be either ASC or DESC.  The
-** *pbRev value is set to 1 if the ORDER BY clause is all DESC and it is
-** set to 0 if the ORDER BY clause is all ASC.
+** All terms of the ORDER BY that match against the index must be either
+** ASC or DESC.  (Terms of the ORDER BY clause past the end of a UNIQUE
+** index do not need to satisfy this constraint.)  The *pbRev value is
+** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if
+** the ORDER BY clause is all ASC.
 */
-static Index *findSortingIndex(
-  Parse *pParse,
+static int isSortingIndex(
+  Parse *pParse,          /* Parsing context */
+  Index *pIdx,            /* The index we are testing */
   Table *pTab,            /* The table to be sorted */
   int base,               /* Cursor number for pTab */
   ExprList *pOrderBy,     /* The ORDER BY clause */
-  Index *pPreferredIdx,   /* Use this index, if possible and not NULL */
-  int nEqCol,             /* Number of index columns used with == constraints */
+  int nEqCol,             /* Number of index columns with == constraints */
   int *pbRev              /* Set to 1 if ORDER BY is DESC */
 ){
-  int i, j;
-  Index *pMatch;
-  Index *pIdx;
-  int sortOrder;
+  int i, j;                    /* Loop counters */
+  int sortOrder;               /* Which direction we are sorting */
+  int nTerm;                   /* Number of ORDER BY terms */
+  struct ExprList_item *pTerm; /* A term of the ORDER BY clause */
   sqlite3 *db = pParse->db;
 
   assert( pOrderBy!=0 );
-  assert( pOrderBy->nExpr>0 );
-  sortOrder = pOrderBy->a[0].sortOrder;
-  for(i=0; i<pOrderBy->nExpr; i++){
-    Expr *p;
-    if( pOrderBy->a[i].sortOrder!=sortOrder ){
-      /* Indices can only be used if all ORDER BY terms are either
-      ** DESC or ASC.  Indices cannot be used on a mixture. */
-      return 0;
-    }
-    p = pOrderBy->a[i].pExpr;
-    if( p->op!=TK_COLUMN || p->iTable!=base ){
+  nTerm = pOrderBy->nExpr;
+  assert( nTerm>0 );
+
+  /* Match terms of the ORDER BY clause against columns of
+  ** the index.
+  */
+  for(i=j=0, pTerm=pOrderBy->a; j<nTerm && i<pIdx->nColumn; i++){
+    Expr *pExpr;       /* The expression of the ORDER BY pTerm */
+    CollSeq *pColl;    /* The collating sequence of pExpr */
+
+    pExpr = pTerm->pExpr;
+    if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){
       /* Can not use an index sort on anything that is not a column in the
       ** left-most table of the FROM clause */
       return 0;
     }
-  }
-
-  /* If we get this far, it means the ORDER BY clause consists only of
-  ** ascending columns in the left-most table of the FROM clause.  Now
-  ** check for a matching index.
-  */
-  pMatch = 0;
-  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
-    int nExpr = pOrderBy->nExpr;
-    if( pIdx->nColumn < nEqCol || pIdx->nColumn < nExpr ) continue;
-    for(i=j=0; i<nEqCol; i++){
-      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pOrderBy->a[j].pExpr);
-      if( !pColl ) pColl = db->pDfltColl;
-      if( pPreferredIdx->aiColumn[i]!=pIdx->aiColumn[i] ) break;
-      if( pPreferredIdx->keyInfo.aColl[i]!=pIdx->keyInfo.aColl[i] ) break;
-      if( j<nExpr && 
-          pOrderBy->a[j].pExpr->iColumn==pIdx->aiColumn[i] &&
-          pColl==pIdx->keyInfo.aColl[i]
-      ){ 
-        j++; 
+    pColl = sqlite3ExprCollSeq(pParse, pExpr);
+    if( !pColl ) pColl = db->pDfltColl;
+    if( pExpr->iColumn!=pIdx->aiColumn[i] || pColl!=pIdx->keyInfo.aColl[i] ){
+      /* Term j of the ORDER BY clause does not match column i of the index */
+      if( i<nEqCol ){
+        /* If an index column that is constrained by == fails to match an
+        ** ORDER BY term, that is OK.  Just ignore that column of the index
+        */
+        continue;
+      }else{
+        /* If an index column fails to match and is not constrained by ==
+        ** then the index cannot satisfy the ORDER BY constraint.
+        */
+        return 0;
       }
     }
-    if( i<nEqCol ) continue;
-    for(i=0; i+j<nExpr; i++){
-      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pOrderBy->a[i+j].pExpr);
-      if( !pColl ) pColl = db->pDfltColl;
-      if( pOrderBy->a[i+j].pExpr->iColumn!=pIdx->aiColumn[i+nEqCol] ||
-          pColl!=pIdx->keyInfo.aColl[i+nEqCol] ) break;
-    }
-    if( i+j>=nExpr ){
-      pMatch = pIdx;
-      if( pIdx==pPreferredIdx ) break;
+    if( i>nEqCol ){
+      if( pTerm->sortOrder!=sortOrder ){
+        /* Indices can only be used if all ORDER BY terms past the
+        ** equality constraints are all either DESC or ASC. */
+        return 0;
+      }
+    }else{
+      sortOrder = pTerm->sortOrder;
     }
+    j++;
+    pTerm++;
   }
-  if( pMatch && pbRev ){
+
+  /* The index can be used for sorting if all terms of the ORDER BY clause
+  ** or covered or if we ran out of index columns and the it is a UNIQUE
+  ** index.
+  */
+  if( j>=nTerm || (i>=pIdx->nColumn && pIdx->onError!=OE_None) ){
     *pbRev = sortOrder==SQLITE_SO_DESC;
+    return 1;
+  }
+  return 0;
+}
+
+/*
+** Check table to see if the ORDER BY clause in pOrderBy can be satisfied
+** by sorting in order of ROWID.  Return true if so and set *pbRev to be
+** true for reverse ROWID and false for forward ROWID order.
+*/
+static int sortableByRowid(
+  int base,               /* Cursor number for table to be sorted */
+  ExprList *pOrderBy,     /* The ORDER BY clause */
+  int *pbRev              /* Set to 1 if ORDER BY is DESC */
+){
+  Expr *p;
+
+  assert( pOrderBy!=0 );
+  assert( pOrderBy->nExpr>0 );
+  p = pOrderBy->a[0].pExpr;
+  if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1 ){
+    *pbRev = pOrderBy->a[0].sortOrder;
+    return 1;
   }
-  return pMatch;
+  return 0;
 }
 
+
 /*
 ** Disable a term in the WHERE clause.  Except, do not disable the term
 ** if it controls a LEFT OUTER JOIN and it did not originate in the ON
@@ -331,7 +438,7 @@ static Index *findSortingIndex(
 **   (2)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
 **   (3)  SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
 **
-** The t2.z='ok' is disabled in the in (2) because it did not originate
+** The t2.z='ok' is disabled in the in (2) because it originates
 ** in the ON clause.  The term is disabled in (3) because it is not part
 ** of a LEFT OUTER JOIN.  In (1), the term is not disabled.
 **
@@ -382,22 +489,33 @@ static void codeEqualityTerm(
   if( pX->op!=TK_IN ){
     assert( pX->op==TK_EQ );
     sqlite3ExprCode(pParse, pX->pRight);
+#ifndef SQLITE_OMIT_SUBQUERY
   }else{
-    int iTab = pX->iTable;
+    int iTab;
     Vdbe *v = pParse->pVdbe;
+
+    sqlite3CodeSubselect(pParse, pX);
+    iTab = pX->iTable;
     sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk);
     sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1);
-    pLevel->inP2 = sqlite3VdbeAddOp(v, OP_IdxColumn, iTab, 0);
+    VdbeComment((v, "# %.*s", pX->span.n, pX->span.z));
+    pLevel->inP2 = sqlite3VdbeAddOp(v, OP_Column, iTab, 0);
     pLevel->inOp = OP_Next;
     pLevel->inP1 = iTab;
+#endif
   }
   disableTerm(pLevel, &pTerm->p);
 }
 
+/*
+** The number of bits in a Bitmask
+*/
+#define BMS  (sizeof(Bitmask)*8-1)
+
 
 /*
 ** Generate the beginning of the loop used for WHERE clause processing.
-** The return value is a pointer to an (opaque) structure that contains
+** The return value is a pointer to an opaque structure that contains
 ** information needed to terminate the loop.  Later, the calling routine
 ** should invoke sqlite3WhereEnd() with the return value of this function
 ** in order to complete the WHERE clause processing.
@@ -426,6 +544,11 @@ static void codeEqualityTerm(
 ** And so forth.  This routine generates code to open those VDBE cursors
 ** and sqlite3WhereEnd() generates the code to close them.
 **
+** The code that sqlite3WhereBegin() generates leaves the cursors named
+** in pTabList pointing at their appropriate entries.  The [...] code
+** can use OP_Column and OP_Recno opcodes on these cursors to extract
+** data from the various tables of the loop.
+**
 ** If the WHERE clause is empty, the foreach loops must each scan their
 ** entire tables.  Thus a three-way join is an O(N^3) operation.  But if
 ** the tables have indices and there are terms in the WHERE clause that
@@ -473,30 +596,35 @@ static void codeEqualityTerm(
 ** output order, then the *ppOrderBy is unchanged.
 */
 WhereInfo *sqlite3WhereBegin(
-  Parse *pParse,       /* The parser context */
-  SrcList *pTabList,   /* A list of all tables to be scanned */
-  Expr *pWhere,        /* The WHERE clause */
-  int pushKey,         /* If TRUE, leave the table key on the stack */
-  ExprList **ppOrderBy /* An ORDER BY clause, or NULL */
+  Parse *pParse,        /* The parser context */
+  SrcList *pTabList,    /* A list of all tables to be scanned */
+  Expr *pWhere,         /* The WHERE clause */
+  ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
+  Fetch *pFetch         /* Initial location of cursors.  NULL otherwise */
 ){
   int i;                     /* Loop counter */
   WhereInfo *pWInfo;         /* Will become the return value of this function */
   Vdbe *v = pParse->pVdbe;   /* The virtual database engine */
   int brk, cont = 0;         /* Addresses used during code generation */
   int nExpr;           /* Number of subexpressions in the WHERE clause */
-  int loopMask;        /* One bit set for each outer loop */
-  int haveKey = 0;     /* True if KEY is on the stack */
+  Bitmask loopMask;    /* One bit set for each outer loop */
   ExprInfo *pTerm;     /* A single term in the WHERE clause; ptr to aExpr[] */
   ExprMaskSet maskSet; /* The expression mask set */
-  int iDirectEq[32];   /* Term of the form ROWID==X for the N-th table */
-  int iDirectLt[32];   /* Term of the form ROWID<X or ROWID<=X */
-  int iDirectGt[32];   /* Term of the form ROWID>X or ROWID>=X */
+  int iDirectEq[BMS];  /* Term of the form ROWID==X for the N-th table */
+  int iDirectLt[BMS];  /* Term of the form ROWID<X or ROWID<=X */
+  int iDirectGt[BMS];  /* Term of the form ROWID>X or ROWID>=X */
   ExprInfo aExpr[101]; /* The WHERE clause is divided into these terms */
+  struct SrcList_item *pTabItem;  /* A single entry from pTabList */
+  WhereLevel *pLevel;             /* A single level in the pWInfo list */
 
-  /* pushKey is only allowed if there is a single table (as in an INSERT or
-  ** UPDATE statement)
+  /* The number of terms in the FROM clause is limited by the number of
+  ** bits in a Bitmask 
   */
-  assert( pushKey==0 || pTabList->nSrc==1 );
+  if( pTabList->nSrc>sizeof(Bitmask)*8 ){
+    sqlite3ErrorMsg(pParse, "at most %d tables in a join",
+       sizeof(Bitmask)*8);
+    return 0;
+  }
 
   /* Split the WHERE clause into separate subexpressions where each
   ** subexpression is separated by an AND operator.  If the aExpr[]
@@ -511,7 +639,7 @@ WhereInfo *sqlite3WhereBegin(
        "than %d terms allowed", (int)ARRAYSIZE(aExpr)-1);
     return 0;
   }
-  
+    
   /* Allocate and initialize the WhereInfo structure that will become the
   ** return value.
   */
@@ -534,28 +662,11 @@ WhereInfo *sqlite3WhereBegin(
 
   /* Analyze all of the subexpressions.
   */
+  for(i=0; i<pTabList->nSrc; i++){
+    createMask(&maskSet, pTabList->a[i].iCursor);
+  }
   for(pTerm=aExpr, i=0; i<nExpr; i++, pTerm++){
-    TriggerStack *pStack;
     exprAnalyze(pTabList, &maskSet, pTerm);
-
-    /* If we are executing a trigger body, remove all references to
-    ** new.* and old.* tables from the prerequisite masks.
-    */
-    if( (pStack = pParse->trigStack)!=0 ){
-      int x;
-      if( (x=pStack->newIdx) >= 0 ){
-        int mask = ~getMask(&maskSet, x);
-        pTerm->prereqRight &= mask;
-        pTerm->prereqLeft &= mask;
-        pTerm->prereqAll &= mask;
-      }
-      if( (x=pStack->oldIdx) >= 0 ){
-        int mask = ~getMask(&maskSet, x);
-        pTerm->prereqRight &= mask;
-        pTerm->prereqLeft &= mask;
-        pTerm->prereqAll &= mask;
-      }
-    }
   }
 
   /* Figure out what index to use (if any) for each nested loop.
@@ -575,15 +686,17 @@ WhereInfo *sqlite3WhereBegin(
   ** to the limit of 32 bits in an integer bitmask.
   */
   loopMask = 0;
-  for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++){
+  pTabItem = pTabList->a;
+  pLevel = pWInfo->a;
+  for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++,pTabItem++,pLevel++){
     int j;
-    WhereLevel *pLevel = &pWInfo->a[i];
-    int iCur = pTabList->a[i].iCursor;    /* The cursor for this table */
-    int mask = getMask(&maskSet, iCur);   /* Cursor mask for this table */
-    Table *pTab = pTabList->a[i].pTab;
+    int iCur = pTabItem->iCursor;            /* The cursor for this table */
+    Bitmask mask = getMask(&maskSet, iCur);  /* Cursor mask for this table */
+    Table *pTab = pTabItem->pTab;
     Index *pIdx;
     Index *pBestIdx = 0;
     int bestScore = 0;
+    int bestRev = 0;
 
     /* Check to see if there is an expression that uses only the
     ** ROWID field of this table.  For terms of the form ROWID==expr
@@ -593,7 +706,7 @@ WhereInfo *sqlite3WhereBegin(
     **
     ** (Added:) Treat ROWID IN expr like ROWID=expr.
     */
-    pLevel->iCur = -1;
+    pLevel->iIdxCur = -1;
     iDirectEq[i] = -1;
     iDirectLt[i] = -1;
     iDirectGt[i] = -1;
@@ -611,6 +724,12 @@ WhereInfo *sqlite3WhereBegin(
         }
       }
     }
+
+    /* If we found a term that tests ROWID with == or IN, that term
+    ** will be used to locate the rows in the database table.  There
+    ** is not need to continue into the code below that looks for
+    ** an index.  We will always use the ROWID over an index.
+    */
     if( iDirectEq[i]>=0 ){
       loopMask |= mask;
       pLevel->pIdx = 0;
@@ -621,19 +740,28 @@ WhereInfo *sqlite3WhereBegin(
     ** the "best" index.  pBestIdx is left set to NULL if no indices
     ** are usable.
     **
-    ** The best index is determined as follows.  For each of the
+    ** The best index is the one with the highest score.  The score
+    ** for the index is determined as follows.  For each of the
     ** left-most terms that is fixed by an equality operator, add
-    ** 8 to the score.  The right-most term of the index may be
-    ** constrained by an inequality.  Add 1 if for an "x<..." constraint
-    ** and add 2 for an "x>..." constraint.  Chose the index that
-    ** gives the best score.
+    ** 32 to the score.  The right-most term of the index may be
+    ** constrained by an inequality.  Add 4 if for an "x<..." constraint
+    ** and add 8 for an "x>..." constraint.  If both constraints
+    ** are present, add 12.
+    **
+    ** If the left-most term of the index uses an IN operator
+    ** (ex:  "x IN (...)")  then add 16 to the score.
+    **
+    ** If an index can be used for sorting, add 2 to the score.
+    ** If an index contains all the terms of a table that are ever
+    ** used by any expression in the SQL statement, then add 1 to
+    ** the score.
     **
     ** This scoring system is designed so that the score can later be
-    ** used to determine how the index is used.  If the score&7 is 0
-    ** then all constraints are equalities.  If score&1 is not 0 then
+    ** used to determine how the index is used.  If the score&0x1c is 0
+    ** then all constraints are equalities.  If score&0x4 is not 0 then
     ** there is an inequality used as a termination key.  (ex: "x<...")
-    ** If score&2 is not 0 then there is an inequality used as the
-    ** start key.  (ex: "x>...").  A score or 4 is the special case
+    ** If score&0x8 is not 0 then there is an inequality used as the
+    ** start key.  (ex: "x>...").  A score or 0x10 is the special case
     ** of an IN operator constraint.  (ex:  "x IN ...").
     **
     ** The IN operator (as in "<expr> IN (...)") is treated the same as
@@ -643,13 +771,16 @@ WhereInfo *sqlite3WhereBegin(
     ** other columns of the index.
     */
     for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
-      int eqMask = 0;  /* Index columns covered by an x=... term */
-      int ltMask = 0;  /* Index columns covered by an x<... term */
-      int gtMask = 0;  /* Index columns covered by an x>... term */
-      int inMask = 0;  /* Index columns covered by an x IN .. term */
-      int nEq, m, score;
+      Bitmask eqMask = 0;  /* Index columns covered by an x=... term */
+      Bitmask ltMask = 0;  /* Index columns covered by an x<... term */
+      Bitmask gtMask = 0;  /* Index columns covered by an x>... term */
+      Bitmask inMask = 0;  /* Index columns covered by an x IN .. term */
+      Bitmask m;
+      int nEq, score, bRev = 0;
 
-      if( pIdx->nColumn>32 ) continue;  /* Ignore indices too many columns */
+      if( pIdx->nColumn>sizeof(eqMask)*8 ){
+        continue;  /* Ignore indices with too many columns to analyze */
+      }
       for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){
         Expr *pX = pTerm->p;
         CollSeq *pColl = sqlite3ExprCollSeq(pParse, pX->pLeft);
@@ -676,17 +807,17 @@ WhereInfo *sqlite3WhereBegin(
                   break;
                 }
                 case TK_EQ: {
-                  eqMask |= 1<<k;
+                  eqMask |= ((Bitmask)1)<<k;
                   break;
                 }
                 case TK_LE:
                 case TK_LT: {
-                  ltMask |= 1<<k;
+                  ltMask |= ((Bitmask)1)<<k;
                   break;
                 }
                 case TK_GE:
                 case TK_GT: {
-                  gtMask |= 1<<k;
+                  gtMask |= ((Bitmask)1)<<k;
                   break;
                 }
                 default: {
@@ -705,25 +836,58 @@ WhereInfo *sqlite3WhereBegin(
       ** on the left of the index with == constraints.
       */
       for(nEq=0; nEq<pIdx->nColumn; nEq++){
-        m = (1<<(nEq+1))-1;
+        m = (((Bitmask)1)<<(nEq+1))-1;
         if( (m & eqMask)!=m ) break;
       }
-      score = nEq*8;   /* Base score is 8 times number of == constraints */
-      m = 1<<nEq;
-      if( m & ltMask ) score++;    /* Increase score for a < constraint */
-      if( m & gtMask ) score+=2;   /* Increase score for a > constraint */
-      if( score==0 && inMask ) score = 4;  /* Default score for IN constraint */
+
+      /* Begin assemblying the score
+      */
+      score = nEq*32;   /* Base score is 32 times number of == constraints */
+      m = ((Bitmask)1)<<nEq;
+      if( m & ltMask ) score+=4;    /* Increase score for a < constraint */
+      if( m & gtMask ) score+=8;    /* Increase score for a > constraint */
+      if( score==0 && inMask ) score = 16; /* Default score for IN constraint */
+
+      /* Give bonus points if this index can be used for sorting
+      */
+      if( i==0 && score!=16 && ppOrderBy && *ppOrderBy ){
+        int base = pTabList->a[0].iCursor;
+        if( isSortingIndex(pParse, pIdx, pTab, base, *ppOrderBy, nEq, &bRev) ){
+          score += 2;
+        }
+      }
+
+      /* Check to see if we can get away with using just the index without
+      ** ever reading the table.  If that is the case, then add one bonus
+      ** point to the score.
+      */
+      if( score && pTabItem->colUsed < (((Bitmask)1)<<(BMS-1)) ){
+        for(m=0, j=0; j<pIdx->nColumn; j++){
+          int x = pIdx->aiColumn[j];
+          if( x<BMS-1 ){
+            m |= ((Bitmask)1)<<x;
+          }
+        }
+        if( (pTabItem->colUsed & m)==pTabItem->colUsed ){
+          score++;
+        }
+      }
+
+      /* If the score for this index is the best we have seen so far, then
+      ** save it
+      */
       if( score>bestScore ){
         pBestIdx = pIdx;
         bestScore = score;
+        bestRev = bRev;
       }
     }
     pLevel->pIdx = pBestIdx;
     pLevel->score = bestScore;
-    pLevel->bRev = 0;
+    pLevel->bRev = bestRev;
     loopMask |= mask;
     if( pBestIdx ){
-      pLevel->iCur = pParse->nTab++;
+      pLevel->iIdxCur = pParse->nTab++;
     }
   }
 
@@ -731,65 +895,88 @@ WhereInfo *sqlite3WhereBegin(
   ** use of an index on the first table.
   */
   if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){
-     Index *pSortIdx;
-     Index *pIdx;
-     Table *pTab;
-     int bRev = 0;
-
-     pTab = pTabList->a[0].pTab;
-     pIdx = pWInfo->a[0].pIdx;
-     if( pIdx && pWInfo->a[0].score==4 ){
-       /* If there is already an IN index on the left-most table,
-       ** it will not give the correct sort order.
-       ** So, pretend that no suitable index is found.
-       */
-       pSortIdx = 0;
-     }else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ){
-       /* If the left-most column is accessed using its ROWID, then do
-       ** not try to sort by index.
-       */
-       pSortIdx = 0;
-     }else{
-       int nEqCol = (pWInfo->a[0].score+4)/8;
-       pSortIdx = findSortingIndex(pParse, pTab, pTabList->a[0].iCursor, 
-                                   *ppOrderBy, pIdx, nEqCol, &bRev);
-     }
-     if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){
-       if( pIdx==0 ){
-         pWInfo->a[0].pIdx = pSortIdx;
-         pWInfo->a[0].iCur = pParse->nTab++;
-       }
-       pWInfo->a[0].bRev = bRev;
-       *ppOrderBy = 0;
-     }
+    Index *pIdx;             /* Index derived from the WHERE clause */
+    Table *pTab;             /* Left-most table in the FROM clause */
+    int bRev = 0;            /* True to reverse the output order */
+    int iCur;                /* Btree-cursor that will be used by pTab */
+    WhereLevel *pLevel0 = &pWInfo->a[0];
+
+    pTab = pTabList->a[0].pTab;
+    pIdx = pLevel0->pIdx;
+    iCur = pTabList->a[0].iCursor;
+    if( pIdx==0 && sortableByRowid(iCur, *ppOrderBy, &bRev) ){
+      /* The ORDER BY clause specifies ROWID order, which is what we
+      ** were going to be doing anyway...
+      */
+      *ppOrderBy = 0;
+      pLevel0->bRev = bRev;
+    }else if( pLevel0->score==16 ){
+      /* If there is already an IN index on the left-most table,
+      ** it will not give the correct sort order.
+      ** So, pretend that no suitable index is found.
+      */
+    }else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ){
+      /* If the left-most column is accessed using its ROWID, then do
+      ** not try to sort by index.  But do delete the ORDER BY clause
+      ** if it is redundant.
+      */
+    }else if( (pLevel0->score&2)!=0 ){
+      /* The index that was selected for searching will cause rows to
+      ** appear in sorted order.
+      */
+      *ppOrderBy = 0;
+    }
   }
 
-  /* Open all tables in the pTabList and all indices used by those tables.
+  /* Open all tables in the pTabList and any indices selected for
+  ** searching those tables.
   */
   sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
-  for(i=0; i<pTabList->nSrc; i++){
+  pLevel = pWInfo->a;
+  for(i=0, pTabItem=pTabList->a; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
     Table *pTab;
     Index *pIx;
+    int iIdxCur = pLevel->iIdxCur;
 
-    pTab = pTabList->a[i].pTab;
+    pTab = pTabItem->pTab;
     if( pTab->isTransient || pTab->pSelect ) continue;
-    sqlite3OpenTableForReading(v, pTabList->a[i].iCursor, pTab);
-    sqlite3CodeVerifySchema(pParse, pTab->iDb);
-    if( (pIx = pWInfo->a[i].pIdx)!=0 ){
+    if( (pLevel->score & 1)==0 ){
+      sqlite3OpenTableForReading(v, pTabItem->iCursor, pTab);
+    }
+    pLevel->iTabCur = pTabItem->iCursor;
+    if( (pIx = pLevel->pIdx)!=0 ){
       sqlite3VdbeAddOp(v, OP_Integer, pIx->iDb, 0);
-      sqlite3VdbeOp3(v, OP_OpenRead, pWInfo->a[i].iCur, pIx->tnum,
+      sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum,
                      (char*)&pIx->keyInfo, P3_KEYINFO);
     }
+    if( (pLevel->score & 1)!=0 ){
+      sqlite3VdbeAddOp(v, OP_KeyAsData, iIdxCur, 1);
+      sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
+    }
+    sqlite3CodeVerifySchema(pParse, pTab->iDb);
   }
+  pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
 
   /* Generate the code to do the search
   */
   loopMask = 0;
-  for(i=0; i<pTabList->nSrc; i++){
+  pLevel = pWInfo->a;
+  pTabItem = pTabList->a;
+  for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
     int j, k;
-    int iCur = pTabList->a[i].iCursor;
-    Index *pIdx;
-    WhereLevel *pLevel = &pWInfo->a[i];
+    int iCur = pTabItem->iCursor;  /* The VDBE cursor for the table */
+    Index *pIdx;       /* The index we will be using */
+    int iIdxCur;       /* The VDBE cursor for the index */
+    int omitTable;     /* True if we use the index only */
+
+    pIdx = pLevel->pIdx;
+    iIdxCur = pLevel->iIdxCur;
+    pLevel->inOp = OP_Noop;
+
+    /* Check to see if it is appropriate to omit the use of the table
+    ** here and use its index instead.
+    */
+    omitTable = (pLevel->score&1)!=0;
 
     /* If this is the right table of a LEFT OUTER JOIN, allocate and
     ** initialize a memory cell that records if this table matches any
@@ -803,8 +990,6 @@ WhereInfo *sqlite3WhereBegin(
       VdbeComment((v, "# init LEFT JOIN no-match flag"));
     }
 
-    pIdx = pLevel->pIdx;
-    pLevel->inOp = OP_Noop;
     if( i<ARRAYSIZE(iDirectEq) && (k = iDirectEq[i])>=0 ){
       /* Case 1:  We can directly reference a single row using an
       **          equality comparison against the ROWID field.  Or
@@ -815,19 +1000,20 @@ WhereInfo *sqlite3WhereBegin(
       pTerm = &aExpr[k];
       assert( pTerm->p!=0 );
       assert( pTerm->idxLeft==iCur );
+      assert( omitTable==0 );
       brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
       codeEqualityTerm(pParse, pTerm, brk, pLevel);
       cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
       sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk);
-      haveKey = 0;
       sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk);
+      VdbeComment((v, "pk"));
       pLevel->op = OP_Noop;
-    }else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){
+    }else if( pIdx!=0 && pLevel->score>3 && (pLevel->score&0x0c)==0 ){
       /* Case 2:  There is an index and all terms of the WHERE clause that
-      **          refer to the index use the "==" or "IN" operators.
+      **          refer to the index using the "==" or "IN" operators.
       */
       int start;
-      int nColumn = (pLevel->score+4)/8;
+      int nColumn = (pLevel->score+16)/32;
       brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
 
       /* For each column of the index, find the term of the WHERE clause that
@@ -840,6 +1026,7 @@ WhereInfo *sqlite3WhereBegin(
           if( pTerm->idxLeft==iCur
              && (pTerm->prereqRight & loopMask)==pTerm->prereqRight 
              && pX->pLeft->iColumn==pIdx->aiColumn[j]
+             && (pX->op==TK_EQ || pX->op==TK_IN)
           ){
             char idxaff = pIdx->pTable->aCol[pX->pLeft->iColumn].affinity;
             if( sqlite3IndexAffinityOk(pX, idxaff) ){
@@ -861,36 +1048,40 @@ WhereInfo *sqlite3WhereBegin(
       ** iteration of the scan to see if the scan has finished. */
       if( pLevel->bRev ){
         /* Scan in reverse order */
-        sqlite3VdbeAddOp(v, OP_MoveLe, pLevel->iCur, brk);
+        sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, brk);
         start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
-        sqlite3VdbeAddOp(v, OP_IdxLT, pLevel->iCur, brk);
+        sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, brk);
         pLevel->op = OP_Prev;
       }else{
         /* Scan in the forward order */
-        sqlite3VdbeAddOp(v, OP_MoveGe, pLevel->iCur, brk);
+        sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, brk);
         start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
-        sqlite3VdbeOp3(v, OP_IdxGE, pLevel->iCur, brk, "+", P3_STATIC);
+        sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, brk, "+", P3_STATIC);
         pLevel->op = OP_Next;
       }
-      sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
+      sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
       sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
-      sqlite3VdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
-      if( i==pTabList->nSrc-1 && pushKey ){
-        haveKey = 1;
-      }else{
+      if( !omitTable ){
+        sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0);
         sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
-        haveKey = 0;
       }
-      pLevel->p1 = pLevel->iCur;
+      pLevel->p1 = iIdxCur;
       pLevel->p2 = start;
     }else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ){
       /* Case 3:  We have an inequality comparison against the ROWID field.
       */
       int testOp = OP_Noop;
       int start;
+      int bRev = pLevel->bRev;
 
+      assert( omitTable==0 );
       brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
       cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
+      if( bRev ){
+        int t = iDirectGt[i];
+        iDirectGt[i] = iDirectLt[i];
+        iDirectLt[i] = t;
+      }
       if( iDirectGt[i]>=0 ){
         Expr *pX;
         k = iDirectGt[i];
@@ -900,11 +1091,12 @@ WhereInfo *sqlite3WhereBegin(
         assert( pX!=0 );
         assert( pTerm->idxLeft==iCur );
         sqlite3ExprCode(pParse, pX->pRight);
-        sqlite3VdbeAddOp(v, OP_ForceInt, pX->op==TK_LT || pX->op==TK_GT, brk);
-        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, brk);
+        sqlite3VdbeAddOp(v, OP_ForceInt, pX->op==TK_LE || pX->op==TK_GT, brk);
+        sqlite3VdbeAddOp(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk);
+        VdbeComment((v, "pk"));
         disableTerm(pLevel, &pTerm->p);
       }else{
-        sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
+        sqlite3VdbeAddOp(v, bRev ? OP_Last : OP_Rewind, iCur, brk);
       }
       if( iDirectLt[i]>=0 ){
         Expr *pX;
@@ -918,14 +1110,14 @@ WhereInfo *sqlite3WhereBegin(
         pLevel->iMem = pParse->nMem++;
         sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
         if( pX->op==TK_LT || pX->op==TK_GT ){
-          testOp = OP_Ge;
+          testOp = bRev ? OP_Le : OP_Ge;
         }else{
-          testOp = OP_Gt;
+          testOp = bRev ? OP_Lt : OP_Gt;
         }
         disableTerm(pLevel, &pTerm->p);
       }
       start = sqlite3VdbeCurrentAddr(v);
-      pLevel->op = OP_Next;
+      pLevel->op = bRev ? OP_Prev : OP_Next;
       pLevel->p1 = iCur;
       pLevel->p2 = start;
       if( testOp!=OP_Noop ){
@@ -933,21 +1125,27 @@ WhereInfo *sqlite3WhereBegin(
         sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
         sqlite3VdbeAddOp(v, testOp, 0, brk);
       }
-      haveKey = 0;
     }else if( pIdx==0 ){
       /* Case 4:  There is no usable index.  We must do a complete
       **          scan of the entire database table.
       */
       int start;
+      int opRewind;
 
+      assert( omitTable==0 );
       brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
       cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
-      sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
+      if( pLevel->bRev ){
+        opRewind = OP_Last;
+        pLevel->op = OP_Prev;
+      }else{
+        opRewind = OP_Rewind;
+        pLevel->op = OP_Next;
+      }
+      sqlite3VdbeAddOp(v, opRewind, iCur, brk);
       start = sqlite3VdbeCurrentAddr(v);
-      pLevel->op = OP_Next;
       pLevel->p1 = iCur;
       pLevel->p2 = start;
-      haveKey = 0;
     }else{
       /* Case 5: The WHERE clause term that refers to the right-most
       **         column of the index is an inequality.  For example, if
@@ -961,7 +1159,7 @@ WhereInfo *sqlite3WhereBegin(
       **         to force the output order to conform to an ORDER BY.
       */
       int score = pLevel->score;
-      int nEqColumn = score/8;
+      int nEqColumn = score/32;
       int start;
       int leFlag=0, geFlag=0;
       int testOp;
@@ -1005,7 +1203,7 @@ WhereInfo *sqlite3WhereBegin(
       ** 2002-Dec-04: On a reverse-order scan, the so-called "termination"
       ** key computed here really ends up being the start key.
       */
-      if( (score & 1)!=0 ){
+      if( (score & 4)!=0 ){
         for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){
           Expr *pX = pTerm->p;
           if( pX==0 ) continue;
@@ -1026,17 +1224,17 @@ WhereInfo *sqlite3WhereBegin(
         leFlag = 1;
       }
       if( testOp!=OP_Noop ){
-        int nCol = nEqColumn + (score & 1);
+        int nCol = nEqColumn + ((score & 4)!=0);
         pLevel->iMem = pParse->nMem++;
         buildIndexProbe(v, nCol, brk, pIdx);
         if( pLevel->bRev ){
           int op = leFlag ? OP_MoveLe : OP_MoveLt;
-          sqlite3VdbeAddOp(v, op, pLevel->iCur, brk);
+          sqlite3VdbeAddOp(v, op, iIdxCur, brk);
         }else{
           sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
         }
       }else if( pLevel->bRev ){
-        sqlite3VdbeAddOp(v, OP_Last, pLevel->iCur, brk);
+        sqlite3VdbeAddOp(v, OP_Last, iIdxCur, brk);
       }
 
       /* Generate the start key.  This is the key that defines the lower
@@ -1048,7 +1246,7 @@ WhereInfo *sqlite3WhereBegin(
       ** 2002-Dec-04: In the case of a reverse-order search, the so-called
       ** "start" key really ends up being used as the termination key.
       */
-      if( (score & 2)!=0 ){
+      if( (score & 8)!=0 ){
         for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){
           Expr *pX = pTerm->p;
           if( pX==0 ) continue;
@@ -1066,8 +1264,8 @@ WhereInfo *sqlite3WhereBegin(
       }else{
         geFlag = 1;
       }
-      if( nEqColumn>0 || (score&2)!=0 ){
-        int nCol = nEqColumn + ((score&2)!=0);
+      if( nEqColumn>0 || (score&8)!=0 ){
+        int nCol = nEqColumn + ((score&8)!=0);
         buildIndexProbe(v, nCol, brk, pIdx);
         if( pLevel->bRev ){
           pLevel->iMem = pParse->nMem++;
@@ -1075,12 +1273,12 @@ WhereInfo *sqlite3WhereBegin(
           testOp = OP_IdxLT;
         }else{
           int op = geFlag ? OP_MoveGe : OP_MoveGt;
-          sqlite3VdbeAddOp(v, op, pLevel->iCur, brk);
+          sqlite3VdbeAddOp(v, op, iIdxCur, brk);
         }
       }else if( pLevel->bRev ){
         testOp = OP_Noop;
       }else{
-        sqlite3VdbeAddOp(v, OP_Rewind, pLevel->iCur, brk);
+        sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, brk);
       }
 
       /* Generate the the top of the loop.  If there is a termination
@@ -1090,25 +1288,22 @@ WhereInfo *sqlite3WhereBegin(
       start = sqlite3VdbeCurrentAddr(v);
       if( testOp!=OP_Noop ){
         sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
-        sqlite3VdbeAddOp(v, testOp, pLevel->iCur, brk);
+        sqlite3VdbeAddOp(v, testOp, iIdxCur, brk);
         if( (leFlag && !pLevel->bRev) || (!geFlag && pLevel->bRev) ){
           sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
         }
       }
-      sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
-      sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + (score & 1), cont);
-      sqlite3VdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
-      if( i==pTabList->nSrc-1 && pushKey ){
-        haveKey = 1;
-      }else{
+      sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
+      sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + ((score&4)!=0), cont);
+      if( !omitTable ){
+        sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0);
         sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
-        haveKey = 0;
       }
 
       /* Record the instruction used to terminate the loop.
       */
       pLevel->op = pLevel->bRev ? OP_Prev : OP_Next;
-      pLevel->p1 = pLevel->iCur;
+      pLevel->p1 = iIdxCur;
       pLevel->p2 = start;
     }
     loopMask |= getMask(&maskSet, iCur);
@@ -1122,10 +1317,6 @@ WhereInfo *sqlite3WhereBegin(
       if( pLevel->iLeftJoin && !ExprHasProperty(pTerm->p,EP_FromJoin) ){
         continue;
       }
-      if( haveKey ){
-        haveKey = 0;
-        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
-      }
       sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1);
       pTerm->p = 0;
     }
@@ -1142,23 +1333,12 @@ WhereInfo *sqlite3WhereBegin(
       for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){
         if( pTerm->p==0 ) continue;
         if( (pTerm->prereqAll & loopMask)!=pTerm->prereqAll ) continue;
-        if( haveKey ){
-          /* Cannot happen.  "haveKey" can only be true if pushKey is true
-          ** an pushKey can only be true for DELETE and UPDATE and there are
-          ** no outer joins with DELETE and UPDATE.
-          */
-          haveKey = 0;
-          sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
-        }
         sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1);
         pTerm->p = 0;
       }
     }
   }
   pWInfo->iContinue = cont;
-  if( pushKey && !haveKey ){
-    sqlite3VdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0);
-  }
   freeMaskSet(&maskSet);
   return pWInfo;
 }
@@ -1172,7 +1352,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
   int i;
   WhereLevel *pLevel;
   SrcList *pTabList = pWInfo->pTabList;
+  struct SrcList_item *pTabItem;
 
+  /* Generate loop termination code.
+  */
   for(i=pTabList->nSrc-1; i>=0; i--){
     pLevel = &pWInfo->a[i];
     sqlite3VdbeResolveLabel(v, pLevel->cont);
@@ -1186,25 +1369,74 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
     if( pLevel->iLeftJoin ){
       int addr;
       addr = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0);
-      sqlite3VdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iCur>=0));
+      sqlite3VdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iIdxCur>=0));
       sqlite3VdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0);
-      if( pLevel->iCur>=0 ){
-        sqlite3VdbeAddOp(v, OP_NullRow, pLevel->iCur, 0);
+      if( pLevel->iIdxCur>=0 ){
+        sqlite3VdbeAddOp(v, OP_NullRow, pLevel->iIdxCur, 0);
       }
       sqlite3VdbeAddOp(v, OP_Goto, 0, pLevel->top);
     }
   }
+
+  /* The "break" point is here, just past the end of the outer loop.
+  ** Set it.
+  */
   sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
-  for(i=0; i<pTabList->nSrc; i++){
-    Table *pTab = pTabList->a[i].pTab;
+
+  /* Close all of the cursors that were opend by sqlite3WhereBegin.
+  */
+  pLevel = pWInfo->a;
+  pTabItem = pTabList->a;
+  for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
+    Table *pTab = pTabItem->pTab;
     assert( pTab!=0 );
     if( pTab->isTransient || pTab->pSelect ) continue;
-    pLevel = &pWInfo->a[i];
-    sqlite3VdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0);
+    if( (pLevel->score & 1)==0 ){
+      sqlite3VdbeAddOp(v, OP_Close, pTabItem->iCursor, 0);
+    }
     if( pLevel->pIdx!=0 ){
-      sqlite3VdbeAddOp(v, OP_Close, pLevel->iCur, 0);
+      sqlite3VdbeAddOp(v, OP_Close, pLevel->iIdxCur, 0);
+    }
+
+    /* Make cursor substitutions for cases where we want to use
+    ** just the index and never reference the table.
+    ** 
+    ** Calls to the code generator in between sqlite3WhereBegin and
+    ** sqlite3WhereEnd will have created code that references the table
+    ** directly.  This loop scans all that code looking for opcodes
+    ** that reference the table and converts them into opcodes that
+    ** reference the index.
+    */
+    if( pLevel->score & 1 ){
+      int i, j, last;
+      VdbeOp *pOp;
+      Index *pIdx = pLevel->pIdx;
+
+      assert( pIdx!=0 );
+      pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
+      last = sqlite3VdbeCurrentAddr(v);
+      for(i=pWInfo->iTop; i<last; i++, pOp++){
+        if( pOp->p1!=pLevel->iTabCur ) continue;
+        if( pOp->opcode==OP_Column ){
+          pOp->p1 = pLevel->iIdxCur;
+          for(j=0; j<pIdx->nColumn; j++){
+            if( pOp->p2==pIdx->aiColumn[j] ){
+              pOp->p2 = j;
+              break;
+            }
+          }
+        }else if( pOp->opcode==OP_Recno ){
+          pOp->p1 = pLevel->iIdxCur;
+          pOp->opcode = OP_IdxRecno;
+        }else if( pOp->opcode==OP_NullRow ){
+          pOp->opcode = OP_Noop;
+        }
+      }
     }
   }
+
+  /* Final cleanup
+  */
   sqliteFree(pWInfo);
   return;
 }
index 1e51d0ebb2325b6902a2c5894f2edbfcf648f6e0..265e3d1ea2de73516f19c261c316b6c9be32c4e5 100644 (file)
@@ -15,118 +15,204 @@ typedef struct Keyword Keyword;
 struct Keyword {
   char *zName;         /* The keyword name */
   char *zTokenType;    /* Token value for this keyword */
+  int mask;            /* Code this keyword if non-zero */
+  int id;              /* Unique ID for this record */
   int hash;            /* Hash on the keyword */
   int offset;          /* Offset to start of name string */
   int len;             /* Length of this keyword, not counting final \000 */
+  int prefix;          /* Number of characters in prefix */
   int iNext;           /* Index in aKeywordTable[] of next with same hash */
+  int substrId;        /* Id to another keyword this keyword is embedded in */
+  int substrOffset;    /* Offset into substrId for start of this keyword */
 };
 
+/*
+** Define masks used to determine which keywords are allowed
+*/
+#ifdef SQLITE_OMIT_ALTERTABLE
+#  define ALTER      0
+#else
+#  define ALTER      1
+#endif
+#define ALWAYS     2
+#ifdef SQLITE_OMIT_ATTACH
+#  define ATTACH     0
+#else
+#  define ATTACH     4
+#endif
+#ifdef SQLITE_OMIT_AUTOINCREMENT
+#  define AUTOINCR   0
+#else
+#  define AUTOINCR   8
+#endif
+#ifdef SQLITE_OMIT_COMPOUND_SELECT
+#  define COMPOUND   0
+#else
+#  define COMPOUND   16
+#endif
+#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
+#  define CONFLICT   0
+#else
+#  define CONFLICT   32
+#endif
+#ifdef SQLITE_OMIT_EXPLAIN
+#  define EXPLAIN    0
+#else
+#  define EXPLAIN    128
+#endif
+#ifdef SQLITE_OMIT_FOREIGN_KEY
+#  define FKEY       0
+#else
+#  define FKEY       256
+#endif
+#ifdef SQLITE_OMIT_PRAGMA
+#  define PRAGMA     0
+#else
+#  define PRAGMA     512
+#endif
+#ifdef SQLITE_OMIT_REINDEX
+#  define REINDEX    0
+#else
+#  define REINDEX    1024
+#endif
+#ifdef SQLITE_OMIT_SUBQUERY
+#  define SUBQUERY   0
+#else
+#  define SUBQUERY   2048
+#endif
+#ifdef SQLITE_OMIT_TRIGGER
+#  define TRIGGER    0
+#else
+#  define TRIGGER    4096
+#endif
+#ifdef SQLITE_OMIT_VACUUM
+#  define VACUUM     0
+#else
+#  define VACUUM     8192
+#endif
+#ifdef SQLITE_OMIT_VIEW
+#  define VIEW       0
+#else
+#  define VIEW       16384
+#endif
+
+
 /*
 ** These are the keywords
 */
 static Keyword aKeywordTable[] = {
-  { "ABORT",            "TK_ABORT",        },
-  { "AFTER",            "TK_AFTER",        },
-  { "ALL",              "TK_ALL",          },
-  { "AND",              "TK_AND",          },
-  { "AS",               "TK_AS",           },
-  { "ASC",              "TK_ASC",          },
-  { "ATTACH",           "TK_ATTACH",       },
-  { "BEFORE",           "TK_BEFORE",       },
-  { "BEGIN",            "TK_BEGIN",        },
-  { "BETWEEN",          "TK_BETWEEN",      },
-  { "BY",               "TK_BY",           },
-  { "CASCADE",          "TK_CASCADE",      },
-  { "CASE",             "TK_CASE",         },
-  { "CHECK",            "TK_CHECK",        },
-  { "COLLATE",          "TK_COLLATE",      },
-  { "COMMIT",           "TK_COMMIT",       },
-  { "CONFLICT",         "TK_CONFLICT",     },
-  { "CONSTRAINT",       "TK_CONSTRAINT",   },
-  { "CREATE",           "TK_CREATE",       },
-  { "CROSS",            "TK_JOIN_KW",      },
-  { "DATABASE",         "TK_DATABASE",     },
-  { "DEFAULT",          "TK_DEFAULT",      },
-  { "DEFERRED",         "TK_DEFERRED",     },
-  { "DEFERRABLE",       "TK_DEFERRABLE",   },
-  { "DELETE",           "TK_DELETE",       },
-  { "DESC",             "TK_DESC",         },
-  { "DETACH",           "TK_DETACH",       },
-  { "DISTINCT",         "TK_DISTINCT",     },
-  { "DROP",             "TK_DROP",         },
-  { "END",              "TK_END",          },
-  { "EACH",             "TK_EACH",         },
-  { "ELSE",             "TK_ELSE",         },
-  { "EXCEPT",           "TK_EXCEPT",       },
-  { "EXCLUSIVE",        "TK_EXCLUSIVE",    },
-  { "EXPLAIN",          "TK_EXPLAIN",      },
-  { "FAIL",             "TK_FAIL",         },
-  { "FOR",              "TK_FOR",          },
-  { "FOREIGN",          "TK_FOREIGN",      },
-  { "FROM",             "TK_FROM",         },
-  { "FULL",             "TK_JOIN_KW",      },
-  { "GLOB",             "TK_GLOB",         },
-  { "GROUP",            "TK_GROUP",        },
-  { "HAVING",           "TK_HAVING",       },
-  { "IGNORE",           "TK_IGNORE",       },
-  { "IMMEDIATE",        "TK_IMMEDIATE",    },
-  { "IN",               "TK_IN",           },
-  { "INDEX",            "TK_INDEX",        },
-  { "INITIALLY",        "TK_INITIALLY",    },
-  { "INNER",            "TK_JOIN_KW",      },
-  { "INSERT",           "TK_INSERT",       },
-  { "INSTEAD",          "TK_INSTEAD",      },
-  { "INTERSECT",        "TK_INTERSECT",    },
-  { "INTO",             "TK_INTO",         },
-  { "IS",               "TK_IS",           },
-  { "ISNULL",           "TK_ISNULL",       },
-  { "JOIN",             "TK_JOIN",         },
-  { "KEY",              "TK_KEY",          },
-  { "LEFT",             "TK_JOIN_KW",      },
-  { "LIKE",             "TK_LIKE",         },
-  { "LIMIT",            "TK_LIMIT",        },
-  { "MATCH",            "TK_MATCH",        },
-  { "NATURAL",          "TK_JOIN_KW",      },
-  { "NOT",              "TK_NOT",          },
-  { "NOTNULL",          "TK_NOTNULL",      },
-  { "NULL",             "TK_NULL",         },
-  { "OF",               "TK_OF",           },
-  { "OFFSET",           "TK_OFFSET",       },
-  { "ON",               "TK_ON",           },
-  { "OR",               "TK_OR",           },
-  { "ORDER",            "TK_ORDER",        },
-  { "OUTER",            "TK_JOIN_KW",      },
-  { "PRAGMA",           "TK_PRAGMA",       },
-  { "PRIMARY",          "TK_PRIMARY",      },
-  { "RAISE",            "TK_RAISE",        },
-  { "REFERENCES",       "TK_REFERENCES",   },
-  { "REPLACE",          "TK_REPLACE",      },
-  { "RESTRICT",         "TK_RESTRICT",     },
-  { "RIGHT",            "TK_JOIN_KW",      },
-  { "ROLLBACK",         "TK_ROLLBACK",     },
-  { "ROW",              "TK_ROW",          },
-  { "SELECT",           "TK_SELECT",       },
-  { "SET",              "TK_SET",          },
-  { "STATEMENT",        "TK_STATEMENT",    },
-  { "TABLE",            "TK_TABLE",        },
-  { "TEMP",             "TK_TEMP",         },
-  { "TEMPORARY",        "TK_TEMP",         },
-  { "THEN",             "TK_THEN",         },
-  { "TRANSACTION",      "TK_TRANSACTION",  },
-  { "TRIGGER",          "TK_TRIGGER",      },
-  { "UNION",            "TK_UNION",        },
-  { "UNIQUE",           "TK_UNIQUE",       },
-  { "UPDATE",           "TK_UPDATE",       },
-  { "USING",            "TK_USING",        },
-  { "VACUUM",           "TK_VACUUM",       },
-  { "VALUES",           "TK_VALUES",       },
-  { "VIEW",             "TK_VIEW",         },
-  { "WHEN",             "TK_WHEN",         },
-  { "WHERE",            "TK_WHERE",        },
+  { "ABORT",            "TK_ABORT",        CONFLICT|TRIGGER       },
+  { "AFTER",            "TK_AFTER",        TRIGGER                },
+  { "ALL",              "TK_ALL",          ALWAYS                 },
+  { "ALTER",            "TK_ALTER",        ALTER                  },
+  { "AND",              "TK_AND",          ALWAYS                 },
+  { "AS",               "TK_AS",           ALWAYS                 },
+  { "ASC",              "TK_ASC",          ALWAYS                 },
+  { "ATTACH",           "TK_ATTACH",       ATTACH                 },
+  { "AUTOINCREMENT",    "TK_AUTOINCR",     AUTOINCR               },
+  { "BEFORE",           "TK_BEFORE",       TRIGGER                },
+  { "BEGIN",            "TK_BEGIN",        ALWAYS                 },
+  { "BETWEEN",          "TK_BETWEEN",      ALWAYS                 },
+  { "BY",               "TK_BY",           ALWAYS                 },
+  { "CASCADE",          "TK_CASCADE",      FKEY                   },
+  { "CASE",             "TK_CASE",         ALWAYS                 },
+  { "CHECK",            "TK_CHECK",        ALWAYS                 },
+  { "COLLATE",          "TK_COLLATE",      ALWAYS                 },
+  { "COMMIT",           "TK_COMMIT",       ALWAYS                 },
+  { "CONFLICT",         "TK_CONFLICT",     CONFLICT               },
+  { "CONSTRAINT",       "TK_CONSTRAINT",   ALWAYS                 },
+  { "CREATE",           "TK_CREATE",       ALWAYS                 },
+  { "CROSS",            "TK_JOIN_KW",      ALWAYS                 },
+  { "CURRENT_DATE",     "TK_CDATE",        ALWAYS                 },
+  { "CURRENT_TIME",     "TK_CTIME",        ALWAYS                 },
+  { "CURRENT_TIMESTAMP","TK_CTIMESTAMP",   ALWAYS                 },
+  { "DATABASE",         "TK_DATABASE",     ATTACH                 },
+  { "DEFAULT",          "TK_DEFAULT",      ALWAYS                 },
+  { "DEFERRED",         "TK_DEFERRED",     ALWAYS                 },
+  { "DEFERRABLE",       "TK_DEFERRABLE",   FKEY                   },
+  { "DELETE",           "TK_DELETE",       ALWAYS                 },
+  { "DESC",             "TK_DESC",         ALWAYS                 },
+  { "DETACH",           "TK_DETACH",       ATTACH                 },
+  { "DISTINCT",         "TK_DISTINCT",     ALWAYS                 },
+  { "DROP",             "TK_DROP",         ALWAYS                 },
+  { "END",              "TK_END",          ALWAYS                 },
+  { "EACH",             "TK_EACH",         TRIGGER                },
+  { "ELSE",             "TK_ELSE",         ALWAYS                 },
+  { "ESCAPE",           "TK_ESCAPE",       ALWAYS                 },
+  { "EXCEPT",           "TK_EXCEPT",       COMPOUND               },
+  { "EXCLUSIVE",        "TK_EXCLUSIVE",    ALWAYS                 },
+  { "EXISTS",           "TK_EXISTS",       SUBQUERY               },
+  { "EXPLAIN",          "TK_EXPLAIN",      EXPLAIN                },
+  { "FAIL",             "TK_FAIL",         CONFLICT|TRIGGER       },
+  { "FOR",              "TK_FOR",          TRIGGER                },
+  { "FOREIGN",          "TK_FOREIGN",      FKEY                   },
+  { "FROM",             "TK_FROM",         ALWAYS                 },
+  { "FULL",             "TK_JOIN_KW",      ALWAYS                 },
+  { "GLOB",             "TK_GLOB",         ALWAYS                 },
+  { "GROUP",            "TK_GROUP",        ALWAYS                 },
+  { "HAVING",           "TK_HAVING",       ALWAYS                 },
+  { "IGNORE",           "TK_IGNORE",       CONFLICT|TRIGGER       },
+  { "IMMEDIATE",        "TK_IMMEDIATE",    ALWAYS                 },
+  { "IN",               "TK_IN",           ALWAYS                 },
+  { "INDEX",            "TK_INDEX",        ALWAYS                 },
+  { "INITIALLY",        "TK_INITIALLY",    FKEY                   },
+  { "INNER",            "TK_JOIN_KW",      ALWAYS                 },
+  { "INSERT",           "TK_INSERT",       ALWAYS                 },
+  { "INSTEAD",          "TK_INSTEAD",      TRIGGER                },
+  { "INTERSECT",        "TK_INTERSECT",    COMPOUND               },
+  { "INTO",             "TK_INTO",         ALWAYS                 },
+  { "IS",               "TK_IS",           ALWAYS                 },
+  { "ISNULL",           "TK_ISNULL",       ALWAYS                 },
+  { "JOIN",             "TK_JOIN",         ALWAYS                 },
+  { "KEY",              "TK_KEY",          ALWAYS                 },
+  { "LEFT",             "TK_JOIN_KW",      ALWAYS                 },
+  { "LIKE",             "TK_LIKE",         ALWAYS                 },
+  { "LIMIT",            "TK_LIMIT",        ALWAYS                 },
+  { "MATCH",            "TK_MATCH",        ALWAYS                 },
+  { "NATURAL",          "TK_JOIN_KW",      ALWAYS                 },
+  { "NOT",              "TK_NOT",          ALWAYS                 },
+  { "NOTNULL",          "TK_NOTNULL",      ALWAYS                 },
+  { "NULL",             "TK_NULL",         ALWAYS                 },
+  { "OF",               "TK_OF",           ALWAYS                 },
+  { "OFFSET",           "TK_OFFSET",       ALWAYS                 },
+  { "ON",               "TK_ON",           ALWAYS                 },
+  { "OR",               "TK_OR",           ALWAYS                 },
+  { "ORDER",            "TK_ORDER",        ALWAYS                 },
+  { "OUTER",            "TK_JOIN_KW",      ALWAYS                 },
+  { "PRAGMA",           "TK_PRAGMA",       PRAGMA                 },
+  { "PRIMARY",          "TK_PRIMARY",      ALWAYS                 },
+  { "RAISE",            "TK_RAISE",        TRIGGER                },
+  { "REFERENCES",       "TK_REFERENCES",   FKEY                   },
+  { "REINDEX",          "TK_REINDEX",      REINDEX                },
+  { "RENAME",           "TK_RENAME",       ALTER                  },
+  { "REPLACE",          "TK_REPLACE",      CONFLICT               },
+  { "RESTRICT",         "TK_RESTRICT",     FKEY                   },
+  { "RIGHT",            "TK_JOIN_KW",      ALWAYS                 },
+  { "ROLLBACK",         "TK_ROLLBACK",     ALWAYS                 },
+  { "ROW",              "TK_ROW",          TRIGGER                },
+  { "SELECT",           "TK_SELECT",       ALWAYS                 },
+  { "SET",              "TK_SET",          ALWAYS                 },
+  { "STATEMENT",        "TK_STATEMENT",    TRIGGER                },
+  { "TABLE",            "TK_TABLE",        ALWAYS                 },
+  { "TEMP",             "TK_TEMP",         ALWAYS                 },
+  { "TEMPORARY",        "TK_TEMP",         ALWAYS                 },
+  { "THEN",             "TK_THEN",         ALWAYS                 },
+  { "TO",               "TK_TO",           ALTER                  },
+  { "TRANSACTION",      "TK_TRANSACTION",  ALWAYS                 },
+  { "TRIGGER",          "TK_TRIGGER",      TRIGGER                },
+  { "UNION",            "TK_UNION",        COMPOUND               },
+  { "UNIQUE",           "TK_UNIQUE",       ALWAYS                 },
+  { "UPDATE",           "TK_UPDATE",       ALWAYS                 },
+  { "USING",            "TK_USING",        ALWAYS                 },
+  { "VACUUM",           "TK_VACUUM",       VACUUM                 },
+  { "VALUES",           "TK_VALUES",       ALWAYS                 },
+  { "VIEW",             "TK_VIEW",         VIEW                   },
+  { "WHEN",             "TK_WHEN",         ALWAYS                 },
+  { "WHERE",            "TK_WHERE",        ALWAYS                 },
 };
 
 /* Number of keywords */
-#define NKEYWORD (sizeof(aKeywordTable)/sizeof(aKeywordTable[0]))
+static int NKEYWORD = (sizeof(aKeywordTable)/sizeof(aKeywordTable[0]));
 
 /* An array to map all upper-case characters into their corresponding
 ** lower-case character. 
@@ -153,10 +239,37 @@ const unsigned char sqlite3UpperToLower[] = {
 /*
 ** Comparision function for two Keyword records
 */
-static int keywordCompare(const void *a, const void *b){
+static int keywordCompare1(const void *a, const void *b){
+  const Keyword *pA = (Keyword*)a;
+  const Keyword *pB = (Keyword*)b;
+  int n = pA->len - pB->len;
+  if( n==0 ){
+    n = strcmp(pA->zName, pB->zName);
+  }
+  return n;
+}
+static int keywordCompare2(const void *a, const void *b){
+  const Keyword *pA = (Keyword*)a;
+  const Keyword *pB = (Keyword*)b;
+  int n = strcmp(pA->zName, pB->zName);
+  return n;
+}
+static int keywordCompare3(const void *a, const void *b){
   const Keyword *pA = (Keyword*)a;
   const Keyword *pB = (Keyword*)b;
-  return strcmp(pA->zName, pB->zName);
+  int n = pA->offset - pB->offset;
+  return n;
+}
+
+/*
+** Return a KeywordTable entry with the given id
+*/
+static Keyword *findById(int id){
+  int i;
+  for(i=0; i<NKEYWORD; i++){
+    if( aKeywordTable[i].id==id ) break;
+  }
+  return &aKeywordTable[i];
 }
 
 /*
@@ -164,32 +277,89 @@ static int keywordCompare(const void *a, const void *b){
 ** output.
 */
 int main(int argc, char **argv){
-  int i, j, h;
+  int i, j, k, h;
   int bestSize, bestCount;
   int count;
   int nChar;
   int aHash[1000];  /* 1000 is much bigger than NKEYWORD */
 
-  /* Make sure the table is sorted */
-  qsort(aKeywordTable, NKEYWORD, sizeof(aKeywordTable[0]), keywordCompare);
+  /* Remove entries from the list of keywords that have mask==0 */
+  for(i=j=0; i<NKEYWORD; i++){
+    if( aKeywordTable[i].mask==0 ) continue;
+    if( j<i ){
+      aKeywordTable[j] = aKeywordTable[i];
+    }
+    j++;
+  }
+  NKEYWORD = j;
 
-  /* Fill in the hash value, length, and offset for all entries */
-  nChar = 0;
+  /* Fill in the lengths of strings and hashes for all entries. */
   for(i=0; i<NKEYWORD; i++){
     Keyword *p = &aKeywordTable[i];
     p->len = strlen(p->zName);
-    /* p->hash = sqlite3HashNoCase(p->zName, p->len); */
-    p->hash = UpperToLower[p->zName[0]]*5 +
-              UpperToLower[p->zName[p->len-1]]*3 + p->len;
+    p->hash = (UpperToLower[p->zName[0]]*4) ^
+              (UpperToLower[p->zName[p->len-1]]*3) ^ p->len;
+    p->id = i+1;
+  }
+
+  /* Sort the table from shortest to longest keyword */
+  qsort(aKeywordTable, NKEYWORD, sizeof(aKeywordTable[0]), keywordCompare1);
+
+  /* Look for short keywords embedded in longer keywords */
+  for(i=NKEYWORD-2; i>=0; i--){
+    Keyword *p = &aKeywordTable[i];
+    for(j=NKEYWORD-1; j>i && p->substrId==0; j--){
+      Keyword *pOther = &aKeywordTable[j];
+      if( pOther->substrId ) continue;
+      if( pOther->len<=p->len ) continue;
+      for(k=0; k<=pOther->len-p->len; k++){
+        if( memcmp(p->zName, &pOther->zName[k], p->len)==0 ){
+          p->substrId = pOther->id;
+          p->substrOffset = k;
+          break;
+        }
+      }
+    }
+  }
+
+  /* Sort the table into alphabetical order */
+  qsort(aKeywordTable, NKEYWORD, sizeof(aKeywordTable[0]), keywordCompare2);
+
+  /* Fill in the offset for all entries */
+  nChar = 0;
+  for(i=0; i<NKEYWORD; i++){
+    Keyword *p = &aKeywordTable[i];
+    if( p->offset>0 || p->substrId ) continue;
     p->offset = nChar;
-    if( i<NKEYWORD-1 && strncmp(p->zName, aKeywordTable[i+1].zName,p->len)==0 ){
-      /* This entry is a prefix of the one that follows.  Do not advance
-      ** the offset */
-    }else{
-      nChar += p->len;
+    nChar += p->len;
+    for(k=p->len-1; k>=1; k--){
+      for(j=i+1; j<NKEYWORD; j++){
+        Keyword *pOther = &aKeywordTable[j];
+        if( pOther->offset>0 || pOther->substrId ) continue;
+        if( pOther->len<=k ) continue;
+        if( memcmp(&p->zName[p->len-k], pOther->zName, k)==0 ){
+          p = pOther;
+          p->offset = nChar - k;
+          nChar = p->offset + p->len;
+          p->zName += k;
+          p->len -= k;
+          p->prefix = k;
+          j = i;
+          k = p->len;
+        }
+      }
+    }
+  }
+  for(i=0; i<NKEYWORD; i++){
+    Keyword *p = &aKeywordTable[i];
+    if( p->substrId ){
+      p->offset = findById(p->substrId)->offset + p->substrOffset;
     }
   }
 
+  /* Sort the table by offset */
+  qsort(aKeywordTable, NKEYWORD, sizeof(aKeywordTable[0]), keywordCompare3);
+
   /* Figure out how big to make the hash table in order to minimize the
   ** number of collisions */
   bestSize = NKEYWORD;
@@ -217,12 +387,13 @@ int main(int argc, char **argv){
   }
 
   /* Begin generating code */
-  printf("int sqlite3KeywordCode(const char *z, int n){\n");
+  printf("/* Hash score: %d */\n", bestCount);
+  printf("static int keywordCode(const char *z, int n){\n");
 
   printf("  static const char zText[%d] =\n", nChar+1);
   for(i=j=0; i<NKEYWORD; i++){
     Keyword *p = &aKeywordTable[i];
-    if( i<NKEYWORD-1 && p->offset==aKeywordTable[i+1].offset ) continue;
+    if( p->substrId ) continue;
     if( j==0 ) printf("    \"");
     printf("%s", p->zName);
     j += p->len;
@@ -260,7 +431,7 @@ int main(int argc, char **argv){
   printf("  static const unsigned char aLen[%d] = {\n", NKEYWORD);
   for(i=j=0; i<NKEYWORD; i++){
     if( j==0 ) printf("    ");
-    printf(" %3d,", aKeywordTable[i].len);
+    printf(" %3d,", aKeywordTable[i].len+aKeywordTable[i].prefix);
     j++;
     if( j>12 ){
       printf("\n");
@@ -296,8 +467,8 @@ int main(int argc, char **argv){
 
   printf("  int h, i;\n");
   printf("  if( n<2 ) return TK_ID;\n");
-  printf("  h = (sqlite3UpperToLower[((unsigned char*)z)[0]]*5 + \n"
-         "      sqlite3UpperToLower[((unsigned char*)z)[n-1]]*3 +\n"
+  printf("  h = ((sqlite3UpperToLower[((unsigned char*)z)[0]]*4) ^\n"
+         "      (sqlite3UpperToLower[((unsigned char*)z)[n-1]]*3) ^\n"
          "      n) %% %d;\n", bestSize);
   printf("  for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){\n");
   printf("    if( aLen[i]==n &&"
@@ -307,6 +478,9 @@ int main(int argc, char **argv){
   printf("  }\n");
   printf("  return TK_ID;\n");
   printf("}\n");
+  printf("int sqlite3KeywordCode(const char *z, int n){\n");
+  printf("  return keywordCode(z, n);\n");
+  printf("}\n");
 
   return 0;
 }
index 38d091c9d7f3d1de97ee5d20817b80ba51f11481..1c2c02ca30fe98ff7ca496064f7a7ec395c80590 100644 (file)
@@ -176,15 +176,16 @@ static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
        stmt->columns[colno].namelen = strlen(stmt->columns[colno].name);
        stmt->columns[colno].maxlen = 0xffffffff;
        stmt->columns[colno].precision = 0;
-
+       
        switch (sqlite3_column_type(S->stmt, colno)) {
                case SQLITE_INTEGER:
                case SQLITE_FLOAT:
-               case SQLITE_TEXT:
+               case SQLITE3_TEXT:
                case SQLITE_BLOB:
                        stmt->columns[colno].param_type = PDO_PARAM_STR;
                        break;
                case SQLITE_NULL:
+               default:
                        stmt->columns[colno].param_type = PDO_PARAM_NULL;
                        break;
        }
@@ -214,10 +215,20 @@ static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsi
                        *ptr = (char*)sqlite3_column_blob(S->stmt, colno);
                        *len = sqlite3_column_bytes(S->stmt, colno);
                        return 1;
+
+               case SQLITE3_TEXT:
+                       *ptr = (char*)sqlite3_column_text(S->stmt, colno);
+                       *len = sqlite3_column_bytes(S->stmt, colno);
+                       if (*len) {
+                               /* sqlite3.h says "the NUL terminator is included in the byte count
+                                * for TEXT values" */
+                               *len--;
+                       }
+                       return 1;
                
                default:
                        *ptr = (char*)sqlite3_column_text(S->stmt, colno);
-                       *len = strlen(*ptr);
+                       *len = sqlite3_column_bytes(S->stmt, colno);
                        return 1;
        }
 }