]> granicus.if.org Git - php/commitdiff
Upgrade sqlite lib to 3.2.5
authorIlia Alshanetsky <iliaa@php.net>
Sun, 28 Aug 2005 16:57:01 +0000 (16:57 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Sun, 28 Aug 2005 16:57:01 +0000 (16:57 +0000)
64 files changed:
ext/pdo_sqlite/config.m4
ext/pdo_sqlite/config.w32
ext/pdo_sqlite/sqlite/Makefile.in
ext/pdo_sqlite/sqlite/Makefile.linux-gcc
ext/pdo_sqlite/sqlite/README
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/mkdll.sh
ext/pdo_sqlite/sqlite/mkopcodeh.awk
ext/pdo_sqlite/sqlite/sqlite3.def
ext/pdo_sqlite/sqlite/src/alter.c
ext/pdo_sqlite/sqlite/src/analyze.c [new file with mode: 0644]
ext/pdo_sqlite/sqlite/src/attach.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/callback.c
ext/pdo_sqlite/sqlite/src/date.c
ext/pdo_sqlite/sqlite/src/delete.c
ext/pdo_sqlite/sqlite/src/experimental.c
ext/pdo_sqlite/sqlite/src/expr.c
ext/pdo_sqlite/sqlite/src/func.c
ext/pdo_sqlite/sqlite/src/insert.c
ext/pdo_sqlite/sqlite/src/keywordhash.h
ext/pdo_sqlite/sqlite/src/main.c
ext/pdo_sqlite/sqlite/src/opcodes.h
ext/pdo_sqlite/sqlite/src/os_unix.c
ext/pdo_sqlite/sqlite/src/os_unix.h
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/prepare.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/test4.c
ext/pdo_sqlite/sqlite/src/tokenize.c
ext/pdo_sqlite/sqlite/src/update.c
ext/pdo_sqlite/sqlite/src/util.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/vdbefifo.c [new file with mode: 0644]
ext/pdo_sqlite/sqlite/src/vdbemem.c
ext/pdo_sqlite/sqlite/src/where.c
ext/pdo_sqlite/sqlite/tool/lemon.c
ext/pdo_sqlite/sqlite/tool/lempar.c
ext/pdo_sqlite/sqlite/tool/memleak.awk
ext/pdo_sqlite/sqlite/tool/memleak3.tcl
ext/pdo_sqlite/sqlite/tool/mkkeywordhash.c
ext/pdo_sqlite/sqlite/tool/spaceanal.tcl

index 20d8c57d0c1a676fb9ac54068a79098b5208aaa0..4c781fcac38ebaad8e5f448c657b8db0100da66e 100644 (file)
@@ -75,11 +75,11 @@ if test "$PHP_PDO_SQLITE" != "no"; then
       sqlite/src/main.c sqlite/src/os_mac.c sqlite/src/os_unix.c sqlite/src/os_win.c \
       sqlite/src/pager.c sqlite/src/pragma.c sqlite/src/prepare.c \
       sqlite/src/printf.c sqlite/src/random.c sqlite/src/select.c \
-      sqlite/src/table.c sqlite/src/tokenize.c \
+      sqlite/src/table.c sqlite/src/tokenize.c sqlite/src/analyze.c \
       sqlite/src/trigger.c sqlite/src/update.c sqlite/src/utf.c sqlite/src/util.c \
       sqlite/src/vacuum.c sqlite/src/vdbeapi.c sqlite/src/vdbeaux.c sqlite/src/vdbe.c \
       sqlite/src/vdbemem.c sqlite/src/where.c sqlite/src/parse.c sqlite/src/opcodes.c \
-      sqlite/src/alter.c sqlite/src/experimental.c"
+      sqlite/src/alter.c sqlite/src/vdbefifo.c sqlite/src/experimental.c"
 
       PHP_NEW_EXTENSION(pdo_sqlite,
         $php_pdo_sqlite_sources_core $pdo_sqlite_sources,
index 297423f045e8e2dddde78027f61040662f8d3fbd..fed572403a778796ed359d88cdfdd62f3396bbd0 100644 (file)
@@ -23,8 +23,8 @@ if (PHP_PDO_SQLITE != "no") {
        ADD_SOURCES(configure_module_dirname + "/sqlite/src",
                "attach.c auth.c btree.c build.c callback.c date.c delete.c expr.c func.c hash.c insert.c \
                 legacy.c main.c os_mac.c os_unix.c os_win.c pager.c pragma.c prepare.c printf.c random.c \
-                select.c table.c tokenize.c trigger.c update.c utf.c util.c vacuum.c vdbeapi.c \
-                vdbeaux.c vdbe.c vdbemem.c where.c parse.c opcodes.c alter.c experimental.c", "pdo_sqlite");
+                select.c table.c tokenize.c trigger.c update.c utf.c util.c vacuum.c vdbeapi.c analyze.c \
+                vdbeaux.c vdbe.c vdbemem.c vdbefifo.c where.c parse.c opcodes.c alter.c experimental.c", "pdo_sqlite");
        
        ADD_EXTENSION_DEP('pdo_sqlite', 'pdo');
 }
index 462772a967c28b855341e1bc12477fe6347ba5ee..db4714422514109370e95d02a0382a80415bb37a 100644 (file)
@@ -52,7 +52,7 @@ LIBREADLINE = @TARGET_READLINE_LIBS@
 
 # Should the database engine be compiled threadsafe
 #
-THREADSAFE = -DTHREADSAFE=@THREADSAFE@
+TCC += -DTHREADSAFE=@THREADSAFE@
 
 # The pthreads library if needed
 #
@@ -112,24 +112,28 @@ TCC += -DSQLITE_OMIT_CURSOR
 
 # Object files for the SQLite library.
 #
-LIBOBJ = alter.lo attach.lo auth.lo btree.lo build.lo callback.lo date.lo \
+LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btree.lo build.lo \
+         callback.lo complete.lo date.lo \
          delete.lo expr.lo func.lo hash.lo insert.lo \
          main.lo opcodes.lo os_unix.lo os_win.lo \
          pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \
          select.lo table.lo tokenize.lo trigger.lo update.lo \
-         util.lo vacuum.lo vdbe.lo vdbeapi.lo vdbeaux.lo vdbemem.lo \
+         util.lo vacuum.lo \
+         vdbe.lo vdbeapi.lo vdbeaux.lo vdbefifo.lo vdbemem.lo \
          where.lo utf.lo legacy.lo
 
 # All of the source code files.
 #
 SRC = \
   $(TOP)/src/alter.c \
+  $(TOP)/src/analyze.c \
   $(TOP)/src/attach.c \
   $(TOP)/src/auth.c \
   $(TOP)/src/btree.c \
   $(TOP)/src/btree.h \
   $(TOP)/src/build.c \
   $(TOP)/src/callback.c \
+  $(TOP)/src/complete.c \
   $(TOP)/src/date.c \
   $(TOP)/src/delete.c \
   $(TOP)/src/expr.c \
@@ -164,6 +168,7 @@ SRC = \
   $(TOP)/src/vdbe.h \
   $(TOP)/src/vdbeapi.c \
   $(TOP)/src/vdbeaux.c \
+  $(TOP)/src/vdbefifo.c \
   $(TOP)/src/vdbemem.c \
   $(TOP)/src/vdbeInt.h \
   $(TOP)/src/where.c
@@ -187,14 +192,14 @@ TESTSRC = \
   $(TOP)/src/utf.c \
   $(TOP)/src/util.c \
   $(TOP)/src/vdbe.c \
-  $(TOP)/src/md5.c
+  $(TOP)/src/md5.c \
+  $(TOP)/src/where.c
 
 # Header files used by all library source files.
 #
 HDR = \
    sqlite3.h  \
    $(TOP)/src/btree.h \
-   config.h \
    $(TOP)/src/hash.h \
    opcodes.h \
    $(TOP)/src/os.h \
@@ -266,6 +271,9 @@ lemon$(BEXE):       $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
 alter.lo:      $(TOP)/src/alter.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/alter.c
 
+analyze.lo:    $(TOP)/src/analyze.c $(HDR)
+       $(LTCOMPILE) -c $(TOP)/src/analyze.c
+
 attach.lo:     $(TOP)/src/attach.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/attach.c
 
@@ -278,21 +286,11 @@ btree.lo: $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h
 build.lo:      $(TOP)/src/build.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/build.c
 
-# The config.h file will contain a single #define that tells us how
-# many bytes are in a pointer.  This only works if a pointer is the
-# same size on the host as it is on the target.  If you are cross-compiling
-# to a target with a different pointer size, you'll need to manually
-# configure the config.h file.
-#
-config.h:      
-       echo '#include <stdio.h>' >temp.c
-       echo 'int main(){printf(' >>temp.c
-       echo '"#define SQLITE_PTR_SZ %d",sizeof(char*));' >>temp.c
-       echo 'exit(0);}' >>temp.c
-       $(BCC) -o temp temp.c
-       ./temp >config.h
-       echo >>config.h
-       rm -f temp.c temp
+callback.lo:   $(TOP)/src/callback.c $(HDR)
+       $(LTCOMPILE) -c $(TOP)/src/callback.c
+
+complete.lo:   $(TOP)/src/complete.c $(HDR)
+       $(LTCOMPILE) -c $(TOP)/src/complete.c
 
 date.lo:       $(TOP)/src/date.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/date.c
@@ -331,10 +329,10 @@ 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_unix.lo:    $(TOP)/src/os_unix.c $(HDR)
-       $(LTCOMPILE) $(THREADSAFE) -c $(TOP)/src/os_unix.c
+       $(LTCOMPILE) -c $(TOP)/src/os_unix.c
 
 os_win.lo:     $(TOP)/src/os_win.c $(HDR)
-       $(LTCOMPILE) $(THREADSAFE) -c $(TOP)/src/os_win.c
+       $(LTCOMPILE) -c $(TOP)/src/os_win.c
 
 parse.lo:      parse.c $(HDR)
        $(LTCOMPILE) -c parse.c
@@ -348,8 +346,8 @@ parse.c:    $(TOP)/src/parse.y lemon$(BEXE)
 pragma.lo:     $(TOP)/src/pragma.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/pragma.c
 
-prepare.lo:     $(TOP)/src/prepare.c $(HDR)
-        $(LTCOMPILE) -c $(TOP)/src/prepare.c
+prepare.lo:    $(TOP)/src/prepare.c $(HDR)
+       $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/prepare.c
 
 printf.lo:     $(TOP)/src/printf.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/printf.c
@@ -401,6 +399,9 @@ vdbeapi.lo: $(TOP)/src/vdbeapi.c $(VDBEHDR)
 vdbeaux.lo:    $(TOP)/src/vdbeaux.c $(VDBEHDR)
        $(LTCOMPILE) -c $(TOP)/src/vdbeaux.c
 
+vdbefifo.lo:   $(TOP)/src/vdbefifo.c $(VDBEHDR)
+       $(LTCOMPILE) -c $(TOP)/src/vdbefifo.c
+
 vdbemem.lo:    $(TOP)/src/vdbemem.c $(VDBEHDR)
        $(LTCOMPILE) -c $(TOP)/src/vdbemem.c
 
@@ -417,17 +418,16 @@ tclsqlite3:       tclsqlite-shell.lo libsqlite3.la
        $(LTLINK) -o tclsqlite3 tclsqlite-shell.lo \
                 libsqlite3.la $(LIBTCL)
 
-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 $(LIBTCL)
+testfixture$(TEXE):    $(TOP)/src/tclsqlite.c libsqlite3.la $(TESTSRC)
+       $(LTLINK) -DTCLSH=1 -DSQLITE_TEST=1 $(TEMP_STORE) \
+               -o testfixture $(TESTSRC) $(TOP)/src/tclsqlite.c \
+               libsqlite3.la $(LIBTCL)
 
 crashtest$(TEXE):      $(TOP)/src/tclsqlite.c libsqlite3.la $(TESTSRC) $(TOP)/src/os_test.c
        $(LTLINK) -DOS_TEST=1 -DTCLSH=1 -DSQLITE_TEST=1 \
                -o crashtest \
                $(TESTSRC) $(TOP)/src/os_test.c $(TOP)/src/tclsqlite.c \
-               libsqlite3.la $(LIBTCL) $(THREADLIB)
+               libsqlite3.la $(LIBTCL)
 
 
 
@@ -446,8 +446,7 @@ sqlite3_analyzer$(TEXE):    $(TOP)/src/tclsqlite.c libtclsqlite3.la \
          -e 's,^,",' \
          -e 's,$$,\\n",' \
          $(TOP)/tool/spaceanal.tcl >spaceanal_tcl.h
-       $(LTLINK) -DTCLSH=2 -DSQLITE_TEST=1\
-                $(THREADSAFE) $(TEMP_STORE)\
+       $(LTLINK) -DTCLSH=2 -DSQLITE_TEST=1 $(TEMP_STORE)\
                 -o sqlite3_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \
                libtclsqlite3.la $(LIBTCL)
 
@@ -570,7 +569,7 @@ version3.html:      $(TOP)/www/version3.tcl
 #
 DOC = \
   arch.html \
-  arch.png \
+  arch2.gif \
   autoinc.html \
   c_interface.html \
   capi3.html \
@@ -653,7 +652,8 @@ implib: sqlite3.lib
 #make Borland C++ and/or Microsoft VC import library for the dll
 #   ignore any errors (usually due to missing programs)
 sqlite3.lib: sqlite3.dll
-       -implib -a sqlite3.lib sqlite3.dll
+       -impdef -a sqlite3.def sqlite3.dll
+       -implib sqlite3.lib sqlite3.def
        -lib /machine:i386 /def:$(TOP)/sqlite3.def 
 
 distclean:     clean
index aa5ced6ab5ddbdcdbae863c908af5206096b48eb..202f4a1ee2523f11464ae615754744aab87a271d 100644 (file)
@@ -94,13 +94,13 @@ LIBTCL = /home/drh/tcltk/8.4linux/libtcl8.4g.a -lm -ldl
 
 #### Compiler options needed for programs that use the readline() library.
 #
-#READLINE_FLAGS =
-READLINE_FLAGS = -DHAVE_READLINE=1 -I/usr/include/readline
+READLINE_FLAGS =
+#READLINE_FLAGS = -DHAVE_READLINE=1 -I/usr/include/readline
 
 #### Linker options needed by programs using readline() must link against.
 #
-#LIBREADLINE =
-LIBREADLINE = -static -lreadline -ltermcap
+LIBREADLINE =
+#LIBREADLINE = -static -lreadline -ltermcap
 
 #### Should the database engine assume text is coded as UTF-8 or iso8859?
 #
index be1fa31568cc9feda4ca7a114c0664fce4e24559..6e4f392054fc01c9469287d879bf093aefae4672 100644 (file)
@@ -15,6 +15,7 @@ For example:
     cd bld                   ;#  Change to the build directory
     ../sqlite/configure      ;#  Run the configure script
     make                     ;#  Run the makefile.
+    make install             ;#  (Optional) Install the build products
 
 The configure script uses autoconf 2.50 and libtool.  If the configure
 script does not work out for you, there is a generic makefile named
index be94e6f53db6b394e5e7cc7ceb12115a81870306..5ae69bd5f0e841ccaf8765eaa00f9fba9d93d01c 100644 (file)
@@ -1 +1 @@
-3.2.2
+3.2.5
index 779a859463860cc2459e683a95ec60f9bc2afda3..11e3c9c51bec032c5a93f9f7f54f06e5e978f3cf 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 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_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP CPP CXX CXXFLAGS ac_ct_CXX CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA program_prefix VERSION RELEASE VERSION_NUMBER BUILD_CC BUILD_CFLAGS BUILD_LIBS TARGET_CC TARGET_CFLAGS TARGET_LINK TARGET_LFLAGS TARGET_RANLIB TARGET_AR THREADSAFE TARGET_THREAD_LIB ALLOWRELEASE TEMP_STORE BUILD_EXEEXT OS_UNIX OS_WIN TARGET_EXEEXT TARGET_LIBS TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR TCL_LIBS TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC HAVE_TCL TARGET_READLINE_LIBS TARGET_READLINE_INC TARGET_HAVE_READLINE TARGET_DEBUG LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -18430,11 +18430,11 @@ RELEASE=`cat $srcdir/VERSION`
 echo "Release set to $RELEASE"
 
 VERSION_NUMBER=`cat $srcdir/VERSION  \
-               | sed 's/[^0-9]/ /g' \
+                           | 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,
 # then check for a files named "$host.hints" and ../$hosts.hints where
@@ -21018,8 +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,@VERSION_NUMBER@,$VERSION_NUMBER,;t t
 s,@BUILD_CC@,$BUILD_CC,;t t
 s,@BUILD_CFLAGS@,$BUILD_CFLAGS,;t t
 s,@BUILD_LIBS@,$BUILD_LIBS,;t t
index 6137f39d20a83952bfee3ab487e62d9bdf3a8020..3682bf82107f36491014df18dd2e45e884e896e1 100644 (file)
@@ -138,9 +138,9 @@ AC_SUBST(VERSION)
 RELEASE=`cat $srcdir/VERSION`
 echo "Release set to $RELEASE"
 AC_SUBST(RELEASE)
-VERSION_NUMBER=`cat $srcdir/VERSION  \
+VERSION_NUMBER=[`cat $srcdir/VERSION  \
                            | sed 's/[^0-9]/ /g' \
-                | awk '{printf "%d%03d%03d",$1,$2,$3}'`
+                | awk '{printf "%d%03d%03d",$1,$2,$3}'`]
 echo "Version number set to $VERSION_NUMBER"
 AC_SUBST(VERSION_NUMBER)
 
index f6fc40c136567e9ec833de292485cba0203a8a60..d931e281aed438a44c243f788cf44d50b16bd4b2 100644 (file)
@@ -54,24 +54,28 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src
 
 # Object files for the SQLite library.
 #
-LIBOBJ+= alter.o attach.o auth.o btree.o build.o date.o delete.o \
+LIBOBJ+= alter.o analyze.o attach.o auth.o btree.o build.o \
+         callback.o complete.o date.o delete.o \
          expr.o func.o hash.o insert.o \
          main.o opcodes.o os_unix.o os_win.o \
-         pager.o parse.o pragma.o printf.o random.o \
+         pager.o parse.o pragma.o prepare.o printf.o random.o \
          select.o table.o tclsqlite.o tokenize.o trigger.o \
          update.o util.o vacuum.o \
-         vdbe.o vdbeapi.o vdbeaux.o vdbemem.o \
+         vdbe.o vdbeapi.o vdbeaux.o vdbefifo.o vdbemem.o \
          where.o utf.o legacy.o
 
 # All of the source code files.
 #
 SRC = \
   $(TOP)/src/alter.c \
+  $(TOP)/src/analyze.c \
   $(TOP)/src/attach.c \
   $(TOP)/src/auth.c \
   $(TOP)/src/btree.c \
   $(TOP)/src/btree.h \
   $(TOP)/src/build.c \
+  $(TOP)/src/callback.c \
+  $(TOP)/src/complete.c \
   $(TOP)/src/date.c \
   $(TOP)/src/delete.c \
   $(TOP)/src/expr.c \
@@ -87,6 +91,7 @@ SRC = \
   $(TOP)/src/pager.h \
   $(TOP)/src/parse.y \
   $(TOP)/src/pragma.c \
+  $(TOP)/src/prepare.c \
   $(TOP)/src/printf.c \
   $(TOP)/src/random.c \
   $(TOP)/src/select.c \
@@ -105,6 +110,7 @@ SRC = \
   $(TOP)/src/vdbe.h \
   $(TOP)/src/vdbeapi.c \
   $(TOP)/src/vdbeaux.c \
+  $(TOP)/src/vdbefifo.c \
   $(TOP)/src/vdbemem.c \
   $(TOP)/src/vdbeInt.h \
   $(TOP)/src/where.c
@@ -128,14 +134,14 @@ TESTSRC = \
   $(TOP)/src/utf.c \
   $(TOP)/src/util.c \
   $(TOP)/src/vdbe.c \
-  $(TOP)/src/md5.c
+  $(TOP)/src/md5.c \
+  $(TOP)/src/where.c
 
 # Header files used by all library source files.
 #
 HDR = \
    sqlite3.h  \
    $(TOP)/src/btree.h \
-   config.h \
    $(TOP)/src/hash.h \
    opcodes.h \
    $(TOP)/src/os.h \
@@ -155,7 +161,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 config.h libsqlite3.a sqlite3$(EXE)
+all:   sqlite3.h libsqlite3.a sqlite3$(EXE)
 
 # Generate the file "last_change" which contains the date of change
 # of the most recently modified source code file
@@ -199,6 +205,9 @@ lemon:      $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
 alter.o:       $(TOP)/src/alter.c $(HDR)
        $(TCCX) -c $(TOP)/src/alter.c
 
+analyze.o:     $(TOP)/src/analyze.c $(HDR)
+       $(TCCX) -c $(TOP)/src/analyze.c
+
 attach.o:      $(TOP)/src/attach.c $(HDR)
        $(TCCX) -c $(TOP)/src/attach.c
 
@@ -211,21 +220,11 @@ btree.o:  $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h
 build.o:       $(TOP)/src/build.c $(HDR)
        $(TCCX) -c $(TOP)/src/build.c
 
-# The config.h file will contain a single #define that tells us how
-# many bytes are in a pointer.  This only works if a pointer is the
-# same size on the host as it is on the target.  If you are cross-compiling
-# to a target with a different pointer size, you'll need to manually
-# configure the config.h file.
-#
-config.h:      
-       echo '#include <stdio.h>' >temp.c
-       echo 'int main(){printf(' >>temp.c
-       echo '"#define SQLITE_PTR_SZ %d",sizeof(char*));' >>temp.c
-       echo 'exit(0);}' >>temp.c
-       $(BCC) -o temp temp.c
-       ./temp >config.h
-       echo >>config.h
-       rm -f temp.c temp
+callback.o:    $(TOP)/src/callback.c $(HDR)
+       $(TCCX) -c $(TOP)/src/callback.c
+
+complete.o:    $(TOP)/src/complete.c $(HDR)
+       $(TCCX) -c $(TOP)/src/complete.c
 
 date.o:        $(TOP)/src/date.c $(HDR)
        $(TCCX) -c $(TOP)/src/date.c
@@ -281,6 +280,9 @@ parse.c:    $(TOP)/src/parse.y lemon
 pragma.o:      $(TOP)/src/pragma.c $(HDR)
        $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/pragma.c
 
+prepare.o:     $(TOP)/src/prepare.c $(HDR)
+       $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/prepare.c
+
 printf.o:      $(TOP)/src/printf.c $(HDR)
        $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/printf.c
 
@@ -332,6 +334,9 @@ vdbeapi.o:  $(TOP)/src/vdbeapi.c $(VDBEHDR)
 vdbeaux.o:     $(TOP)/src/vdbeaux.c $(VDBEHDR)
        $(TCCX) -c $(TOP)/src/vdbeaux.c
 
+vdbefifo.o:    $(TOP)/src/vdbefifo.c $(VDBEHDR)
+       $(TCCX) -c $(TOP)/src/vdbefifo.c
+
 vdbemem.o:     $(TOP)/src/vdbemem.c $(VDBEHDR)
        $(TCCX) -c $(TOP)/src/vdbemem.c
 
@@ -382,6 +387,9 @@ arch.html:  $(TOP)/www/arch.tcl
 arch.png:      $(TOP)/www/arch.png
        cp $(TOP)/www/arch.png .
 
+arch2.gif:     $(TOP)/www/arch2.gif
+       cp $(TOP)/www/arch2.gif .
+
 autoinc.html:  $(TOP)/www/autoinc.tcl
        tclsh $(TOP)/www/autoinc.tcl >autoinc.html
 
@@ -421,6 +429,9 @@ datatypes.html:     $(TOP)/www/datatypes.tcl
 datatype3.html:        $(TOP)/www/datatype3.tcl
        tclsh $(TOP)/www/datatype3.tcl >datatype3.html
 
+different.html:        $(TOP)/www/different.tcl
+       tclsh $(TOP)/www/different.tcl >different.html
+
 docs.html:     $(TOP)/www/docs.tcl
        tclsh $(TOP)/www/docs.tcl >docs.html
 
@@ -497,6 +508,7 @@ whentouse.html:     $(TOP)/www/whentouse.tcl
 DOC = \
   arch.html \
   arch.png \
+  arch2.gif \
   autoinc.html \
   c_interface.html \
   capi3.html \
@@ -509,6 +521,7 @@ DOC = \
   conflict.html \
   datatypes.html \
   datatype3.html \
+  different.html \
   docs.html \
   download.html \
   faq.html \
@@ -545,7 +558,7 @@ install:    sqlite3 libsqlite3.a sqlite3.h
        mv sqlite3.h /usr/include
 
 clean: 
-       rm -f *.o sqlite3 libsqlite3.a sqlite3.h opcodes.*
+       rm -f *.o sqlite3 libsqlite3.a sqlite3.h opcodes.* crashtest
        rm -f lemon lempar.c parse.* sqlite*.tar.gz mkkeywordhash keywordhash.h
        rm -f $(PUBLISH)
        rm -f *.da *.bb *.bbg gmon.out
index bad8619f3e50aad25276a38b4f2ed4f553a15069..1ad5f83326f24e9b285085628cd83bf51b744124 100644 (file)
@@ -21,7 +21,9 @@ for i in *.c; do
 done
 echo 'EXPORTS' >tclsqlite3.def
 echo 'Tclsqlite3_Init' >>tclsqlite3.def
+echo 'Tclsqlite_Init' >>tclsqlite3.def
 echo 'Sqlite3_Init' >>tclsqlite3.def
+echo 'Sqlite_Init' >>tclsqlite3.def
 i386-mingw32msvc-dllwrap \
      --def tclsqlite3.def -v --export-all \
      --driver-name i386-mingw32msvc-gcc \
index 641b987a81e63764e8c9c84839d0f7049e68698a..a258194ca831026bbcd02417c1c3dab994c6072a 100644 (file)
@@ -24,6 +24,7 @@
 # the total library smaller.
 #
 
+
 # Remember the TK_ values from the parse.h file
 /^#define TK_/ {
   tk[$2] = $3
   gsub(/:/,"",name)
   gsub("\r","",name)
   op[name] = -1
-  for(i=3; i<NF-2; i++){
+  for(i=3; i<NF; i++){
     if($i=="same" && $(i+1)=="as"){
-      op[name] = tk[$(i+2)]
+      sym = $(i+2)
+      sub(/,/,"",sym)
+      op[name] = tk[sym]
       used[op[name]] = 1
-      sameas[op[name]] = $(i+2)
+      sameas[op[name]] = sym
+    }
+    if($i=="no-push"){
+      nopush[name] = 1
     }
   }
 }
@@ -75,4 +81,30 @@ END {
       printf "#define %-25s %15d\n", sprintf( "OP_NotUsed_%-3d", i ), i
     }
   }
+
+  # Generate the 10 16-bit bitmasks used by function opcodeUsesStack()
+  # in vdbeaux.c. See comments in that function for details.
+  # 
+  nopush[0] = 0              # 0..15
+  nopush[1] = 0              # 16..31
+  nopush[2] = 0              # 32..47
+  nopush[3] = 0              # 48..63
+  nopush[4] = 0              # 64..79
+  nopush[5] = 0              # 80..95
+  nopush[6] = 0              # 96..111
+  nopush[7] = 0              # 112..127
+  nopush[8] = 0              # 128..143
+  nopush[9] = 0              # 144..159
+  for(name in op){
+    if( nopush[name] ){
+      n = op[name]
+      j = n%16
+      i = ((n - j)/16)
+      nopush[i] = nopush[i] + (2^j)
+    }
+  }
+  printf "\n"
+  for(i=0; i<10; i++){
+    printf "#define NOPUSH_MASK_%d %d\n", i, nopush[i]
+  }
 }
index 0a4b793113d0a58b631842c843065129e078193f..c57ca6897308cfb7e1a91b670a6df9e6dce900fe 100644 (file)
@@ -39,18 +39,23 @@ sqlite3_create_collation16
 sqlite3_create_function
 sqlite3_create_function16
 sqlite3_data_count
+sqlite3_db_handle
 sqlite3_errcode
 sqlite3_errmsg
 sqlite3_errmsg16
 sqlite3_exec
+sqlite3_expired
 sqlite3_finalize
 sqlite3_free
 sqlite3_free_table
+sqlite3_get_autocommit
 sqlite3_get_auxdata
 sqlite3_get_table
+sqlite3_global_recover
 sqlite3_interrupt
 sqlite3_last_insert_rowid
 sqlite3_libversion
+sqlite3_libversion_number
 sqlite3_mprintf
 sqlite3_open
 sqlite3_open16
@@ -76,6 +81,7 @@ sqlite3_snprintf
 sqlite3_step
 sqlite3_total_changes
 sqlite3_trace
+sqlite3_transfer_bindings
 sqlite3_user_data
 sqlite3_value_blob
 sqlite3_value_bytes
index c5be6b61c7450a2a3d4015b59a653347cba6fab9..ada0769b5ddcde7329670e70750230ed63652cb1 100644 (file)
@@ -258,6 +258,7 @@ void sqlite3AlterRenameTable(
   char *zWhere = 0;         /* Where clause to locate temp triggers */
 #endif
   
+  if( sqlite3_malloc_failed ) goto exit_rename_table;
   assert( pSrc->nSrc==1 );
 
   pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
@@ -500,8 +501,10 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
   int i;
   int nAlloc;
 
+
   /* Look up the table being altered. */
-  assert( !pParse->pNewTable );
+  assert( pParse->pNewTable==0 );
+  if( sqlite3_malloc_failed ) goto exit_begin_add_column;
   pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
   if( !pTab ) goto exit_begin_add_column;
 
@@ -520,6 +523,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
   pNew = (Table *)sqliteMalloc(sizeof(Table));
   if( !pNew ) goto exit_begin_add_column;
   pParse->pNewTable = pNew;
+  pNew->nRef = 1;
   pNew->nCol = pTab->nCol;
   assert( pNew->nCol>0 );
   nAlloc = (((pNew->nCol-1)/8)*8)+8;
diff --git a/ext/pdo_sqlite/sqlite/src/analyze.c b/ext/pdo_sqlite/sqlite/src/analyze.c
new file mode 100644 (file)
index 0000000..7f0f00a
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+** 2005 July 8
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code associated with the ANALYZE command.
+**
+** @(#) $Id$
+*/
+#ifndef SQLITE_OMIT_ANALYZE
+#include "sqliteInt.h"
+
+/*
+** This routine generates code that opens the sqlite_stat1 table on cursor
+** iStatCur.
+**
+** If the sqlite_stat1 tables does not previously exist, it is created.
+** If it does previously exist, all entires associated with table zWhere
+** are removed.  If zWhere==0 then all entries are removed.
+*/
+static void openStatTable(
+  Parse *pParse,          /* Parsing context */
+  int iDb,                /* The database we are looking in */
+  int iStatCur,           /* Open the sqlite_stat1 table on this cursor */
+  const char *zWhere      /* Delete entries associated with this table */
+){
+  sqlite3 *db = pParse->db;
+  Db *pDb;
+  int iRootPage;
+  Table *pStat;
+  Vdbe *v = sqlite3GetVdbe(pParse);
+
+  pDb = &db->aDb[iDb];
+  if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
+    /* The sqlite_stat1 tables does not exist.  Create it.  
+    ** Note that a side-effect of the CREATE TABLE statement is to leave
+    ** the rootpage of the new table on the top of the stack.  This is
+    ** important because the OpenWrite opcode below will be needing it. */
+    sqlite3NestedParse(pParse,
+      "CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)",
+      pDb->zName
+    );
+    iRootPage = 0;  /* Cause rootpage to be taken from top of stack */
+  }else if( zWhere ){
+    /* The sqlite_stat1 table exists.  Delete all entries associated with
+    ** the table zWhere. */
+    sqlite3NestedParse(pParse,
+       "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q",
+       pDb->zName, zWhere
+    );
+    iRootPage = pStat->tnum;
+  }else{
+    /* The sqlite_stat1 table already exists.  Delete all rows. */
+    iRootPage = pStat->tnum;
+    sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb);
+  }
+
+  /* Open the sqlite_stat1 table for writing.
+  */
+  sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
+  sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage);
+  sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3);
+}
+
+/*
+** Generate code to do an analysis of all indices associated with
+** a single table.
+*/
+static void analyzeOneTable(
+  Parse *pParse,   /* Parser context */
+  Table *pTab,     /* Table whose indices are to be analyzed */
+  int iStatCur,    /* Cursor that writes to the sqlite_stat1 table */
+  int iMem         /* Available memory locations begin here */
+){
+  Index *pIdx;     /* An index to being analyzed */
+  int iIdxCur;     /* Cursor number for index being analyzed */
+  int nCol;        /* Number of columns in the index */
+  Vdbe *v;         /* The virtual machine being built up */
+  int i;           /* Loop counter */
+  int topOfLoop;   /* The top of the loop */
+  int endOfLoop;   /* The end of the loop */
+  int addr;        /* The address of an instruction */
+
+  v = sqlite3GetVdbe(pParse);
+  if( pTab==0 || pTab->pIndex==0 || pTab->pIndex->pNext==0 ){
+    /* Do no analysis for tables with fewer than 2 indices */
+    return;
+  }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+  if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
+      pParse->db->aDb[pTab->iDb].zName ) ){
+    return;
+  }
+#endif
+
+  iIdxCur = pParse->nTab;
+  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+    /* Open a cursor to the index to be analyzed
+    */
+    sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
+    VdbeComment((v, "# %s", pIdx->zName));
+    sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum,
+                     (char*)&pIdx->keyInfo, P3_KEYINFO);
+    nCol = pIdx->nColumn;
+    if( iMem+nCol*2>=pParse->nMem ){
+      pParse->nMem = iMem+nCol*2+1;
+    }
+    sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, nCol+1);
+
+    /* Memory cells are used as follows:
+    **
+    **    mem[iMem]:             The total number of rows in the table.
+    **    mem[iMem+1]:           Number of distinct values in column 1
+    **    ...
+    **    mem[iMem+nCol]:        Number of distinct values in column N
+    **    mem[iMem+nCol+1]       Last observed value of column 1
+    **    ...
+    **    mem[iMem+nCol+nCol]:   Last observed value of column N
+    **
+    ** Cells iMem through iMem+nCol are initialized to 0.  The others
+    ** are initialized to NULL.
+    */
+    sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
+    for(i=0; i<=nCol; i++){
+      sqlite3VdbeAddOp(v, OP_MemStore, iMem+i, i==nCol);
+    }
+    sqlite3VdbeAddOp(v, OP_Null, 0, 0);
+    for(i=0; i<nCol; i++){
+      sqlite3VdbeAddOp(v, OP_MemStore, iMem+nCol+i+1, i==nCol-1);
+    }
+
+    /* Do the analysis.
+    */
+    endOfLoop = sqlite3VdbeMakeLabel(v);
+    sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, endOfLoop);
+    topOfLoop = sqlite3VdbeCurrentAddr(v);
+    sqlite3VdbeAddOp(v, OP_MemIncr, iMem, 0);
+    for(i=0; i<nCol; i++){
+      sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
+      sqlite3VdbeAddOp(v, OP_MemLoad, iMem+nCol+i+1, 0);
+      sqlite3VdbeAddOp(v, OP_Ne, 0x100, 0);
+    }
+    sqlite3VdbeAddOp(v, OP_Goto, 0, endOfLoop);
+    for(i=0; i<nCol; i++){
+      addr = sqlite3VdbeAddOp(v, OP_MemIncr, iMem+i+1, 0);
+      sqlite3VdbeChangeP2(v, topOfLoop + 3*i + 3, addr);
+      sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
+      sqlite3VdbeAddOp(v, OP_MemStore, iMem+nCol+i+1, 1);
+    }
+    sqlite3VdbeResolveLabel(v, endOfLoop);
+    sqlite3VdbeAddOp(v, OP_Next, iIdxCur, topOfLoop);
+    sqlite3VdbeAddOp(v, OP_Close, iIdxCur, 0);
+
+    /* Store the results.  
+    **
+    ** The result is a single row of the sqlite_stmt1 table.  The first
+    ** two columns are the names of the table and index.  The third column
+    ** is a string composed of a list of integer statistics about the
+    ** index.  The first integer in the list is the total number of entires
+    ** in the index.  There is one additional integer in the list for each
+    ** column of the table.  This additional integer is a guess of how many
+    ** rows of the table the index will select.  If D is the count of distinct
+    ** values and K is the total number of rows, then the integer is computed
+    ** as:
+    **
+    **        I = (K+D-1)/D
+    **
+    ** If K==0 then no entry is made into the sqlite_stat1 table.  
+    ** If K>0 then it is always the case the D>0 so division by zero
+    ** is never possible.
+    */
+    sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
+    addr = sqlite3VdbeAddOp(v, OP_IfNot, 0, 0);
+    sqlite3VdbeAddOp(v, OP_NewRowid, iStatCur, 0);
+    sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
+    sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0);
+    sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
+    sqlite3VdbeOp3(v, OP_String8, 0, 0, " ", 0);
+    for(i=0; i<nCol; i++){
+      sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
+      sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0);
+      sqlite3VdbeAddOp(v, OP_Add, 0, 0);
+      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);
+      sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0);
+      sqlite3VdbeAddOp(v, OP_Divide, 0, 0);
+      if( i==nCol-1 ){
+        sqlite3VdbeAddOp(v, OP_Concat, nCol*2-1, 0);
+      }else{
+        sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
+      }
+    }
+    sqlite3VdbeOp3(v, OP_MakeRecord, 3, 0, "ttt", 0);
+    sqlite3VdbeAddOp(v, OP_Insert, iStatCur, 0);
+    sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
+  }
+}
+
+/*
+** Generate code that will cause the most recent index analysis to
+** be laoded into internal hash tables where is can be used.
+*/
+static void loadAnalysis(Parse *pParse, int iDb){
+  Vdbe *v = sqlite3GetVdbe(pParse);
+  sqlite3VdbeAddOp(v, OP_LoadAnalysis, iDb, 0);
+}
+
+/*
+** Generate code that will do an analysis of an entire database
+*/
+static void analyzeDatabase(Parse *pParse, int iDb){
+  sqlite3 *db = pParse->db;
+  HashElem *k;
+  int iStatCur;
+  int iMem;
+
+  sqlite3BeginWriteOperation(pParse, 0, iDb);
+  iStatCur = pParse->nTab++;
+  openStatTable(pParse, iDb, iStatCur, 0);
+  iMem = pParse->nMem;
+  for(k=sqliteHashFirst(&db->aDb[iDb].tblHash);  k; k=sqliteHashNext(k)){
+    Table *pTab = (Table*)sqliteHashData(k);
+    analyzeOneTable(pParse, pTab, iStatCur, iMem);
+  }
+  loadAnalysis(pParse, iDb);
+}
+
+/*
+** Generate code that will do an analysis of a single table in
+** a database.
+*/
+static void analyzeTable(Parse *pParse, Table *pTab){
+  int iDb;
+  int iStatCur;
+
+  assert( pTab!=0 );
+  iDb = pTab->iDb;
+  sqlite3BeginWriteOperation(pParse, 0, iDb);
+  iStatCur = pParse->nTab++;
+  openStatTable(pParse, iDb, iStatCur, pTab->zName);
+  analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem);
+  loadAnalysis(pParse, iDb);
+}
+
+/*
+** Generate code for the ANALYZE command.  The parser calls this routine
+** when it recognizes an ANALYZE command.
+**
+**        ANALYZE                            -- 1
+**        ANALYZE  <database>                -- 2
+**        ANALYZE  ?<database>.?<tablename>  -- 3
+**
+** Form 1 causes all indices in all attached databases to be analyzed.
+** Form 2 analyzes all indices the single database named.
+** Form 3 analyzes all indices associated with the named table.
+*/
+void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
+  sqlite3 *db = pParse->db;
+  int iDb;
+  int i;
+  char *z, *zDb;
+  Table *pTab;
+  Token *pTableName;
+
+  /* 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 ){
+    /* Form 1:  Analyze everything */
+    for(i=0; i<db->nDb; i++){
+      if( i==1 ) continue;  /* Do not analyze the TEMP database */
+      analyzeDatabase(pParse, i);
+    }
+  }else if( pName2==0 || pName2->n==0 ){
+    /* Form 2:  Analyze the database or table named */
+    iDb = sqlite3FindDb(db, pName1);
+    if( iDb>=0 ){
+      analyzeDatabase(pParse, iDb);
+    }else{
+      z = sqlite3NameFromToken(pName1);
+      pTab = sqlite3LocateTable(pParse, z, 0);
+      sqliteFree(z);
+      if( pTab ){
+        analyzeTable(pParse, pTab);
+      }
+    }
+  }else{
+    /* Form 3: Analyze the fully qualified table name */
+    iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
+    if( iDb>=0 ){
+      zDb = db->aDb[iDb].zName;
+      z = sqlite3NameFromToken(pTableName);
+      pTab = sqlite3LocateTable(pParse, z, zDb);
+      sqliteFree(z);
+      if( pTab ){
+        analyzeTable(pParse, pTab);
+      }
+    }   
+  }
+}
+
+/*
+** Used to pass information from the analyzer reader through to the
+** callback routine.
+*/
+typedef struct analysisInfo analysisInfo;
+struct analysisInfo {
+  sqlite3 *db;
+  const char *zDatabase;
+};
+
+/*
+** This callback is invoked once for each index when reading the
+** sqlite_stat1 table.  
+**
+**     argv[0] = name of the index
+**     argv[1] = results of analysis - on integer for each column
+*/
+static int analysisLoader(void *pData, int argc, char **argv, char **azNotUsed){
+  analysisInfo *pInfo = (analysisInfo*)pData;
+  Index *pIndex;
+  int i, c;
+  unsigned int v;
+  const char *z;
+
+  assert( argc==2 );
+  if( argv[0]==0 || argv[1]==0 ){
+    return 0;
+  }
+  pIndex = sqlite3FindIndex(pInfo->db, argv[0], pInfo->zDatabase);
+  if( pIndex==0 ){
+    return 0;
+  }
+  z = argv[1];
+  for(i=0; *z && i<=pIndex->nColumn; i++){
+    v = 0;
+    while( (c=z[0])>='0' && c<='9' ){
+      v = v*10 + c - '0';
+      z++;
+    }
+    pIndex->aiRowEst[i] = v;
+    if( *z==' ' ) z++;
+  }
+  return 0;
+}
+
+/*
+** Load the content of the sqlite_stat1 table into the index hash tables.
+*/
+void sqlite3AnalysisLoad(sqlite3 *db, int iDb){
+  analysisInfo sInfo;
+  HashElem *i;
+  char *zSql;
+
+  /* Clear any prior statistics */
+  for(i=sqliteHashFirst(&db->aDb[iDb].idxHash); i; i=sqliteHashNext(i)){
+    Index *pIdx = sqliteHashData(i);
+    sqlite3DefaultRowEst(pIdx);
+  }
+
+  /* Check to make sure the sqlite_stat1 table existss */
+  sInfo.db = db;
+  sInfo.zDatabase = db->aDb[iDb].zName;
+  if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
+     return;
+  }
+
+
+  /* Load new statistics out of the sqlite_stat1 table */
+  zSql = sqlite3MPrintf("SELECT idx, stat FROM %Q.sqlite_stat1",
+                        sInfo.zDatabase);
+  sqlite3SafetyOff(db);
+  sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
+  sqlite3SafetyOn(db);
+  sqliteFree(zSql);
+}
+
+
+#endif /* SQLITE_OMIT_ANALYZE */
index 5c8953467c38b9afa6ba6d10294d52690ecffdc4..46b653e97509280bcd908cd27626e57e6e91318a 100644 (file)
@@ -146,8 +146,8 @@ void sqlite3Attach(
       db->aDb[i].pBt = 0;
     }
     sqlite3ResetInternalSchema(db, 0);
-    if( 0==pParse->nErr ){
-      pParse->nErr++;
+    assert( pParse->nErr>0 );  /* Always set by sqlite3ReadSchema() */
+    if( pParse->rc==SQLITE_OK ){
       pParse->rc = SQLITE_ERROR;
     }
   }
index 5cfc118d446a2c3653ad35d6834ae9de7c13214f..3f1dfa92c74e2f86abdcaf25b5e0e946ea36daed 100644 (file)
@@ -234,8 +234,19 @@ typedef struct MemPage MemPage;
 /*
 ** This is a magic string that appears at the beginning of every
 ** SQLite database in order to identify the file as a real database.
-**                                  123456789 123456 */
-static const char zMagicHeader[] = "SQLite format 3";
+**
+** You can change this value at compile-time by specifying a
+** -DSQLITE_FILE_HEADER="..." on the compiler command-line.  The
+** header must be exactly 16 bytes including the zero-terminator so
+** the string itself should be 15 characters long.  If you change
+** the header, then your custom library will not be able to read 
+** databases generated by the standard tools and the standard tools
+** will not be able to read databases created by your custom library.
+*/
+#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
+#  define SQLITE_FILE_HEADER "SQLite format 3"
+#endif
+static const char zMagicHeader[] = SQLITE_FILE_HEADER;
 
 /*
 ** Page type flags.  An ORed combination of these flags appear as the
@@ -1334,6 +1345,15 @@ int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){
 }
 #endif
 
+/*
+** Return TRUE if the given btree is set to safety level 1.  In other
+** words, return TRUE if no sync() occurs on the disk files.
+*/
+int sqlite3BtreeSyncDisabled(Btree *pBt){
+  assert( pBt && pBt->pPager );
+  return sqlite3pager_nosync(pBt->pPager);
+}
+
 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
 /*
 ** Change the default pages size and the number of reserved bytes per page.
@@ -1595,8 +1615,6 @@ static int newDatabase(Btree *pBt){
 */
 int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){
   int rc = SQLITE_OK;
-  int busy = 0;
-  BusyHandler *pH;
 
   /* If the btree is already in a write-transaction, or it
   ** is already in a read-transaction and a read-transaction
@@ -1630,9 +1648,7 @@ int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){
       unlockBtreeIfUnused(pBt);
     }
   }while( rc==SQLITE_BUSY && pBt->inTrans==TRANS_NONE &&
-      (pH = pBt->pBusyHandler)!=0 && 
-      pH->xFunc && pH->xFunc(pH->pArg, busy++)
-  );
+          sqlite3InvokeBusyHandler(pBt->pBusyHandler) );
   return rc;
 }
 
@@ -3595,17 +3611,19 @@ static void assemblePage(
   data = pPage->aData;
   hdr = pPage->hdrOffset;
   put2byte(&data[hdr+3], nCell);
-  cellbody = allocateSpace(pPage, totalSize);
-  assert( cellbody>0 );
-  assert( pPage->nFree >= 2*nCell );
-  pPage->nFree -= 2*nCell;
-  for(i=0; i<nCell; i++){
-    put2byte(&data[cellptr], cellbody);
-    memcpy(&data[cellbody], apCell[i], aSize[i]);
-    cellptr += 2;
-    cellbody += aSize[i];
+  if( nCell ){
+    cellbody = allocateSpace(pPage, totalSize);
+    assert( cellbody>0 );
+    assert( pPage->nFree >= 2*nCell );
+    pPage->nFree -= 2*nCell;
+    for(i=0; i<nCell; i++){
+      put2byte(&data[cellptr], cellbody);
+      memcpy(&data[cellbody], apCell[i], aSize[i]);
+      cellptr += 2;
+      cellbody += aSize[i];
+    }
+    assert( cellbody==pPage->pBt->usableSize );
   }
-  assert( cellbody==pPage->pBt->usableSize );
   pPage->nCell = nCell;
 }
 
@@ -3809,7 +3827,7 @@ static int balance_nonroot(MemPage *pPage){
   /*
   ** 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
+  ** and 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.
@@ -4082,7 +4100,12 @@ static int balance_nonroot(MemPage *pPage){
     szNew[i] = szRight;
     szNew[i-1] = szLeft;
   }
-  assert( cntNew[0]>0 );
+
+  /* Either we found one or more cells (cntnew[0])>0) or we are the
+  ** a virtual root page.  A virtual root page is when the real root
+  ** page is page 1 and we are the only child of that page.
+  */
+  assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) );
 
   /*
   ** Allocate k new pages.  Reuse old pages where possible.
@@ -4171,7 +4194,7 @@ static int balance_nonroot(MemPage *pPage){
     assert( j<nMaxCells );
     assert( pNew->pgno==pgnoNew[i] );
     assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]);
-    assert( pNew->nCell>0 );
+    assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) );
     assert( pNew->nOverflow==0 );
 
 #ifndef SQLITE_OMIT_AUTOVACUUM
index bd09b46423b85e4b33f8847404c960163584fb5c..9d4401ac81851e2998ceb2a9e54666850fa23e9b 100644 (file)
@@ -58,6 +58,7 @@ int sqlite3BtreeClose(Btree*);
 int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
 int sqlite3BtreeSetCacheSize(Btree*,int);
 int sqlite3BtreeSetSafetyLevel(Btree*,int);
+int sqlite3BtreeSyncDisabled(Btree*);
 int sqlite3BtreeSetPageSize(Btree*,int,int);
 int sqlite3BtreeGetPageSize(Btree*);
 int sqlite3BtreeGetReserve(Btree*);
index 450316e5a4b5defc5919ad66c55ce8d47064cc80..67e83e970bdba5387909e3a6dd258ee544617d62 100644 (file)
@@ -200,9 +200,6 @@ Table *sqlite3LocateTable(Parse *pParse, const char *zName, const char *zDbase){
   if( p==0 ){
     if( zDbase ){
       sqlite3ErrorMsg(pParse, "no such table: %s.%s", zDbase, zName);
-    }else if( sqlite3FindTable(pParse->db, zName, 0)!=0 ){
-      sqlite3ErrorMsg(pParse, "table \"%s\" is not in database \"%s\"",
-         zName, zDbase);
     }else{
       sqlite3ErrorMsg(pParse, "no such table: %s", zName);
     }
@@ -258,10 +255,7 @@ static void sqliteDeleteIndex(sqlite3 *db, Index *p){
   assert( db!=0 && p->zName!=0 );
   pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName,
                           strlen(p->zName)+1, 0);
-  if( pOld!=0 && pOld!=p ){
-    sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
-                     strlen(pOld->zName)+1, pOld);
-  }
+  assert( pOld==0 || pOld==p );
   freeIndex(p);
 }
 
@@ -535,7 +529,7 @@ void sqlite3OpenMasterTable(Vdbe *v, int iDb){
 ** index of the named database in db->aDb[], or -1 if the named db 
 ** does not exist.
 */
-static int findDb(sqlite3 *db, Token *pName){
+int sqlite3FindDb(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 */
@@ -583,7 +577,7 @@ int sqlite3TwoPartName(
   if( pName2 && pName2->n>0 ){
     assert( !db->init.busy );
     *pUnqual = pName2;
-    iDb = findDb(db, pName1);
+    iDb = sqlite3FindDb(db, pName1);
     if( iDb<0 ){
       sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
       pParse->nErr++;
@@ -745,7 +739,7 @@ void sqlite3StartTable(
   ** so that INSERT can find the table easily.
   */
 #ifndef SQLITE_OMIT_AUTOINCREMENT
-  if( strcmp(zName, "sqlite_sequence")==0 ){
+  if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
     db->aDb[iDb].pSeqTab = pTable;
   }
 #endif
@@ -902,11 +896,11 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
 ** If none of the substrings in the above table are found,
 ** SQLITE_AFF_NUMERIC is returned.
 */
-static char sqlite3AffinityType(const char *zType, int nType){
+char sqlite3AffinityType(const Token *pType){
   u32 h = 0;
   char aff = SQLITE_AFF_NUMERIC;
-  const unsigned char *zIn = zType;
-  const unsigned char *zEnd = (zIn+nType);
+  const unsigned char *zIn = pType->z;
+  const unsigned char *zEnd = &pType->z[pType->n];
 
   while( zIn!=zEnd ){
     h = (h<<8) + sqlite3UpperToLower[*zIn];
@@ -938,30 +932,18 @@ static char sqlite3AffinityType(const char *zType, int nType){
 ** that contains the typename of the column and store that string
 ** in zType.
 */ 
-void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
+void sqlite3AddColumnType(Parse *pParse, Token *pType){
   Table *p;
-  int i, j;
-  int n;
-  char *z;
-  const unsigned char *zIn;
-
+  int i;
   Column *pCol;
+
   if( (p = pParse->pNewTable)==0 ) return;
   i = p->nCol-1;
   if( i<0 ) return;
   pCol = &p->aCol[i];
-  zIn = pFirst->z;
-  n = pLast->n + (pLast->z - zIn);
   assert( pCol->zType==0 );
-  z = pCol->zType = sqliteMallocRaw(n+1);
-  if( z==0 ) return;
-  for(i=j=0; i<n; i++){
-    int c = zIn[i];
-    if( isspace(c) ) continue;
-    z[j++] = c;
-  }
-  z[j] = 0;
-  pCol->affinity = sqlite3AffinityType(z, n);
+  pCol->zType = sqlite3NameFromToken(pType);
+  pCol->affinity = sqlite3AffinityType(pType);
 }
 
 /*
@@ -977,14 +959,15 @@ void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
 void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
   Table *p;
   Column *pCol;
-  if( (p = pParse->pNewTable)==0 ) return;
-  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);
+  if( (p = pParse->pNewTable)!=0 ){
+    pCol = &(p->aCol[p->nCol-1]);
+    if( !sqlite3ExprIsConstantOrFunction(pExpr) ){
+      sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
+          pCol->zName);
+    }else{
+      sqlite3ExprDelete(pCol->pDflt);
+      pCol->pDflt = sqlite3ExprDup(pExpr);
+    }
   }
   sqlite3ExprDelete(pExpr);
 }
@@ -1317,13 +1300,11 @@ void sqlite3EndTable(
     */
     if( p->pSelect==0 ){
       /* A regular table */
-      /* sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0); */
       zType = "table";
       zType2 = "TABLE";
 #ifndef SQLITE_OMIT_VIEW
     }else{
       /* A view */
-    /*  sqlite3VdbeAddOp(v, OP_Integer, 0, 0); */
       zType = "view";
       zType2 = "VIEW";
 #endif
@@ -1535,10 +1516,13 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
   ** Actually, this error is caught previously and so the following test
   ** should always fail.  But we will leave it in place just to be safe.
   */
+#if 0
   if( pTable->nCol<0 ){
     sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
     return 1;
   }
+#endif
+  assert( pTable->nCol>=0 );
 
   /* If we get this far, it means we need to compute the table names.
   ** Note that the call to sqlite3ResultSetOfSelect() will expand any
@@ -1973,7 +1957,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   int addr1;                     /* Address of top of loop */
   int tnum;                      /* Root page of index */
   Vdbe *v;                       /* Generate code into this virtual machine */
-  int isUnique;                  /* True for a unique index */
 
 #ifndef SQLITE_OMIT_AUTHORIZATION
   if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
@@ -2002,16 +1985,21 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   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);
+  sqlite3OpenTableForReading(v, iTab, pTab);
   addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
   sqlite3GenerateIndexKey(v, pIndex, iTab);
-  isUnique = pIndex->onError!=OE_None;
-  sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, isUnique);
-  if( isUnique ){
-    sqlite3VdbeChangeP3(v, -1, "indexed columns are not unique", P3_STATIC);
-  }
+  if( pIndex->onError!=OE_None ){
+    int curaddr = sqlite3VdbeCurrentAddr(v);
+    int addr2 = curaddr+4;
+    sqlite3VdbeChangeP2(v, curaddr-1, addr2);
+    sqlite3VdbeAddOp(v, OP_Rowid, iTab, 0);
+    sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
+    sqlite3VdbeAddOp(v, OP_IsUnique, iIdx, addr2);
+    sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort,
+                    "indexed columns are not unique", P3_STATIC);
+    assert( addr2==sqlite3VdbeCurrentAddr(v) );
+  }
+  sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, 0);
   sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1);
   sqlite3VdbeChangeP2(v, addr1, sqlite3VdbeCurrentAddr(v));
   sqlite3VdbeAddOp(v, OP_Close, iTab, 0);
@@ -2079,7 +2067,9 @@ void sqlite3CreateIndex(
     if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
         sqlite3FixSrcList(&sFix, pTblName)
     ){
-      goto exit_create_index;
+      /* Because the parser constructs pTblName from a single identifier,
+      ** sqlite3FixSrcList can never fail. */
+      assert(0);
     }
     pTab = sqlite3LocateTable(pParse, pTblName->a[0].zName, 
         pTblName->a[0].zDatabase);
@@ -2177,11 +2167,12 @@ void sqlite3CreateIndex(
   /* 
   ** Allocate the index structure. 
   */
-  pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 +
-                        (sizeof(int) + sizeof(CollSeq*))*pList->nExpr );
+  pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + sizeof(int) +
+                        (sizeof(int)*2 + sizeof(CollSeq*))*pList->nExpr );
   if( sqlite3_malloc_failed ) goto exit_create_index;
   pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nExpr];
-  pIndex->zName = (char*)&pIndex->aiColumn[pList->nExpr];
+  pIndex->aiRowEst = &pIndex->aiColumn[pList->nExpr];
+  pIndex->zName = (char*)&pIndex->aiRowEst[pList->nExpr+1];
   strcpy(pIndex->zName, zName);
   pIndex->pTable = pTab;
   pIndex->nColumn = pList->nExpr;
@@ -2217,6 +2208,7 @@ void sqlite3CreateIndex(
     }
   }
   pIndex->keyInfo.nField = pList->nExpr;
+  sqlite3DefaultRowEst(pIndex);
 
   if( pTab==pParse->pNewTable ){
     /* This routine has been called to create an automatic index as a
@@ -2383,6 +2375,37 @@ exit_create_index:
   return;
 }
 
+/*
+** Fill the Index.aiRowEst[] array with default information - information
+** to be used when we have not run the ANALYZE command.
+**
+** aiRowEst[0] is suppose to contain the number of elements in the index.
+** Since we do not know, guess 1 million.  aiRowEst[1] is an estimate of the
+** number of rows in the table that match any particular value of the
+** first column of the index.  aiRowEst[2] is an estimate of the number
+** of rows that match any particular combiniation of the first 2 columns
+** of the index.  And so forth.  It must always be the case that
+*
+**           aiRowEst[N]<=aiRowEst[N-1]
+**           aiRowEst[N]>=1
+**
+** Apart from that, we have little to go on besides intuition as to
+** how aiRowEst[] should be initialized.  The numbers generated here
+** are based on typical values found in actual indices.
+*/
+void sqlite3DefaultRowEst(Index *pIdx){
+  int *a = pIdx->aiRowEst;
+  int i;
+  assert( a!=0 );
+  a[0] = 1000000;
+  for(i=pIdx->nColumn; i>=1; i--){
+    a[i] = 10;
+  }
+  if( pIdx->onError!=OE_None ){
+    a[pIdx->nColumn] = 1;
+  }
+}
+
 /*
 ** This routine will drop an existing named index.  This routine
 ** implements the DROP INDEX statement.
@@ -2472,6 +2495,32 @@ IdList *sqlite3IdListAppend(IdList *pList, Token *pToken){
   return pList;
 }
 
+/*
+** Delete an IdList.
+*/
+void sqlite3IdListDelete(IdList *pList){
+  int i;
+  if( pList==0 ) return;
+  for(i=0; i<pList->nId; i++){
+    sqliteFree(pList->a[i].zName);
+  }
+  sqliteFree(pList->a);
+  sqliteFree(pList);
+}
+
+/*
+** Return the index in pList of the identifier named zId.  Return -1
+** if not found.
+*/
+int sqlite3IdListIndex(IdList *pList, const char *zName){
+  int i;
+  if( pList==0 ) return -1;
+  for(i=0; i<pList->nId; i++){
+    if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
+  }
+  return -1;
+}
+
 /*
 ** Append a new table name to the given SrcList.  Create a new SrcList if
 ** need be.  A new entry is created in the SrcList even if pToken is NULL.
@@ -2556,32 +2605,6 @@ void sqlite3SrcListAddAlias(SrcList *pList, Token *pToken){
   }
 }
 
-/*
-** Delete an IdList.
-*/
-void sqlite3IdListDelete(IdList *pList){
-  int i;
-  if( pList==0 ) return;
-  for(i=0; i<pList->nId; i++){
-    sqliteFree(pList->a[i].zName);
-  }
-  sqliteFree(pList->a);
-  sqliteFree(pList);
-}
-
-/*
-** Return the index in pList of the identifier named zId.  Return -1
-** if not found.
-*/
-int sqlite3IdListIndex(IdList *pList, const char *zName){
-  int i;
-  if( pList==0 ) return -1;
-  for(i=0; i<pList->nId; i++){
-    if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
-  }
-  return -1;
-}
-
 /*
 ** Delete an entire SrcList including all its substructure.
 */
@@ -2784,7 +2807,7 @@ static int collationMatch(CollSeq *pColl, Index *pIndex){
 ** If pColl==0 then recompute all indices of pTab.
 */
 #ifndef SQLITE_OMIT_REINDEX
-void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
+static void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
   Index *pIndex;              /* An index associated with pTab */
 
   for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
@@ -2802,7 +2825,7 @@ void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
 ** all indices everywhere.
 */
 #ifndef SQLITE_OMIT_REINDEX
-void reindexDatabases(Parse *pParse, CollSeq *pColl){
+static void reindexDatabases(Parse *pParse, CollSeq *pColl){
   Db *pDb;                    /* A single database */
   int iDb;                    /* The database index number */
   sqlite3 *db = pParse->db;   /* The database connection */
@@ -2811,7 +2834,7 @@ void reindexDatabases(Parse *pParse, CollSeq *pColl){
 
   for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
     if( pDb==0 ) continue;
-      for(k=sqliteHashFirst(&pDb->tblHash);  k; k=sqliteHashNext(k)){
+    for(k=sqliteHashFirst(&pDb->tblHash);  k; k=sqliteHashNext(k)){
       pTab = (Table*)sqliteHashData(k);
       reindexTable(pParse, pTab, pColl);
     }
index 9fa621752f12b8f715dc8ce6feb7e39d178ee549..2103c3f711575a0ef5e1a2749781a5ba27d2f21a 100644 (file)
@@ -147,7 +147,7 @@ int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
 ** the collation sequence name. A pointer to this string is stored in
 ** each collation sequence structure.
 */
-static CollSeq * findCollSeqEntry(
+static CollSeq *findCollSeqEntry(
   sqlite3 *db,
   const char *zName,
   int nName,
@@ -286,10 +286,9 @@ FuncDef *sqlite3FindFunction(
   ** new entry to the hash table and return it.
   */
   if( createFlag && bestmatch<6 && 
-      (pBest = sqliteMalloc(sizeof(*pBest)+nName+1)) ){
+      (pBest = sqliteMalloc(sizeof(*pBest)+nName)) ){
     pBest->nArg = nArg;
     pBest->pNext = pFirst;
-    pBest->zName = (char*)&pBest[1];
     pBest->iPrefEnc = enc;
     memcpy(pBest->zName, zName, nName);
     pBest->zName[nName] = 0;
index c6872831b9e4216c303113190f0b8251b5c94fc7..7d398df489995215ba817fcbbe22a1b518de95e8 100644 (file)
@@ -124,11 +124,7 @@ static int getDigits(const char *zDate, ...){
 ** Read text from z[] and convert into a floating point number.  Return
 ** the number of digits converted.
 */
-static int getValue(const char *z, double *pR){
-  const char *zEnd;
-  *pR = sqlite3AtoF(z, &zEnd);
-  return zEnd - z;
-}
+#define getValue sqlite3AtoF
 
 /*
 ** Parse a timezone extension on the end of a date-time.
@@ -320,7 +316,7 @@ static int parseDateOrTime(const char *zDate, DateTime *p){
     p->validJD = 1;
     return 0;
   }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
-    p->rJD = sqlite3AtoF(zDate, 0);
+    getValue(zDate, &p->rJD);
     p->validJD = 1;
     return 0;
   }
index 15eb8f4e8d373e7f13d2b5b047e7226a3db30162..f9bb49e57732091854a344496b28842560c2911f 100644 (file)
@@ -65,8 +65,8 @@ void sqlite3OpenTableForReading(
   Table *pTab     /* The table to be opened */
 ){
   sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-  sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
   VdbeComment((v, "# %s", pTab->zName));
+  sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
   sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
 }
 
@@ -240,7 +240,7 @@ void sqlite3DeleteFrom(
     /* Remember the rowid of every item to be deleted.
     */
     sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
-    sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
+    sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
     if( db->flags & SQLITE_CountRows ){
       sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
     }
@@ -260,14 +260,13 @@ void sqlite3DeleteFrom(
     ** database scan.  We have to delete items after the scan is complete
     ** because deleting an item can change the scan order.
     */
-    sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
     end = sqlite3VdbeMakeLabel(v);
 
     /* This is the beginning of the delete loop when there are
     ** row triggers.
     */
     if( triggers_exist ){
-      addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
+      addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
       if( !isView ){
         sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
         sqlite3OpenTableForReading(v, iCur, pTab);
@@ -288,7 +287,7 @@ void sqlite3DeleteFrom(
     if( !isView ){
       /* Open cursors for the table we are deleting from and all its
       ** indices.  If there are row triggers, this happens inside the
-      ** OP_ListRead loop because the cursor have to all be closed
+      ** OP_FifoRead loop because the cursor have to all be closed
       ** before the trigger fires.  If there are no row triggers, the
       ** cursors are opened only once on the outside the loop.
       */
@@ -297,7 +296,7 @@ void sqlite3DeleteFrom(
       /* This is the beginning of the delete loop when there are no
       ** row triggers */
       if( !triggers_exist ){ 
-        addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
+        addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
       }
 
       /* Delete the row */
@@ -322,7 +321,6 @@ void sqlite3DeleteFrom(
     /* End of the delete loop */
     sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
     sqlite3VdbeResolveLabel(v, end);
-    sqlite3VdbeAddOp(v, OP_ListReset, 0, 0);
 
     /* Close the cursors after the loop if there are no row triggers */
     if( !triggers_exist ){
@@ -442,6 +440,6 @@ void sqlite3GenerateIndexKey(
       sqlite3ColumnDefault(v, pTab, idx);
     }
   }
-  sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24));
+  sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
   sqlite3IndexAffinityStr(v, pIdx);
 }
index ec40891a3aea863237d5e5f3fc280e2469048b5a..0bb0ae334eb2c45793ea150bf262e0fe3bcf0838 100644 (file)
@@ -15,7 +15,6 @@
 ** $Id$
 */
 #include "sqliteInt.h"
-#include "os.h"
 
 /*
 ** Set all the parameters in the compiled SQL statement to NULL.
index 70bdd8692fa87c4dad5b9f2bc31bb68caa9f700f..a83b9d78cf6d743b12ed622052516ec877108963 100644 (file)
 ** SELECT * FROM t1 WHERE (select a from t1);
 */
 char sqlite3ExprAffinity(Expr *pExpr){
-  if( pExpr->op==TK_AS ){
+  int op = pExpr->op;
+  if( op==TK_AS ){
     return sqlite3ExprAffinity(pExpr->pLeft);
   }
-  if( pExpr->op==TK_SELECT ){
+  if( op==TK_SELECT ){
     return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr);
   }
+#ifndef SQLITE_OMIT_CAST
+  if( op==TK_CAST ){
+    return sqlite3AffinityType(&pExpr->token);
+  }
+#endif
   return pExpr->affinity;
 }
 
@@ -51,7 +57,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
   CollSeq *pColl = 0;
   if( pExpr ){
     pColl = pExpr->pColl;
-    if( pExpr->op==TK_AS && !pColl ){
+    if( (pExpr->op==TK_AS || pExpr->op==TK_CAST) && !pColl ){
       return sqlite3ExprCollSeq(pParse, pExpr->pLeft);
     }
   }
@@ -87,6 +93,7 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){
     return SQLITE_AFF_NONE;
   }else{
     /* One side is a column, the other is not. Use the columns affinity. */
+    assert( aff1==0 || aff2==0 );
     return (aff1 + aff2);
   }
 }
@@ -207,9 +214,8 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
 /*
 ** 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.
+** on the stack.  "#0" means the top of the stack.
+** "#1" means the next down on the stack.  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.
@@ -220,23 +226,19 @@ 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;
   }
+  if( v==0 ) 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;
-  }
+  p->iTable = pParse->nMem++;
+  sqlite3VdbeAddOp(v, OP_Dup, depth, 0);
+  sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1);
   return p;
 }
 
@@ -378,6 +380,21 @@ void sqlite3ExprDelete(Expr *p){
   sqliteFree(p);
 }
 
+/*
+** The Expr.token field might be a string literal that is quoted.
+** If so, remove the quotation marks.
+*/
+void sqlite3DequoteExpr(Expr *p){
+  if( ExprHasAnyProperty(p, EP_Dequoted) ){
+    return;
+  }
+  ExprSetProperty(p, EP_Dequoted);
+  if( p->token.dyn==0 ){
+    sqlite3TokenCopy(&p->token, &p->token);
+  }
+  sqlite3Dequote((char*)p->token.z);
+}
+
 
 /*
 ** The following group of routines make deep copies of expressions,
@@ -529,7 +546,7 @@ Select *sqlite3SelectDup(Select *p){
   pNew->pOffset = sqlite3ExprDup(p->pOffset);
   pNew->iLimit = -1;
   pNew->iOffset = -1;
-  pNew->ppOpenTemp = 0;
+  pNew->ppOpenVirtual = 0;
   pNew->isResolved = p->isResolved;
   pNew->isAgg = p->isAgg;
   return pNew;
@@ -607,6 +624,8 @@ void sqlite3ExprListDelete(ExprList *pList){
 **
 ** The return value from this routine is 1 to abandon the tree walk
 ** and 0 to continue.
+**
+** NOTICE:  This routine does *not* descend into subqueries.
 */
 static int walkExprList(ExprList *, int (*)(void *, Expr*), void *);
 static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
@@ -664,17 +683,26 @@ static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){
 */
 static int exprNodeIsConstant(void *pArg, Expr *pExpr){
   switch( pExpr->op ){
+    /* Consider functions to be constant if all their arguments are constant
+    ** and *pArg==2 */
+    case TK_FUNCTION:
+      if( *((int*)pArg)==2 ) return 0;
+      /* Fall through */
     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;
+    case TK_IN:
+      if( pExpr->pSelect ){
+        *((int*)pArg) = 0;
+        return 2;
+      }
     default:
       return 0;
   }
@@ -682,7 +710,7 @@ static int exprNodeIsConstant(void *pArg, Expr *pExpr){
 
 /*
 ** Walk an expression tree.  Return 1 if the expression is constant
-** and 0 if it involves variables.
+** and 0 if it involves variables or function calls.
 **
 ** For the purposes of this function, a double-quoted string (ex: "abc")
 ** is considered a variable but a single-quoted string (ex: 'abc') is
@@ -694,6 +722,21 @@ int sqlite3ExprIsConstant(Expr *p){
   return isConst;
 }
 
+/*
+** Walk an expression tree.  Return 1 if the expression is constant
+** or a function call with constant arguments.  Return and 0 if there
+** are any variables.
+**
+** For the purposes of this function, a double-quoted string (ex: "abc")
+** is considered a variable but a single-quoted string (ex: 'abc') is
+** a constant.
+*/
+int sqlite3ExprIsConstantOrFunction(Expr *p){
+  int isConst = 2;
+  walkExprTree(p, exprNodeIsConstant, &isConst);
+  return isConst!=0;
+}
+
 /*
 ** If the expression p codes a constant integer that is small enough
 ** to fit in a 32-bit integer, return 1 and put the value of the integer
@@ -1218,19 +1261,25 @@ struct QueryCoder {
 */
 #ifndef SQLITE_OMIT_SUBQUERY
 void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
-  int label = 0;                         /* Address after sub-select code */
+  int testAddr = 0;                       /* One-time test address */
   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).
+  /* This code must be run in its entirety every time it is encountered
+  ** if any of the following is true:
+  **
+  **    *  The right-hand side is a correlated subquery
+  **    *  The right-hand side is an expression list containing variables
+  **    *  We are inside a trigger
+  **
+  ** If all of the above are false, then we can run this code just once
+  ** save the results, and reuse the same result on subsequent invocations.
   */
   if( !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);
+    testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0);
+    assert( testAddr>0 );
     sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
     sqlite3VdbeAddOp(v, OP_MemStore, mem, 1);
   }
@@ -1243,12 +1292,12 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
     case TK_IN: {
       char affinity;
       KeyInfo keyInfo;
-      int addr;        /* Address of OP_OpenTemp instruction */
+      int addr;        /* Address of OP_OpenVirtual instruction */
 
       affinity = sqlite3ExprAffinity(pExpr->pLeft);
 
       /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
-      ** expression it is handled the same way. A temporary table is 
+      ** expression it is handled the same way. A virtual table is 
       ** filled with single-field index keys representing the results
       ** from the SELECT or the <exprlist>.
       **
@@ -1261,7 +1310,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
       ** is used.
       */
       pExpr->iTable = pParse->nTab++;
-      addr = sqlite3VdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 0);
+      addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, pExpr->iTable, 0);
       memset(&keyInfo, 0, sizeof(keyInfo));
       keyInfo.nField = 1;
       sqlite3VdbeAddOp(v, OP_SetNumColumns, pExpr->iTable, 1);
@@ -1290,20 +1339,30 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
         ** a column, use numeric affinity.
         */
         int i;
+        ExprList *pList = pExpr->pList;
+        struct ExprList_item *pItem;
+
         if( !affinity ){
           affinity = SQLITE_AFF_NUMERIC;
         }
         keyInfo.aColl[0] = pExpr->pLeft->pColl;
 
         /* Loop through each expression in <exprlist>. */
-        for(i=0; i<pExpr->pList->nExpr; i++){
-          Expr *pE2 = pExpr->pList->a[i].pExpr;
-
-          /* Check that the expression is constant and valid. */
-          if( !sqlite3ExprIsConstant(pE2) ){
-            sqlite3ErrorMsg(pParse,
-              "right-hand side of IN operator must be constant");
-            return;
+        for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
+          Expr *pE2 = pItem->pExpr;
+
+          /* If the expression is not constant then we will need to
+          ** disable the test that was generated above that makes sure
+          ** this code only executes once.  Because for a non-constant
+          ** expression we need to rerun this code each time.
+          */
+          if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){
+            VdbeOp *aOp = sqlite3VdbeGetOp(v, testAddr-1);
+            int i;
+            for(i=0; i<4; i++){
+              aOp[i].opcode = OP_Noop;
+            }
+            testAddr = 0;
           }
 
           /* Evaluate the expression and insert it into the temp table */
@@ -1344,8 +1403,8 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
   if( pExpr->pSelect ){
     sqlite3VdbeAddOp(v, OP_AggContextPop, 0, 0);
   }
-  if( label<0 ){
-    sqlite3VdbeResolveLabel(v, label);
+  if( testAddr ){
+    sqlite3VdbeChangeP2(v, testAddr, sqlite3VdbeCurrentAddr(v));
   }
   return;
 }
@@ -1360,7 +1419,7 @@ static void codeInteger(Vdbe *v, const char *z, int n){
   if( sqlite3GetInt32(z, &i) ){
     sqlite3VdbeAddOp(v, OP_Integer, i, 0);
   }else if( sqlite3FitsIn64Bits(z) ){
-    sqlite3VdbeOp3(v, OP_Integer, 0, 0, z, n);
+    sqlite3VdbeOp3(v, OP_Int64, 0, 0, z, n);
   }else{
     sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n);
   }
@@ -1405,8 +1464,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
     case TK_STRING: {
       assert( TK_FLOAT==OP_Real );
       assert( TK_STRING==OP_String8 );
+      sqlite3DequoteExpr(pExpr);
       sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z, pExpr->token.n);
-      sqlite3VdbeDequoteP3(v, -1);
       break;
     }
     case TK_NULL: {
@@ -1415,9 +1474,16 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
     }
 #ifndef SQLITE_OMIT_BLOB_LITERAL
     case TK_BLOB: {
+      int n;
+      const char *z;
       assert( TK_BLOB==OP_HexBlob );
-      sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z+1, pExpr->token.n-1);
-      sqlite3VdbeDequoteP3(v, -1);
+      n = pExpr->token.n - 3;
+      z = pExpr->token.z + 2;
+      assert( n>=0 );
+      if( n==0 ){
+        z = "";
+      }
+      sqlite3VdbeOp3(v, op, 0, 0, z, n);
       break;
     }
 #endif
@@ -1432,6 +1498,22 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
       sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0);
       break;
     }
+#ifndef SQLITE_OMIT_CAST
+    case TK_CAST: {
+      /* Expressions of the form:   CAST(pLeft AS token) */
+      int aff, op;
+      sqlite3ExprCode(pParse, pExpr->pLeft);
+      aff = sqlite3AffinityType(&pExpr->token);
+      switch( aff ){
+        case SQLITE_AFF_INTEGER:   op = OP_ToInt;      break;
+        case SQLITE_AFF_NUMERIC:   op = OP_ToNumeric;  break;
+        case SQLITE_AFF_TEXT:      op = OP_ToText;     break;
+        case SQLITE_AFF_NONE:      op = OP_ToBlob;     break;
+      }
+      sqlite3VdbeAddOp(v, op, 0, 0);
+      break;
+    }
+#endif /* SQLITE_OMIT_CAST */
     case TK_LT:
     case TK_LE:
     case TK_GT:
@@ -1663,9 +1745,9 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
          assert( pExpr->iColumn==OE_Rollback ||
                  pExpr->iColumn == OE_Abort ||
                  pExpr->iColumn == OE_Fail );
+         sqlite3DequoteExpr(pExpr);
          sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,
                         pExpr->token.z, pExpr->token.n);
-         sqlite3VdbeDequoteP3(v, -1);
       } else {
          assert( pExpr->iColumn == OE_Ignore );
          sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);
@@ -1717,11 +1799,9 @@ int sqlite3ExprCodeExprList(
 ){
   struct ExprList_item *pItem;
   int i, n;
-  Vdbe *v;
   if( pList==0 ) return 0;
-  v = sqlite3GetVdbe(pParse);
   n = pList->nExpr;
-  for(pItem=pList->a, i=0; i<n; i++, pItem++){
+  for(pItem=pList->a, i=n; i>0; i--, pItem++){
     sqlite3ExprCode(pParse, pItem->pExpr);
   }
   return n;
index 92b8625fc6c802d4dca3449c111246ab098e212a..326d98eef622ec8052afa905c9de0b1d7bee568a 100644 (file)
@@ -26,6 +26,9 @@
 #include "vdbeInt.h"
 #include "os.h"
 
+/*
+** Return the collating function associated with a function.
+*/
 static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
   return context->pColl;
 }
@@ -78,6 +81,7 @@ static void typeofFunc(
   sqlite3_result_text(context, z, -1, SQLITE_STATIC);
 }
 
+
 /*
 ** Implementation of the length() function
 */
@@ -183,7 +187,7 @@ static void substrFunc(
 static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   int n = 0;
   double r;
-  char zBuf[100];
+  char zBuf[500];  /* larger than the %f representation of the largest double */
   assert( argc==1 || argc==2 );
   if( argc==2 ){
     if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
@@ -193,7 +197,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   }
   if( SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
   r = sqlite3_value_double(argv[0]);
-  sprintf(zBuf,"%.*f",n,r);
+  sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r);
   sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
 }
 
@@ -307,8 +311,14 @@ struct compareInfo {
   u8 matchSet;
   u8 noCase;
 };
+
 static const struct compareInfo globInfo = { '*', '?', '[', 0 };
-static const struct compareInfo likeInfo = { '%', '_',   0, 1 };
+/* The correct SQL-92 behavior is for the LIKE operator to ignore
+** case.  Thus  'a' LIKE 'A' would be true. */
+static const struct compareInfo likeInfoNorm = { '%', '_',   0, 1 };
+/* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator
+** is case sensitive causing 'a' LIKE 'A' to be false */
+static const struct compareInfo likeInfoAlt = { '%', '_',   0, 0 };
 
 /*
 ** X is a pointer to the first byte of a UTF-8 character.  Increment
@@ -450,6 +460,15 @@ static int patternCompare(
   return *zString==0;
 }
 
+/*
+** Count the number of times that the LIKE operator (or GLOB which is
+** just a variation of LIKE) gets called.  This is used for testing
+** only.
+*/
+#ifdef SQLITE_TEST
+int sqlite3_like_count = 0;
+#endif
+
 
 /*
 ** Implementation of the like() SQL function.  This function implements
@@ -460,8 +479,8 @@ static int patternCompare(
 **
 ** is implemented as like(B,A).
 **
-** If the pointer retrieved by via a call to sqlite3_user_data() is
-** not NULL, then this function uses UTF-16. Otherwise UTF-8.
+** This same function (with a different compareInfo structure) computes
+** the GLOB operator.
 */
 static void likeFunc(
   sqlite3_context *context, 
@@ -484,24 +503,11 @@ static void likeFunc(
     escape = sqlite3ReadUtf8(zEsc);
   }
   if( zA && zB ){
-    sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo, escape));
-  }
-}
-
-/*
-** Implementation of the glob() SQL function.  This function implements
-** the build-in GLOB operator.  The first argument to the function is the
-** string and the second argument is the pattern.  So, the SQL statements:
-**
-**       A GLOB 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, 0));
+    struct compareInfo *pInfo = sqlite3_user_data(context);
+#ifdef SQLITE_TEST
+    sqlite3_like_count++;
+#endif
+    sqlite3_result_int(context, patternCompare(zA, zB, pInfo, escape));
   }
 }
 
@@ -876,16 +882,6 @@ static void countFinalize(sqlite3_context *context){
   sqlite3_result_int(context, p ? p->n : 0);
 }
 
-/*
-** This function tracks state information for the min() and max()
-** aggregate functions.
-*/
-typedef struct MinMaxCtx MinMaxCtx;
-struct MinMaxCtx {
-  char *z;         /* The best so far */
-  char zBuf[28];   /* Space that can be used for storage */
-};
-
 /*
 ** Routines to implement min() and max() aggregate functions.
 */
@@ -962,9 +958,6 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
     { "coalesce",           1, 0, SQLITE_UTF8,    0, 0          },
     { "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},
     { "quote",              1, 0, SQLITE_UTF8,    0, quoteFunc  },
@@ -1036,8 +1029,77 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
   }
   sqlite3RegisterDateTimeFunctions(db);
 #ifdef SQLITE_SSE
-  {
-    sqlite3SseFunctions(db);
-  }
+  sqlite3SseFunctions(db);
+#endif
+#ifdef SQLITE_CASE_SENSITIVE_LIKE
+  sqlite3RegisterLikeFunctions(db, 1);
+#else
+  sqlite3RegisterLikeFunctions(db, 0);
 #endif
 }
+
+/*
+** Set the LIKEOPT flag on the 2-argument function with the given name.
+*/
+static void setLikeOptFlag(sqlite3 *db, const char *zName){
+  FuncDef *pDef;
+  pDef = sqlite3FindFunction(db, zName, strlen(zName), 2, SQLITE_UTF8, 0);
+  if( pDef ){
+    pDef->flags = SQLITE_FUNC_LIKEOPT;
+  }
+}
+
+/*
+** Register the built-in LIKE and GLOB functions.  The caseSensitive
+** parameter determines whether or not the LIKE operator is case
+** sensitive.  GLOB is always case sensitive.
+*/
+void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
+  struct compareInfo *pInfo;
+  if( caseSensitive ){
+    pInfo = (struct compareInfo*)&likeInfoAlt;
+  }else{
+    pInfo = (struct compareInfo*)&likeInfoNorm;
+  }
+  sqlite3_create_function(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
+  sqlite3_create_function(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
+  sqlite3_create_function(db, "glob", 2, SQLITE_UTF8, 
+      (struct compareInfo*)&globInfo, likeFunc, 0,0);
+  setLikeOptFlag(db, "glob");
+  if( caseSensitive ){
+    setLikeOptFlag(db, "like");
+  }
+}
+
+/*
+** pExpr points to an expression which implements a function.  If
+** it is appropriate to apply the LIKE optimization to that function
+** then set aWc[0] through aWc[2] to the wildcard characters and
+** return TRUE.  If the function is not a LIKE-style function then
+** return FALSE.
+*/
+int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, char *aWc){
+  FuncDef *pDef;
+  if( pExpr->op!=TK_FUNCTION ){
+    return 0;
+  }
+  if( pExpr->pList->nExpr!=2 ){
+    return 0;
+  }
+  pDef = sqlite3FindFunction(db, pExpr->token.z, pExpr->token.n, 2,
+                             SQLITE_UTF8, 0);
+  if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKEOPT)==0 ){
+    return 0;
+  }
+
+  /* The memcpy() statement assumes that the wildcard characters are
+  ** the first three statements in the compareInfo structure.  The
+  ** asserts() that follow verify that assumption
+  */
+  memcpy(aWc, pDef->pUserData, 3);
+  assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
+  assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
+  assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
+
+  return 1;
+}
index ebcc70aedf922f67df225b13aacaf4f19cb08a22..52ac2e55caf7afaabf2fdafa7eeeb410ba7f18ab 100644 (file)
@@ -373,7 +373,7 @@ void sqlite3Insert(
       ** back up and execute the SELECT code above.
       */
       sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v));
-      sqlite3VdbeAddOp(v, OP_OpenTemp, srcTab, 0);
+      sqlite3VdbeAddOp(v, OP_OpenVirtual, srcTab, 0);
       sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn);
       sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);
       sqlite3VdbeResolveLabel(v, iCleanup);
@@ -949,7 +949,7 @@ void sqlite3GenerateConstraintChecks(
         sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);
       }
     }
-    jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24));
+    jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
     sqlite3IndexAffinityStr(v, pIdx);
 
     /* Find out what action to take in case there is an indexing conflict */
@@ -1019,9 +1019,8 @@ void sqlite3GenerateConstraintChecks(
       }
     }
     contAddr = sqlite3VdbeCurrentAddr(v);
-    assert( contAddr<(1<<24) );
 #if NULL_DISTINCT_FOR_UNIQUE
-    sqlite3VdbeChangeP2(v, jumpInst1, contAddr | (1<<24));
+    sqlite3VdbeChangeP2(v, jumpInst1, contAddr);
 #endif
     sqlite3VdbeChangeP2(v, jumpInst2, contAddr);
   }
@@ -1097,11 +1096,12 @@ void sqlite3OpenTableAndIndices(
   Vdbe *v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
   sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-  sqlite3VdbeAddOp(v, op, base, pTab->tnum);
   VdbeComment((v, "# %s", pTab->zName));
+  sqlite3VdbeAddOp(v, op, base, pTab->tnum);
   sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol);
   for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
     sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
+    VdbeComment((v, "# %s", pIdx->zName));
     sqlite3VdbeOp3(v, op, i+base, pIdx->tnum,
                    (char*)&pIdx->keyInfo, P3_KEYINFO);
   }
index 2eef13b20d9bec8ffc1ca4e8c5956593f3687dc4..f825ba977c4721c39339c849e5fa45f82d2f9ef1 100644 (file)
@@ -1,83 +1,84 @@
-/* Hash score: 153 */
+/* Hash score: 156 */
 static int keywordCode(const char *z, int n){
-  static const char zText[515] =
+  static const char zText[526] =
     "ABORTABLEFTEMPORARYADDATABASELECTHENDEFAULTRANSACTIONATURALTER"
-    "AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYAND"
-    "EFERRABLEXCLUSIVEXISTSTATEMENTATTACHAVINGLOBEFOREIGNOREINDEXAUTOINCREMENT"
-    "BEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETECASECOLLATECOLUMN"
-    "COMMITCONFLICTCONSTRAINTERSECTCREATECROSSCURRENT_DATECURRENT_TIMESTAMP"
-    "RAGMATCHDESCDETACHDISTINCTDROPRIMARYFAILIMITFROMFULLGROUPDATE"
-    "IMMEDIATEINSERTINSTEADINTOFFSETISNULLJOINORDEREPLACEOUTERESTRICT"
-    "RIGHTROLLBACKROWHENUNIONUNIQUEUSINGVACUUMVALUESVIEWHERE";
+    "AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYANALYZE"
+    "XCLUSIVEXISTSTATEMENTANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEX"
+    "AUTOINCREMENTBEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETE"
+    "CASECASTCOLLATECOLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSS"
+    "CURRENT_DATECURRENT_TIMESTAMPRAGMATCHDESCDETACHDISTINCTDROPRIMARY"
+    "FAILIMITFROMFULLGROUPDATEIMMEDIATEINSERTINSTEADINTOFFSETISNULL"
+    "JOINORDEREPLACEOUTERESTRICTRIGHTROLLBACKROWHENUNIONUNIQUEUSING"
+    "VACUUMVALUESVIEWHERE";
   static const unsigned char aHash[127] = {
-      89,  79, 102,  88,   0,   4,   0,   0, 109,   0,  75,   0,   0,
-      92,  43,   0,  90,   0, 101, 104,  94,   0,   0,  10,   0,   0,
-     108,   0, 105, 100,   0,  28,  47,   0,  40,   0,   0,  63,  69,
-       0,  62,  19,   0,   0,  32,  81,   0, 103,  72,   0,   0,  34,
-       0,  60,  33,   0,   8,   0, 110,  37,  12,   0,  76,  39,  25,
-      64,   0,   0,  31,  80,  52,  30,  49,  20,  86,   0,  35,   0,
-      73,  26,   0,  70,   0,   0,   0,   0,  46,  65,  22,  85,  29,
-      67,  84,   0,   1,   0,   9,  98,  57,  18,   0, 107,  74,  96,
-      53,   6,  83,   0,   0,  48,  91,   0,  99,   0,  68,   0,   0,
-      15,   0, 111,  50,  55,   0,   2,  54,   0, 106,
+      91,  81, 104,  90,   0,   4,   0,   0, 111,   0,  77,   0,   0,
+      94,  44,   0,  92,   0, 103, 106,  96,   0,   0,  10,   0,   0,
+     110,   0, 107, 102,   0,  28,  48,   0,  41,   0,   0,  65,  71,
+       0,  63,  19,   0,   0,  36,  83,   0, 105,  74,   0,   0,  33,
+       0,  61,  37,   0,   8,   0, 112,  38,  12,   0,  78,  40,  25,
+      66,   0,   0,  31,  82,  53,  30,  50,  20,  88,   0,  34,   0,
+      75,  26,   0,  72,   0,   0,   0,  64,  47,  67,  22,  87,  29,
+      69,  86,   0,   1,   0,   9, 100,  58,  18,   0, 109,  76,  98,
+      54,   6,  85,   0,   0,  49,  93,   0, 101,   0,  70,   0,   0,
+      15,   0, 113,  51,  56,   0,   2,  55,   0, 108,
   };
-  static const unsigned char aNext[111] = {
+  static const unsigned char aNext[113] = {
        0,   0,   0,   0,   0,   3,   0,   0,   0,   0,   0,   0,   0,
        0,   0,   0,   0,   0,   0,   0,   0,  17,   0,   0,   0,   0,
-       0,  11,   0,   0,   0,   7,   0,   5,  13,   0,   0,   0,   0,
-       0,   0,   0,   0,   0,   0,  42,   0,   0,   0,   0,   0,   0,
-       0,  16,   0,  23,  51,   0,   0,   0,   0,  44,  58,   0,   0,
-       0,   0,   0,   0,   0,   0,  71,  41,   0,   0,  24,  59,  21,
-       0,  78,   0,  66,   0,   0,  82,  45,   0,   0,   0,   0,   0,
-       0,   0,  38,  93,  95,   0,   0,  97,   0,  14,  27,  77,   0,
-      56,  87,   0,  36,   0,  61,   0,
+       0,  11,   0,   0,   0,   0,   5,  13,   0,   7,   0,   0,   0,
+       0,   0,   0,   0,   0,   0,   0,  43,   0,   0,   0,   0,   0,
+       0,   0,  16,   0,  23,  52,   0,   0,   0,   0,  45,   0,  59,
+       0,   0,   0,   0,   0,   0,   0,   0,  73,  42,   0,   0,  24,
+      60,  21,   0,  80,  32,  68,   0,   0,  84,  46,   0,   0,   0,
+       0,   0,   0,   0,  39,  95,  97,   0,   0,  99,   0,  14,  27,
+      79,   0,  57,  89,   0,  35,   0,  62,   0,
   };
-  static const unsigned char aLen[111] = {
+  static const unsigned char aLen[113] = {
        5,   5,   4,   4,   9,   2,   3,   8,   2,   6,   4,   3,   7,
       11,   2,   7,   5,   5,   4,   5,   3,   5,  10,   6,   4,   6,
-       7,   6,   7,   9,   3,   3,  10,   9,   6,   9,   6,   6,   4,
-       6,   3,   7,   6,   7,   5,  13,   2,   2,   5,   5,   6,   7,
-       3,   7,   4,   4,   2,   7,   3,   8,   6,   4,   7,   6,   6,
-       8,  10,   9,   6,   5,  12,  12,  17,   6,   5,   4,   6,   8,
-       2,   4,   7,   4,   5,   4,   4,   5,   6,   9,   6,   7,   4,
-       2,   6,   3,   6,   4,   5,   7,   5,   8,   5,   8,   3,   4,
-       5,   6,   5,   6,   6,   4,   5,
+       7,   6,   7,   9,   3,   7,   9,   6,   9,   3,  10,   6,   6,
+       4,   6,   3,   7,   6,   7,   5,  13,   2,   2,   5,   5,   6,
+       7,   3,   7,   4,   4,   2,   7,   3,   8,   6,   4,   4,   7,
+       6,   6,   8,  10,   9,   6,   5,  12,  12,  17,   6,   5,   4,
+       6,   8,   2,   4,   7,   4,   5,   4,   4,   5,   6,   9,   6,
+       7,   4,   2,   6,   3,   6,   4,   5,   7,   5,   8,   5,   8,
+       3,   4,   5,   6,   5,   6,   6,   4,   5,
   };
-  static const unsigned short int aOffset[111] = {
+  static const unsigned short int aOffset[113] = {
        0,   4,   7,  10,  10,  14,  19,  21,  26,  27,  32,  34,  36,
       42,  51,  52,  57,  61,  65,  67,  71,  74,  78,  86,  91,  94,
-      99, 105, 108, 113, 118, 122, 124, 133, 141, 146, 155, 160, 165,
-     168, 170, 170, 174, 178, 180, 185, 187, 189, 198, 201, 205, 211,
-     217, 217, 220, 223, 227, 229, 230, 234, 241, 247, 251, 258, 264,
-     270, 278, 285, 294, 300, 305, 317, 317, 333, 337, 342, 346, 352,
-     353, 360, 363, 370, 373, 378, 382, 386, 389, 395, 404, 410, 417,
-     420, 420, 423, 426, 432, 436, 440, 447, 451, 459, 464, 472, 474,
-     478, 483, 489, 494, 500, 506, 509,
+      99, 105, 108, 113, 118, 122, 128, 136, 141, 150, 152, 162, 167,
+     172, 175, 177, 177, 181, 185, 187, 192, 194, 196, 205, 208, 212,
+     218, 224, 224, 227, 230, 234, 236, 237, 241, 248, 254, 258, 262,
+     269, 275, 281, 289, 296, 305, 311, 316, 328, 328, 344, 348, 353,
+     357, 363, 364, 371, 374, 381, 384, 389, 393, 397, 400, 406, 415,
+     421, 428, 431, 431, 434, 437, 443, 447, 451, 458, 462, 470, 475,
+     483, 485, 489, 494, 500, 505, 511, 517, 520,
   };
-  static const unsigned char aCode[111] = {
+  static const unsigned char aCode[113] = {
     TK_ABORT,      TK_TABLE,      TK_JOIN_KW,    TK_TEMP,       TK_TEMP,       
     TK_OR,         TK_ADD,        TK_DATABASE,   TK_AS,         TK_SELECT,     
     TK_THEN,       TK_END,        TK_DEFAULT,    TK_TRANSACTION,TK_ON,         
     TK_JOIN_KW,    TK_ALTER,      TK_RAISE,      TK_EACH,       TK_CHECK,      
     TK_KEY,        TK_AFTER,      TK_REFERENCES, TK_ESCAPE,     TK_ELSE,       
     TK_EXCEPT,     TK_TRIGGER,    TK_LIKE_KW,    TK_EXPLAIN,    TK_INITIALLY,  
-    TK_ALL,        TK_AND,        TK_DEFERRABLE, TK_EXCLUSIVE,  TK_EXISTS,     
-    TK_STATEMENT,  TK_ATTACH,     TK_HAVING,     TK_LIKE_KW,    TK_BEFORE,     
-    TK_FOR,        TK_FOREIGN,    TK_IGNORE,     TK_REINDEX,    TK_INDEX,      
-    TK_AUTOINCR,   TK_TO,         TK_IN,         TK_BEGIN,      TK_JOIN_KW,    
-    TK_RENAME,     TK_BETWEEN,    TK_NOT,        TK_NOTNULL,    TK_NULL,       
-    TK_LIKE_KW,    TK_BY,         TK_CASCADE,    TK_ASC,        TK_DEFERRED,   
-    TK_DELETE,     TK_CASE,       TK_COLLATE,    TK_COLUMNKW,   TK_COMMIT,     
-    TK_CONFLICT,   TK_CONSTRAINT, TK_INTERSECT,  TK_CREATE,     TK_JOIN_KW,    
-    TK_CTIME_KW,   TK_CTIME_KW,   TK_CTIME_KW,   TK_PRAGMA,     TK_MATCH,      
-    TK_DESC,       TK_DETACH,     TK_DISTINCT,   TK_IS,         TK_DROP,       
-    TK_PRIMARY,    TK_FAIL,       TK_LIMIT,      TK_FROM,       TK_JOIN_KW,    
-    TK_GROUP,      TK_UPDATE,     TK_IMMEDIATE,  TK_INSERT,     TK_INSTEAD,    
-    TK_INTO,       TK_OF,         TK_OFFSET,     TK_SET,        TK_ISNULL,     
-    TK_JOIN,       TK_ORDER,      TK_REPLACE,    TK_JOIN_KW,    TK_RESTRICT,   
-    TK_JOIN_KW,    TK_ROLLBACK,   TK_ROW,        TK_WHEN,       TK_UNION,      
-    TK_UNIQUE,     TK_USING,      TK_VACUUM,     TK_VALUES,     TK_VIEW,       
-    TK_WHERE,      
+    TK_ALL,        TK_ANALYZE,    TK_EXCLUSIVE,  TK_EXISTS,     TK_STATEMENT,  
+    TK_AND,        TK_DEFERRABLE, TK_ATTACH,     TK_HAVING,     TK_LIKE_KW,    
+    TK_BEFORE,     TK_FOR,        TK_FOREIGN,    TK_IGNORE,     TK_REINDEX,    
+    TK_INDEX,      TK_AUTOINCR,   TK_TO,         TK_IN,         TK_BEGIN,      
+    TK_JOIN_KW,    TK_RENAME,     TK_BETWEEN,    TK_NOT,        TK_NOTNULL,    
+    TK_NULL,       TK_LIKE_KW,    TK_BY,         TK_CASCADE,    TK_ASC,        
+    TK_DEFERRED,   TK_DELETE,     TK_CASE,       TK_CAST,       TK_COLLATE,    
+    TK_COLUMNKW,   TK_COMMIT,     TK_CONFLICT,   TK_CONSTRAINT, TK_INTERSECT,  
+    TK_CREATE,     TK_JOIN_KW,    TK_CTIME_KW,   TK_CTIME_KW,   TK_CTIME_KW,   
+    TK_PRAGMA,     TK_MATCH,      TK_DESC,       TK_DETACH,     TK_DISTINCT,   
+    TK_IS,         TK_DROP,       TK_PRIMARY,    TK_FAIL,       TK_LIMIT,      
+    TK_FROM,       TK_JOIN_KW,    TK_GROUP,      TK_UPDATE,     TK_IMMEDIATE,  
+    TK_INSERT,     TK_INSTEAD,    TK_INTO,       TK_OF,         TK_OFFSET,     
+    TK_SET,        TK_ISNULL,     TK_JOIN,       TK_ORDER,      TK_REPLACE,    
+    TK_JOIN_KW,    TK_RESTRICT,   TK_JOIN_KW,    TK_ROLLBACK,   TK_ROW,        
+    TK_WHEN,       TK_UNION,      TK_UNIQUE,     TK_USING,      TK_VACUUM,     
+    TK_VALUES,     TK_VIEW,       TK_WHERE,      
   };
   int h, i;
   if( n<2 ) return TK_ID;
index dfc9dd7c620cab4cdb1a4e0d5501d45bfd2eb7a0..d0ecd4fe5248365a364823cecb9edb094938b0ff 100644 (file)
@@ -234,7 +234,6 @@ const char *sqlite3ErrStr(int rc){
     case SQLITE_DONE:
     case SQLITE_OK:         z = "not an error";                          break;
     case SQLITE_ERROR:      z = "SQL logic error or missing database";   break;
-    case SQLITE_INTERNAL:   z = "internal SQLite implementation flaw";   break;
     case SQLITE_PERM:       z = "access permission denied";              break;
     case SQLITE_ABORT:      z = "callback requested query abort";        break;
     case SQLITE_BUSY:       z = "database is locked";                    break;
@@ -244,13 +243,11 @@ const char *sqlite3ErrStr(int rc){
     case SQLITE_INTERRUPT:  z = "interrupted";                           break;
     case SQLITE_IOERR:      z = "disk I/O error";                        break;
     case SQLITE_CORRUPT:    z = "database disk image is malformed";      break;
-    case SQLITE_NOTFOUND:   z = "table or record not found";             break;
-    case SQLITE_FULL:       z = "database is full";                      break;
+    case SQLITE_FULL:       z = "database or disk is full";              break;
     case SQLITE_CANTOPEN:   z = "unable to open database file";          break;
     case SQLITE_PROTOCOL:   z = "database locking protocol failure";     break;
     case SQLITE_EMPTY:      z = "table contains no data";                break;
     case SQLITE_SCHEMA:     z = "database schema has changed";           break;
-    case SQLITE_TOOBIG:     z = "too much data for one table row";       break;
     case SQLITE_CONSTRAINT: z = "constraint failed";                     break;
     case SQLITE_MISMATCH:   z = "datatype mismatch";                     break;
     case SQLITE_MISUSE:     z = "library routine called out of sequence";break;
@@ -298,7 +295,7 @@ static int sqliteDefaultBusyCallback(
   sqlite3OsSleep(delay);
   return 1;
 #else
-  int timeout = (int)Timeout;
+  int timeout = ((sqlite3 *)ptr)->busyTimeout;
   if( (count+1)*1000 > timeout ){
     return 0;
   }
@@ -307,6 +304,25 @@ static int sqliteDefaultBusyCallback(
 #endif
 }
 
+/*
+** Invoke the given busy handler.
+**
+** This routine is called when an operation failed with a lock.
+** If this routine returns non-zero, the lock is retried.  If it
+** returns 0, the operation aborts with an SQLITE_BUSY error.
+*/
+int sqlite3InvokeBusyHandler(BusyHandler *p){
+  int rc;
+  if( p==0 || p->xFunc==0 || p->nBusy<0 ) return 0;
+  rc = p->xFunc(p->pArg, p->nBusy);
+  if( rc==0 ){
+    p->nBusy = -1;
+  }else{
+    p->nBusy++;
+  }
+  return rc; 
+}
+
 /*
 ** This routine sets the busy callback for an Sqlite database to the
 ** given callback function with the given argument.
@@ -321,6 +337,7 @@ int sqlite3_busy_handler(
   }
   db->busyHandler.xFunc = xBusy;
   db->busyHandler.pArg = pArg;
+  db->busyHandler.nBusy = 0;
   return SQLITE_OK;
 }
 
@@ -454,6 +471,7 @@ int sqlite3_create_function(
 
   p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);
   if( p==0 ) return SQLITE_NOMEM;
+  p->flags = 0;
   p->xFunc = xFunc;
   p->xStep = xStep;
   p->xFinalize = xFinal;
@@ -530,11 +548,11 @@ void *sqlite3_commit_hook(
 ** opened and used.  If zFilename is the magic name ":memory:" then
 ** the database is stored in memory (and is thus forgotten as soon as
 ** the connection is closed.)  If zFilename is NULL then the database
-** is for temporary use only and is deleted as soon as the connection
-** is closed.
+** is a "virtual" database for transient use only and is deleted as
+** soon as the connection is closed.
 **
-** A temporary database can be either a disk file (that is automatically
-** deleted when the file is closed) or a set of red-black trees held in memory,
+** A virtual database can be either a disk file (that is automatically
+** deleted when the file is closed) or it an be held entirely in memory,
 ** depending on the values of the TEMP_STORE compile-time macro and the
 ** db->temp_store variable, according to the following chart:
 **
index 9757cd8ac208772d58d4086ca273204decd7db78..dd8823c277a9443b6cc566b8f9241302fa530088 100644 (file)
@@ -1,51 +1,51 @@
 /* Automatically generated.  Do not edit */
 /* See the mkopcodeh.awk script for details */
 #define OP_MemLoad                              1
-#define OP_HexBlob                            129   /* same as TK_BLOB     */
+#define OP_HexBlob                            131   /* same as TK_BLOB     */
 #define OP_Column                               2
 #define OP_SetCookie                            3
 #define OP_IfMemPos                             4
-#define OP_Real                               128   /* same as TK_FLOAT    */
+#define OP_Real                               130   /* same as TK_FLOAT    */
 #define OP_MoveGt                               5
-#define OP_Ge                                  75   /* same as TK_GE       */
+#define OP_Ge                                  77   /* same as TK_GE       */
 #define OP_AggFocus                             6
 #define OP_RowKey                               7
 #define OP_AggNext                              8
-#define OP_Eq                                  71   /* same as TK_EQ       */
+#define OP_Eq                                  73   /* same as TK_EQ       */
 #define OP_OpenWrite                            9
-#define OP_NotNull                             69   /* same as TK_NOTNULL  */
+#define OP_NotNull                             71   /* same as TK_NOTNULL  */
 #define OP_If                                  10
-#define OP_String8                             90   /* same as TK_STRING   */
-#define OP_Pop                                 11
-#define OP_AggContextPush                      12
-#define OP_CollSeq                             13
-#define OP_OpenRead                            14
-#define OP_Expire                              15
-#define OP_SortReset                           16
-#define OP_AutoCommit                          17
-#define OP_Gt                                  72   /* same as TK_GT       */
-#define OP_Sort                                18
-#define OP_ListRewind                          19
+#define OP_ToInt                               11
+#define OP_String8                             92   /* same as TK_STRING   */
+#define OP_Pop                                 12
+#define OP_AggContextPush                      13
+#define OP_CollSeq                             14
+#define OP_OpenRead                            15
+#define OP_Expire                              16
+#define OP_SortReset                           17
+#define OP_AutoCommit                          18
+#define OP_Gt                                  74   /* same as TK_GT       */
+#define OP_Sort                                19
 #define OP_IntegrityCk                         20
 #define OP_SortInsert                          21
 #define OP_Function                            22
-#define OP_And                                 63   /* same as TK_AND      */
-#define OP_Subtract                            82   /* same as TK_MINUS    */
+#define OP_And                                 65   /* same as TK_AND      */
+#define OP_Subtract                            84   /* same as TK_MINUS    */
 #define OP_Noop                                23
 #define OP_Return                              24
-#define OP_Remainder                           85   /* same as TK_REM      */
+#define OP_Remainder                           87   /* same as TK_REM      */
 #define OP_NewRowid                            25
-#define OP_Multiply                            83   /* same as TK_STAR     */
+#define OP_Multiply                            85   /* same as TK_STAR     */
 #define OP_Variable                            26
 #define OP_String                              27
 #define OP_ParseSchema                         28
 #define OP_AggFunc                             29
 #define OP_Close                               30
-#define OP_ListWrite                           31
-#define OP_CreateIndex                         32
-#define OP_IsUnique                            33
-#define OP_IdxIsNull                           34
-#define OP_NotFound                            35
+#define OP_CreateIndex                         31
+#define OP_IsUnique                            32
+#define OP_IdxIsNull                           33
+#define OP_NotFound                            34
+#define OP_Int64                               35
 #define OP_MustBeInt                           36
 #define OP_Halt                                37
 #define OP_Rowid                               38
 #define OP_RowData                             42
 #define OP_MemMax                              43
 #define OP_Push                                44
-#define OP_Or                                  62   /* same as TK_OR       */
+#define OP_Or                                  64   /* same as TK_OR       */
 #define OP_NotExists                           45
-#define OP_OpenTemp                            46
-#define OP_MemIncr                             47
-#define OP_Gosub                               48
-#define OP_Divide                              84   /* same as TK_SLASH    */
-#define OP_AggSet                              49
-#define OP_Integer                             50
+#define OP_MemIncr                             46
+#define OP_Gosub                               47
+#define OP_Divide                              86   /* same as TK_SLASH    */
+#define OP_AggSet                              48
+#define OP_Integer                             49
+#define OP_ToNumeric                           50
 #define OP_SortNext                            51
 #define OP_Prev                                52
-#define OP_Concat                              86   /* same as TK_CONCAT   */
-#define OP_BitAnd                              77   /* same as TK_BITAND   */
+#define OP_Concat                              88   /* same as TK_CONCAT   */
+#define OP_BitAnd                              79   /* same as TK_BITAND   */
 #define OP_CreateTable                         53
 #define OP_Last                                54
-#define OP_IsNull                              68   /* same as TK_ISNULL   */
+#define OP_IsNull                              70   /* same as TK_ISNULL   */
 #define OP_IdxRowid                            55
-#define OP_ShiftRight                          80   /* same as TK_RSHIFT   */
-#define OP_ResetCount                          56
-#define OP_Callback                            57
-#define OP_ContextPush                         58
-#define OP_DropTrigger                         59
-#define OP_DropIndex                           60
-#define OP_IdxGE                               61
-#define OP_IdxDelete                           65
-#define OP_Vacuum                              66
-#define OP_MoveLe                              67
-#define OP_IfNot                               76
-#define OP_DropTable                           88
-#define OP_MakeRecord                          91
-#define OP_Delete                              92
-#define OP_AggContextPop                       93
-#define OP_ListRead                            94
-#define OP_ListReset                           95
-#define OP_ShiftLeft                           79   /* same as TK_LSHIFT   */
-#define OP_Dup                                 96
-#define OP_Goto                                97
-#define OP_Clear                               98
-#define OP_IdxGT                               99
-#define OP_MoveLt                             100
-#define OP_Le                                  73   /* same as TK_LE       */
-#define OP_VerifyCookie                       101
-#define OP_Pull                               102
-#define OP_Not                                 64   /* same as TK_NOT      */
-#define OP_SetNumColumns                      103
-#define OP_AbsValue                           104
-#define OP_Transaction                        105
-#define OP_Negative                            87   /* same as TK_UMINUS   */
-#define OP_Ne                                  70   /* same as TK_NE       */
-#define OP_AggGet                             106
-#define OP_ContextPop                         107
-#define OP_BitOr                               78   /* same as TK_BITOR    */
-#define OP_Next                               108
-#define OP_AggInit                            109
-#define OP_IdxInsert                          110
-#define OP_Distinct                           111
-#define OP_Lt                                  74   /* same as TK_LT       */
-#define OP_AggReset                           112
-#define OP_Insert                             113
-#define OP_Destroy                            114
-#define OP_ReadCookie                         115
-#define OP_ForceInt                           116
-#define OP_OpenPseudo                         117
-#define OP_Null                               118
-#define OP_Blob                               119
-#define OP_Add                                 81   /* same as TK_PLUS     */
-#define OP_MemStore                           120
-#define OP_Rewind                             121
-#define OP_MoveGe                             122
-#define OP_BitNot                              89   /* same as TK_BITNOT   */
-#define OP_Found                              123
-#define OP_NullRow                            124
-
-/* The following opcode values are never used */
-#define OP_NotUsed_125                        125
-#define OP_NotUsed_126                        126
-#define OP_NotUsed_127                        127
+#define OP_MakeIdxRec                          56
+#define OP_ShiftRight                          82   /* same as TK_RSHIFT   */
+#define OP_ResetCount                          57
+#define OP_FifoWrite                           58
+#define OP_Callback                            59
+#define OP_ContextPush                         60
+#define OP_DropTrigger                         61
+#define OP_DropIndex                           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_ToBlob                              94
+#define OP_Delete                              95
+#define OP_AggContextPop                       96
+#define OP_ShiftLeft                           81   /* same as TK_LSHIFT   */
+#define OP_Dup                                 97
+#define OP_Goto                                98
+#define OP_FifoRead                            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_ToText                             105
+#define OP_Not                                 66   /* same as TK_NOT      */
+#define OP_SetNumColumns                      106
+#define OP_AbsValue                           107
+#define OP_Transaction                        108
+#define OP_Negative                            89   /* same as TK_UMINUS   */
+#define OP_Ne                                  72   /* same as TK_NE       */
+#define OP_AggGet                             109
+#define OP_ContextPop                         110
+#define OP_BitOr                               80   /* same as TK_BITOR    */
+#define OP_Next                               111
+#define OP_AggInit                            112
+#define OP_IdxInsert                          113
+#define OP_Distinct                           114
+#define OP_Lt                                  76   /* same as TK_LT       */
+#define OP_AggReset                           115
+#define OP_Insert                             116
+#define OP_Destroy                            117
+#define OP_ReadCookie                         118
+#define OP_ForceInt                           119
+#define OP_LoadAnalysis                       120
+#define OP_OpenVirtual                        121
+#define OP_OpenPseudo                         122
+#define OP_Null                               123
+#define OP_Blob                               124
+#define OP_Add                                 83   /* same as TK_PLUS     */
+#define OP_MemStore                           125
+#define OP_Rewind                             126
+#define OP_MoveGe                             127
+#define OP_BitNot                              91   /* same as TK_BITNOT   */
+#define OP_Found                              128
+#define OP_NullRow                            129
 
 #define NOPUSH_MASK_0 65400
-#define NOPUSH_MASK_1 61871
-#define NOPUSH_MASK_2 64446
-#define NOPUSH_MASK_3 65363
+#define NOPUSH_MASK_1 29103
+#define NOPUSH_MASK_2 64439
+#define NOPUSH_MASK_3 65109
 #define NOPUSH_MASK_4 65535
-#define NOPUSH_MASK_5 46015
-#define NOPUSH_MASK_6 64254
-#define NOPUSH_MASK_7 7987
-#define NOPUSH_MASK_8 0
+#define NOPUSH_MASK_5 52991
+#define NOPUSH_MASK_6 55285
+#define NOPUSH_MASK_7 59295
+#define NOPUSH_MASK_8 3
 #define NOPUSH_MASK_9 0
index 9c361a17170609c51f4d6f6ff8d2d351c33549dc..2ea9aa8e35f8eefbb3a1e0e64c66527436b4f774 100644 (file)
 #endif
 
 /*
-** Macros used to determine whether or not to use threads.  The
-** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for
-** Posix threads and SQLITE_W32_THREADS is defined if we are
-** synchronizing using Win32 threads.
+** Include code that is common to all os_*.c files
 */
-#if defined(THREADSAFE) && THREADSAFE
-# include <pthread.h>
-# define SQLITE_UNIX_THREADS 1
-#endif
-
+#include "os_common.h"
 
 /*
-** Include code that is common to all os_*.c files
+** The threadid macro resolves to the thread-id or to 0.  Used for
+** testing and debugging only.
 */
-#include "os_common.h"
+#ifdef SQLITE_UNIX_THREADS
+#define threadid pthread_self()
+#else
+#define threadid 0
+#endif
 
-#if defined(THREADSAFE) && THREADSAFE && defined(__linux__)
-#define getpid pthread_self
+/*
+** Set or check the OsFile.tid field.  This field is set when an OsFile
+** is first opened.  All subsequent uses of the OsFile verify that the
+** same thread is operating on the OsFile.  Some operating systems do
+** not allow locks to be overridden by other threads and that restriction
+** means that sqlite3* database handles cannot be moved from one thread
+** to another.  This logic makes sure a user does not try to do that
+** by mistake.
+*/
+#ifdef SQLITE_UNIX_THREADS
+# define SET_THREADID(X)   X->tid = pthread_self()
+# define CHECK_THREADID(X) (!pthread_equal(X->tid, pthread_self()))
+#else
+# define SET_THREADID(X)
+# define CHECK_THREADID(X) 0
 #endif
 
 /*
@@ -264,6 +275,65 @@ struct threadTestData {
   int result;            /* Result of the locking operation */
 };
 
+#ifdef SQLITE_LOCK_TRACE
+/*
+** Print out information about all locking operations.
+**
+** This routine is used for troubleshooting locks on multithreaded
+** platforms.  Enable by compiling with the -DSQLITE_LOCK_TRACE
+** command-line option on the compiler.  This code is normally
+** turnned off.
+*/
+static int lockTrace(int fd, int op, struct flock *p){
+  char *zOpName, *zType;
+  int s;
+  int savedErrno;
+  if( op==F_GETLK ){
+    zOpName = "GETLK";
+  }else if( op==F_SETLK ){
+    zOpName = "SETLK";
+  }else{
+    s = fcntl(fd, op, p);
+    sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
+    return s;
+  }
+  if( p->l_type==F_RDLCK ){
+    zType = "RDLCK";
+  }else if( p->l_type==F_WRLCK ){
+    zType = "WRLCK";
+  }else if( p->l_type==F_UNLCK ){
+    zType = "UNLCK";
+  }else{
+    assert( 0 );
+  }
+  assert( p->l_whence==SEEK_SET );
+  s = fcntl(fd, op, p);
+  savedErrno = errno;
+  sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
+     threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
+     (int)p->l_pid, s);
+  if( s && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
+    struct flock l2;
+    l2 = *p;
+    fcntl(fd, F_GETLK, &l2);
+    if( l2.l_type==F_RDLCK ){
+      zType = "RDLCK";
+    }else if( l2.l_type==F_WRLCK ){
+      zType = "WRLCK";
+    }else if( l2.l_type==F_UNLCK ){
+      zType = "UNLCK";
+    }else{
+      assert( 0 );
+    }
+    sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
+       zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
+  }
+  errno = savedErrno;
+  return s;
+}
+#define fcntl lockTrace
+#endif /* SQLITE_LOCK_TRACE */
+
 /*
 ** The testThreadLockingBehavior() routine launches two separate
 ** threads on this routine.  This routine attempts to lock a file
@@ -443,6 +513,7 @@ int sqlite3OsOpenReadWrite(
   int rc;
   assert( !id->isOpen );
   id->dirfd = -1;
+  SET_THREADID(id);
   id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,
                           SQLITE_DEFAULT_FILE_PERMISSIONS);
   if( id->h<0 ){
@@ -494,9 +565,11 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
   if( access(zFilename, 0)==0 ){
     return SQLITE_CANTOPEN;
   }
+  SET_THREADID(id);
   id->dirfd = -1;
   id->h = open(zFilename,
-                O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600);
+                O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY,
+                SQLITE_DEFAULT_FILE_PERMISSIONS);
   if( id->h<0 ){
     return SQLITE_CANTOPEN;
   }
@@ -528,6 +601,7 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
 int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
   int rc;
   assert( !id->isOpen );
+  SET_THREADID(id);
   id->dirfd = -1;
   id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
   if( id->h<0 ){
@@ -572,6 +646,7 @@ int sqlite3OsOpenDirectory(
     ** open. */
     return SQLITE_CANTOPEN;
   }
+  SET_THREADID(id);
   assert( id->dirfd<0 );
   id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0);
   if( id->dirfd<0 ){
@@ -839,6 +914,7 @@ int sqlite3OsCheckReservedLock(OsFile *id){
   int r = 0;
 
   assert( id->isOpen );
+  if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
   sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */
 
   /* Check if a thread in this process holds such a lock */
@@ -956,6 +1032,7 @@ int sqlite3OsLock(OsFile *id, int locktype){
   TRACE7("LOCK    %d %s was %s(%s,%d) pid=%d\n", id->h, locktypeName(locktype), 
       locktypeName(id->locktype), locktypeName(pLock->locktype), pLock->cnt
       ,getpid() );
+  if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
 
   /* If there is already a lock of this type or more restrictive on the
   ** OsFile, do nothing. Don't use the end_lock: exit path, as
@@ -1002,6 +1079,7 @@ int sqlite3OsLock(OsFile *id, int locktype){
   }
 
   lock.l_len = 1L;
+
   lock.l_whence = SEEK_SET;
 
   /* A PENDING lock is needed before acquiring a SHARED lock and before
@@ -1037,7 +1115,10 @@ int sqlite3OsLock(OsFile *id, int locktype){
     lock.l_start = PENDING_BYTE;
     lock.l_len = 1L;
     lock.l_type = F_UNLCK;
-    fcntl(id->h, F_SETLK, &lock);
+    if( fcntl(id->h, F_SETLK, &lock)!=0 ){
+      rc = SQLITE_IOERR;  /* This should never happen */
+      goto end_lock;
+    }
     if( s ){
       rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
     }else{
@@ -1107,6 +1188,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
   assert( id->isOpen );
   TRACE7("UNLOCK  %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype, 
       id->pLock->locktype, id->pLock->cnt, getpid());
+  if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
 
   assert( locktype<=SHARED_LOCK );
   if( id->locktype<=locktype ){
@@ -1131,8 +1213,11 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
     lock.l_whence = SEEK_SET;
     lock.l_start = PENDING_BYTE;
     lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
-    fcntl(id->h, F_SETLK, &lock);
-    pLock->locktype = SHARED_LOCK;
+    if( fcntl(id->h, F_SETLK, &lock)==0 ){
+      pLock->locktype = SHARED_LOCK;
+    }else{
+      rc = SQLITE_IOERR;  /* This should never happen */
+    }
   }
   if( locktype==NO_LOCK ){
     struct openCnt *pOpen;
@@ -1146,8 +1231,11 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
       lock.l_type = F_UNLCK;
       lock.l_whence = SEEK_SET;
       lock.l_start = lock.l_len = 0L;
-      fcntl(id->h, F_SETLK, &lock);
-      pLock->locktype = NO_LOCK;
+      if( fcntl(id->h, F_SETLK, &lock)==0 ){
+        pLock->locktype = NO_LOCK;
+      }else{
+        rc = SQLITE_IOERR;  /* This should never happen */
+      }
     }
 
     /* Decrement the count of locks against this same file.  When the
@@ -1177,6 +1265,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
 */
 int sqlite3OsClose(OsFile *id){
   if( !id->isOpen ) return SQLITE_OK;
+  if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
   sqlite3OsUnlock(id, NO_LOCK);
   if( id->dirfd>=0 ) close(id->dirfd);
   id->dirfd = -1;
@@ -1189,13 +1278,13 @@ int sqlite3OsClose(OsFile *id){
     */
     int *aNew;
     struct openCnt *pOpen = id->pOpen;
-    pOpen->nPending++;
-    aNew = sqliteRealloc( pOpen->aPending, pOpen->nPending*sizeof(int) );
+    aNew = sqliteRealloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
     if( aNew==0 ){
       /* If a malloc fails, just leak the file descriptor */
     }else{
       pOpen->aPending = aNew;
-      pOpen->aPending[pOpen->nPending-1] = id->h;
+      pOpen->aPending[pOpen->nPending] = id->h;
+      pOpen->nPending++;
     }
   }else{
     /* There are no outstanding locks so we can close the file immediately */
index 4ea0aee362d6cc395889cd0b1e7a6944fdae675b..5fdfc2ff4ce17cb63f0378bc0fd41afc2dcbaf3c 100644 (file)
 #include <fcntl.h>
 #include <unistd.h>
 
+/*
+** Macros used to determine whether or not to use threads.  The
+** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for
+** Posix threads and SQLITE_W32_THREADS is defined if we are
+** synchronizing using Win32 threads.
+*/
+#if defined(THREADSAFE) && THREADSAFE
+# include <pthread.h>
+# define SQLITE_UNIX_THREADS 1
+#endif
+
 /*
 ** The OsFile structure is a operating-system independing representation
 ** of an open file handle.  It is defined differently for each architecture.
@@ -70,6 +81,9 @@ struct OsFile {
   unsigned char isOpen;     /* True if needs to be closed */
   unsigned char fullSync;   /* Use F_FULLSYNC if available */
   int dirfd;                /* File descriptor for the directory */
+#ifdef SQLITE_UNIX_THREADS
+  pthread_t tid;            /* The thread authorized to use this OsFile */
+#endif
 };
 
 /*
index 892757406f95fe00935bfa27f5233807c96f07c0..8fd65ba88eedc6f8477b93f6e613482dc689c31b 100644 (file)
@@ -779,7 +779,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
   if( rc!=SQLITE_OK ) return rc;
 
   rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
-  pPager->needSync = 1;
+  pPager->needSync = !pPager->noSync;
   return rc;
 }
 
@@ -1758,7 +1758,11 @@ int sqlite3pager_pagecount(Pager *pPager){
     pPager->errMask |= PAGER_ERR_DISK;
     return 0;
   }
-  n /= pPager->pageSize;
+  if( n>0 && n<pPager->pageSize ){
+    n = 1;
+  }else{
+    n /= pPager->pageSize;
+  }
   if( !MEMDB && n==PENDING_BYTE/pPager->pageSize ){
     n++;
   }
@@ -1866,7 +1870,7 @@ static void memoryTruncate(Pager *pPager){
 
 /*
 ** 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
+** is currently not available.  Repeat until the busy callback returns
 ** false or until the lock succeeds.
 **
 ** Return SQLITE_OK on success and an error code if we cannot obtain
@@ -1880,14 +1884,9 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
   if( pPager->state>=locktype ){
     rc = SQLITE_OK;
   }else{
-    int busy = 1;
-    BusyHandler *pH;
     do {
       rc = sqlite3OsLock(&pPager->fd, locktype);
-    }while( rc==SQLITE_BUSY && 
-        (pH = pPager->pBusyHandler)!=0 && 
-        pH->xFunc && pH->xFunc(pH->pArg, busy++)
-    );
+    }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) );
     if( rc==SQLITE_OK ){
       pPager->state = locktype;
     }
@@ -3346,6 +3345,14 @@ const char *sqlite3pager_journalname(Pager *pPager){
   return pPager->zJournal;
 }
 
+/*
+** Return true if fsync() calls are disabled for this pager.  Return FALSE
+** if fsync()s are executed normally.
+*/
+int sqlite3pager_nosync(Pager *pPager){
+  return pPager->noSync;
+}
+
 /*
 ** Set the codec for this pager
 */
index 63baf0dfd1e9f6fd7d3b7c72de04d9920d04502c..c3311c824ba66e0b50ffa1d0d0112b1802a3ed33 100644 (file)
@@ -100,6 +100,7 @@ void sqlite3pager_set_safety_level(Pager*,int);
 const char *sqlite3pager_filename(Pager*);
 const char *sqlite3pager_dirname(Pager*);
 const char *sqlite3pager_journalname(Pager*);
+int sqlite3pager_nosync(Pager*);
 int sqlite3pager_rename(Pager*, const char *zNewName);
 void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
 int sqlite3pager_movepage(Pager*,void*,Pgno);
index e3cd4429fb273071195dcf68fc3858270eeeac31..11acdde36c3382eca5677e0613b6c2cf9c24698f 100644 (file)
@@ -1,10 +1,10 @@
 /* Driver template for the LEMON parser generator.
-**  The author disclaims copyright to this source code.
+** 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/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 51 "parse.y"
 
 #include "sqliteInt.h"
 #include "parse.h"
@@ -43,7 +43,7 @@ struct TrigEvent { int a; IdList * b; };
 */
 struct AttachKey { int type;  Token key; };
 
-#line 48 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 48 "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 241
+#define YYNOCODE 244
 #define YYACTIONTYPE unsigned short int
 #define sqlite3ParserTOKENTYPE Token
 typedef union {
   sqlite3ParserTOKENTYPE yy0;
-  Expr* yy2;
-  struct {int value; int mask;} yy47;
-  SrcList* yy67;
-  ExprList* yy82;
-  struct AttachKey yy132;
-  struct TrigEvent yy210;
-  IdList* yy240;
-  struct LimitVal yy244;
-  Token yy258;
-  TriggerStep* yy347;
-  int yy412;
-  struct LikeOp yy438;
-  Select* yy459;
-  int yy481;
+  struct {int value; int mask;} yy35;
+  Expr* yy44;
+  int yy58;
+  Select* yy99;
+  struct LimitVal yy112;
+  Token yy144;
+  TriggerStep* yy203;
+  struct TrigEvent yy234;
+  IdList* yy258;
+  struct AttachKey yy300;
+  SrcList* yy367;
+  ExprList* yy412;
+  struct LikeOp yy432;
+  int yy487;
 } 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 565
-#define YYNRULE 305
-#define YYERRORSYMBOL 141
-#define YYERRSYMDT yy481
+#define YYNSTATE 578
+#define YYNRULE 310
+#define YYERRORSYMBOL 143
+#define YYERRSYMDT yy487
 #define YYFALLBACK 1
 #define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
 #define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
@@ -175,467 +175,486 @@ typedef union {
 **  yy_default[]       Default action for each state.
 */
 static const YYACTIONTYPE yy_action[] = {
- /*     0 */   259,   65,  257,  112,  114,  110,  116,   66,  122,  124,
- /*    10 */   126,  128,  130,  132,  134,  136,  138,  140,  568,  142,
- /*    20 */   150,  122,  124,  126,  128,  130,  132,  134,  136,  138,
- /*    30 */   140,  130,  132,  134,  136,  138,  140,  108,   94,  143,
- /*    40 */   153,  158,  163,  152,  157,  118,  120,  112,  114,  110,
- /*    50 */   116,   72,  122,  124,  126,  128,  130,  132,  134,  136,
- /*    60 */   138,  140,    7,  106,  219,  258,  122,  124,  126,  128,
- /*    70 */   130,  132,  134,  136,  138,  140,  367,   13,    9,  369,
- /*    80 */   376,  381,  142,  871,    1,  564,   92,   27,    4,  399,
- /*    90 */   363,  384,  844,  341,  291,   28,   10,   95,  398,   33,
- /*   100 */   108,   94,  143,  153,  158,  163,  152,  157,  118,  120,
- /*   110 */   112,  114,  110,  116,   96,  122,  124,  126,  128,  130,
- /*   120 */   132,  134,  136,  138,  140,  456,  565,  142,  395,  305,
- /*   130 */   101,  102,  103,  288,   75,  394,    3,  563,  231,  275,
- /*   140 */    14,   15,  575,  597,  437,  108,   94,  143,  153,  158,
- /*   150 */   163,  152,  157,  118,  120,  112,  114,  110,  116,   13,
- /*   160 */   122,  124,  126,  128,  130,  132,  134,  136,  138,  140,
- /*   170 */   573,   77,  142,  223,  232,   13,  490,  462,  452,  167,
- /*   180 */   306,  169,  170,  276,  254,    3,  563,   81,  277,  183,
- /*   190 */   108,   94,  143,  153,  158,  163,  152,  157,  118,  120,
- /*   200 */   112,  114,  110,  116,   52,  122,  124,  126,  128,  130,
- /*   210 */   132,  134,  136,  138,  140,   48,   54,  799,  448,   51,
- /*   220 */   797,   77,   14,   15,   49,  363,  134,  136,  138,  140,
- /*   230 */    16,   17,   18,   32,   33,   50,  308,  197,   14,   15,
- /*   240 */   367,  261,   13,  369,  376,  381,  142,   37,  337,   40,
- /*   250 */    59,   67,   69,  301,  332,  384,  364,  397,  259,  807,
- /*   260 */   257,  334,   51,  193,  108,   94,  143,  153,  158,  163,
- /*   270 */   152,  157,  118,  120,  112,  114,  110,  116,  262,  122,
- /*   280 */   124,  126,  128,  130,  132,  134,  136,  138,  140,   13,
- /*   290 */   171,  142,   40,   59,   67,   69,  301,  332,  642,  148,
- /*   300 */   365,  159,  164,  261,  334,   14,   15,   44,   45,  108,
- /*   310 */    94,  143,  153,  158,  163,  152,  157,  118,  120,  112,
- /*   320 */   114,  110,  116,  258,  122,  124,  126,  128,  130,  132,
- /*   330 */   134,  136,  138,  140,  148,  218,  159,  164,  184,   12,
- /*   340 */   284,  417,   48,  360,  358,  293,  290,  347,  352,  353,
- /*   350 */   289,   49,   14,   15,  688,    2,   96,  148,    4,  159,
- /*   360 */   164,  257,   50,  530,   46,  142,  367,  155,  165,  369,
- /*   370 */   376,  381,   13,  576,   47,  167,   75,  169,  170,  554,
- /*   380 */   172,  384,  207,  108,   94,  143,  153,  158,  163,  152,
- /*   390 */   157,  118,  120,  112,  114,  110,  116,  154,  122,  124,
- /*   400 */   126,  128,  130,  132,  134,  136,  138,  140,  299,  354,
- /*   410 */   350,  352,  353,   96,   96,   13,   34,   20,  294,  362,
- /*   420 */   345,  144,  581,  167,  258,  169,  170,  821,  142,  558,
- /*   430 */   213,  244,  254,   75,   75,   14,   15,  172,  186,  167,
- /*   440 */   533,  169,  170,  146,  147,  417,  108,   94,  143,  153,
- /*   450 */   158,  163,  152,  157,  118,  120,  112,  114,  110,  116,
- /*   460 */    96,  122,  124,  126,  128,  130,  132,  134,  136,  138,
- /*   470 */   140,  145,  354,  142,   22,  239,  383,  589,   14,   15,
- /*   480 */    75,   36,  336,  419,  172,  187,  842,  213,  528,  582,
- /*   490 */   331,  108,   94,  143,  153,  158,  163,  152,  157,  118,
- /*   500 */   120,  112,  114,  110,  116,  249,  122,  124,  126,  128,
- /*   510 */   130,  132,  134,  136,  138,  140,  306,  661,  142,  327,
- /*   520 */   574,  849,  148,   11,  159,  164,  309,  316,  318,  168,
- /*   530 */    42,  327,  666,  327,  212,  393,  108,   94,  143,  153,
- /*   540 */   158,  163,  152,  157,  118,  120,  112,  114,  110,  116,
- /*   550 */    96,  122,  124,  126,  128,  130,  132,  134,  136,  138,
- /*   560 */   140,  847,   83,  142,  321,  641,  372,   31,  663,  282,
- /*   570 */    75,  242,  308,  689,  231,  246,  167,  334,  169,  170,
- /*   580 */   269,  108,   94,  143,  153,  158,  163,  152,  157,  118,
- /*   590 */   120,  112,  114,  110,  116,  324,  122,  124,  126,  128,
- /*   600 */   130,  132,  134,  136,  138,  140,  246,  328,  142,  328,
- /*   610 */   225,  434,   24,   39,  433,  210,  167,  211,  169,  170,
- /*   620 */   167,  331,  169,  170,  583,  435,  108,  161,  143,  153,
- /*   630 */   158,  163,  152,  157,  118,  120,  112,  114,  110,  116,
- /*   640 */   248,  122,  124,  126,  128,  130,  132,  134,  136,  138,
- /*   650 */   140,   57,   58,  142,  624,  837,  323,  727,  271,  261,
- /*   660 */   167,  243,  169,  170,  313,  312,  247,  167,  798,  169,
- /*   670 */   170,  248,   94,  143,  153,  158,  163,  152,  157,  118,
- /*   680 */   120,  112,  114,  110,  116,   96,  122,  124,  126,  128,
- /*   690 */   130,  132,  134,  136,  138,  140,  279,  247,  142,  360,
- /*   700 */   358,    6,    5,  363,  346,   75,  274,   25,  257,  489,
- /*   710 */    13,  561,   33,  503,   13,  268,  267,  269,  143,  153,
- /*   720 */   158,  163,  152,  157,  118,  120,  112,  114,  110,  116,
- /*   730 */    64,  122,  124,  126,  128,  130,  132,  134,  136,  138,
- /*   740 */   140,   26,   76,   96,  400,   77,   71,  584,   96,  451,
- /*   750 */   166,  485,   29,   76,  402,   78,  167,   71,  169,  170,
- /*   760 */   295,  451,  211,   75,   30,  257,  314,  172,   75,  195,
- /*   770 */   514,  258,  292,   14,   15,  690,   77,   14,   15,  106,
- /*   780 */   195,   77,   77,  173,  191,  315,  203,   77,  344,  215,
- /*   790 */   106,  690,  327,   77,  173,  495,  338,  588,  529,  403,
- /*   800 */   179,  177,  296,  453,  251,  209,  475,  327,  175,   73,
- /*   810 */    74,  179,  177,   95,  531,  532,   35,  213,  475,  175,
- /*   820 */    73,   74,  457,   38,   95,  378,  438,  459,  258,  501,
- /*   830 */   449,  497,  841,  411,  461,  406,  653,   76,  311,  459,
- /*   840 */   387,   71,  322,   81,  323,   42,  101,  102,  103,  104,
- /*   850 */   105,  181,  185,   96,  356,  357,   96,  101,  102,  103,
- /*   860 */   104,  105,  181,  185,  195,   76,  655,  544,  328,   71,
- /*   870 */    96,  271,  431,   75,  106,  354,   75,  489,  173,  327,
- /*   880 */   298,  215,  410,  328,  428,  430,  429,  426,  427,   96,
- /*   890 */    75,  721,  195,   76,   91,  179,  177,   71,  348,  379,
- /*   900 */   349,  323,  106,  175,   73,   74,  173,  467,   95,   75,
- /*   910 */   271,  499,  445,   93,   77,  388,  446,  323,  323,  521,
- /*   920 */   195,  454,   45,  179,  177,  285,  836,   42,   41,  432,
- /*   930 */   106,  175,   73,   74,  173,  480,   95,  269,  488,   43,
- /*   940 */   486,  101,  102,  103,  104,  105,  181,  185,  800,  721,
- /*   950 */   417,  179,  177,  229,  422,  328,   96,   96,   96,  175,
- /*   960 */    73,   74,  814,   96,   95,  522,   53,  486,  479,  101,
- /*   970 */   102,  103,  104,  105,  181,  185,   75,   75,   75,   13,
- /*   980 */   107,  109,  423,   75,   55,    8,  106,  111,  496,  857,
- /*   990 */    19,   21,   23,  401,   96,  472,   56,  101,  102,  103,
- /*  1000 */   104,  105,  181,  185,  536,  240,   81,  339,  342,  863,
- /*  1010 */   546,   61,   96,   96,   75,   96,  341,  482,  113,  483,
- /*  1020 */    95,   96,  525,  417,  456,  542,   13,   96,   96,  523,
- /*  1030 */   417,  549,   75,   75,  552,   75,  115,  117,  472,  119,
- /*  1040 */    96,   75,   14,   15,   81,  121,   96,   75,   75,   77,
- /*  1050 */   417,  123,  125,  101,  102,  103,   60,  519,  466,   96,
- /*  1060 */    75,  498,  417,  240,  127,  417,   75,   64,  500,   62,
- /*  1070 */   129,   96,   63,  690,   96,  504,  508,  452,   68,   75,
- /*  1080 */   417,  494,   96,  131,   96,   96,   81,   96,  502,   14,
- /*  1090 */    15,   75,   96,   96,   75,  133,  555,   70,  135,   96,
- /*  1100 */   506,  512,   75,  510,   75,   75,  137,   75,  139,  141,
- /*  1110 */    96,  149,   75,   75,   81,   96,  151,  160,  516,   75,
- /*  1120 */    96,   96,   96,  162,  598,   80,  599,   96,   96,   82,
- /*  1130 */    75,  240,  221,   84,  174,   75,   96,   96,   96,  176,
- /*  1140 */    75,   75,   75,   96,  178,  180,  192,   75,   75,  518,
- /*  1150 */    96,  194,  204,   96,   79,  286,   75,   75,   75,  237,
- /*  1160 */   206,  208,  220,   75,   96,   96,   96,  236,   85,  235,
- /*  1170 */    75,   96,   87,   75,  241,   75,  867,  273,  215,  283,
- /*  1180 */    86,   77,   90,   97,   75,   75,   75,   88,  382,  470,
- /*  1190 */   474,   75,   89,   98,   99,  487,  100,  140,  156,  214,
- /*  1200 */   667,  668,  669,  182,  205,  188,  190,  189,  196,  199,
- /*  1210 */   198,  201,  215,  200,  202,  216,  217,  224,  222,  228,
- /*  1220 */   227,  229,  230,  226,  234,  238,  211,  245,  233,  253,
- /*  1230 */   250,  252,  255,  272,  260,  263,  265,  256,  264,  266,
- /*  1240 */   270,  278,  287,  280,  297,  281,  300,  320,  303,  302,
- /*  1250 */   305,  307,  304,  325,  333,  329,  310,  317,  326,  351,
- /*  1260 */   355,  370,  359,  330,  319,  340,  343,  368,  371,  361,
- /*  1270 */   374,  377,  385,  335,  375,  373,  396,  386,  380,  389,
- /*  1280 */   390,   54,  366,  391,  404,  392,  407,  405,  409,  408,
- /*  1290 */   412,  413,  418,  416,  829,  414,  424,  425,  415,  834,
- /*  1300 */   420,  439,  835,  421,  436,  440,  441,  442,  443,  444,
- /*  1310 */   447,  805,  450,  806,  455,  458,  828,  460,  728,  464,
- /*  1320 */   729,  843,  453,  465,  468,  471,  463,  845,  476,  469,
- /*  1330 */   481,  478,  473,  477,  484,  846,  493,  491,  848,  492,
- /*  1340 */   660,  662,  813,  855,  505,  507,  720,  509,  511,  723,
- /*  1350 */   513,  726,  515,  815,  524,  526,  527,  520,  517,  816,
- /*  1360 */   817,  818,  819,  534,  535,  820,  856,  539,  858,  540,
- /*  1370 */   545,  538,  543,  859,  862,  548,  551,  864,  553,  550,
- /*  1380 */   537,  557,  541,  547,  865,  556,  866,  560,  559,  547,
- /*  1390 */   562,
+ /*     0 */   283,  581,  110,  137,  139,  135,  141,  268,  147,  149,
+ /*    10 */   151,  153,  155,  157,  159,  161,  163,  165,  114,  119,
+ /*    20 */   120,  167,  175,  147,  149,  151,  153,  155,  157,  159,
+ /*    30 */   161,  163,  165,  155,  157,  159,  161,  163,  165,  132,
+ /*    40 */    94,  168,  178,  183,  188,  177,  182,  143,  145,  137,
+ /*    50 */   139,  135,  141,   72,  147,  149,  151,  153,  155,  157,
+ /*    60 */   159,  161,  163,  165,   44,   45,  245,  111,  147,  149,
+ /*    70 */   151,  153,  155,  157,  159,  161,  163,  165,   13,  427,
+ /*    80 */   121,  578,  657,  639,  375,  347,  167,   39,    6,    5,
+ /*    90 */    92,    3,  576,  363,   25,  355,  299,  255,   34,  269,
+ /*   100 */   513,  129,  372,  112,  132,   94,  168,  178,  183,  188,
+ /*   110 */   177,  182,  143,  145,  137,  139,  135,  141,  567,  147,
+ /*   120 */   149,  151,  153,  155,  157,  159,  161,  163,  165,   77,
+ /*   130 */   109,  373,  133,   77,  117,  119,  120,    7,   13,   32,
+ /*   140 */    33,  300,  280,   14,   15,  377,  301,  610,  379,  386,
+ /*   150 */   391,  167,  377,  366,  369,  379,  386,  391,  524,  330,
+ /*   160 */   394,   64,  368,  374,  407,  705,   95,  394,  571,  132,
+ /*   170 */    94,  168,  178,  183,  188,  177,  182,  143,  145,  137,
+ /*   180 */   139,  135,  141,    9,  147,  149,  151,  153,  155,  157,
+ /*   190 */   159,  161,  163,  165,  127,  125,  121,  373,  167,  101,
+ /*   200 */   102,  103,   28,   14,   15,  408,   33,  860,  889,    1,
+ /*   210 */   577,    3,  576,    4,  540,  332,  132,   94,  168,  178,
+ /*   220 */   183,  188,  177,  182,  143,  145,  137,  139,  135,  141,
+ /*   230 */   295,  147,  149,  151,  153,  155,  157,  159,  161,  163,
+ /*   240 */   165,    2,  466,  377,    4,  167,  379,  386,  391,   16,
+ /*   250 */    17,   18,  285,  159,  161,  163,  165,  240,  394,  173,
+ /*   260 */   243,  184,  189,  132,   94,  168,  178,  183,  188,  177,
+ /*   270 */   182,  143,  145,  137,  139,  135,  141,   96,  147,  149,
+ /*   280 */   151,  153,  155,  157,  159,  161,  163,  165,  815,  291,
+ /*   290 */   308,  813,   51,  500,  472,  462,  588,  539,   75,  322,
+ /*   300 */    27,  133,  409,  704,   81,  272,   10,  173,   96,  184,
+ /*   310 */   189,   96,  190,   13,  541,  542,   13,  393,   78,  167,
+ /*   320 */    37,  361,   40,   59,   67,   69,  325,  356,  586,   75,
+ /*   330 */   197,  368,   75,  316,  358,   95,  218,  132,   94,  168,
+ /*   340 */   178,  183,  188,  177,  182,  143,  145,  137,  139,  135,
+ /*   350 */   141,   77,  147,  149,  151,  153,  155,  157,  159,  161,
+ /*   360 */   163,  165,  173,  113,  184,  189,  167,  110,  101,  102,
+ /*   370 */   103,  318,  274,  405,  329,  121,   12,  461,   14,   15,
+ /*   380 */   404,   14,   15,  238,  132,   94,  168,  178,  183,  188,
+ /*   390 */   177,  182,  143,  145,  137,  139,  135,  141,  273,  147,
+ /*   400 */   149,  151,  153,  155,  157,  159,  161,  163,  165,   96,
+ /*   410 */    77,   51,  315,  427,   48,   36,  360,  196,  317,  129,
+ /*   420 */   130,  112,  314,   49,  355,  209,  313,   13,   96,  110,
+ /*   430 */    75,  197,  111,   96,  814,  485,   50,  589,   46,  461,
+ /*   440 */   167,   40,   59,   67,   69,  325,  356,  482,   47,   75,
+ /*   450 */   257,  467,  429,  358,   75,  197,  469,  232,  132,   94,
+ /*   460 */   168,  178,  183,  188,  177,  182,  143,  145,  137,  139,
+ /*   470 */   135,  141,   77,  147,  149,  151,  153,  155,  157,  159,
+ /*   480 */   161,  163,  165,  323,  237,   13,  830,  169,  249,  258,
+ /*   490 */    13,  703,   14,   15,  111,   96,  265,  485,   96,  192,
+ /*   500 */    96,  194,  195,   13,  192,  167,  194,  195,  238,  171,
+ /*   510 */   172,  476,  192,  471,  194,  195,   75,  211,  469,   75,
+ /*   520 */   257,   75,   91,  132,   94,  168,  178,  183,  188,  177,
+ /*   530 */   182,  143,  145,  137,  139,  135,  141,  170,  147,  149,
+ /*   540 */   151,  153,  155,  157,  159,  161,  163,  165,  365,   48,
+ /*   550 */    14,   15,  216,   65,  228,   14,   15,  298,   49,  251,
+ /*   560 */    66,   13,  602,   13,  330,   96,  676,  212,   14,   15,
+ /*   570 */   167,   50,  865,  222,   57,   58,  678,  275,  192,   20,
+ /*   580 */   194,  195,  277,  403,   26,  351,   75,  499,  132,   94,
+ /*   590 */   168,  178,  183,  188,  177,  182,  143,  145,  137,  139,
+ /*   600 */   135,  141,   96,  147,  149,  151,  153,  155,  157,  159,
+ /*   610 */   161,  163,  165,  587,  863,   83,   11,  167,  742,  345,
+ /*   620 */   332,  312,  306,   75,   93,  358,   14,   15,   14,   15,
+ /*   630 */   858,  173,  495,  184,  189,  132,   94,  168,  178,  183,
+ /*   640 */   188,  177,  182,  143,  145,  137,  139,  135,  141,  594,
+ /*   650 */   147,  149,  151,  153,  155,  157,  159,  161,  163,  165,
+ /*   660 */    22,  272,  352,  192,  167,  194,  195,  192,  295,  194,
+ /*   670 */   195,  285,  505,  192,   42,  194,  195,  192,  351,  194,
+ /*   680 */   195,  595,  132,   94,  168,  178,  183,  188,  177,  182,
+ /*   690 */   143,  145,  137,  139,  135,  141,  338,  147,  149,  151,
+ /*   700 */   153,  155,  157,  159,  161,  163,  165,  837,  511,  286,
+ /*   710 */   507,  167,  382,  127,  125,  192,  339,  194,  195,  192,
+ /*   720 */   543,  194,  195,  333,  340,  342,  351,  442,  274,  132,
+ /*   730 */    94,  168,  178,  183,  188,  177,  182,  143,  145,  137,
+ /*   740 */   139,  135,  141,   96,  147,  149,  151,  153,  155,  157,
+ /*   750 */   159,  161,  163,  165,  273,  352,  110,  371,  167,  373,
+ /*   760 */   388,  438,  440,  439,   75,  499,  362,  574,   33,  335,
+ /*   770 */   538,  668,  656,  351,   31,  413,  132,  186,  168,  178,
+ /*   780 */   183,  188,  177,  182,  143,  145,  137,  139,  135,  141,
+ /*   790 */   509,  147,  149,  151,  153,  155,  157,  159,  161,  163,
+ /*   800 */   165,   96,  736,  352,  283,  167,  110,  397,  123,  124,
+ /*   810 */   531,  421,  193,  416,  115,  681,  116,  235,  477,  236,
+ /*   820 */   351,  111,   75,  244,   94,  168,  178,  183,  188,  177,
+ /*   830 */   182,  143,  145,  137,  139,  135,  141,   96,  147,  149,
+ /*   840 */   151,  153,  155,  157,  159,  161,  163,  165,   96,  879,
+ /*   850 */   352,  881,  167,  292,  455,  293,  270,  280,   75,  108,
+ /*   860 */   554,  319,  857,  236,   42,  447,   13,  351,   13,   75,
+ /*   870 */   134,  111,  168,  178,  183,  188,  177,  182,  143,  145,
+ /*   880 */   137,  139,  135,  141,   96,  147,  149,  151,  153,  155,
+ /*   890 */   157,  159,  161,  163,  165,   96,   76,  352,  444,   96,
+ /*   900 */    71,   96,  443,   52,  208,   75,  136,   76,  106,   24,
+ /*   910 */   412,   71,  180,  596,  445,   54,   75,  138,  266,  106,
+ /*   920 */    75,  140,   75,  142,  441,  220,   96,  337,  336,   29,
+ /*   930 */    96,   14,   15,   14,   15,  133,  220,   77,   96,  198,
+ /*   940 */    96,  458,  179,  346,  348,  347,  133,   75,  433,   96,
+ /*   950 */   198,   75,  144,  389,  285,  347,  204,  202,  320,   75,
+ /*   960 */   146,   75,  148,  410,  200,   73,   74,  204,  202,   95,
+ /*   970 */    75,  150,  398,   96,  347,  200,   73,   74,  852,   96,
+ /*   980 */    95,   76,  823,  448,  597,   71,  432,  459,  293,  420,
+ /*   990 */    96,  705,  303,  106,   75,  480,   77,  436,  437,   81,
+ /*  1000 */    75,  152,  101,  102,  103,  104,  105,  206,  210,  705,
+ /*  1010 */   220,   75,  154,  101,  102,  103,  104,  105,  206,  210,
+ /*  1020 */   133,   30,   77,  240,  198,  456,   96,  347,   35,  464,
+ /*  1030 */    45,  490,  463,  293,   96,  873,  498,   96,  496,   96,
+ /*  1040 */    76,  204,  202,  736,   71,   96,  601,   75,  156,  200,
+ /*  1050 */    73,   74,  106,   96,   95,   75,  158,  295,   75,  160,
+ /*  1060 */    75,  162,   38,  492,   96,  853,   75,  164,   76,  220,
+ /*  1070 */    41,  191,   71,  552,   75,  166,  482,   43,  427,  133,
+ /*  1080 */   106,  528,  568,  198,   96,   75,  197,  101,  102,  103,
+ /*  1090 */   104,  105,  206,  210,  816,  670,   77,  220,  240,   81,
+ /*  1100 */   204,  202,  309,   96,   77,   75,  174,  133,  200,   73,
+ /*  1110 */    74,  198,  493,   95,   77,    8,  489,  506,  427,  427,
+ /*  1120 */    19,   21,   23,  411,   75,  176,   42,  234,  204,  202,
+ /*  1130 */   427,   81,  427,  562,  427,  546,  200,   73,   74,  238,
+ /*  1140 */   522,   95,  556,   96,  529,  427,  101,  102,  103,  104,
+ /*  1150 */   105,  206,  210,  532,  535,  496,  466,  508,  510,  266,
+ /*  1160 */    96,  533,  885,  559,   75,  185,  565,   96,   56,  512,
+ /*  1170 */    96,  516,   96,  520,  101,  102,  103,  104,  105,  206,
+ /*  1180 */   210,   75,  187,   55,  526,   53,   60,   61,   75,  199,
+ /*  1190 */    96,   75,  201,   75,  203,   96,   64,   62,   96,   70,
+ /*  1200 */    96,   63,   96,   68,   96,  611,   96,  514,  518,  462,
+ /*  1210 */    84,   75,  205,  504,   96,  612,   75,  217,   81,   75,
+ /*  1220 */   219,   75,  229,   75,  231,   75,  233,   75,  246,   81,
+ /*  1230 */    79,   80,   96,  266,   82,   75,  262,   96,  263,  310,
+ /*  1240 */    86,   96,  261,   96,   85,   96,  247,   96,   87,   97,
+ /*  1250 */    99,   88,   90,   75,  267,  107,   89,   98,   75,  297,
+ /*  1260 */    75,  307,   75,  364,   75,  392,   75,  484,   75,  497,
+ /*  1270 */   118,  100,  131,  128,  165,  122,  181,  682,  239,  683,
+ /*  1280 */   684,  207,  230,  213,  126,  214,  215,  221,  225,  224,
+ /*  1290 */   223,  226,  240,  227,  241,  248,  242,  250,  254,  253,
+ /*  1300 */   252,  255,  236,  264,  259,  256,  260,  271,  276,  278,
+ /*  1310 */   279,  281,  284,  296,  282,  289,  287,  290,  288,  294,
+ /*  1320 */   302,  305,  311,  304,  321,  324,  326,  344,  328,  327,
+ /*  1330 */   331,  349,  357,  329,  353,  334,  341,  343,  380,  350,
+ /*  1340 */   378,  381,  354,  367,  359,  370,  384,  387,  396,  395,
+ /*  1350 */   399,  400,  385,   54,  406,  414,  376,  401,  390,  383,
+ /*  1360 */   415,  417,  418,  402,  419,  422,  425,  423,  424,  434,
+ /*  1370 */   426,  428,  430,  845,  431,  435,  850,  446,  851,  449,
+ /*  1380 */   450,  451,  452,  453,  821,  454,  822,  457,  460,  465,
+ /*  1390 */   743,  468,  744,  844,  470,  859,  463,  481,  475,  479,
+ /*  1400 */   861,  474,  473,  478,  483,  486,  487,  491,  488,  494,
+ /*  1410 */   862,  501,  502,  503,  864,  675,  677,  829,  871,  517,
+ /*  1420 */   515,  735,  519,  521,  523,  738,  525,  741,  831,  534,
+ /*  1430 */   832,  833,  530,  536,  834,  527,  537,  835,  544,  836,
+ /*  1440 */   545,  547,  872,  874,  549,  875,  557,  555,  548,  550,
+ /*  1450 */   553,  878,  880,  882,  561,  558,  883,  560,  551,  563,
+ /*  1460 */   566,  569,  564,  570,  572,  573,  884,  555,  555,  555,
+ /*  1470 */   555,  575,
 };
 static const YYCODETYPE yy_lookahead[] = {
- /*     0 */    25,   30,   27,   72,   73,   74,   75,   36,   77,   78,
- /*    10 */    79,   80,   81,   82,   83,   84,   85,   86,   10,   44,
- /*    20 */    76,   77,   78,   79,   80,   81,   82,   83,   84,   85,
- /*    30 */    86,   81,   82,   83,   84,   85,   86,   62,   63,   64,
+ /*     0 */    25,   10,   27,   74,   75,   76,   77,   26,   79,   80,
+ /*    10 */    81,   82,   83,   84,   85,   86,   87,   88,  168,  169,
+ /*    20 */   170,   46,   78,   79,   80,   81,   82,   83,   84,   85,
+ /*    30 */    86,   87,   88,   83,   84,   85,   86,   87,   88,   64,
  /*    40 */    65,   66,   67,   68,   69,   70,   71,   72,   73,   74,
- /*    50 */    75,   23,   77,   78,   79,   80,   81,   82,   83,   84,
- /*    60 */    85,   86,   10,   60,   26,   90,   77,   78,   79,   80,
- /*    70 */    81,   82,   83,   84,   85,   86,   92,   27,  148,   95,
- /*    80 */    96,   97,   44,  142,  143,  144,   48,   23,  147,   25,
- /*    90 */   150,  107,   18,   90,   24,  155,  149,   94,  158,  159,
- /*   100 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71,
- /*   110 */    72,   73,   74,   75,  150,   77,   78,   79,   80,   81,
- /*   120 */    82,   83,   84,   85,   86,   51,    0,   44,  177,  178,
- /*   130 */   127,  128,  129,   83,  170,  184,   10,   11,  174,  157,
- /*   140 */    90,   91,   10,  115,   22,   62,   63,   64,   65,   66,
- /*   150 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   27,
- /*   160 */    77,   78,   79,   80,   81,   82,   83,   84,   85,   86,
- /*   170 */    10,  189,   44,  209,  210,   27,  102,  103,  104,  109,
- /*   180 */    45,  111,  112,  201,  202,   10,   11,  113,  206,  157,
- /*   190 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71,
- /*   200 */    72,   73,   74,   75,   94,   77,   78,   79,   80,   81,
- /*   210 */    82,   83,   84,   85,   86,   19,  106,  134,   96,   64,
- /*   220 */    18,  189,   90,   91,   28,  150,   83,   84,   85,   86,
- /*   230 */    14,   15,   16,  158,  159,   39,  101,   41,   90,   91,
- /*   240 */    92,  163,   27,   95,   96,   97,   44,   92,   93,   94,
- /*   250 */    95,   96,   97,   98,   99,  107,  181,  182,   25,  137,
- /*   260 */    27,  106,   64,  135,   62,   63,   64,   65,   66,   67,
- /*   270 */    68,   69,   70,   71,   72,   73,   74,   75,  200,   77,
- /*   280 */    78,   79,   80,   81,   82,   83,   84,   85,   86,   27,
- /*   290 */    24,   44,   94,   95,   96,   97,   98,   99,   24,  217,
- /*   300 */    26,  219,  220,  163,  106,   90,   91,  186,  187,   62,
- /*   310 */    63,   64,   65,   66,   67,   68,   69,   70,   71,   72,
- /*   320 */    73,   74,   75,   90,   77,   78,   79,   80,   81,   82,
- /*   330 */    83,   84,   85,   86,  217,  218,  219,  220,   24,  150,
- /*   340 */   200,  150,   19,   81,   82,   24,  110,  165,  166,  167,
- /*   350 */   114,   28,   90,   91,   24,  144,  150,  217,  147,  219,
- /*   360 */   220,   27,   39,  101,   41,   44,   92,   64,   23,   95,
- /*   370 */    96,   97,   27,   10,   51,  109,  170,  111,  112,  188,
- /*   380 */   174,  107,  135,   62,   63,   64,   65,   66,   67,   68,
- /*   390 */    69,   70,   71,   72,   73,   74,   75,   94,   77,   78,
- /*   400 */    79,   80,   81,   82,   83,   84,   85,   86,   24,  227,
- /*   410 */   165,  166,  167,  150,  150,   27,  160,  149,  212,  163,
- /*   420 */   164,   44,   10,  109,   90,  111,  112,   10,   44,  238,
- /*   430 */   224,  201,  202,  170,  170,   90,   91,  174,  174,  109,
- /*   440 */    23,  111,  112,   66,   67,  150,   62,   63,   64,   65,
- /*   450 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75,
- /*   460 */   150,   77,   78,   79,   80,   81,   82,   83,   84,   85,
- /*   470 */    86,   94,  227,   44,  149,  212,  171,   10,   90,   91,
- /*   480 */   170,  168,  169,  188,  174,  221,   12,  224,   71,   10,
- /*   490 */   177,   62,   63,   64,   65,   66,   67,   68,   69,   70,
- /*   500 */    71,   72,   73,   74,   75,  117,   77,   78,   79,   80,
- /*   510 */    81,   82,   83,   84,   85,   86,   45,   10,   44,  150,
- /*   520 */    10,   10,  217,   13,  219,  220,  102,  103,  104,  110,
- /*   530 */   101,  150,  113,  150,  224,   64,   62,   63,   64,   65,
- /*   540 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75,
- /*   550 */   150,   77,   78,   79,   80,   81,   82,   83,   84,   85,
- /*   560 */    86,   10,  192,   44,  183,   24,  183,   26,   10,  199,
- /*   570 */   170,   26,  101,   24,  174,   26,  109,  106,  111,  112,
- /*   580 */    26,   62,   63,   64,   65,   66,   67,   68,   69,   70,
- /*   590 */    71,   72,   73,   74,   75,  226,   77,   78,   79,   80,
- /*   600 */    81,   82,   83,   84,   85,   86,   26,  226,   44,  226,
- /*   610 */   210,   29,  149,  169,   32,   24,  109,   26,  111,  112,
- /*   620 */   109,  177,  111,  112,   10,   43,   62,   63,   64,   65,
- /*   630 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75,
- /*   640 */    91,   77,   78,   79,   80,   81,   82,   83,   84,   85,
- /*   650 */    86,   14,   15,   44,   24,  101,   26,   10,  150,  163,
- /*   660 */   109,  116,  111,  112,   93,   94,  117,  109,   18,  111,
- /*   670 */   112,   91,   63,   64,   65,   66,   67,   68,   69,   70,
- /*   680 */    71,   72,   73,   74,   75,  150,   77,   78,   79,   80,
- /*   690 */    81,   82,   83,   84,   85,   86,  200,  117,   44,   81,
- /*   700 */    82,  145,  146,  150,   23,  170,   23,  151,   27,  174,
- /*   710 */    27,  158,  159,  157,   27,   24,  208,   26,   64,   65,
- /*   720 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75,
- /*   730 */   100,   77,   78,   79,   80,   81,   82,   83,   84,   85,
- /*   740 */    86,  152,   23,  150,  157,  189,   27,   10,  150,  157,
- /*   750 */   157,  216,  156,   23,  153,  157,  109,   27,  111,  112,
- /*   760 */    24,  157,   26,  170,   24,   27,   33,  174,  170,   50,
- /*   770 */   214,   90,  174,   90,   91,  101,  189,   90,   91,   60,
- /*   780 */    50,  189,  189,   64,  134,   52,  136,  189,  162,  115,
- /*   790 */    60,   25,  150,  189,   64,   21,  170,   10,  150,   21,
- /*   800 */    81,   82,   83,   62,  117,  212,  214,  150,   89,   90,
- /*   810 */    91,   81,   82,   94,  166,  167,  161,  224,  214,   89,
- /*   820 */    90,   91,  230,  150,   94,  183,  225,  235,   90,   55,
- /*   830 */   229,   57,   12,   55,  230,   57,   10,   23,  105,  235,
- /*   840 */   183,   27,   24,  113,   26,  101,  127,  128,  129,  130,
- /*   850 */   131,  132,  133,  150,  127,  128,  150,  127,  128,  129,
- /*   860 */   130,  131,  132,  133,   50,   23,  125,  129,  226,   27,
- /*   870 */   150,  150,   47,  170,   60,  227,  170,  174,   64,  150,
- /*   880 */   174,  115,  157,  226,  102,  103,  104,   53,   54,  150,
- /*   890 */   170,   10,   50,   23,  174,   81,   82,   27,   24,   24,
- /*   900 */    26,   26,   60,   89,   90,   91,   64,   26,   94,  170,
- /*   910 */   150,  137,  183,  174,  189,   24,   24,   26,   26,  216,
- /*   920 */    50,  186,  187,   81,   82,   83,  101,  101,  171,  208,
- /*   930 */    60,   89,   90,   91,   64,   24,   94,   26,   24,   34,
- /*   940 */    26,  127,  128,  129,  130,  131,  132,  133,  134,   10,
- /*   950 */   150,   81,   82,   27,  134,  226,  150,  150,  150,   89,
- /*   960 */    90,   91,   10,  150,   94,   24,  171,   26,  208,  127,
- /*   970 */   128,  129,  130,  131,  132,  133,  170,  170,  170,   27,
- /*   980 */   174,  174,  174,  170,  180,   12,   60,  174,  188,   10,
- /*   990 */    17,   18,   19,   20,  150,  150,   42,  127,  128,  129,
- /*  1000 */   130,  131,  132,  133,   31,  124,  113,   81,   82,   10,
- /*  1010 */    37,  172,  150,  150,  170,  150,   90,  157,  174,  126,
- /*  1020 */    94,  150,   49,  150,   51,   46,   27,  150,  150,   56,
- /*  1030 */   150,   58,  170,  170,   61,  170,  174,  174,  150,  174,
- /*  1040 */   150,  170,   90,   91,  113,  174,  150,  170,  170,  189,
- /*  1050 */   150,  174,  174,  127,  128,  129,   46,  126,  213,  150,
- /*  1060 */   170,  188,  150,  124,  174,  150,  170,  100,  188,  171,
- /*  1070 */   174,  150,  173,   10,  150,  102,  103,  104,  171,  170,
- /*  1080 */   150,  108,  150,  174,  150,  150,  113,  150,  188,   90,
- /*  1090 */    91,  170,  150,  150,  170,  174,   59,   23,  174,  150,
- /*  1100 */   188,  213,  170,  188,  170,  170,  174,  170,  174,  174,
- /*  1110 */   150,  174,  170,  170,  113,  150,  174,  174,  188,  170,
- /*  1120 */   150,  150,  150,  174,  115,  189,  115,  150,  150,  191,
- /*  1130 */   170,  124,  119,  193,  174,  170,  150,  150,  150,  174,
- /*  1140 */   170,  170,  170,  150,  174,  174,  174,  170,  170,  157,
- /*  1150 */   150,  174,  174,  150,  190,  150,  170,  170,  170,  121,
- /*  1160 */   174,  174,  174,  170,  150,  150,  150,  174,  194,  122,
- /*  1170 */   170,  150,  196,  170,  174,  170,  139,  174,  115,  174,
- /*  1180 */   195,  189,  123,  115,  170,  170,  170,  197,  174,  174,
- /*  1190 */   174,  170,  198,  150,  115,  174,  150,   86,   94,  150,
- /*  1200 */   113,  113,  113,   23,  134,  222,   18,  223,   23,  187,
- /*  1210 */    24,  150,  115,   26,   24,  150,  154,   26,  120,   99,
- /*  1220 */   172,   27,  162,  211,  172,  120,   26,  203,  211,  117,
- /*  1230 */   150,  150,  150,  101,  150,  204,  118,  154,  205,   23,
- /*  1240 */   150,   24,  115,  204,   24,  205,  171,   23,  175,  150,
- /*  1250 */   178,  150,  176,  211,  162,  211,  179,  179,  172,   24,
- /*  1260 */   228,   46,  228,  172,  179,  170,  170,  150,   23,  163,
- /*  1270 */    24,   23,   46,  180,  171,  173,  182,   23,  171,   98,
- /*  1280 */   150,  106,  182,  175,  150,  176,  150,  154,   25,  154,
- /*  1290 */   150,  154,  154,  101,   12,  231,   40,   38,  232,  101,
- /*  1300 */   233,  137,  101,  234,   47,  150,  154,  101,  150,   23,
- /*  1310 */   171,   10,   12,  137,  185,   18,   10,   10,  125,  150,
- /*  1320 */   125,   18,   62,  105,  150,  194,  185,   10,  125,   71,
- /*  1330 */   215,   23,   71,  150,   23,   10,  194,  116,   10,  150,
- /*  1340 */    10,   10,   10,   10,  116,  194,   10,  185,  105,   10,
- /*  1350 */   194,   10,  125,   10,  150,  150,  154,   23,  215,   10,
- /*  1360 */    10,   10,   10,  150,   24,   10,   10,   25,   10,  150,
- /*  1370 */    35,  163,  163,   10,   10,  150,  154,   10,   21,  150,
- /*  1380 */   236,  150,  237,  236,   10,  138,   10,  239,  139,  240,
- /*  1390 */   140,
+ /*    50 */    75,   76,   77,   23,   79,   80,   81,   82,   83,   84,
+ /*    60 */    85,   86,   87,   88,  189,  190,   26,   92,   79,   80,
+ /*    70 */    81,   82,   83,   84,   85,   86,   87,   88,   27,  152,
+ /*    80 */   230,    0,   24,   24,   26,   26,   46,  172,  147,  148,
+ /*    90 */    50,   10,   11,   23,  153,  180,  159,   27,  162,  118,
+ /*   100 */   159,  165,  166,  167,   64,   65,   66,   67,   68,   69,
+ /*   110 */    70,   71,   72,   73,   74,   75,   76,   77,  191,   79,
+ /*   120 */    80,   81,   82,   83,   84,   85,   86,   87,   88,  192,
+ /*   130 */    25,  152,   62,  192,  168,  169,  170,   10,   27,  160,
+ /*   140 */   161,  204,  205,   92,   93,   94,  209,  117,   97,   98,
+ /*   150 */    99,   46,   94,   83,   84,   97,   98,   99,  217,   47,
+ /*   160 */   109,  102,   92,  184,  185,   25,   96,  109,  241,   64,
+ /*   170 */    65,   66,   67,   68,   69,   70,   71,   72,   73,   74,
+ /*   180 */    75,   76,   77,  150,   79,   80,   81,   82,   83,   84,
+ /*   190 */    85,   86,   87,   88,   83,   84,  230,  152,   46,  129,
+ /*   200 */   130,  131,  157,   92,   93,  160,  161,   18,  144,  145,
+ /*   210 */   146,   10,   11,  149,  103,  103,   64,   65,   66,   67,
+ /*   220 */    68,   69,   70,   71,   72,   73,   74,   75,   76,   77,
+ /*   230 */   152,   79,   80,   81,   82,   83,   84,   85,   86,   87,
+ /*   240 */    88,  146,   53,   94,  149,   46,   97,   98,   99,   14,
+ /*   250 */    15,   16,  165,   85,   86,   87,   88,  117,  109,  220,
+ /*   260 */   221,  222,  223,   64,   65,   66,   67,   68,   69,   70,
+ /*   270 */    71,   72,   73,   74,   75,   76,   77,  152,   79,   80,
+ /*   280 */    81,   82,   83,   84,   85,   86,   87,   88,  136,  211,
+ /*   290 */   203,   18,   66,  104,  105,  106,   10,  152,  173,  174,
+ /*   300 */    23,   62,   25,   24,  115,   26,  151,  220,  152,  222,
+ /*   310 */   223,  152,   23,   27,  169,  170,   27,  175,  159,   46,
+ /*   320 */    94,   95,   96,   97,   98,   99,  100,  101,   10,  173,
+ /*   330 */   174,   92,  173,  174,  108,   96,  137,   64,   65,   66,
+ /*   340 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   76,
+ /*   350 */    77,  192,   79,   80,   81,   82,   83,   84,   85,   86,
+ /*   360 */    87,   88,  220,   23,  222,  223,   46,   27,  129,  130,
+ /*   370 */   131,  215,   93,  180,  181,  230,  152,  159,   92,   93,
+ /*   380 */   187,   92,   93,  227,   64,   65,   66,   67,   68,   69,
+ /*   390 */    70,   71,   72,   73,   74,   75,   76,   77,  119,   79,
+ /*   400 */    80,   81,   82,   83,   84,   85,   86,   87,   88,  152,
+ /*   410 */   192,   66,   24,  152,   19,  171,  172,   24,   24,  165,
+ /*   420 */   166,  167,  112,   28,  180,   24,  116,   27,  152,   27,
+ /*   430 */   173,  174,   92,  152,   18,  217,   41,   10,   43,  159,
+ /*   440 */    46,   96,   97,   98,   99,  100,  101,  152,   53,  173,
+ /*   450 */   174,  233,  191,  108,  173,  174,  238,  137,   64,   65,
+ /*   460 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75,
+ /*   470 */    76,   77,  192,   79,   80,   81,   82,   83,   84,   85,
+ /*   480 */    86,   87,   88,   24,  227,   27,   10,   46,  212,  213,
+ /*   490 */    27,   24,   92,   93,   92,  152,  215,  217,  152,  111,
+ /*   500 */   152,  113,  114,   27,  111,   46,  113,  114,  227,   68,
+ /*   510 */    69,  216,  111,  233,  113,  114,  173,  174,  238,  173,
+ /*   520 */   174,  173,  174,   64,   65,   66,   67,   68,   69,   70,
+ /*   530 */    71,   72,   73,   74,   75,   76,   77,   96,   79,   80,
+ /*   540 */    81,   82,   83,   84,   85,   86,   87,   88,   24,   19,
+ /*   550 */    92,   93,  136,   31,  138,   92,   93,   23,   28,  213,
+ /*   560 */    38,   27,   10,   27,   47,  152,   10,  224,   92,   93,
+ /*   570 */    46,   41,   10,   43,   14,   15,   10,  119,  111,  151,
+ /*   580 */   113,  114,  119,   66,  154,  152,  173,  174,   64,   65,
+ /*   590 */    66,   67,   68,   69,   70,   71,   72,   73,   74,   75,
+ /*   600 */    76,   77,  152,   79,   80,   81,   82,   83,   84,   85,
+ /*   610 */    86,   87,   88,   10,   10,  195,   13,   46,   10,  186,
+ /*   620 */   103,   85,  202,  173,  174,  108,   92,   93,   92,   93,
+ /*   630 */    12,  220,  219,  222,  223,   64,   65,   66,   67,   68,
+ /*   640 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   10,
+ /*   650 */    79,   80,   81,   82,   83,   84,   85,   86,   87,   88,
+ /*   660 */   151,   26,  229,  111,   46,  113,  114,  111,  152,  113,
+ /*   670 */   114,  165,   21,  111,  103,  113,  114,  111,  152,  113,
+ /*   680 */   114,   10,   64,   65,   66,   67,   68,   69,   70,   71,
+ /*   690 */    72,   73,   74,   75,   76,   77,   34,   79,   80,   81,
+ /*   700 */    82,   83,   84,   85,   86,   87,   88,   10,   57,  203,
+ /*   710 */    59,   46,  186,   83,   84,  111,   54,  113,  114,  111,
+ /*   720 */    23,  113,  114,  104,  105,  106,  152,  211,   93,   64,
+ /*   730 */    65,   66,   67,   68,   69,   70,   71,   72,   73,   74,
+ /*   740 */    75,   76,   77,  152,   79,   80,   81,   82,   83,   84,
+ /*   750 */    85,   86,   87,   88,  119,  229,   27,  164,   46,  152,
+ /*   760 */   186,  104,  105,  106,  173,  174,  173,  160,  161,  107,
+ /*   770 */    73,   10,   24,  152,   26,   21,   64,   65,   66,   67,
+ /*   780 */    68,   69,   70,   71,   72,   73,   74,   75,   76,   77,
+ /*   790 */   139,   79,   80,   81,   82,   83,   84,   85,   86,   87,
+ /*   800 */    88,  152,   10,  229,   25,   46,   27,  186,  129,  130,
+ /*   810 */   219,   57,  112,   59,   24,  115,   26,   24,   26,   26,
+ /*   820 */   152,   92,  173,  174,   65,   66,   67,   68,   69,   70,
+ /*   830 */    71,   72,   73,   74,   75,   76,   77,  152,   79,   80,
+ /*   840 */    81,   82,   83,   84,   85,   86,   87,   88,  152,   10,
+ /*   850 */   229,   10,   46,   24,  186,   26,  204,  205,  173,  174,
+ /*   860 */   131,   24,   12,   26,  103,   22,   27,  152,   27,  173,
+ /*   870 */   174,   92,   66,   67,   68,   69,   70,   71,   72,   73,
+ /*   880 */    74,   75,   76,   77,  152,   79,   80,   81,   82,   83,
+ /*   890 */    84,   85,   86,   87,   88,  152,   23,  229,   29,  152,
+ /*   900 */    27,  152,   33,   96,  159,  173,  174,   23,   35,  151,
+ /*   910 */   155,   27,   66,   10,   45,  108,  173,  174,  126,   35,
+ /*   920 */   173,  174,  173,  174,   49,   52,  152,   95,   96,  158,
+ /*   930 */   152,   92,   93,   92,   93,   62,   52,  192,  152,   66,
+ /*   940 */   152,   98,   96,   24,  229,   26,   62,  173,  174,  152,
+ /*   950 */    66,  173,  174,   24,  165,   26,   83,   84,   85,  173,
+ /*   960 */   174,  173,  174,  159,   91,   92,   93,   83,   84,   96,
+ /*   970 */   173,  174,   24,  152,   26,   91,   92,   93,  103,  152,
+ /*   980 */    96,   23,  139,  228,   10,   27,  136,  232,   26,  159,
+ /*   990 */   152,   10,  203,   35,  173,  174,  192,   55,   56,  115,
+ /*  1000 */   173,  174,  129,  130,  131,  132,  133,  134,  135,  103,
+ /*  1010 */    52,  173,  174,  129,  130,  131,  132,  133,  134,  135,
+ /*  1020 */    62,   24,  192,  117,   66,   24,  152,   26,  163,  189,
+ /*  1030 */   190,   24,   64,   26,  152,   10,   24,  152,   26,  152,
+ /*  1040 */    23,   83,   84,   10,   27,  152,   10,  173,  174,   91,
+ /*  1050 */    92,   93,   35,  152,   96,  173,  174,  152,  173,  174,
+ /*  1060 */   173,  174,  152,  159,  152,  103,  173,  174,   23,   52,
+ /*  1070 */   175,  159,   27,   48,  173,  174,  152,   36,  152,   62,
+ /*  1080 */    35,  159,   61,   66,  152,  173,  174,  129,  130,  131,
+ /*  1090 */   132,  133,  134,  135,  136,  127,  192,   52,  117,  115,
+ /*  1100 */    83,   84,   85,  152,  192,  173,  174,   62,   91,   92,
+ /*  1110 */    93,   66,  128,   96,  192,   12,  211,  191,  152,  152,
+ /*  1120 */    17,   18,   19,   20,  173,  174,  103,  215,   83,   84,
+ /*  1130 */   152,  115,  152,   30,  152,   32,   91,   92,   93,  227,
+ /*  1140 */   216,   96,   39,  152,  128,  152,  129,  130,  131,  132,
+ /*  1150 */   133,  134,  135,   24,   51,   26,   53,  191,  191,  126,
+ /*  1160 */   152,   58,  141,   60,  173,  174,   63,  152,   44,  191,
+ /*  1170 */   152,  191,  152,  191,  129,  130,  131,  132,  133,  134,
+ /*  1180 */   135,  173,  174,  183,  191,  175,   48,  176,  173,  174,
+ /*  1190 */   152,  173,  174,  173,  174,  152,  102,  175,  152,   23,
+ /*  1200 */   152,  177,  152,  175,  152,  117,  152,  104,  105,  106,
+ /*  1210 */   196,  173,  174,  110,  152,  117,  173,  174,  115,  173,
+ /*  1220 */   174,  173,  174,  173,  174,  173,  174,  173,  174,  115,
+ /*  1230 */   193,  192,  152,  126,  194,  173,  174,  152,  123,  152,
+ /*  1240 */   198,  152,  124,  152,  197,  152,  121,  152,  199,  117,
+ /*  1250 */   117,  200,  125,  173,  174,   23,  201,  152,  173,  174,
+ /*  1260 */   173,  174,  173,  174,  173,  174,  173,  174,  173,  174,
+ /*  1270 */    24,  152,   24,  165,   88,  231,   96,  115,  152,  115,
+ /*  1280 */   115,   23,  136,  225,  231,  226,   18,   23,   26,  190,
+ /*  1290 */    24,  152,  117,   24,  152,  122,  156,   26,  101,  176,
+ /*  1300 */   214,   27,   26,  122,  214,  164,  176,  206,  152,  152,
+ /*  1310 */   119,  152,  152,  103,  156,  120,  207,   23,  208,  152,
+ /*  1320 */    24,  208,  117,  207,   24,  175,  152,   23,  179,  178,
+ /*  1330 */   152,  214,  164,  181,  214,  182,  182,  182,   48,  176,
+ /*  1340 */   152,   23,  176,  173,  183,  173,   24,   23,   23,   48,
+ /*  1350 */   100,  152,  175,  108,  185,  152,  185,  178,  175,  177,
+ /*  1360 */   156,  152,  156,  179,   25,  152,  235,  156,  234,   42,
+ /*  1370 */   103,  156,  236,   12,  237,   40,  103,   49,  103,  139,
+ /*  1380 */   152,  156,  103,  152,   10,   23,  139,  175,   12,  188,
+ /*  1390 */   127,   18,  127,   10,   10,   18,   64,  197,  107,   73,
+ /*  1400 */    10,  152,  188,  152,   73,  127,  152,  218,   23,   23,
+ /*  1410 */    10,  118,  152,  197,   10,   10,   10,   10,   10,  197,
+ /*  1420 */   118,   10,  188,  107,  197,   10,  127,   10,   10,  152,
+ /*  1430 */    10,   10,   23,  152,   10,  218,  156,   10,  152,   10,
+ /*  1440 */    24,  239,   10,   10,   25,   10,  239,   37,  165,  152,
+ /*  1450 */   165,   10,   10,   10,  156,  152,   10,  152,  240,  152,
+ /*  1460 */    21,  140,  156,  152,  141,  242,   10,  243,  243,  243,
+ /*  1470 */   243,  142,
 };
-#define YY_SHIFT_USE_DFLT (-70)
+#define YY_SHIFT_USE_DFLT (-72)
 static const short yy_shift_ofst[] = {
- /*     0 */   175,  126,  -70,  -70,  973,    8,   52,  -70,  216,  510,
- /*    10 */   160,  132,  363,  -70,  -70,  -70,  -70,  -70,  -70,  510,
- /*    20 */   412,  510,  479,  510,  614,   64,  737,  215,  541,  740,
- /*    30 */   787,  148,  -70,  334,  -70,  155,  -70,  215,  198,  -70,
- /*    40 */   744,  -70,  905,  323,  -70,  -70,  -70,  -70,  -70,  -70,
- /*    50 */   -70,  110,  744,  -70,  954,  -70,  637,  -70,  -70, 1010,
- /*    60 */   -29,  744,  967,  -70,  -70,  -70,  -70,  744,  -70, 1074,
- /*    70 */   870,   28,  719, 1009, 1011,  -70,  730,  -70,   70, 1001,
- /*    80 */   -70,  236,  -70,  545, 1007, 1038, 1047, 1013, 1059,  -70,
- /*    90 */   870,   38,  870,  519,  870,  -70, 1068,  215, 1079,  215,
- /*   100 */   -70,  -70,  -70,  -70,  -70,  -70,  -70,  654,  870,  609,
- /*   110 */   870,  -11,  870,  -11,  870,  -11,  870,  -11,  870,  -69,
- /*   120 */   870,  -69,  870,  -50,  870,  -50,  870,  -50,  870,  -50,
- /*   130 */   870,  143,  870,  143,  870, 1111,  870, 1111,  870, 1111,
- /*   140 */   870,  -70,  -70,  377,  -70,  -70,  -70,  -70,  870,  -56,
- /*   150 */   870,  -11,  -70,  303,  -70, 1104,  -70,  -70,  -70,  870,
- /*   160 */   564,  870,  -69,  -70,  345,  730,  266,  419, 1087, 1088,
- /*   170 */  1089,  -70,  519,  870,  654,  870,  -70,  870,  -70,  870,
- /*   180 */   -70, 1180, 1001,  314,  -70,  814,   83, 1070,  650, 1188,
- /*   190 */   -70,  870,  128,  870,  519, 1185,  196, 1186,  -70, 1187,
- /*   200 */   215, 1190,  -70,  870,  202,  870,  247,  870,  519,  591,
- /*   210 */   -70,  870,  -70,  -70, 1097,  215,  -70,  -70,  -70,  870,
- /*   220 */   519, 1098,  870, 1191,  870, 1120,  -29,  -70, 1194,  -70,
- /*   230 */   -70,  519, 1120,  -29,  -70,  870,  519, 1105,  870, 1200,
- /*   240 */   870,  519,  -70,  -70,  580,  -70,  -70,  -70,  388,  -70,
- /*   250 */   687,  -70, 1112,  -70,  683, 1097,  233,  -70,  -70,  215,
- /*   260 */   -70,  -70, 1132, 1118,  -70, 1216,  215,  691,  -70,  215,
- /*   270 */   -70,  -70,  870,  519, 1001,  330,  549, 1217,  233, 1132,
- /*   280 */  1118,  -70,  842,  -25,  -70,  -70, 1127,   50,  -70,  -70,
- /*   290 */   -70,  -70,  321,  -70,  736,  -70, 1220,  -70,  384,  744,
- /*   300 */   -70,  215, 1224,  -70,  135,  -70,  215,  -70,  424,  733,
- /*   310 */   -70,  571,  -70,  -70,  -70,  -70,  733,  -70,  733,  -70,
- /*   320 */   215,  818,  -70,  215, 1120,  -29,  -70,  -70, 1120,  -29,
- /*   330 */   -70,  -70, 1194,  -70,  954,  -70,  -70,  926,  -70,    3,
- /*   340 */   -70,  -70,    3,  -70,  -70,  681,  618,  874,  -70,  618,
- /*   350 */  1235,  -70,  -70,  -70,  727,  -70,  -70,  -70,  727,  -70,
- /*   360 */   -70,  -70,  -70,  -70,  274,  -16,  -70,  215,  -70, 1215,
- /*   370 */  1245,  215,  630, 1246,  744,  -70, 1248,  215,  875,  744,
- /*   380 */   -70,  870,  429,  -70, 1226, 1254,  215,  891, 1181,  215,
- /*   390 */  1224,  -70,  471, 1175,  -70,  -70,  -70,  -70,  -70, 1001,
- /*   400 */   467,  122,  778,  215, 1097,  -70,  215,  766, 1263, 1001,
- /*   410 */   507,  215, 1097,  582,  782, 1192,  215, 1097,  -70, 1256,
- /*   420 */   820, 1282,  870,  474, 1259,  834,  -70,  -70, 1198, 1201,
- /*   430 */   825,  215,  554,  -70,  -70, 1257,  -70,  -70, 1164,  215,
- /*   440 */   674, 1206,  215, 1286,  215,  892,  826, 1301, 1176, 1300,
- /*   450 */    74,  511,  741,  323,  -70, 1193, 1195, 1297, 1306, 1307,
- /*   460 */    74, 1303, 1260,  215, 1218,  215,  881,  215, 1258,  870,
- /*   470 */   519, 1317, 1261,  870,  519, 1203,  215, 1308,  215,  911,
- /*   480 */   -70,  893,  551, 1311,  870,  914,  870,  519, 1325,  519,
- /*   490 */  1221,  215,  939, 1328,  774,  215, 1330,  215, 1331,  215,
- /*   500 */  1332,  215, 1333,  558, 1228,  215,  939, 1336, 1260,  215,
- /*   510 */  1243,  215,  881, 1339, 1227,  215, 1308,  931,  647, 1334,
- /*   520 */   870,  941, 1341,  952, 1343,  215, 1097,  417,  262, 1349,
- /*   530 */  1350, 1351, 1352,  215, 1340, 1355, 1335,  334, 1342,  215,
- /*   540 */   979, 1356,  738, 1358, 1363,  -70, 1335,  215, 1364,  999,
- /*   550 */  1063, 1367, 1357,  215, 1037, 1247,  215, 1374, 1249, 1250,
- /*   560 */   215, 1376,  -70,  -70,  -70,
+ /*     0 */   201,   81,  -72,  -72, 1103,   -9,  127,  -72,  235,  603,
+ /*    10 */   318,  286,  427,  -72,  -72,  -72,  -72,  -72,  -72,  603,
+ /*    20 */   639,  603,  671,  603,  903,  277,  974,  400,  748,  997,
+ /*    30 */  1036,   51,  -72,  402,  -72,  226,  -72,  400,  345,  -72,
+ /*    40 */  1023,  -72, 1041,  395,  -72,  -72,  -72,  -72,  -72,  -72,
+ /*    50 */   -72,  807, 1023,  -72, 1124,  -72,  560,  -72,  -72, 1138,
+ /*    60 */   522, 1023, 1094,  -72,  -72,  -72,  -72, 1023,  -72, 1176,
+ /*    70 */  1045,   30,  873, 1088, 1098,  -72,  884,  -72,  388, 1114,
+ /*    80 */   -72,  310,  -72,  -19, 1107, 1115, 1118, 1125, 1127,  -72,
+ /*    90 */  1045,   40, 1045,  665, 1045,  -72, 1132,  400, 1133,  400,
+ /*   100 */   -72,  -72,  -72,  -72,  -72,  -72, 1232, 1045,  105,  402,
+ /*   110 */   -72,  -72,  340,  630,  790,  -72,  630, 1246,  -72,  -72,
+ /*   120 */   -72,  679,  -72,  -72,  -72,  679,  -72,  -72,  -72,  -72,
+ /*   130 */  1248,  -72, 1045,  -72,  759, 1045,  -11, 1045,  -11, 1045,
+ /*   140 */   -11, 1045,  -11, 1045,  -71, 1045,  -71, 1045,  -50, 1045,
+ /*   150 */   -50, 1045,  -50, 1045,  -50, 1045,  168, 1045,  168, 1045,
+ /*   160 */  1186, 1045, 1186, 1045, 1186, 1045,  -72,  -72,  441,  -72,
+ /*   170 */   -72,  -72,  -72, 1045,  -56, 1045,  -11,  -72,  846,  -72,
+ /*   180 */  1180,  -72,  -72,  -72, 1045,  712, 1045,  -71,  -72,  289,
+ /*   190 */   884,  393,  700, 1162, 1164, 1165,  -72,  665, 1045,  806,
+ /*   200 */  1045,  -72, 1045,  -72, 1045,  -72, 1258, 1114,  401,  -72,
+ /*   210 */   958,  152, 1146,  416, 1268,  -72, 1045,  199, 1045,  665,
+ /*   220 */  1264,  530, 1266,  -72, 1262,  400, 1269,  -72, 1045,  273,
+ /*   230 */  1045,  320, 1045,  665,  793,  -72, 1045,  -72,  -72, 1175,
+ /*   240 */   400,  -72,  -72,  -72,  806, 1045,  665, 1173, 1045, 1271,
+ /*   250 */  1045, 1197,  522,  -72, 1274,  -72,  -72,  665, 1197,  522,
+ /*   260 */   -72, 1045,  665, 1181, 1045, 1276, 1045,  665,  -72,  -72,
+ /*   270 */   635,  -72,  -72,  -72,  458,  -72,  463,  -72, 1191,  -72,
+ /*   280 */   534, 1175,  779,  400,  -72,  -72, 1210, 1195,  -72, 1294,
+ /*   290 */   400,  829,  -72,  400,  -72,  -72, 1045,  665, 1114,  467,
+ /*   300 */   279, 1296,  779, 1210, 1195,  -72, 1017,  -25,  -72,  -72,
+ /*   310 */  1205,  536,  -72,  -72,  -72,  -72,  394,  -72,  837,  -72,
+ /*   320 */  1300,  -72,  459, 1023,  -72,  400, 1304,  -72,  112,  -72,
+ /*   330 */   400,  -72,  619,  662,  -72,  832,  -72,  -72,  -72,  -72,
+ /*   340 */   662,  -72,  662,  -72,  400,  919,  -72,  400, 1197,  522,
+ /*   350 */   -72,  -72, 1197,  522,  -72,  -72, 1274,  -72, 1124,  -72,
+ /*   360 */   -72,   70,  -72, 1045,  524,  -72,  239,  -72,  -72,  239,
+ /*   370 */   -72,  -72,  -72,  -72,   58,  149,  -72,  400,  -72, 1290,
+ /*   380 */  1318,  400,   59, 1322, 1023,  -72, 1324,  400,  929, 1023,
+ /*   390 */   -72, 1045,  571,  -72, 1301, 1325,  400,  948, 1250,  400,
+ /*   400 */  1304,  -72,  517, 1245,  -72,  -72,  -72,  -72,  -72, 1114,
+ /*   410 */   552,  843,  754,  400, 1175,  -72,  400,  140, 1339, 1114,
+ /*   420 */   556,  400, 1175,  869,  657, 1267,  400, 1175,  -72, 1327,
+ /*   430 */   850, 1361, 1045,  618, 1335,  942,  -72,  -72, 1273, 1275,
+ /*   440 */   875,  400,  962,  -72,  -72, 1328,  -72,  -72, 1240,  400,
+ /*   450 */   906, 1279,  400, 1362,  400, 1001,  761, 1374, 1247, 1376,
+ /*   460 */   189,  562,  968,  395,  -72, 1263, 1265, 1373, 1383, 1384,
+ /*   470 */   189, 1377, 1332,  400, 1291,  400,  792,  400, 1326, 1045,
+ /*   480 */   665, 1390, 1331, 1045,  665, 1278,  400, 1385,  400, 1007,
+ /*   490 */   -72,  984,  604, 1386, 1045, 1012, 1045,  665, 1400,  665,
+ /*   500 */  1293,  400, 1033, 1404,  651,  400, 1405,  400, 1406,  400,
+ /*   510 */  1407,  400, 1408,  566, 1302,  400, 1033, 1411, 1332,  400,
+ /*   520 */  1316,  400,  792, 1415, 1299,  400, 1385, 1016,  608, 1409,
+ /*   530 */  1045, 1129, 1417,  476, 1418,  400, 1175,  697,  111, 1420,
+ /*   540 */  1421, 1424, 1427,  400, 1416, 1429, 1410,  402, 1419,  400,
+ /*   550 */  1025, 1432,  729, 1433, 1435,  -72, 1410,  400, 1441,  839,
+ /*   560 */   981, 1442,  841,  981, 1443, 1439,  400, 1021, 1321,  400,
+ /*   570 */  1446, 1323, 1329,  400, 1456,  -72,  -72,  -72,
 };
-#define YY_REDUCE_USE_DFLT (-71)
+#define YY_REDUCE_USE_DFLT (-151)
 static const short yy_reduce_ofst[] = {
- /*     0 */   -59,  211,  -71,  -71,  556,  -71,  -71,  -71,  -70,  -53,
- /*    10 */   -71,  189,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  268,
- /*    20 */   -71,  325,  -71,  463,  -71,  589,  -71,  -60,  596,  -71,
- /*    30 */   -71,   75,  -71,  256,  655,  313,  -71,  673,  444,  -71,
- /*    40 */   757,  -71,  -71,  121,  -71,  -71,  -71,  -71,  -71,  -71,
- /*    50 */   -71,  -71,  795,  -71,  804,  -71,  -71,  -71,  -71,  -71,
- /*    60 */   839,  898,  899,  -71,  -71,  -71,  -71,  907,  -71,  -71,
- /*    70 */   706,  -71,  206,  -71,  -71,  -71,  598,  -71,  964,  936,
- /*    80 */   -71,  938,  370,  940,  974,  985,  976,  990,  994,  -71,
- /*    90 */   720,   82,  739,   82,  806,  -71,  -71, 1043,  -71, 1046,
- /*   100 */   -71,  -71,  -71,  -71,  -71,  -71,  -71,   82,  807,   82,
- /*   110 */   813,   82,  844,   82,  862,   82,  863,   82,  865,   82,
- /*   120 */   871,   82,  877,   82,  878,   82,  890,   82,  896,   82,
- /*   130 */   909,   82,  921,   82,  924,   82,  932,   82,  934,   82,
- /*   140 */   935,   82,  -71,  -71,  -71,  -71,  -71,  -71,  937,  117,
- /*   150 */   942,   82,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  943,
- /*   160 */    82,  949,   82,  -71, 1049,  593,  964,  -71,  -71,  -71,
- /*   170 */   -71,  -71,   82,  960,   82,  965,   82,  970,   82,  971,
- /*   180 */    82,  -71,   32,  964,  -71,  264,   82,  983,  984,  -71,
- /*   190 */   -71,  972,   82,  977,   82,  -71, 1022,  -71,  -71,  -71,
- /*   200 */  1061,  -71,  -71,  978,   82,  986,   82,  987,   82,  -71,
- /*   210 */   -71,  310,  -71,  -71, 1062, 1065,  -71,  -71,  -71,  988,
- /*   220 */    82,  -71,  -36,  -71,  400, 1012, 1048,  -71, 1060,  -71,
- /*   230 */   -71,   82, 1017, 1052,  -71,  993,   82,  -71,  263,  -71,
- /*   240 */  1000,   82,  -71,  230, 1024,  -71,  -71,  -71, 1080,  -71,
- /*   250 */  1081,  -71,  -71,  -71, 1082, 1083,   78,  -71,  -71, 1084,
- /*   260 */   -71,  -71, 1031, 1033,  -71,  -71,  508,  -71,  -71, 1090,
- /*   270 */   -71,  -71, 1003,   82,  -18,  964, 1024,  -71,  496, 1039,
- /*   280 */  1040,  -71, 1005,  140,  -71,  -71,  -71, 1043,  -71,  -71,
- /*   290 */   -71,  -71,   82,  -71,  -71,  -71,  -71,  -71,   82, 1075,
- /*   300 */   -71, 1099, 1073, 1076, 1072,  -71, 1101,  -71,  -71, 1077,
- /*   310 */   -71,  -71,  -71,  -71,  -71,  -71, 1078,  -71, 1085,  -71,
- /*   320 */   381,  -71,  -71,  369, 1042, 1086,  -71,  -71, 1044, 1091,
- /*   330 */   -71,  -71, 1092,  -71, 1093,  -71,  -71,  626,  -71, 1095,
- /*   340 */   -71,  -71, 1096,  -71,  -71, 1106,  182,  -71,  -71,  245,
- /*   350 */   -71,  -71,  -71,  -71, 1032,  -71,  -71,  -71, 1034,  -71,
- /*   360 */   -71,  -71,  -71,  -71, 1094, 1100,  -71, 1117,  -71,  -71,
- /*   370 */   -71,  383, 1102,  -71, 1103,  -71,  -71,  642,  -71, 1107,
- /*   380 */   -71, 1014,  305,  -71,  -71,  -71,  657,  -71,  -71, 1130,
- /*   390 */  1108, 1109,  -49,  -71,  -71,  -71,  -71,  -71,  -71,  587,
- /*   400 */   964,  601,  -71, 1134, 1133,  -71, 1136, 1135,  -71,  725,
- /*   410 */   964, 1140, 1137, 1064, 1066,  -71,  295, 1138,  -71, 1067,
- /*   420 */  1069,  -71,  808,   82,  -71,  -71,  -71,  -71,  -71,  -71,
- /*   430 */   -71,  721,  -71,  -71,  -71,  -71,  -71,  -71,  -71, 1155,
- /*   440 */  1152,  -71, 1158,  -71,  729,  -71, 1139,  -71,  -71,  -71,
- /*   450 */   592,  964, 1129,  735,  -71,  -71,  -71,  -71,  -71,  -71,
- /*   460 */   604,  -71, 1141, 1169,  -71,  845, 1131, 1174,  -71, 1015,
- /*   470 */    82,  -71,  -71, 1016,   82,  -71, 1183, 1115,  760,  -71,
- /*   480 */   -71,  860,  964,  -71,  535,  -71, 1021,   82,  -71,   82,
- /*   490 */   -71, 1189, 1142,  -71,  -71,  800,  -71,  873,  -71,  880,
- /*   500 */   -71,  900,  -71,  964,  -71,  912, 1151,  -71, 1162,  915,
- /*   510 */   -71,  888, 1156,  -71,  -71,  930, 1143,  992,  964,  -71,
- /*   520 */   703,  -71,  -71, 1204,  -71, 1205, 1202,  -71,  648,  -71,
- /*   530 */   -71,  -71,  -71, 1213,  -71,  -71, 1144, 1208,  -71, 1219,
- /*   540 */  1145,  -71, 1209,  -71,  -71,  -71, 1147, 1225,  -71, 1229,
- /*   550 */  1222,  -71,  -71,  191,  -71,  -71, 1231,  -71,  -71, 1148,
- /*   560 */   553,  -71,  -71,  -71,  -71,
+ /*     0 */    64,   95, -151, -151,  -59, -151, -151, -151,   33,  155,
+ /*    10 */  -151,  224, -151, -151, -151, -151, -151, -151, -151,  428,
+ /*    20 */  -151,  509, -151,  758, -151,  430, -151,   45,  771, -151,
+ /*    30 */  -151,  -21, -151,  -64,  865,  244, -151,  910,  -85, -151,
+ /*    40 */   895, -151, -151, -125, -151, -151, -151, -151, -151, -151,
+ /*    50 */  -151, -151, 1010, -151, 1000, -151, -151, -151, -151, -151,
+ /*    60 */  1011, 1022, 1024, -151, -151, -151, -151, 1028, -151, -151,
+ /*    70 */   125, -151,  156, -151, -151, -151,  159, -151, 1037, 1039,
+ /*    80 */  -151, 1040,  420, 1014, 1047, 1042, 1049, 1051, 1055, -151,
+ /*    90 */   348,  411,  450,  411,  649, -151, -151, 1105, -151, 1119,
+ /*   100 */  -151, -151, -151, -151, -151, -151, -151,  685,  411,  254,
+ /*   110 */  -151, -151, 1108, -150, -151, -151,  -34, -151, -151, -151,
+ /*   120 */  -151, 1044, -151, -151, -151, 1053, -151, -151, -151, -151,
+ /*   130 */  -151, -151,  696, -151,  411,  732,  411,  743,  411,  747,
+ /*   140 */   411,  749,  411,  778,  411,  786,  411,  788,  411,  797,
+ /*   150 */   411,  827,  411,  838,  411,  874,  411,  882,  411,  885,
+ /*   160 */   411,  887,  411,  893,  411,  901,  411, -151, -151, -151,
+ /*   170 */  -151, -151, -151,  932,   39,  951,  411, -151, -151, -151,
+ /*   180 */  -151, -151, -151, -151,  991,  411, 1008,  411, -151, 1126,
+ /*   190 */   912, 1037, -151, -151, -151, -151, -151,  411, 1015,  411,
+ /*   200 */  1018,  411, 1020,  411, 1038,  411, -151,  745, 1037, -151,
+ /*   210 */   343,  411, 1058, 1059, -151, -151, 1043,  411, 1046,  411,
+ /*   220 */  -151, 1099, -151, -151, -151, 1139, -151, -151, 1048,  411,
+ /*   230 */  1050,  411, 1052,  411, -151, -151,  257, -151, -151, 1140,
+ /*   240 */  1142, -151, -151, -151,  411, 1054,  411, -151,  276, -151,
+ /*   250 */   346, 1086, 1123, -151, 1141, -151, -151,  411, 1090, 1130,
+ /*   260 */  -151, 1062,  411, -151,  281, -151, 1080,  411, -151,  652,
+ /*   270 */  1101, -151, -151, -151, 1156, -151, 1157, -151, -151, -151,
+ /*   280 */  1159, 1158,  506, 1160, -151, -151, 1109, 1110, -151, -151,
+ /*   290 */    78, -151, -151, 1167, -151, -151, 1085,  411,  -63, 1037,
+ /*   300 */  1101, -151,  789, 1116, 1113, -151, 1087,   87, -151, -151,
+ /*   310 */  -151, 1105, -151, -151, -151, -151,  411, -151, -151, -151,
+ /*   320 */  -151, -151,  411, 1150, -151, 1174, 1151, 1149, 1152, -151,
+ /*   330 */  1178, -151, -151, 1153, -151, -151, -151, -151, -151, -151,
+ /*   340 */  1154, -151, 1155, -151,  433, -151, -151,  715, 1117, 1163,
+ /*   350 */  -151, -151, 1120, 1166, -151, -151, 1168, -151, 1161, -151,
+ /*   360 */  -151,  593, -151, 1089,  411, -151, 1170, -151, -151, 1172,
+ /*   370 */  -151, -151, -151, -151, 1169, 1171, -151, 1188, -151, -151,
+ /*   380 */  -151,  526, 1182, -151, 1177, -151, -151,  574, -151, 1183,
+ /*   390 */  -151, 1091,  142, -151, -151, -151,  621, -151, -151, 1199,
+ /*   400 */  1179, 1184,  193, -151, -151, -151, -151, -151, -151,  804,
+ /*   410 */  1037,  755, -151, 1203, 1204, -151, 1209, 1206, -151,  830,
+ /*   420 */  1037, 1213, 1211, 1134, 1131, -151,  261, 1215, -151, 1136,
+ /*   430 */  1137, -151,  774,  411, -151, -151, -151, -151, -151, -151,
+ /*   440 */  -151,  516, -151, -151, -151, -151, -151, -151, -151, 1228,
+ /*   450 */  1225, -151, 1231, -151,  668, -151, 1212, -151, -151, -151,
+ /*   460 */   218, 1037, 1201,  840, -151, -151, -151, -151, -151, -151,
+ /*   470 */   280, -151, 1214, 1249, -151,  295, 1200, 1251, -151,  821,
+ /*   480 */   411, -151, -151, 1093,  411, -151, 1254, 1189,  905, -151,
+ /*   490 */  -151,  904, 1037, -151,  413, -151, 1095,  411, -151,  411,
+ /*   500 */  -151, 1260, 1216, -151, -151,  926, -151,  966, -151,  967,
+ /*   510 */  -151,  978, -151, 1037, -151,  980, 1222, -151, 1234,  982,
+ /*   520 */  -151,  924, 1227, -151, -151,  993, 1217,  922, 1037, -151,
+ /*   530 */   591, -151, -151, 1277, -151, 1281, 1280, -151,  145, -151,
+ /*   540 */  -151, -151, -151, 1286, -151, -151, 1202, 1283, -151, 1297,
+ /*   550 */  1218, -151, 1285, -151, -151, -151, 1207, 1303, -151, 1305,
+ /*   560 */  1298, -151, 1307, 1306, -151, -151,  -73, -151, -151, 1311,
+ /*   570 */  -151, -151, 1223,  607, -151, -151, -151, -151,
 };
 static const YYACTIONTYPE yy_default[] = {
- /*     0 */   571,  571,  566,  569,  870,  870,  870,  570,  577,  870,
- /*    10 */   870,  870,  870,  597,  598,  599,  578,  579,  580,  870,
- /*    20 */   870,  870,  870,  870,  870,  870,  870,  870,  870,  870,
- /*    30 */   870,  870,  590,  600,  609,  592,  608,  870,  870,  610,
- /*    40 */   653,  616,  870,  870,  654,  657,  658,  659,  852,  853,
- /*    50 */   854,  870,  653,  617,  638,  636,  870,  639,  640,  870,
- /*    60 */   709,  653,  624,  618,  625,  707,  708,  653,  619,  870,
- /*    70 */   870,  739,  804,  745,  740,  736,  870,  664,  870,  870,
- /*    80 */   665,  673,  675,  682,  721,  712,  714,  702,  716,  670,
- /*    90 */   870,  717,  870,  718,  870,  738,  870,  870,  741,  870,
- /*   100 */   742,  743,  744,  746,  747,  748,  751,  752,  870,  753,
- /*   110 */   870,  754,  870,  755,  870,  756,  870,  757,  870,  758,
- /*   120 */   870,  759,  870,  760,  870,  761,  870,  762,  870,  763,
- /*   130 */   870,  764,  870,  765,  870,  766,  870,  767,  870,  768,
- /*   140 */   870,  769,  770,  870,  771,  778,  785,  788,  870,  773,
- /*   150 */   870,  772,  775,  870,  776,  870,  779,  777,  784,  870,
- /*   160 */   870,  870,  786,  787,  870,  804,  870,  870,  870,  870,
- /*   170 */   870,  791,  803,  870,  780,  870,  781,  870,  782,  870,
- /*   180 */   783,  870,  870,  870,  793,  870,  870,  870,  870,  870,
- /*   190 */   794,  870,  870,  870,  795,  870,  870,  870,  850,  870,
- /*   200 */   870,  870,  851,  870,  870,  870,  870,  870,  796,  870,
- /*   210 */   789,  804,  801,  802,  690,  870,  691,  792,  774,  870,
- /*   220 */   719,  870,  870,  703,  870,  710,  709,  704,  870,  594,
- /*   230 */   711,  706,  710,  709,  705,  870,  715,  870,  804,  713,
- /*   240 */   870,  722,  674,  685,  683,  684,  693,  694,  870,  695,
- /*   250 */   870,  696,  870,  697,  870,  690,  681,  595,  596,  870,
- /*   260 */   679,  680,  699,  701,  686,  870,  870,  870,  700,  870,
- /*   270 */   734,  735,  870,  698,  685,  870,  870,  870,  681,  699,
- /*   280 */   701,  687,  870,  681,  676,  677,  870,  870,  678,  671,
- /*   290 */   672,  790,  870,  737,  870,  749,  870,  750,  870,  653,
- /*   300 */   620,  870,  808,  626,  621,  627,  870,  628,  870,  870,
- /*   310 */   629,  870,  632,  633,  634,  635,  870,  630,  870,  631,
- /*   320 */   870,  870,  809,  870,  710,  709,  810,  812,  710,  709,
- /*   330 */   811,  622,  870,  623,  638,  637,  611,  870,  612,  870,
- /*   340 */   613,  745,  870,  614,  615,  601,  827,  870,  602,  827,
- /*   350 */   870,  603,  606,  607,  870,  822,  824,  825,  870,  823,
- /*   360 */   826,  605,  604,  593,  870,  870,  643,  870,  646,  870,
- /*   370 */   870,  870,  870,  870,  653,  647,  870,  870,  870,  653,
- /*   380 */   648,  870,  653,  649,  870,  870,  870,  870,  870,  870,
- /*   390 */   808,  626,  651,  870,  650,  652,  644,  645,  591,  870,
- /*   400 */   870,  587,  870,  870,  690,  585,  870,  870,  870,  870,
- /*   410 */   870,  870,  690,  833,  870,  870,  870,  690,  692,  838,
- /*   420 */   870,  870,  870,  870,  870,  870,  839,  840,  870,  870,
- /*   430 */   870,  870,  870,  830,  831,  870,  832,  586,  870,  870,
- /*   440 */   870,  870,  870,  870,  870,  870,  870,  870,  870,  870,
- /*   450 */   870,  870,  870,  870,  656,  870,  870,  870,  870,  870,
- /*   460 */   870,  870,  655,  870,  870,  870,  870,  870,  870,  870,
- /*   470 */   724,  870,  870,  870,  725,  870,  870,  732,  870,  870,
- /*   480 */   733,  870,  870,  870,  870,  870,  870,  730,  870,  731,
- /*   490 */   870,  870,  870,  870,  870,  870,  870,  870,  870,  870,
- /*   500 */   870,  870,  870,  870,  870,  870,  870,  870,  655,  870,
- /*   510 */   870,  870,  870,  870,  870,  870,  732,  870,  870,  870,
- /*   520 */   870,  870,  870,  870,  870,  870,  690,  870,  827,  870,
- /*   530 */   870,  870,  870,  870,  870,  870,  861,  870,  870,  870,
- /*   540 */   870,  870,  870,  870,  870,  860,  861,  870,  870,  870,
- /*   550 */   870,  870,  870,  870,  870,  870,  870,  870,  870,  868,
- /*   560 */   870,  870,  869,  572,  567,
+ /*     0 */   584,  584,  579,  582,  888,  888,  888,  583,  590,  888,
+ /*    10 */   888,  888,  888,  610,  611,  612,  591,  592,  593,  888,
+ /*    20 */   888,  888,  888,  888,  888,  888,  888,  888,  888,  888,
+ /*    30 */   888,  888,  603,  613,  623,  605,  622,  888,  888,  624,
+ /*    40 */   668,  631,  888,  888,  669,  672,  673,  674,  868,  869,
+ /*    50 */   870,  888,  668,  632,  653,  651,  888,  654,  655,  888,
+ /*    60 */   724,  668,  639,  633,  640,  722,  723,  668,  634,  888,
+ /*    70 */   888,  754,  820,  760,  755,  751,  888,  679,  888,  888,
+ /*    80 */   680,  688,  690,  697,  736,  727,  729,  717,  731,  685,
+ /*    90 */   888,  732,  888,  733,  888,  753,  888,  888,  756,  888,
+ /*   100 */   757,  758,  759,  761,  762,  763,  888,  888,  888,  888,
+ /*   110 */   608,  609,  615,  843,  888,  616,  843,  888,  617,  620,
+ /*   120 */   621,  888,  838,  840,  841,  888,  839,  842,  619,  618,
+ /*   130 */   888,  764,  888,  767,  769,  888,  770,  888,  771,  888,
+ /*   140 */   772,  888,  773,  888,  774,  888,  775,  888,  776,  888,
+ /*   150 */   777,  888,  778,  888,  779,  888,  780,  888,  781,  888,
+ /*   160 */   782,  888,  783,  888,  784,  888,  785,  786,  888,  787,
+ /*   170 */   794,  801,  804,  888,  789,  888,  788,  791,  888,  792,
+ /*   180 */   888,  795,  793,  800,  888,  888,  888,  802,  803,  888,
+ /*   190 */   820,  888,  888,  888,  888,  888,  807,  819,  888,  796,
+ /*   200 */   888,  797,  888,  798,  888,  799,  888,  888,  888,  809,
+ /*   210 */   888,  888,  888,  888,  888,  810,  888,  888,  888,  811,
+ /*   220 */   888,  888,  888,  866,  888,  888,  888,  867,  888,  888,
+ /*   230 */   888,  888,  888,  812,  888,  805,  820,  817,  818,  705,
+ /*   240 */   888,  706,  808,  790,  768,  888,  734,  888,  888,  718,
+ /*   250 */   888,  725,  724,  719,  888,  607,  726,  721,  725,  724,
+ /*   260 */   720,  888,  730,  888,  820,  728,  888,  737,  689,  700,
+ /*   270 */   698,  699,  708,  709,  888,  710,  888,  711,  888,  712,
+ /*   280 */   888,  705,  696,  888,  694,  695,  714,  716,  701,  888,
+ /*   290 */   888,  888,  715,  888,  749,  750,  888,  713,  700,  888,
+ /*   300 */   888,  888,  696,  714,  716,  702,  888,  696,  691,  692,
+ /*   310 */   888,  888,  693,  686,  687,  806,  888,  752,  888,  765,
+ /*   320 */   888,  766,  888,  668,  635,  888,  824,  641,  636,  642,
+ /*   330 */   888,  643,  888,  888,  644,  888,  647,  648,  649,  650,
+ /*   340 */   888,  645,  888,  646,  888,  888,  825,  888,  725,  724,
+ /*   350 */   826,  828,  725,  724,  827,  637,  888,  638,  653,  652,
+ /*   360 */   625,  888,  626,  888,  888,  627,  888,  628,  760,  888,
+ /*   370 */   629,  630,  614,  606,  888,  888,  658,  888,  661,  888,
+ /*   380 */   888,  888,  888,  888,  668,  662,  888,  888,  888,  668,
+ /*   390 */   663,  888,  668,  664,  888,  888,  888,  888,  888,  888,
+ /*   400 */   824,  641,  666,  888,  665,  667,  659,  660,  604,  888,
+ /*   410 */   888,  600,  888,  888,  705,  598,  888,  888,  888,  888,
+ /*   420 */   888,  888,  705,  849,  888,  888,  888,  705,  707,  854,
+ /*   430 */   888,  888,  888,  888,  888,  888,  855,  856,  888,  888,
+ /*   440 */   888,  888,  888,  846,  847,  888,  848,  599,  888,  888,
+ /*   450 */   888,  888,  888,  888,  888,  888,  888,  888,  888,  888,
+ /*   460 */   888,  888,  888,  888,  671,  888,  888,  888,  888,  888,
+ /*   470 */   888,  888,  670,  888,  888,  888,  888,  888,  888,  888,
+ /*   480 */   739,  888,  888,  888,  740,  888,  888,  747,  888,  888,
+ /*   490 */   748,  888,  888,  888,  888,  888,  888,  745,  888,  746,
+ /*   500 */   888,  888,  888,  888,  888,  888,  888,  888,  888,  888,
+ /*   510 */   888,  888,  888,  888,  888,  888,  888,  888,  670,  888,
+ /*   520 */   888,  888,  888,  888,  888,  888,  747,  888,  888,  888,
+ /*   530 */   888,  888,  888,  888,  888,  888,  705,  888,  843,  888,
+ /*   540 */   888,  888,  888,  888,  888,  888,  877,  888,  888,  888,
+ /*   550 */   888,  888,  888,  888,  888,  876,  877,  888,  888,  888,
+ /*   560 */   888,  888,  888,  888,  888,  888,  888,  888,  888,  888,
+ /*   570 */   888,  888,  886,  888,  888,  887,  585,  580,
 };
 #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
 
@@ -681,10 +700,12 @@ static const YYCODETYPE yyFallback[] = {
     0,  /*         ID => nothing */
    27,  /*      ABORT => ID */
    27,  /*      AFTER => ID */
+   27,  /*    ANALYZE => ID */
    27,  /*        ASC => ID */
    27,  /*     ATTACH => ID */
    27,  /*     BEFORE => ID */
    27,  /*    CASCADE => ID */
+   27,  /*       CAST => ID */
    27,  /*   CONFLICT => ID */
    27,  /*   DATABASE => ID */
    27,  /*       DESC => ID */
@@ -869,59 +890,60 @@ static const char *const yyTokenName[] = {
   "EXCLUSIVE",     "COMMIT",        "END",           "ROLLBACK",    
   "CREATE",        "TABLE",         "TEMP",          "LP",          
   "RP",            "AS",            "COMMA",         "ID",          
-  "ABORT",         "AFTER",         "ASC",           "ATTACH",      
-  "BEFORE",        "CASCADE",       "CONFLICT",      "DATABASE",    
-  "DESC",          "DETACH",        "EACH",          "FAIL",        
-  "FOR",           "IGNORE",        "INITIALLY",     "INSTEAD",     
-  "LIKE_KW",       "MATCH",         "KEY",           "OF",          
-  "OFFSET",        "PRAGMA",        "RAISE",         "REPLACE",     
-  "RESTRICT",      "ROW",           "STATEMENT",     "TRIGGER",     
-  "VACUUM",        "VIEW",          "REINDEX",       "RENAME",      
-  "CTIME_KW",      "ALTER",         "OR",            "AND",         
-  "NOT",           "IS",            "BETWEEN",       "IN",          
-  "ISNULL",        "NOTNULL",       "NE",            "EQ",          
-  "GT",            "LE",            "LT",            "GE",          
-  "ESCAPE",        "BITAND",        "BITOR",         "LSHIFT",      
-  "RSHIFT",        "PLUS",          "MINUS",         "STAR",        
-  "SLASH",         "REM",           "CONCAT",        "UMINUS",      
-  "UPLUS",         "BITNOT",        "STRING",        "JOIN_KW",     
-  "CONSTRAINT",    "DEFAULT",       "NULL",          "PRIMARY",     
-  "UNIQUE",        "CHECK",         "REFERENCES",    "COLLATE",     
-  "AUTOINCR",      "ON",            "DELETE",        "UPDATE",      
-  "INSERT",        "SET",           "DEFERRABLE",    "FOREIGN",     
-  "DROP",          "UNION",         "ALL",           "INTERSECT",   
-  "EXCEPT",        "SELECT",        "DISTINCT",      "DOT",         
-  "FROM",          "JOIN",          "USING",         "ORDER",       
-  "BY",            "GROUP",         "HAVING",        "LIMIT",       
-  "WHERE",         "INTO",          "VALUES",        "INTEGER",     
-  "FLOAT",         "BLOB",          "REGISTER",      "VARIABLE",    
-  "EXISTS",        "CASE",          "WHEN",          "THEN",        
-  "ELSE",          "INDEX",         "TO",            "ADD",         
-  "COLUMNKW",      "error",         "input",         "cmdlist",     
-  "ecmd",          "cmdx",          "cmd",           "explain",     
-  "transtype",     "trans_opt",     "nm",            "create_table",
-  "create_table_args",  "temp",          "dbnm",          "columnlist",  
-  "conslist_opt",  "select",        "column",        "columnid",    
-  "type",          "carglist",      "id",            "ids",         
-  "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",       "add_column_fullname",  "kwcolumn_opt",
+  "ABORT",         "AFTER",         "ANALYZE",       "ASC",         
+  "ATTACH",        "BEFORE",        "CASCADE",       "CAST",        
+  "CONFLICT",      "DATABASE",      "DESC",          "DETACH",      
+  "EACH",          "FAIL",          "FOR",           "IGNORE",      
+  "INITIALLY",     "INSTEAD",       "LIKE_KW",       "MATCH",       
+  "KEY",           "OF",            "OFFSET",        "PRAGMA",      
+  "RAISE",         "REPLACE",       "RESTRICT",      "ROW",         
+  "STATEMENT",     "TRIGGER",       "VACUUM",        "VIEW",        
+  "REINDEX",       "RENAME",        "CTIME_KW",      "ALTER",       
+  "OR",            "AND",           "NOT",           "IS",          
+  "BETWEEN",       "IN",            "ISNULL",        "NOTNULL",     
+  "NE",            "EQ",            "GT",            "LE",          
+  "LT",            "GE",            "ESCAPE",        "BITAND",      
+  "BITOR",         "LSHIFT",        "RSHIFT",        "PLUS",        
+  "MINUS",         "STAR",          "SLASH",         "REM",         
+  "CONCAT",        "UMINUS",        "UPLUS",         "BITNOT",      
+  "STRING",        "JOIN_KW",       "CONSTRAINT",    "DEFAULT",     
+  "NULL",          "PRIMARY",       "UNIQUE",        "CHECK",       
+  "REFERENCES",    "COLLATE",       "AUTOINCR",      "ON",          
+  "DELETE",        "UPDATE",        "INSERT",        "SET",         
+  "DEFERRABLE",    "FOREIGN",       "DROP",          "UNION",       
+  "ALL",           "INTERSECT",     "EXCEPT",        "SELECT",      
+  "DISTINCT",      "DOT",           "FROM",          "JOIN",        
+  "USING",         "ORDER",         "BY",            "GROUP",       
+  "HAVING",        "LIMIT",         "WHERE",         "INTO",        
+  "VALUES",        "INTEGER",       "FLOAT",         "BLOB",        
+  "REGISTER",      "VARIABLE",      "EXISTS",        "CASE",        
+  "WHEN",          "THEN",          "ELSE",          "INDEX",       
+  "TO",            "ADD",           "COLUMNKW",      "error",       
+  "input",         "cmdlist",       "ecmd",          "cmdx",        
+  "cmd",           "explain",       "transtype",     "trans_opt",   
+  "nm",            "create_table",  "create_table_args",  "temp",        
+  "dbnm",          "columnlist",    "conslist_opt",  "select",      
+  "column",        "columnid",      "type",          "carglist",    
+  "id",            "ids",           "typetoken",     "typename",    
+  "signed",        "plus_num",      "minus_num",     "carg",        
+  "ccons",         "term",          "expr",          "onconf",      
+  "sortorder",     "autoinc",       "idxlist_opt",   "refargs",     
+  "defer_subclause",  "refarg",        "refact",        "init_deferred_pred_opt",
+  "conslist",      "tcons",         "idxlist",       "defer_subclause_opt",
+  "orconf",        "resolvetype",   "raisetype",     "fullname",    
+  "oneselect",     "multiselect_op",  "distinct",      "selcollist",  
+  "from",          "where_opt",     "groupby_opt",   "having_opt",  
+  "orderby_opt",   "limit_opt",     "sclp",          "as",          
+  "seltablist",    "stl_prefix",    "joinop",        "on_opt",      
+  "using_opt",     "seltablist_paren",  "joinop2",       "inscollist",  
+  "sortlist",      "sortitem",      "collate",       "exprlist",    
+  "setlist",       "insert_cmd",    "inscollist_opt",  "itemlist",    
+  "likeop",        "escape",        "between_op",    "in_op",       
+  "case_operand",  "case_exprlist",  "case_else",     "expritem",    
+  "uniqueflag",    "idxitem",       "plus_opt",      "number",      
+  "trigger_decl",  "trigger_cmd_list",  "trigger_time",  "trigger_event",
+  "foreach_clause",  "when_clause",   "trigger_cmd",   "database_kw_opt",
+  "key_opt",       "add_column_fullname",  "kwcolumn_opt",
 };
 #endif /* NDEBUG */
 
@@ -965,275 +987,280 @@ static const char *const yyRuleName[] = {
  /*  33 */ "nm ::= STRING",
  /*  34 */ "nm ::= JOIN_KW",
  /*  35 */ "type ::=",
- /*  36 */ "type ::= typename",
- /*  37 */ "type ::= typename LP signed RP",
- /*  38 */ "type ::= typename LP signed COMMA signed RP",
- /*  39 */ "typename ::= ids",
- /*  40 */ "typename ::= typename ids",
- /*  41 */ "signed ::= plus_num",
- /*  42 */ "signed ::= minus_num",
- /*  43 */ "carglist ::= carglist carg",
- /*  44 */ "carglist ::=",
- /*  45 */ "carg ::= CONSTRAINT nm ccons",
- /*  46 */ "carg ::= ccons",
- /*  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 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 */ "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 */ "term ::= BLOB",
- /* 182 */ "expr ::= REGISTER",
- /* 183 */ "expr ::= VARIABLE",
- /* 184 */ "expr ::= ID LP exprlist RP",
- /* 185 */ "expr ::= ID LP STAR RP",
- /* 186 */ "term ::= CTIME_KW",
- /* 187 */ "expr ::= expr AND expr",
- /* 188 */ "expr ::= expr OR expr",
- /* 189 */ "expr ::= expr LT expr",
- /* 190 */ "expr ::= expr GT expr",
- /* 191 */ "expr ::= expr LE expr",
- /* 192 */ "expr ::= expr GE expr",
- /* 193 */ "expr ::= expr NE expr",
- /* 194 */ "expr ::= expr EQ expr",
- /* 195 */ "expr ::= expr BITAND expr",
- /* 196 */ "expr ::= expr BITOR expr",
- /* 197 */ "expr ::= expr LSHIFT expr",
- /* 198 */ "expr ::= expr RSHIFT expr",
- /* 199 */ "expr ::= expr PLUS expr",
- /* 200 */ "expr ::= expr MINUS expr",
- /* 201 */ "expr ::= expr STAR expr",
- /* 202 */ "expr ::= expr SLASH expr",
- /* 203 */ "expr ::= expr REM expr",
- /* 204 */ "expr ::= expr CONCAT expr",
- /* 205 */ "likeop ::= LIKE_KW",
- /* 206 */ "likeop ::= NOT LIKE_KW",
- /* 207 */ "escape ::= ESCAPE expr",
- /* 208 */ "escape ::=",
- /* 209 */ "expr ::= expr likeop expr escape",
- /* 210 */ "expr ::= expr ISNULL",
- /* 211 */ "expr ::= expr IS NULL",
- /* 212 */ "expr ::= expr NOTNULL",
- /* 213 */ "expr ::= expr NOT NULL",
- /* 214 */ "expr ::= expr IS NOT NULL",
- /* 215 */ "expr ::= NOT expr",
- /* 216 */ "expr ::= BITNOT expr",
- /* 217 */ "expr ::= MINUS expr",
- /* 218 */ "expr ::= PLUS expr",
- /* 219 */ "between_op ::= BETWEEN",
- /* 220 */ "between_op ::= NOT BETWEEN",
- /* 221 */ "expr ::= expr between_op expr AND expr",
- /* 222 */ "in_op ::= IN",
- /* 223 */ "in_op ::= NOT IN",
- /* 224 */ "expr ::= expr in_op LP exprlist RP",
- /* 225 */ "expr ::= LP select RP",
- /* 226 */ "expr ::= expr in_op LP select RP",
- /* 227 */ "expr ::= expr in_op nm dbnm",
- /* 228 */ "expr ::= EXISTS LP select RP",
- /* 229 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 230 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 231 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 232 */ "case_else ::= ELSE expr",
- /* 233 */ "case_else ::=",
- /* 234 */ "case_operand ::= expr",
- /* 235 */ "case_operand ::=",
- /* 236 */ "exprlist ::= exprlist COMMA expritem",
- /* 237 */ "exprlist ::= expritem",
- /* 238 */ "expritem ::= expr",
- /* 239 */ "expritem ::=",
- /* 240 */ "cmd ::= CREATE uniqueflag INDEX nm dbnm ON nm LP idxlist RP onconf",
- /* 241 */ "uniqueflag ::= UNIQUE",
- /* 242 */ "uniqueflag ::=",
- /* 243 */ "idxlist_opt ::=",
- /* 244 */ "idxlist_opt ::= LP idxlist RP",
- /* 245 */ "idxlist ::= idxlist COMMA idxitem collate sortorder",
- /* 246 */ "idxlist ::= idxitem collate sortorder",
- /* 247 */ "idxitem ::= nm",
- /* 248 */ "cmd ::= DROP INDEX fullname",
- /* 249 */ "cmd ::= VACUUM",
- /* 250 */ "cmd ::= VACUUM nm",
- /* 251 */ "cmd ::= PRAGMA nm dbnm EQ nm",
- /* 252 */ "cmd ::= PRAGMA nm dbnm EQ ON",
- /* 253 */ "cmd ::= PRAGMA nm dbnm EQ plus_num",
- /* 254 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 255 */ "cmd ::= PRAGMA nm dbnm LP nm RP",
- /* 256 */ "cmd ::= PRAGMA nm dbnm",
- /* 257 */ "plus_num ::= plus_opt number",
- /* 258 */ "minus_num ::= MINUS number",
- /* 259 */ "number ::= INTEGER",
- /* 260 */ "number ::= FLOAT",
- /* 261 */ "plus_opt ::= PLUS",
- /* 262 */ "plus_opt ::=",
- /* 263 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 264 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 265 */ "trigger_time ::= BEFORE",
- /* 266 */ "trigger_time ::= AFTER",
- /* 267 */ "trigger_time ::= INSTEAD OF",
- /* 268 */ "trigger_time ::=",
- /* 269 */ "trigger_event ::= DELETE",
- /* 270 */ "trigger_event ::= INSERT",
- /* 271 */ "trigger_event ::= UPDATE",
- /* 272 */ "trigger_event ::= UPDATE OF inscollist",
- /* 273 */ "foreach_clause ::=",
- /* 274 */ "foreach_clause ::= FOR EACH ROW",
- /* 275 */ "foreach_clause ::= FOR EACH STATEMENT",
- /* 276 */ "when_clause ::=",
- /* 277 */ "when_clause ::= WHEN expr",
- /* 278 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list",
- /* 279 */ "trigger_cmd_list ::=",
- /* 280 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 281 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 282 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 283 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 284 */ "trigger_cmd ::= select",
- /* 285 */ "expr ::= RAISE LP IGNORE RP",
- /* 286 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 287 */ "raisetype ::= ROLLBACK",
- /* 288 */ "raisetype ::= ABORT",
- /* 289 */ "raisetype ::= FAIL",
- /* 290 */ "cmd ::= DROP TRIGGER fullname",
- /* 291 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt",
- /* 292 */ "key_opt ::=",
- /* 293 */ "key_opt ::= KEY ids",
- /* 294 */ "key_opt ::= KEY BLOB",
- /* 295 */ "database_kw_opt ::= DATABASE",
- /* 296 */ "database_kw_opt ::=",
- /* 297 */ "cmd ::= DETACH database_kw_opt nm",
- /* 298 */ "cmd ::= REINDEX",
- /* 299 */ "cmd ::= REINDEX nm dbnm",
- /* 300 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 301 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
- /* 302 */ "add_column_fullname ::= fullname",
- /* 303 */ "kwcolumn_opt ::=",
- /* 304 */ "kwcolumn_opt ::= COLUMNKW",
+ /*  36 */ "type ::= typetoken",
+ /*  37 */ "typetoken ::= typename",
+ /*  38 */ "typetoken ::= typename LP signed RP",
+ /*  39 */ "typetoken ::= typename LP signed COMMA signed RP",
+ /*  40 */ "typename ::= ids",
+ /*  41 */ "typename ::= typename ids",
+ /*  42 */ "signed ::= plus_num",
+ /*  43 */ "signed ::= minus_num",
+ /*  44 */ "carglist ::= carglist carg",
+ /*  45 */ "carglist ::=",
+ /*  46 */ "carg ::= CONSTRAINT nm ccons",
+ /*  47 */ "carg ::= ccons",
+ /*  48 */ "carg ::= DEFAULT term",
+ /*  49 */ "carg ::= DEFAULT LP expr RP",
+ /*  50 */ "carg ::= DEFAULT PLUS term",
+ /*  51 */ "carg ::= DEFAULT MINUS term",
+ /*  52 */ "carg ::= DEFAULT id",
+ /*  53 */ "ccons ::= NULL onconf",
+ /*  54 */ "ccons ::= NOT NULL onconf",
+ /*  55 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
+ /*  56 */ "ccons ::= UNIQUE onconf",
+ /*  57 */ "ccons ::= CHECK LP expr RP onconf",
+ /*  58 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
+ /*  59 */ "ccons ::= defer_subclause",
+ /*  60 */ "ccons ::= COLLATE id",
+ /*  61 */ "autoinc ::=",
+ /*  62 */ "autoinc ::= AUTOINCR",
+ /*  63 */ "refargs ::=",
+ /*  64 */ "refargs ::= refargs refarg",
+ /*  65 */ "refarg ::= MATCH nm",
+ /*  66 */ "refarg ::= ON DELETE refact",
+ /*  67 */ "refarg ::= ON UPDATE refact",
+ /*  68 */ "refarg ::= ON INSERT refact",
+ /*  69 */ "refact ::= SET NULL",
+ /*  70 */ "refact ::= SET DEFAULT",
+ /*  71 */ "refact ::= CASCADE",
+ /*  72 */ "refact ::= RESTRICT",
+ /*  73 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
+ /*  74 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
+ /*  75 */ "init_deferred_pred_opt ::=",
+ /*  76 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
+ /*  77 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
+ /*  78 */ "conslist_opt ::=",
+ /*  79 */ "conslist_opt ::= COMMA conslist",
+ /*  80 */ "conslist ::= conslist COMMA tcons",
+ /*  81 */ "conslist ::= conslist tcons",
+ /*  82 */ "conslist ::= tcons",
+ /*  83 */ "tcons ::= CONSTRAINT nm",
+ /*  84 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
+ /*  85 */ "tcons ::= UNIQUE LP idxlist RP onconf",
+ /*  86 */ "tcons ::= CHECK expr onconf",
+ /*  87 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
+ /*  88 */ "defer_subclause_opt ::=",
+ /*  89 */ "defer_subclause_opt ::= defer_subclause",
+ /*  90 */ "onconf ::=",
+ /*  91 */ "onconf ::= ON CONFLICT resolvetype",
+ /*  92 */ "orconf ::=",
+ /*  93 */ "orconf ::= OR resolvetype",
+ /*  94 */ "resolvetype ::= raisetype",
+ /*  95 */ "resolvetype ::= IGNORE",
+ /*  96 */ "resolvetype ::= REPLACE",
+ /*  97 */ "cmd ::= DROP TABLE fullname",
+ /*  98 */ "cmd ::= CREATE temp VIEW nm dbnm AS select",
+ /*  99 */ "cmd ::= DROP VIEW fullname",
+ /* 100 */ "cmd ::= select",
+ /* 101 */ "select ::= oneselect",
+ /* 102 */ "select ::= select multiselect_op oneselect",
+ /* 103 */ "multiselect_op ::= UNION",
+ /* 104 */ "multiselect_op ::= UNION ALL",
+ /* 105 */ "multiselect_op ::= INTERSECT",
+ /* 106 */ "multiselect_op ::= EXCEPT",
+ /* 107 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
+ /* 108 */ "distinct ::= DISTINCT",
+ /* 109 */ "distinct ::= ALL",
+ /* 110 */ "distinct ::=",
+ /* 111 */ "sclp ::= selcollist COMMA",
+ /* 112 */ "sclp ::=",
+ /* 113 */ "selcollist ::= sclp expr as",
+ /* 114 */ "selcollist ::= sclp STAR",
+ /* 115 */ "selcollist ::= sclp nm DOT STAR",
+ /* 116 */ "as ::= AS nm",
+ /* 117 */ "as ::= ids",
+ /* 118 */ "as ::=",
+ /* 119 */ "from ::=",
+ /* 120 */ "from ::= FROM seltablist",
+ /* 121 */ "stl_prefix ::= seltablist joinop",
+ /* 122 */ "stl_prefix ::=",
+ /* 123 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt",
+ /* 124 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt",
+ /* 125 */ "seltablist_paren ::= select",
+ /* 126 */ "seltablist_paren ::= seltablist",
+ /* 127 */ "dbnm ::=",
+ /* 128 */ "dbnm ::= DOT nm",
+ /* 129 */ "fullname ::= nm dbnm",
+ /* 130 */ "joinop ::= COMMA",
+ /* 131 */ "joinop ::= JOIN",
+ /* 132 */ "joinop ::= JOIN_KW JOIN",
+ /* 133 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 134 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 135 */ "on_opt ::= ON expr",
+ /* 136 */ "on_opt ::=",
+ /* 137 */ "using_opt ::= USING LP inscollist RP",
+ /* 138 */ "using_opt ::=",
+ /* 139 */ "orderby_opt ::=",
+ /* 140 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 141 */ "sortlist ::= sortlist COMMA sortitem collate sortorder",
+ /* 142 */ "sortlist ::= sortitem collate sortorder",
+ /* 143 */ "sortitem ::= expr",
+ /* 144 */ "sortorder ::= ASC",
+ /* 145 */ "sortorder ::= DESC",
+ /* 146 */ "sortorder ::=",
+ /* 147 */ "collate ::=",
+ /* 148 */ "collate ::= COLLATE id",
+ /* 149 */ "groupby_opt ::=",
+ /* 150 */ "groupby_opt ::= GROUP BY exprlist",
+ /* 151 */ "having_opt ::=",
+ /* 152 */ "having_opt ::= HAVING expr",
+ /* 153 */ "limit_opt ::=",
+ /* 154 */ "limit_opt ::= LIMIT expr",
+ /* 155 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 156 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 157 */ "cmd ::= DELETE FROM fullname where_opt",
+ /* 158 */ "where_opt ::=",
+ /* 159 */ "where_opt ::= WHERE expr",
+ /* 160 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt",
+ /* 161 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 162 */ "setlist ::= nm EQ expr",
+ /* 163 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
+ /* 164 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
+ /* 165 */ "insert_cmd ::= INSERT orconf",
+ /* 166 */ "insert_cmd ::= REPLACE",
+ /* 167 */ "itemlist ::= itemlist COMMA expr",
+ /* 168 */ "itemlist ::= expr",
+ /* 169 */ "inscollist_opt ::=",
+ /* 170 */ "inscollist_opt ::= LP inscollist RP",
+ /* 171 */ "inscollist ::= inscollist COMMA nm",
+ /* 172 */ "inscollist ::= nm",
+ /* 173 */ "expr ::= term",
+ /* 174 */ "expr ::= LP expr RP",
+ /* 175 */ "term ::= NULL",
+ /* 176 */ "expr ::= ID",
+ /* 177 */ "expr ::= JOIN_KW",
+ /* 178 */ "expr ::= nm DOT nm",
+ /* 179 */ "expr ::= nm DOT nm DOT nm",
+ /* 180 */ "term ::= INTEGER",
+ /* 181 */ "term ::= FLOAT",
+ /* 182 */ "term ::= STRING",
+ /* 183 */ "term ::= BLOB",
+ /* 184 */ "expr ::= REGISTER",
+ /* 185 */ "expr ::= VARIABLE",
+ /* 186 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 187 */ "expr ::= ID LP exprlist RP",
+ /* 188 */ "expr ::= ID LP STAR RP",
+ /* 189 */ "term ::= CTIME_KW",
+ /* 190 */ "expr ::= expr AND expr",
+ /* 191 */ "expr ::= expr OR expr",
+ /* 192 */ "expr ::= expr LT expr",
+ /* 193 */ "expr ::= expr GT expr",
+ /* 194 */ "expr ::= expr LE expr",
+ /* 195 */ "expr ::= expr GE expr",
+ /* 196 */ "expr ::= expr NE expr",
+ /* 197 */ "expr ::= expr EQ expr",
+ /* 198 */ "expr ::= expr BITAND expr",
+ /* 199 */ "expr ::= expr BITOR expr",
+ /* 200 */ "expr ::= expr LSHIFT expr",
+ /* 201 */ "expr ::= expr RSHIFT expr",
+ /* 202 */ "expr ::= expr PLUS expr",
+ /* 203 */ "expr ::= expr MINUS expr",
+ /* 204 */ "expr ::= expr STAR expr",
+ /* 205 */ "expr ::= expr SLASH expr",
+ /* 206 */ "expr ::= expr REM expr",
+ /* 207 */ "expr ::= expr CONCAT expr",
+ /* 208 */ "likeop ::= LIKE_KW",
+ /* 209 */ "likeop ::= NOT LIKE_KW",
+ /* 210 */ "escape ::= ESCAPE expr",
+ /* 211 */ "escape ::=",
+ /* 212 */ "expr ::= expr likeop expr escape",
+ /* 213 */ "expr ::= expr ISNULL",
+ /* 214 */ "expr ::= expr IS NULL",
+ /* 215 */ "expr ::= expr NOTNULL",
+ /* 216 */ "expr ::= expr NOT NULL",
+ /* 217 */ "expr ::= expr IS NOT NULL",
+ /* 218 */ "expr ::= NOT expr",
+ /* 219 */ "expr ::= BITNOT expr",
+ /* 220 */ "expr ::= MINUS expr",
+ /* 221 */ "expr ::= PLUS expr",
+ /* 222 */ "between_op ::= BETWEEN",
+ /* 223 */ "between_op ::= NOT BETWEEN",
+ /* 224 */ "expr ::= expr between_op expr AND expr",
+ /* 225 */ "in_op ::= IN",
+ /* 226 */ "in_op ::= NOT IN",
+ /* 227 */ "expr ::= expr in_op LP exprlist RP",
+ /* 228 */ "expr ::= LP select RP",
+ /* 229 */ "expr ::= expr in_op LP select RP",
+ /* 230 */ "expr ::= expr in_op nm dbnm",
+ /* 231 */ "expr ::= EXISTS LP select RP",
+ /* 232 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 233 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 234 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 235 */ "case_else ::= ELSE expr",
+ /* 236 */ "case_else ::=",
+ /* 237 */ "case_operand ::= expr",
+ /* 238 */ "case_operand ::=",
+ /* 239 */ "exprlist ::= exprlist COMMA expritem",
+ /* 240 */ "exprlist ::= expritem",
+ /* 241 */ "expritem ::= expr",
+ /* 242 */ "expritem ::=",
+ /* 243 */ "cmd ::= CREATE uniqueflag INDEX nm dbnm ON nm LP idxlist RP onconf",
+ /* 244 */ "uniqueflag ::= UNIQUE",
+ /* 245 */ "uniqueflag ::=",
+ /* 246 */ "idxlist_opt ::=",
+ /* 247 */ "idxlist_opt ::= LP idxlist RP",
+ /* 248 */ "idxlist ::= idxlist COMMA idxitem collate sortorder",
+ /* 249 */ "idxlist ::= idxitem collate sortorder",
+ /* 250 */ "idxitem ::= nm",
+ /* 251 */ "cmd ::= DROP INDEX fullname",
+ /* 252 */ "cmd ::= VACUUM",
+ /* 253 */ "cmd ::= VACUUM nm",
+ /* 254 */ "cmd ::= PRAGMA nm dbnm EQ nm",
+ /* 255 */ "cmd ::= PRAGMA nm dbnm EQ ON",
+ /* 256 */ "cmd ::= PRAGMA nm dbnm EQ plus_num",
+ /* 257 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 258 */ "cmd ::= PRAGMA nm dbnm LP nm RP",
+ /* 259 */ "cmd ::= PRAGMA nm dbnm",
+ /* 260 */ "plus_num ::= plus_opt number",
+ /* 261 */ "minus_num ::= MINUS number",
+ /* 262 */ "number ::= INTEGER",
+ /* 263 */ "number ::= FLOAT",
+ /* 264 */ "plus_opt ::= PLUS",
+ /* 265 */ "plus_opt ::=",
+ /* 266 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
+ /* 267 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 268 */ "trigger_time ::= BEFORE",
+ /* 269 */ "trigger_time ::= AFTER",
+ /* 270 */ "trigger_time ::= INSTEAD OF",
+ /* 271 */ "trigger_time ::=",
+ /* 272 */ "trigger_event ::= DELETE",
+ /* 273 */ "trigger_event ::= INSERT",
+ /* 274 */ "trigger_event ::= UPDATE",
+ /* 275 */ "trigger_event ::= UPDATE OF inscollist",
+ /* 276 */ "foreach_clause ::=",
+ /* 277 */ "foreach_clause ::= FOR EACH ROW",
+ /* 278 */ "foreach_clause ::= FOR EACH STATEMENT",
+ /* 279 */ "when_clause ::=",
+ /* 280 */ "when_clause ::= WHEN expr",
+ /* 281 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list",
+ /* 282 */ "trigger_cmd_list ::=",
+ /* 283 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
+ /* 284 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
+ /* 285 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
+ /* 286 */ "trigger_cmd ::= DELETE FROM nm where_opt",
+ /* 287 */ "trigger_cmd ::= select",
+ /* 288 */ "expr ::= RAISE LP IGNORE RP",
+ /* 289 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 290 */ "raisetype ::= ROLLBACK",
+ /* 291 */ "raisetype ::= ABORT",
+ /* 292 */ "raisetype ::= FAIL",
+ /* 293 */ "cmd ::= DROP TRIGGER fullname",
+ /* 294 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt",
+ /* 295 */ "key_opt ::=",
+ /* 296 */ "key_opt ::= KEY ids",
+ /* 297 */ "key_opt ::= KEY BLOB",
+ /* 298 */ "database_kw_opt ::= DATABASE",
+ /* 299 */ "database_kw_opt ::=",
+ /* 300 */ "cmd ::= DETACH database_kw_opt nm",
+ /* 301 */ "cmd ::= REINDEX",
+ /* 302 */ "cmd ::= REINDEX nm dbnm",
+ /* 303 */ "cmd ::= ANALYZE",
+ /* 304 */ "cmd ::= ANALYZE nm dbnm",
+ /* 305 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 306 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
+ /* 307 */ "add_column_fullname ::= fullname",
+ /* 308 */ "kwcolumn_opt ::=",
+ /* 309 */ "kwcolumn_opt ::= COLUMNKW",
 };
 #endif /* NDEBUG */
 
@@ -1291,72 +1318,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 157:
-    case 189:
-    case 206:
-#line 334 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3SelectDelete((yypminor->yy459));}
-#line 1301 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+    case 159:
+    case 192:
+    case 209:
+#line 369 "parse.y"
+{sqlite3SelectDelete((yypminor->yy99));}
+#line 1328 "parse.c"
       break;
-    case 170:
+    case 173:
     case 174:
-    case 194:
-    case 196:
-    case 204:
-    case 210:
-    case 224:
-#line 593 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3ExprDelete((yypminor->yy2));}
-#line 1312 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-      break;
-    case 175:
-    case 183:
-    case 192:
-    case 195:
     case 197:
     case 199:
-    case 209:
-    case 212:
+    case 207:
     case 213:
-    case 216:
-    case 222:
-#line 812 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3ExprListDelete((yypminor->yy82));}
-#line 1327 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+    case 227:
+#line 628 "parse.y"
+{sqlite3ExprDelete((yypminor->yy44));}
+#line 1339 "parse.c"
       break;
-    case 188:
-    case 193:
-    case 201:
+    case 178:
+    case 186:
+    case 195:
+    case 198:
+    case 200:
     case 202:
-#line 463 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3SrcListDelete((yypminor->yy67));}
-#line 1335 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+    case 212:
+    case 215:
+    case 216:
+    case 219:
+    case 225:
+#line 853 "parse.y"
+{sqlite3ExprListDelete((yypminor->yy412));}
+#line 1354 "parse.c"
       break;
-    case 198:
-#line 525 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+    case 191:
+    case 196:
+    case 204:
+    case 205:
+#line 498 "parse.y"
+{sqlite3SrcListDelete((yypminor->yy367));}
+#line 1362 "parse.c"
+      break;
+    case 201:
+#line 560 "parse.y"
 {
-  sqlite3ExprDelete((yypminor->yy244).pLimit);
-  sqlite3ExprDelete((yypminor->yy244).pOffset);
+  sqlite3ExprDelete((yypminor->yy112).pLimit);
+  sqlite3ExprDelete((yypminor->yy112).pOffset);
 }
-#line 1343 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 1370 "parse.c"
       break;
-    case 205:
     case 208:
-    case 215:
-#line 481 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3IdListDelete((yypminor->yy240));}
-#line 1350 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+    case 211:
+    case 218:
+#line 516 "parse.y"
+{sqlite3IdListDelete((yypminor->yy258));}
+#line 1377 "parse.c"
       break;
-    case 230:
-    case 235:
-#line 905 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DeleteTriggerStep((yypminor->yy347));}
-#line 1356 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+    case 233:
+    case 238:
+#line 946 "parse.y"
+{sqlite3DeleteTriggerStep((yypminor->yy203));}
+#line 1383 "parse.c"
       break;
-    case 232:
-#line 889 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3IdListDelete((yypminor->yy210).b);}
-#line 1361 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+    case 235:
+#line 930 "parse.y"
+{sqlite3IdListDelete((yypminor->yy234).b);}
+#line 1388 "parse.c"
       break;
     default:  break;   /* If no destructor action specified: do nothing */
   }
@@ -1532,193 +1559,196 @@ 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[] = {
-  { 142, 1 },
-  { 143, 2 },
-  { 143, 1 },
-  { 145, 1 },
   { 144, 1 },
-  { 144, 3 },
-  { 147, 0 },
+  { 145, 2 },
+  { 145, 1 },
   { 147, 1 },
+  { 146, 1 },
   { 146, 3 },
   { 149, 0 },
   { 149, 1 },
-  { 149, 2 },
-  { 148, 0 },
-  { 148, 1 },
-  { 148, 1 },
-  { 148, 1 },
-  { 146, 2 },
-  { 146, 2 },
-  { 146, 2 },
-  { 146, 2 },
-  { 151, 5 },
-  { 153, 1 },
-  { 153, 0 },
-  { 152, 4 },
-  { 152, 2 },
-  { 155, 3 },
-  { 155, 1 },
-  { 158, 3 },
-  { 159, 1 },
-  { 162, 1 },
-  { 163, 1 },
-  { 163, 1 },
+  { 148, 3 },
+  { 151, 0 },
+  { 151, 1 },
+  { 151, 2 },
+  { 150, 0 },
   { 150, 1 },
   { 150, 1 },
   { 150, 1 },
-  { 160, 0 },
-  { 160, 1 },
-  { 160, 4 },
-  { 160, 6 },
+  { 148, 2 },
+  { 148, 2 },
+  { 148, 2 },
+  { 148, 2 },
+  { 153, 5 },
+  { 155, 1 },
+  { 155, 0 },
+  { 154, 4 },
+  { 154, 2 },
+  { 157, 3 },
+  { 157, 1 },
+  { 160, 3 },
+  { 161, 1 },
   { 164, 1 },
-  { 164, 2 },
   { 165, 1 },
   { 165, 1 },
-  { 161, 2 },
-  { 161, 0 },
-  { 168, 3 },
+  { 152, 1 },
+  { 152, 1 },
+  { 152, 1 },
+  { 162, 0 },
+  { 162, 1 },
+  { 166, 1 },
+  { 166, 4 },
+  { 166, 6 },
+  { 167, 1 },
+  { 167, 2 },
   { 168, 1 },
-  { 168, 2 },
-  { 168, 3 },
-  { 168, 3 },
-  { 168, 2 },
-  { 169, 2 },
-  { 169, 3 },
-  { 169, 5 },
-  { 169, 2 },
-  { 169, 5 },
-  { 169, 4 },
-  { 169, 1 },
-  { 169, 2 },
-  { 173, 0 },
-  { 173, 1 },
-  { 176, 0 },
-  { 176, 2 },
-  { 178, 2 },
-  { 178, 3 },
-  { 178, 3 },
-  { 178, 3 },
-  { 179, 2 },
+  { 168, 1 },
+  { 163, 2 },
+  { 163, 0 },
+  { 171, 3 },
+  { 171, 1 },
+  { 171, 2 },
+  { 171, 4 },
+  { 171, 3 },
+  { 171, 3 },
+  { 171, 2 },
+  { 172, 2 },
+  { 172, 3 },
+  { 172, 5 },
+  { 172, 2 },
+  { 172, 5 },
+  { 172, 4 },
+  { 172, 1 },
+  { 172, 2 },
+  { 177, 0 },
+  { 177, 1 },
+  { 179, 0 },
   { 179, 2 },
-  { 179, 1 },
-  { 179, 1 },
-  { 177, 3 },
-  { 177, 2 },
-  { 180, 0 },
-  { 180, 2 },
-  { 180, 2 },
-  { 156, 0 },
-  { 156, 2 },
-  { 181, 3 },
   { 181, 2 },
-  { 181, 1 },
+  { 181, 3 },
+  { 181, 3 },
+  { 181, 3 },
+  { 182, 2 },
   { 182, 2 },
-  { 182, 7 },
-  { 182, 5 },
-  { 182, 3 },
-  { 182, 10 },
-  { 184, 0 },
+  { 182, 1 },
+  { 182, 1 },
+  { 180, 3 },
+  { 180, 2 },
+  { 183, 0 },
+  { 183, 2 },
+  { 183, 2 },
+  { 158, 0 },
+  { 158, 2 },
+  { 184, 3 },
+  { 184, 2 },
   { 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, 1 },
-  { 190, 1 },
-  { 189, 9 },
-  { 191, 1 },
-  { 191, 1 },
-  { 191, 0 },
-  { 199, 2 },
-  { 199, 0 },
-  { 192, 3 },
-  { 192, 2 },
-  { 192, 4 },
-  { 200, 2 },
-  { 200, 1 },
-  { 200, 0 },
-  { 193, 0 },
+  { 185, 7 },
+  { 185, 5 },
+  { 185, 3 },
+  { 185, 10 },
+  { 187, 0 },
+  { 187, 1 },
+  { 175, 0 },
+  { 175, 3 },
+  { 188, 0 },
+  { 188, 2 },
+  { 189, 1 },
+  { 189, 1 },
+  { 189, 1 },
+  { 148, 3 },
+  { 148, 7 },
+  { 148, 3 },
+  { 148, 1 },
+  { 159, 1 },
+  { 159, 3 },
+  { 193, 1 },
   { 193, 2 },
+  { 193, 1 },
+  { 193, 1 },
+  { 192, 9 },
+  { 194, 1 },
+  { 194, 1 },
+  { 194, 0 },
   { 202, 2 },
   { 202, 0 },
-  { 201, 6 },
-  { 201, 7 },
-  { 206, 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 },
-  { 172, 1 },
-  { 172, 1 },
-  { 172, 0 },
-  { 211, 0 },
-  { 211, 2 },
-  { 195, 0 },
   { 195, 3 },
+  { 195, 2 },
+  { 195, 4 },
+  { 203, 2 },
+  { 203, 1 },
+  { 203, 0 },
   { 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 },
+  { 205, 2 },
+  { 205, 0 },
+  { 204, 6 },
+  { 204, 7 },
+  { 209, 1 },
+  { 209, 1 },
+  { 156, 0 },
+  { 156, 2 },
+  { 191, 2 },
+  { 206, 1 },
+  { 206, 1 },
+  { 206, 2 },
+  { 206, 3 },
+  { 206, 4 },
+  { 207, 2 },
+  { 207, 0 },
+  { 208, 4 },
+  { 208, 0 },
+  { 200, 0 },
+  { 200, 3 },
+  { 212, 5 },
+  { 212, 3 },
+  { 213, 1 },
+  { 176, 1 },
+  { 176, 1 },
+  { 176, 0 },
+  { 214, 0 },
   { 214, 2 },
-  { 214, 1 },
+  { 198, 0 },
+  { 198, 3 },
+  { 199, 0 },
+  { 199, 2 },
+  { 201, 0 },
+  { 201, 2 },
+  { 201, 4 },
+  { 201, 4 },
+  { 148, 4 },
+  { 197, 0 },
+  { 197, 2 },
+  { 148, 6 },
+  { 216, 5 },
   { 216, 3 },
-  { 216, 1 },
-  { 215, 0 },
-  { 215, 3 },
-  { 208, 3 },
-  { 208, 1 },
+  { 148, 8 },
+  { 148, 5 },
+  { 217, 2 },
+  { 217, 1 },
+  { 219, 3 },
+  { 219, 1 },
+  { 218, 0 },
+  { 218, 3 },
+  { 211, 3 },
+  { 211, 1 },
   { 174, 1 },
   { 174, 3 },
-  { 170, 1 },
+  { 173, 1 },
   { 174, 1 },
   { 174, 1 },
   { 174, 3 },
   { 174, 5 },
-  { 170, 1 },
-  { 170, 1 },
-  { 170, 1 },
-  { 170, 1 },
+  { 173, 1 },
+  { 173, 1 },
+  { 173, 1 },
+  { 173, 1 },
   { 174, 1 },
   { 174, 1 },
+  { 174, 6 },
   { 174, 4 },
   { 174, 4 },
-  { 170, 1 },
+  { 173, 1 },
   { 174, 3 },
   { 174, 3 },
   { 174, 3 },
@@ -1737,10 +1767,10 @@ static const struct {
   { 174, 3 },
   { 174, 3 },
   { 174, 3 },
-  { 217, 1 },
-  { 217, 2 },
-  { 218, 2 },
-  { 218, 0 },
+  { 220, 1 },
+  { 220, 2 },
+  { 221, 2 },
+  { 221, 0 },
   { 174, 4 },
   { 174, 2 },
   { 174, 3 },
@@ -1751,92 +1781,94 @@ static const struct {
   { 174, 2 },
   { 174, 2 },
   { 174, 2 },
-  { 219, 1 },
-  { 219, 2 },
+  { 222, 1 },
+  { 222, 2 },
   { 174, 5 },
-  { 220, 1 },
-  { 220, 2 },
+  { 223, 1 },
+  { 223, 2 },
   { 174, 5 },
   { 174, 3 },
   { 174, 5 },
   { 174, 4 },
   { 174, 4 },
   { 174, 5 },
-  { 222, 5 },
-  { 222, 4 },
-  { 223, 2 },
-  { 223, 0 },
-  { 221, 1 },
-  { 221, 0 },
-  { 212, 3 },
-  { 212, 1 },
+  { 225, 5 },
+  { 225, 4 },
+  { 226, 2 },
+  { 226, 0 },
   { 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 },
+  { 215, 3 },
+  { 215, 1 },
   { 227, 1 },
   { 227, 0 },
-  { 146, 5 },
-  { 229, 10 },
+  { 148, 11 },
+  { 228, 1 },
+  { 228, 0 },
+  { 178, 0 },
+  { 178, 3 },
+  { 186, 5 },
+  { 186, 3 },
+  { 229, 1 },
+  { 148, 3 },
+  { 148, 1 },
+  { 148, 2 },
+  { 148, 5 },
+  { 148, 5 },
+  { 148, 5 },
+  { 148, 5 },
+  { 148, 6 },
+  { 148, 3 },
+  { 169, 2 },
+  { 170, 2 },
   { 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, 1 },
   { 230, 0 },
-  { 235, 6 },
-  { 235, 8 },
-  { 235, 5 },
-  { 235, 4 },
+  { 148, 5 },
+  { 232, 10 },
+  { 234, 1 },
+  { 234, 1 },
+  { 234, 2 },
+  { 234, 0 },
   { 235, 1 },
-  { 174, 4 },
-  { 174, 6 },
-  { 187, 1 },
-  { 187, 1 },
-  { 187, 1 },
-  { 146, 3 },
-  { 146, 6 },
+  { 235, 1 },
+  { 235, 1 },
+  { 235, 3 },
+  { 236, 0 },
+  { 236, 3 },
+  { 236, 3 },
   { 237, 0 },
   { 237, 2 },
-  { 237, 2 },
-  { 236, 1 },
-  { 236, 0 },
-  { 146, 3 },
-  { 146, 1 },
-  { 146, 3 },
-  { 146, 6 },
-  { 146, 6 },
+  { 233, 3 },
+  { 233, 0 },
+  { 238, 6 },
+  { 238, 8 },
+  { 238, 5 },
+  { 238, 4 },
   { 238, 1 },
-  { 239, 0 },
+  { 174, 4 },
+  { 174, 6 },
+  { 190, 1 },
+  { 190, 1 },
+  { 190, 1 },
+  { 148, 3 },
+  { 148, 6 },
+  { 240, 0 },
+  { 240, 2 },
+  { 240, 2 },
   { 239, 1 },
+  { 239, 0 },
+  { 148, 3 },
+  { 148, 1 },
+  { 148, 3 },
+  { 148, 1 },
+  { 148, 3 },
+  { 148, 6 },
+  { 148, 6 },
+  { 241, 1 },
+  { 242, 0 },
+  { 242, 1 },
 };
 
 static void yy_accept(yyParser*);  /* Forward Declaration */
@@ -1886,111 +1918,111 @@ static void yy_reduce(
   **     break;
   */
       case 3:
-#line 84 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 102 "parse.y"
 { sqlite3FinishCoding(pParse); }
-#line 1893 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 1925 "parse.c"
         break;
       case 6:
-#line 87 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 105 "parse.y"
 { sqlite3BeginParse(pParse, 0); }
-#line 1898 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 1930 "parse.c"
         break;
       case 7:
-#line 89 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 107 "parse.y"
 { sqlite3BeginParse(pParse, 1); }
-#line 1903 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 1935 "parse.c"
         break;
       case 8:
-#line 95 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy412);}
-#line 1908 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 113 "parse.y"
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy58);}
+#line 1940 "parse.c"
         break;
       case 12:
-#line 100 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = TK_DEFERRED;}
-#line 1913 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 118 "parse.y"
+{yygotominor.yy58 = TK_DEFERRED;}
+#line 1945 "parse.c"
         break;
       case 13:
       case 14:
       case 15:
-      case 101:
       case 103:
-      case 104:
-#line 101 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = yymsp[0].major;}
-#line 1923 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 105:
+      case 106:
+#line 119 "parse.y"
+{yygotominor.yy58 = yymsp[0].major;}
+#line 1955 "parse.c"
         break;
       case 16:
       case 17:
-#line 104 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 122 "parse.y"
 {sqlite3CommitTransaction(pParse);}
-#line 1929 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 1961 "parse.c"
         break;
       case 18:
-#line 106 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 124 "parse.y"
 {sqlite3RollbackTransaction(pParse);}
-#line 1934 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 1966 "parse.c"
         break;
       case 20:
-#line 111 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 129 "parse.y"
 {
-   sqlite3StartTable(pParse,&yymsp[-4].minor.yy0,&yymsp[-1].minor.yy258,&yymsp[0].minor.yy258,yymsp[-3].minor.yy412,0);
+   sqlite3StartTable(pParse,&yymsp[-4].minor.yy0,&yymsp[-1].minor.yy144,&yymsp[0].minor.yy144,yymsp[-3].minor.yy58,0);
 }
-#line 1941 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 1973 "parse.c"
         break;
       case 21:
-      case 60:
-      case 74:
-      case 106:
-      case 220:
+      case 62:
+      case 76:
+      case 108:
       case 223:
-#line 116 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = 1;}
-#line 1951 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 226:
+#line 134 "parse.y"
+{yygotominor.yy58 = 1;}
+#line 1983 "parse.c"
         break;
       case 22:
-      case 59:
-      case 73:
+      case 61:
       case 75:
-      case 86:
-      case 107:
-      case 108:
-      case 219:
+      case 77:
+      case 88:
+      case 109:
+      case 110:
       case 222:
-#line 118 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = 0;}
-#line 1964 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 225:
+#line 136 "parse.y"
+{yygotominor.yy58 = 0;}
+#line 1996 "parse.c"
         break;
       case 23:
-#line 119 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 137 "parse.y"
 {
-  sqlite3EndTable(pParse,&yymsp[-1].minor.yy258,&yymsp[0].minor.yy0,0);
+  sqlite3EndTable(pParse,&yymsp[-1].minor.yy144,&yymsp[0].minor.yy0,0);
 }
-#line 1971 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2003 "parse.c"
         break;
       case 24:
-#line 122 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 140 "parse.y"
 {
-  sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy459);
-  sqlite3SelectDelete(yymsp[0].minor.yy459);
+  sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy99);
+  sqlite3SelectDelete(yymsp[0].minor.yy99);
 }
-#line 1979 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2011 "parse.c"
         break;
       case 27:
-#line 133 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 152 "parse.y"
 {
-  yygotominor.yy258.z = yymsp[-2].minor.yy258.z;
-  yygotominor.yy258.n = (pParse->sLastToken.z-yymsp[-2].minor.yy258.z) + pParse->sLastToken.n;
+  yygotominor.yy144.z = yymsp[-2].minor.yy144.z;
+  yygotominor.yy144.n = (pParse->sLastToken.z-yymsp[-2].minor.yy144.z) + pParse->sLastToken.n;
 }
-#line 1987 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2019 "parse.c"
         break;
       case 28:
-#line 137 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 156 "parse.y"
 {
-  sqlite3AddColumn(pParse,&yymsp[0].minor.yy258);
-  yygotominor.yy258 = yymsp[0].minor.yy258;
+  sqlite3AddColumn(pParse,&yymsp[0].minor.yy144);
+  yygotominor.yy144 = yymsp[0].minor.yy144;
 }
-#line 1995 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2027 "parse.c"
         break;
       case 29:
       case 30:
@@ -1998,640 +2030,657 @@ static void yy_reduce(
       case 32:
       case 33:
       case 34:
-      case 259:
-      case 260:
-#line 147 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = yymsp[0].minor.yy0;}
-#line 2007 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 262:
+      case 263:
+#line 166 "parse.y"
+{yygotominor.yy144 = yymsp[0].minor.yy0;}
+#line 2039 "parse.c"
         break;
       case 36:
-#line 202 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy258,&yymsp[0].minor.yy258);}
-#line 2012 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 226 "parse.y"
+{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy144);}
+#line 2044 "parse.c"
         break;
       case 37:
-#line 203 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[-3].minor.yy258,&yymsp[0].minor.yy0);}
-#line 2017 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 40:
+      case 116:
+      case 117:
+      case 128:
+      case 148:
+      case 250:
+      case 260:
+      case 261:
+#line 227 "parse.y"
+{yygotominor.yy144 = yymsp[0].minor.yy144;}
+#line 2057 "parse.c"
         break;
       case 38:
-#line 205 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[-5].minor.yy258,&yymsp[0].minor.yy0);}
-#line 2022 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 228 "parse.y"
+{
+  yygotominor.yy144.z = yymsp[-3].minor.yy144.z;
+  yygotominor.yy144.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy144.z;
+}
+#line 2065 "parse.c"
         break;
       case 39:
-      case 114:
-      case 115:
-      case 126:
-      case 146:
-      case 247:
-      case 257:
-      case 258:
-#line 207 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = yymsp[0].minor.yy258;}
-#line 2034 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 40:
-#line 208 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258.z=yymsp[-1].minor.yy258.z; yygotominor.yy258.n=yymsp[0].minor.yy258.n+(yymsp[0].minor.yy258.z-yymsp[-1].minor.yy258.z);}
-#line 2039 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 232 "parse.y"
+{
+  yygotominor.yy144.z = yymsp[-5].minor.yy144.z;
+  yygotominor.yy144.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy144.z;
+}
+#line 2073 "parse.c"
         break;
       case 41:
-#line 210 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = atoi(yymsp[0].minor.yy258.z); }
-#line 2044 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 238 "parse.y"
+{yygotominor.yy144.z=yymsp[-1].minor.yy144.z; yygotominor.yy144.n=yymsp[0].minor.yy144.n+(yymsp[0].minor.yy144.z-yymsp[-1].minor.yy144.z);}
+#line 2078 "parse.c"
         break;
       case 42:
-#line 211 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = -atoi(yymsp[0].minor.yy258.z); }
-#line 2049 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 240 "parse.y"
+{ yygotominor.yy58 = atoi(yymsp[0].minor.yy144.z); }
+#line 2083 "parse.c"
+        break;
+      case 43:
+#line 241 "parse.y"
+{ yygotominor.yy58 = -atoi(yymsp[0].minor.yy144.z); }
+#line 2088 "parse.c"
         break;
-      case 47:
       case 48:
-#line 216 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy2);}
-#line 2055 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 50:
+#line 250 "parse.y"
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy44);}
+#line 2094 "parse.c"
         break;
       case 49:
-#line 218 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 251 "parse.y"
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy44);}
+#line 2099 "parse.c"
+        break;
+      case 51:
+#line 253 "parse.y"
 {
-  Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy2, 0, 0);
+  Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy44, 0, 0);
   sqlite3AddDefaultValue(pParse,p);
 }
-#line 2063 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2107 "parse.c"
         break;
-      case 50:
-#line 222 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 52:
+#line 257 "parse.y"
 {
-  Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy258);
+  Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy144);
   sqlite3AddDefaultValue(pParse,p);
 }
-#line 2071 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 52:
-#line 231 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy412);}
-#line 2076 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 53:
-#line 233 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy412,yymsp[0].minor.yy412);}
-#line 2081 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2115 "parse.c"
         break;
       case 54:
-#line 234 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy412,0,0);}
-#line 2086 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 266 "parse.y"
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy58);}
+#line 2120 "parse.c"
         break;
       case 55:
-#line 235 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3ExprDelete(yymsp[-2].minor.yy2);}
-#line 2091 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 268 "parse.y"
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy58,yymsp[0].minor.yy58);}
+#line 2125 "parse.c"
         break;
       case 56:
-#line 237 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy258,yymsp[-1].minor.yy82,yymsp[0].minor.yy412);}
-#line 2096 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 269 "parse.y"
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy58,0,0);}
+#line 2130 "parse.c"
         break;
       case 57:
-#line 238 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy412);}
-#line 2101 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 270 "parse.y"
+{sqlite3ExprDelete(yymsp[-2].minor.yy44);}
+#line 2135 "parse.c"
         break;
       case 58:
-#line 239 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddCollateType(pParse, yymsp[0].minor.yy258.z, yymsp[0].minor.yy258.n);}
-#line 2106 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 272 "parse.y"
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy144,yymsp[-1].minor.yy412,yymsp[0].minor.yy58);}
+#line 2140 "parse.c"
         break;
-      case 61:
-#line 252 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = OE_Restrict * 0x010101; }
-#line 2111 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 59:
+#line 273 "parse.y"
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy58);}
+#line 2145 "parse.c"
         break;
-      case 62:
-#line 253 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = (yymsp[-1].minor.yy412 & yymsp[0].minor.yy47.mask) | yymsp[0].minor.yy47.value; }
-#line 2116 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 60:
+#line 274 "parse.y"
+{sqlite3AddCollateType(pParse, yymsp[0].minor.yy144.z, yymsp[0].minor.yy144.n);}
+#line 2150 "parse.c"
         break;
       case 63:
-#line 255 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = 0;     yygotominor.yy47.mask = 0x000000; }
-#line 2121 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 287 "parse.y"
+{ yygotominor.yy58 = OE_Restrict * 0x010101; }
+#line 2155 "parse.c"
         break;
       case 64:
-#line 256 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = yymsp[0].minor.yy412;     yygotominor.yy47.mask = 0x0000ff; }
-#line 2126 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 288 "parse.y"
+{ yygotominor.yy58 = (yymsp[-1].minor.yy58 & yymsp[0].minor.yy35.mask) | yymsp[0].minor.yy35.value; }
+#line 2160 "parse.c"
         break;
       case 65:
-#line 257 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = yymsp[0].minor.yy412<<8;  yygotominor.yy47.mask = 0x00ff00; }
-#line 2131 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 290 "parse.y"
+{ yygotominor.yy35.value = 0;     yygotominor.yy35.mask = 0x000000; }
+#line 2165 "parse.c"
         break;
       case 66:
-#line 258 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = yymsp[0].minor.yy412<<16; yygotominor.yy47.mask = 0xff0000; }
-#line 2136 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 291 "parse.y"
+{ yygotominor.yy35.value = yymsp[0].minor.yy58;     yygotominor.yy35.mask = 0x0000ff; }
+#line 2170 "parse.c"
         break;
       case 67:
-#line 260 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = OE_SetNull; }
-#line 2141 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 292 "parse.y"
+{ yygotominor.yy35.value = yymsp[0].minor.yy58<<8;  yygotominor.yy35.mask = 0x00ff00; }
+#line 2175 "parse.c"
         break;
       case 68:
-#line 261 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = OE_SetDflt; }
-#line 2146 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 293 "parse.y"
+{ yygotominor.yy35.value = yymsp[0].minor.yy58<<16; yygotominor.yy35.mask = 0xff0000; }
+#line 2180 "parse.c"
         break;
       case 69:
-#line 262 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = OE_Cascade; }
-#line 2151 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 295 "parse.y"
+{ yygotominor.yy58 = OE_SetNull; }
+#line 2185 "parse.c"
         break;
       case 70:
-#line 263 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = OE_Restrict; }
-#line 2156 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 296 "parse.y"
+{ yygotominor.yy58 = OE_SetDflt; }
+#line 2190 "parse.c"
         break;
       case 71:
+#line 297 "parse.y"
+{ yygotominor.yy58 = OE_Cascade; }
+#line 2195 "parse.c"
+        break;
       case 72:
-      case 87:
+#line 298 "parse.y"
+{ yygotominor.yy58 = OE_Restrict; }
+#line 2200 "parse.c"
+        break;
+      case 73:
+      case 74:
       case 89:
       case 91:
-      case 92:
-      case 163:
-#line 265 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = yymsp[0].minor.yy412;}
-#line 2167 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 76:
-#line 275 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258.n = 0; yygotominor.yy258.z = 0;}
-#line 2172 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 93:
+      case 94:
+      case 165:
+#line 300 "parse.y"
+{yygotominor.yy58 = yymsp[0].minor.yy58;}
+#line 2211 "parse.c"
         break;
-      case 77:
-#line 276 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = yymsp[-1].minor.yy0;}
-#line 2177 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 78:
+#line 310 "parse.y"
+{yygotominor.yy144.n = 0; yygotominor.yy144.z = 0;}
+#line 2216 "parse.c"
         break;
-      case 82:
-#line 282 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy82,yymsp[0].minor.yy412,yymsp[-2].minor.yy412);}
-#line 2182 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 79:
+#line 311 "parse.y"
+{yygotominor.yy144 = yymsp[-1].minor.yy0;}
+#line 2221 "parse.c"
         break;
-      case 83:
-#line 284 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy82,yymsp[0].minor.yy412,0,0);}
-#line 2187 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 84:
+#line 317 "parse.y"
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy412,yymsp[0].minor.yy58,yymsp[-2].minor.yy58);}
+#line 2226 "parse.c"
         break;
       case 85:
-#line 287 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 319 "parse.y"
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy412,yymsp[0].minor.yy58,0,0);}
+#line 2231 "parse.c"
+        break;
+      case 87:
+#line 322 "parse.y"
 {
-    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy82, &yymsp[-3].minor.yy258, yymsp[-2].minor.yy82, yymsp[-1].minor.yy412);
-    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy412);
+    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy412, &yymsp[-3].minor.yy144, yymsp[-2].minor.yy412, yymsp[-1].minor.yy58);
+    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy58);
 }
-#line 2195 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2239 "parse.c"
         break;
-      case 88:
       case 90:
-#line 301 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = OE_Default;}
-#line 2201 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 93:
-#line 306 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = OE_Ignore;}
-#line 2206 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 94:
-      case 164:
-#line 307 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = OE_Replace;}
-#line 2212 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 92:
+#line 336 "parse.y"
+{yygotominor.yy58 = OE_Default;}
+#line 2245 "parse.c"
         break;
       case 95:
-#line 311 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{
-  sqlite3DropTable(pParse, yymsp[0].minor.yy67, 0);
-}
-#line 2219 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 341 "parse.y"
+{yygotominor.yy58 = OE_Ignore;}
+#line 2250 "parse.c"
         break;
       case 96:
-#line 318 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{
-  sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy258, &yymsp[-2].minor.yy258, yymsp[0].minor.yy459, yymsp[-5].minor.yy412);
-}
-#line 2226 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 166:
+#line 342 "parse.y"
+{yygotominor.yy58 = OE_Replace;}
+#line 2256 "parse.c"
         break;
       case 97:
-#line 321 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 346 "parse.y"
 {
-  sqlite3DropTable(pParse, yymsp[0].minor.yy67, 1);
+  sqlite3DropTable(pParse, yymsp[0].minor.yy367, 0);
 }
-#line 2233 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2263 "parse.c"
         break;
       case 98:
-#line 328 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 353 "parse.y"
 {
-  sqlite3Select(pParse, yymsp[0].minor.yy459, SRT_Callback, 0, 0, 0, 0, 0);
-  sqlite3SelectDelete(yymsp[0].minor.yy459);
+  sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy144, &yymsp[-2].minor.yy144, yymsp[0].minor.yy99, yymsp[-5].minor.yy58);
 }
-#line 2241 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2270 "parse.c"
         break;
       case 99:
-      case 123:
-#line 338 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy459 = yymsp[0].minor.yy459;}
-#line 2247 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 356 "parse.y"
+{
+  sqlite3DropTable(pParse, yymsp[0].minor.yy367, 1);
+}
+#line 2277 "parse.c"
         break;
       case 100:
-#line 340 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 363 "parse.y"
 {
-  if( yymsp[0].minor.yy459 ){
-    yymsp[0].minor.yy459->op = yymsp[-1].minor.yy412;
-    yymsp[0].minor.yy459->pPrior = yymsp[-2].minor.yy459;
-  }
-  yygotominor.yy459 = yymsp[0].minor.yy459;
+  sqlite3Select(pParse, yymsp[0].minor.yy99, SRT_Callback, 0, 0, 0, 0, 0);
+  sqlite3SelectDelete(yymsp[0].minor.yy99);
 }
-#line 2258 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2285 "parse.c"
         break;
-      case 102:
-#line 349 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = TK_ALL;}
-#line 2263 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 101:
+      case 125:
+#line 373 "parse.y"
+{yygotominor.yy99 = yymsp[0].minor.yy99;}
+#line 2291 "parse.c"
         break;
-      case 105:
-#line 354 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 102:
+#line 375 "parse.y"
 {
-  yygotominor.yy459 = sqlite3SelectNew(yymsp[-6].minor.yy82,yymsp[-5].minor.yy67,yymsp[-4].minor.yy2,yymsp[-3].minor.yy82,yymsp[-2].minor.yy2,yymsp[-1].minor.yy82,yymsp[-7].minor.yy412,yymsp[0].minor.yy244.pLimit,yymsp[0].minor.yy244.pOffset);
+  if( yymsp[0].minor.yy99 ){
+    yymsp[0].minor.yy99->op = yymsp[-1].minor.yy58;
+    yymsp[0].minor.yy99->pPrior = yymsp[-2].minor.yy99;
+  }
+  yygotominor.yy99 = yymsp[0].minor.yy99;
 }
-#line 2270 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2302 "parse.c"
         break;
-      case 109:
-      case 244:
-#line 375 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy82 = yymsp[-1].minor.yy82;}
-#line 2276 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 104:
+#line 384 "parse.y"
+{yygotominor.yy58 = TK_ALL;}
+#line 2307 "parse.c"
         break;
-      case 110:
-      case 137:
-      case 147:
-      case 243:
-#line 376 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy82 = 0;}
-#line 2284 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 107:
+#line 389 "parse.y"
+{
+  yygotominor.yy99 = sqlite3SelectNew(yymsp[-6].minor.yy412,yymsp[-5].minor.yy367,yymsp[-4].minor.yy44,yymsp[-3].minor.yy412,yymsp[-2].minor.yy44,yymsp[-1].minor.yy412,yymsp[-7].minor.yy58,yymsp[0].minor.yy112.pLimit,yymsp[0].minor.yy112.pOffset);
+}
+#line 2314 "parse.c"
         break;
       case 111:
-#line 377 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 247:
+#line 410 "parse.y"
+{yygotominor.yy412 = yymsp[-1].minor.yy412;}
+#line 2320 "parse.c"
+        break;
+      case 112:
+      case 139:
+      case 149:
+      case 246:
+#line 411 "parse.y"
+{yygotominor.yy412 = 0;}
+#line 2328 "parse.c"
+        break;
+      case 113:
+#line 412 "parse.y"
 {
-   yygotominor.yy82 = sqlite3ExprListAppend(yymsp[-2].minor.yy82,yymsp[-1].minor.yy2,yymsp[0].minor.yy258.n?&yymsp[0].minor.yy258:0);
+   yygotominor.yy412 = sqlite3ExprListAppend(yymsp[-2].minor.yy412,yymsp[-1].minor.yy44,yymsp[0].minor.yy144.n?&yymsp[0].minor.yy144:0);
 }
-#line 2291 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2335 "parse.c"
         break;
-      case 112:
-#line 380 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 114:
+#line 415 "parse.y"
 {
-  yygotominor.yy82 = sqlite3ExprListAppend(yymsp[-1].minor.yy82, sqlite3Expr(TK_ALL, 0, 0, 0), 0);
+  yygotominor.yy412 = sqlite3ExprListAppend(yymsp[-1].minor.yy412, sqlite3Expr(TK_ALL, 0, 0, 0), 0);
 }
-#line 2298 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2342 "parse.c"
         break;
-      case 113:
-#line 383 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 115:
+#line 418 "parse.y"
 {
   Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0);
-  Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy258);
-  yygotominor.yy82 = sqlite3ExprListAppend(yymsp[-3].minor.yy82, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0);
+  Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy144);
+  yygotominor.yy412 = sqlite3ExprListAppend(yymsp[-3].minor.yy412, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0);
 }
-#line 2307 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 116:
-#line 395 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258.n = 0;}
-#line 2312 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 117:
-#line 407 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy67 = sqliteMalloc(sizeof(*yygotominor.yy67));}
-#line 2317 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2351 "parse.c"
         break;
       case 118:
-#line 408 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy67 = yymsp[0].minor.yy67;}
-#line 2322 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 430 "parse.y"
+{yygotominor.yy144.n = 0;}
+#line 2356 "parse.c"
         break;
       case 119:
-#line 413 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{
-   yygotominor.yy67 = yymsp[-1].minor.yy67;
-   if( yygotominor.yy67 && yygotominor.yy67->nSrc>0 ) yygotominor.yy67->a[yygotominor.yy67->nSrc-1].jointype = yymsp[0].minor.yy412;
-}
-#line 2330 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 442 "parse.y"
+{yygotominor.yy367 = sqliteMalloc(sizeof(*yygotominor.yy367));}
+#line 2361 "parse.c"
         break;
       case 120:
-#line 417 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy67 = 0;}
-#line 2335 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 443 "parse.y"
+{yygotominor.yy367 = yymsp[0].minor.yy367;}
+#line 2366 "parse.c"
         break;
       case 121:
-#line 418 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 448 "parse.y"
 {
-  yygotominor.yy67 = sqlite3SrcListAppend(yymsp[-5].minor.yy67,&yymsp[-4].minor.yy258,&yymsp[-3].minor.yy258);
-  if( yymsp[-2].minor.yy258.n ) sqlite3SrcListAddAlias(yygotominor.yy67,&yymsp[-2].minor.yy258);
-  if( yymsp[-1].minor.yy2 ){
-    if( yygotominor.yy67 && yygotominor.yy67->nSrc>1 ){ yygotominor.yy67->a[yygotominor.yy67->nSrc-2].pOn = yymsp[-1].minor.yy2; }
-    else { sqlite3ExprDelete(yymsp[-1].minor.yy2); }
+   yygotominor.yy367 = yymsp[-1].minor.yy367;
+   if( yygotominor.yy367 && yygotominor.yy367->nSrc>0 ) yygotominor.yy367->a[yygotominor.yy367->nSrc-1].jointype = yymsp[0].minor.yy58;
+}
+#line 2374 "parse.c"
+        break;
+      case 122:
+#line 452 "parse.y"
+{yygotominor.yy367 = 0;}
+#line 2379 "parse.c"
+        break;
+      case 123:
+#line 453 "parse.y"
+{
+  yygotominor.yy367 = sqlite3SrcListAppend(yymsp[-5].minor.yy367,&yymsp[-4].minor.yy144,&yymsp[-3].minor.yy144);
+  if( yymsp[-2].minor.yy144.n ) sqlite3SrcListAddAlias(yygotominor.yy367,&yymsp[-2].minor.yy144);
+  if( yymsp[-1].minor.yy44 ){
+    if( yygotominor.yy367 && yygotominor.yy367->nSrc>1 ){ yygotominor.yy367->a[yygotominor.yy367->nSrc-2].pOn = yymsp[-1].minor.yy44; }
+    else { sqlite3ExprDelete(yymsp[-1].minor.yy44); }
   }
-  if( yymsp[0].minor.yy240 ){
-    if( yygotominor.yy67 && yygotominor.yy67->nSrc>1 ){ yygotominor.yy67->a[yygotominor.yy67->nSrc-2].pUsing = yymsp[0].minor.yy240; }
-    else { sqlite3IdListDelete(yymsp[0].minor.yy240); }
+  if( yymsp[0].minor.yy258 ){
+    if( yygotominor.yy367 && yygotominor.yy367->nSrc>1 ){ yygotominor.yy367->a[yygotominor.yy367->nSrc-2].pUsing = yymsp[0].minor.yy258; }
+    else { sqlite3IdListDelete(yymsp[0].minor.yy258); }
   }
 }
-#line 2351 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2395 "parse.c"
         break;
-      case 122:
-#line 432 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{
-    yygotominor.yy67 = sqlite3SrcListAppend(yymsp[-6].minor.yy67,0,0);
-    yygotominor.yy67->a[yygotominor.yy67->nSrc-1].pSelect = yymsp[-4].minor.yy459;
-    if( yymsp[-2].minor.yy258.n ) sqlite3SrcListAddAlias(yygotominor.yy67,&yymsp[-2].minor.yy258);
-    if( yymsp[-1].minor.yy2 ){
-      if( yygotominor.yy67 && yygotominor.yy67->nSrc>1 ){ yygotominor.yy67->a[yygotominor.yy67->nSrc-2].pOn = yymsp[-1].minor.yy2; }
-      else { sqlite3ExprDelete(yymsp[-1].minor.yy2); }
+      case 124:
+#line 467 "parse.y"
+{
+    yygotominor.yy367 = sqlite3SrcListAppend(yymsp[-6].minor.yy367,0,0);
+    yygotominor.yy367->a[yygotominor.yy367->nSrc-1].pSelect = yymsp[-4].minor.yy99;
+    if( yymsp[-2].minor.yy144.n ) sqlite3SrcListAddAlias(yygotominor.yy367,&yymsp[-2].minor.yy144);
+    if( yymsp[-1].minor.yy44 ){
+      if( yygotominor.yy367 && yygotominor.yy367->nSrc>1 ){ yygotominor.yy367->a[yygotominor.yy367->nSrc-2].pOn = yymsp[-1].minor.yy44; }
+      else { sqlite3ExprDelete(yymsp[-1].minor.yy44); }
     }
-    if( yymsp[0].minor.yy240 ){
-      if( yygotominor.yy67 && yygotominor.yy67->nSrc>1 ){ yygotominor.yy67->a[yygotominor.yy67->nSrc-2].pUsing = yymsp[0].minor.yy240; }
-      else { sqlite3IdListDelete(yymsp[0].minor.yy240); }
+    if( yymsp[0].minor.yy258 ){
+      if( yygotominor.yy367 && yygotominor.yy367->nSrc>1 ){ yygotominor.yy367->a[yygotominor.yy367->nSrc-2].pUsing = yymsp[0].minor.yy258; }
+      else { sqlite3IdListDelete(yymsp[0].minor.yy258); }
     }
   }
-#line 2368 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2412 "parse.c"
         break;
-      case 124:
-#line 453 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 126:
+#line 488 "parse.y"
 {
-     yygotominor.yy459 = sqlite3SelectNew(0,yymsp[0].minor.yy67,0,0,0,0,0,0,0);
+     yygotominor.yy99 = sqlite3SelectNew(0,yymsp[0].minor.yy367,0,0,0,0,0,0,0);
   }
-#line 2375 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 125:
-#line 459 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258.z=0; yygotominor.yy258.n=0;}
-#line 2380 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2419 "parse.c"
         break;
       case 127:
-#line 464 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy67 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy258,&yymsp[0].minor.yy258);}
-#line 2385 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 494 "parse.y"
+{yygotominor.yy144.z=0; yygotominor.yy144.n=0;}
+#line 2424 "parse.c"
         break;
-      case 128:
       case 129:
-#line 468 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = JT_INNER; }
-#line 2391 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 499 "parse.y"
+{yygotominor.yy367 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy144,&yymsp[0].minor.yy144);}
+#line 2429 "parse.c"
         break;
       case 130:
-#line 470 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
-#line 2396 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 131:
-#line 471 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy258,0); }
-#line 2401 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 503 "parse.y"
+{ yygotominor.yy58 = JT_INNER; }
+#line 2435 "parse.c"
         break;
       case 132:
-#line 473 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy258,&yymsp[-1].minor.yy258); }
-#line 2406 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 505 "parse.y"
+{ yygotominor.yy58 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+#line 2440 "parse.c"
         break;
       case 133:
-      case 141:
-      case 150:
-      case 157:
-      case 171:
-      case 207:
-      case 232:
-      case 234:
-      case 238:
-#line 477 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy2 = yymsp[0].minor.yy2;}
-#line 2419 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 506 "parse.y"
+{ yygotominor.yy58 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy144,0); }
+#line 2445 "parse.c"
         break;
       case 134:
-      case 149:
-      case 156:
-      case 208:
-      case 233:
-      case 235:
-      case 239:
-#line 478 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy2 = 0;}
-#line 2430 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 508 "parse.y"
+{ yygotominor.yy58 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy144,&yymsp[-1].minor.yy144); }
+#line 2450 "parse.c"
         break;
       case 135:
-      case 168:
-#line 482 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy240 = yymsp[-1].minor.yy240;}
-#line 2436 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 143:
+      case 152:
+      case 159:
+      case 173:
+      case 210:
+      case 235:
+      case 237:
+      case 241:
+#line 512 "parse.y"
+{yygotominor.yy44 = yymsp[0].minor.yy44;}
+#line 2463 "parse.c"
         break;
       case 136:
-      case 167:
-#line 483 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy240 = 0;}
-#line 2442 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 151:
+      case 158:
+      case 211:
+      case 236:
+      case 238:
+      case 242:
+#line 513 "parse.y"
+{yygotominor.yy44 = 0;}
+#line 2474 "parse.c"
+        break;
+      case 137:
+      case 170:
+#line 517 "parse.y"
+{yygotominor.yy258 = yymsp[-1].minor.yy258;}
+#line 2480 "parse.c"
         break;
       case 138:
-      case 148:
-#line 494 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy82 = yymsp[0].minor.yy82;}
-#line 2448 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 169:
+#line 518 "parse.y"
+{yygotominor.yy258 = 0;}
+#line 2486 "parse.c"
         break;
-      case 139:
-#line 495 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 140:
+      case 150:
+#line 529 "parse.y"
+{yygotominor.yy412 = yymsp[0].minor.yy412;}
+#line 2492 "parse.c"
+        break;
+      case 141:
+#line 530 "parse.y"
 {
-  yygotominor.yy82 = sqlite3ExprListAppend(yymsp[-4].minor.yy82,yymsp[-2].minor.yy2,yymsp[-1].minor.yy258.n>0?&yymsp[-1].minor.yy258:0);
-  if( yygotominor.yy82 ) yygotominor.yy82->a[yygotominor.yy82->nExpr-1].sortOrder = yymsp[0].minor.yy412;
+  yygotominor.yy412 = sqlite3ExprListAppend(yymsp[-4].minor.yy412,yymsp[-2].minor.yy44,yymsp[-1].minor.yy144.n>0?&yymsp[-1].minor.yy144:0);
+  if( yygotominor.yy412 ) yygotominor.yy412->a[yygotominor.yy412->nExpr-1].sortOrder = yymsp[0].minor.yy58;
 }
-#line 2456 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2500 "parse.c"
         break;
-      case 140:
-#line 499 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 142:
+#line 534 "parse.y"
 {
-  yygotominor.yy82 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy2,yymsp[-1].minor.yy258.n>0?&yymsp[-1].minor.yy258:0);
-  if( yygotominor.yy82 && yygotominor.yy82->a ) yygotominor.yy82->a[0].sortOrder = yymsp[0].minor.yy412;
+  yygotominor.yy412 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy44,yymsp[-1].minor.yy144.n>0?&yymsp[-1].minor.yy144:0);
+  if( yygotominor.yy412 && yygotominor.yy412->a ) yygotominor.yy412->a[0].sortOrder = yymsp[0].minor.yy58;
 }
-#line 2464 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2508 "parse.c"
         break;
-      case 142:
       case 144:
-#line 508 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = SQLITE_SO_ASC;}
-#line 2470 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 143:
-#line 509 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = SQLITE_SO_DESC;}
-#line 2475 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 146:
+#line 543 "parse.y"
+{yygotominor.yy58 = SQLITE_SO_ASC;}
+#line 2514 "parse.c"
         break;
       case 145:
-#line 511 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258.z = 0; yygotominor.yy258.n = 0;}
-#line 2480 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 151:
-#line 529 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy244.pLimit = 0; yygotominor.yy244.pOffset = 0;}
-#line 2485 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 544 "parse.y"
+{yygotominor.yy58 = SQLITE_SO_DESC;}
+#line 2519 "parse.c"
         break;
-      case 152:
-#line 530 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy244.pLimit = yymsp[0].minor.yy2; yygotominor.yy244.pOffset = 0;}
-#line 2490 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 147:
+#line 546 "parse.y"
+{yygotominor.yy144.z = 0; yygotominor.yy144.n = 0;}
+#line 2524 "parse.c"
         break;
       case 153:
-#line 532 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy244.pLimit = yymsp[-2].minor.yy2; yygotominor.yy244.pOffset = yymsp[0].minor.yy2;}
-#line 2495 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 564 "parse.y"
+{yygotominor.yy112.pLimit = 0; yygotominor.yy112.pOffset = 0;}
+#line 2529 "parse.c"
         break;
       case 154:
-#line 534 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy244.pOffset = yymsp[-2].minor.yy2; yygotominor.yy244.pLimit = yymsp[0].minor.yy2;}
-#line 2500 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 565 "parse.y"
+{yygotominor.yy112.pLimit = yymsp[0].minor.yy44; yygotominor.yy112.pOffset = 0;}
+#line 2534 "parse.c"
         break;
       case 155:
-#line 538 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy67,yymsp[0].minor.yy2);}
-#line 2505 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 567 "parse.y"
+{yygotominor.yy112.pLimit = yymsp[-2].minor.yy44; yygotominor.yy112.pOffset = yymsp[0].minor.yy44;}
+#line 2539 "parse.c"
         break;
-      case 158:
-#line 549 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Update(pParse,yymsp[-3].minor.yy67,yymsp[-1].minor.yy82,yymsp[0].minor.yy2,yymsp[-4].minor.yy412);}
-#line 2510 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 156:
+#line 569 "parse.y"
+{yygotominor.yy112.pOffset = yymsp[-2].minor.yy44; yygotominor.yy112.pLimit = yymsp[0].minor.yy44;}
+#line 2544 "parse.c"
         break;
-      case 159:
-#line 555 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy82 = sqlite3ExprListAppend(yymsp[-4].minor.yy82,yymsp[0].minor.yy2,&yymsp[-2].minor.yy258);}
-#line 2515 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 157:
+#line 573 "parse.y"
+{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy367,yymsp[0].minor.yy44);}
+#line 2549 "parse.c"
         break;
       case 160:
-#line 556 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy82 = sqlite3ExprListAppend(0,yymsp[0].minor.yy2,&yymsp[-2].minor.yy258);}
-#line 2520 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 584 "parse.y"
+{sqlite3Update(pParse,yymsp[-3].minor.yy367,yymsp[-1].minor.yy412,yymsp[0].minor.yy44,yymsp[-4].minor.yy58);}
+#line 2554 "parse.c"
         break;
       case 161:
-#line 562 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Insert(pParse, yymsp[-5].minor.yy67, yymsp[-1].minor.yy82, 0, yymsp[-4].minor.yy240, yymsp[-7].minor.yy412);}
-#line 2525 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 590 "parse.y"
+{yygotominor.yy412 = sqlite3ExprListAppend(yymsp[-4].minor.yy412,yymsp[0].minor.yy44,&yymsp[-2].minor.yy144);}
+#line 2559 "parse.c"
         break;
       case 162:
-#line 564 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Insert(pParse, yymsp[-2].minor.yy67, 0, yymsp[0].minor.yy459, yymsp[-1].minor.yy240, yymsp[-4].minor.yy412);}
-#line 2530 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 591 "parse.y"
+{yygotominor.yy412 = sqlite3ExprListAppend(0,yymsp[0].minor.yy44,&yymsp[-2].minor.yy144);}
+#line 2564 "parse.c"
         break;
-      case 165:
-      case 236:
-#line 574 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy82 = sqlite3ExprListAppend(yymsp[-2].minor.yy82,yymsp[0].minor.yy2,0);}
-#line 2536 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 163:
+#line 597 "parse.y"
+{sqlite3Insert(pParse, yymsp[-5].minor.yy367, yymsp[-1].minor.yy412, 0, yymsp[-4].minor.yy258, yymsp[-7].minor.yy58);}
+#line 2569 "parse.c"
         break;
-      case 166:
-      case 237:
-#line 575 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy82 = sqlite3ExprListAppend(0,yymsp[0].minor.yy2,0);}
-#line 2542 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 164:
+#line 599 "parse.y"
+{sqlite3Insert(pParse, yymsp[-2].minor.yy367, 0, yymsp[0].minor.yy99, yymsp[-1].minor.yy258, yymsp[-4].minor.yy58);}
+#line 2574 "parse.c"
         break;
-      case 169:
-#line 584 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy240 = sqlite3IdListAppend(yymsp[-2].minor.yy240,&yymsp[0].minor.yy258);}
-#line 2547 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 167:
+      case 239:
+#line 609 "parse.y"
+{yygotominor.yy412 = sqlite3ExprListAppend(yymsp[-2].minor.yy412,yymsp[0].minor.yy44,0);}
+#line 2580 "parse.c"
         break;
-      case 170:
-#line 585 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy240 = sqlite3IdListAppend(0,&yymsp[0].minor.yy258);}
-#line 2552 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 168:
+      case 240:
+#line 610 "parse.y"
+{yygotominor.yy412 = sqlite3ExprListAppend(0,yymsp[0].minor.yy44,0);}
+#line 2586 "parse.c"
         break;
-      case 172:
-#line 596 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy2 = yymsp[-1].minor.yy2; sqlite3ExprSpan(yygotominor.yy2,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
-#line 2557 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 171:
+#line 619 "parse.y"
+{yygotominor.yy258 = sqlite3IdListAppend(yymsp[-2].minor.yy258,&yymsp[0].minor.yy144);}
+#line 2591 "parse.c"
         break;
-      case 173:
-      case 178:
-      case 179:
-      case 180:
-      case 181:
-#line 597 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy2 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
-#line 2566 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 172:
+#line 620 "parse.y"
+{yygotominor.yy258 = sqlite3IdListAppend(0,&yymsp[0].minor.yy144);}
+#line 2596 "parse.c"
         break;
       case 174:
+#line 631 "parse.y"
+{yygotominor.yy44 = yymsp[-1].minor.yy44; sqlite3ExprSpan(yygotominor.yy44,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
+#line 2601 "parse.c"
+        break;
       case 175:
-#line 598 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
-#line 2572 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 180:
+      case 181:
+      case 182:
+      case 183:
+#line 632 "parse.y"
+{yygotominor.yy44 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
+#line 2610 "parse.c"
         break;
       case 176:
-#line 600 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 177:
+#line 633 "parse.y"
+{yygotominor.yy44 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
+#line 2616 "parse.c"
+        break;
+      case 178:
+#line 635 "parse.y"
 {
-  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy258);
-  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy258);
-  yygotominor.yy2 = sqlite3Expr(TK_DOT, temp1, temp2, 0);
+  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy144);
+  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy144);
+  yygotominor.yy44 = sqlite3Expr(TK_DOT, temp1, temp2, 0);
 }
-#line 2581 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2625 "parse.c"
         break;
-      case 177:
-#line 605 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 179:
+#line 640 "parse.y"
 {
-  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy258);
-  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy258);
-  Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy258);
+  Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy144);
+  Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy144);
+  Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy144);
   Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
-  yygotominor.yy2 = sqlite3Expr(TK_DOT, temp1, temp4, 0);
+  yygotominor.yy44 = sqlite3Expr(TK_DOT, temp1, temp4, 0);
 }
-#line 2592 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2636 "parse.c"
         break;
-      case 182:
-#line 616 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy2 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
-#line 2597 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 184:
+#line 651 "parse.y"
+{yygotominor.yy44 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
+#line 2641 "parse.c"
         break;
-      case 183:
-#line 617 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 185:
+#line 652 "parse.y"
 {
   Token *pToken = &yymsp[0].minor.yy0;
-  Expr *pExpr = yygotominor.yy2 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
+  Expr *pExpr = yygotominor.yy44 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
   sqlite3ExprAssignVarNumber(pParse, pExpr);
 }
-#line 2606 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2650 "parse.c"
         break;
-      case 184:
-#line 622 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 186:
+#line 658 "parse.y"
 {
-  yygotominor.yy2 = sqlite3ExprFunction(yymsp[-1].minor.yy82, &yymsp[-3].minor.yy0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+  yygotominor.yy44 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy44, 0, &yymsp[-1].minor.yy144);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
 }
-#line 2614 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2658 "parse.c"
         break;
-      case 185:
-#line 626 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 187:
+#line 663 "parse.y"
 {
-  yygotominor.yy2 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+  yygotominor.yy44 = sqlite3ExprFunction(yymsp[-1].minor.yy412, &yymsp[-3].minor.yy0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
 }
-#line 2622 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2666 "parse.c"
         break;
-      case 186:
-#line 630 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 188:
+#line 667 "parse.y"
+{
+  yygotominor.yy44 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+}
+#line 2674 "parse.c"
+        break;
+      case 189:
+#line 671 "parse.y"
 {
   /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
   ** treated as functions that return constants */
-  yygotominor.yy2 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0);
-  if( yygotominor.yy2 ) yygotominor.yy2->op = TK_CONST_FUNC;  
+  yygotominor.yy44 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0);
+  if( yygotominor.yy44 ) yygotominor.yy44->op = TK_CONST_FUNC;  
 }
-#line 2632 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2684 "parse.c"
         break;
-      case 187:
-      case 188:
-      case 189:
       case 190:
       case 191:
       case 192:
@@ -2647,476 +2696,489 @@ static void yy_reduce(
       case 202:
       case 203:
       case 204:
-#line 636 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy2 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy2, yymsp[0].minor.yy2, 0);}
-#line 2654 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 205:
-#line 655 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy438.operator = yymsp[0].minor.yy0; yygotominor.yy438.not = 0;}
-#line 2659 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 206:
-#line 656 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy438.operator = yymsp[0].minor.yy0; yygotominor.yy438.not = 1;}
-#line 2664 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 209:
-#line 660 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{
-  ExprList *pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy2, 0);
-  pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy2, 0);
-  if( yymsp[0].minor.yy2 ){
-    pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy2, 0);
-  }
-  yygotominor.yy2 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy438.operator);
-  if( yymsp[-2].minor.yy438.not ) yygotominor.yy2 = sqlite3Expr(TK_NOT, yygotominor.yy2, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy2, &yymsp[-3].minor.yy2->span, &yymsp[-1].minor.yy2->span);
-}
-#line 2678 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 207:
+#line 677 "parse.y"
+{yygotominor.yy44 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy44, yymsp[0].minor.yy44, 0);}
+#line 2706 "parse.c"
         break;
-      case 210:
-#line 671 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{
-  yygotominor.yy2 = sqlite3Expr(TK_ISNULL, yymsp[-1].minor.yy2, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-1].minor.yy2->span,&yymsp[0].minor.yy0);
-}
-#line 2686 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 208:
+#line 696 "parse.y"
+{yygotominor.yy432.operator = yymsp[0].minor.yy0; yygotominor.yy432.not = 0;}
+#line 2711 "parse.c"
         break;
-      case 211:
-#line 675 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{
-  yygotominor.yy2 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy2, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-2].minor.yy2->span,&yymsp[0].minor.yy0);
-}
-#line 2694 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 209:
+#line 697 "parse.y"
+{yygotominor.yy432.operator = yymsp[0].minor.yy0; yygotominor.yy432.not = 1;}
+#line 2716 "parse.c"
         break;
       case 212:
-#line 679 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 701 "parse.y"
 {
-  yygotominor.yy2 = sqlite3Expr(TK_NOTNULL, yymsp[-1].minor.yy2, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-1].minor.yy2->span,&yymsp[0].minor.yy0);
+  ExprList *pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy44, 0);
+  pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy44, 0);
+  if( yymsp[0].minor.yy44 ){
+    pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy44, 0);
+  }
+  yygotominor.yy44 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy432.operator);
+  if( yymsp[-2].minor.yy432.not ) yygotominor.yy44 = sqlite3Expr(TK_NOT, yygotominor.yy44, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy44, &yymsp[-3].minor.yy44->span, &yymsp[-1].minor.yy44->span);
 }
-#line 2702 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2730 "parse.c"
         break;
       case 213:
-#line 683 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 712 "parse.y"
 {
-  yygotominor.yy2 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy2, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-2].minor.yy2->span,&yymsp[0].minor.yy0);
+  yygotominor.yy44 = sqlite3Expr(TK_ISNULL, yymsp[-1].minor.yy44, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-1].minor.yy44->span,&yymsp[0].minor.yy0);
 }
-#line 2710 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2738 "parse.c"
         break;
       case 214:
-#line 687 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 716 "parse.y"
 {
-  yygotominor.yy2 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy2, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-3].minor.yy2->span,&yymsp[0].minor.yy0);
+  yygotominor.yy44 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy44, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-2].minor.yy44->span,&yymsp[0].minor.yy0);
 }
-#line 2718 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2746 "parse.c"
         break;
       case 215:
+#line 720 "parse.y"
+{
+  yygotominor.yy44 = sqlite3Expr(TK_NOTNULL, yymsp[-1].minor.yy44, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-1].minor.yy44->span,&yymsp[0].minor.yy0);
+}
+#line 2754 "parse.c"
+        break;
       case 216:
-#line 691 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 724 "parse.y"
 {
-  yygotominor.yy2 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy2, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy2->span);
+  yygotominor.yy44 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy44, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-2].minor.yy44->span,&yymsp[0].minor.yy0);
 }
-#line 2727 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2762 "parse.c"
         break;
       case 217:
-#line 699 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 728 "parse.y"
 {
-  yygotominor.yy2 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy2, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy2->span);
+  yygotominor.yy44 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy44, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-3].minor.yy44->span,&yymsp[0].minor.yy0);
 }
-#line 2735 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2770 "parse.c"
         break;
       case 218:
-#line 703 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 219:
+#line 732 "parse.y"
 {
-  yygotominor.yy2 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy2, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy2->span);
+  yygotominor.yy44 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy44, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy44->span);
 }
-#line 2743 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2779 "parse.c"
+        break;
+      case 220:
+#line 740 "parse.y"
+{
+  yygotominor.yy44 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy44, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy44->span);
+}
+#line 2787 "parse.c"
         break;
       case 221:
-#line 710 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 744 "parse.y"
 {
-  ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy2, 0);
-  pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy2, 0);
-  yygotominor.yy2 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy2, 0, 0);
-  if( yygotominor.yy2 ) yygotominor.yy2->pList = pList;
-  if( yymsp[-3].minor.yy412 ) yygotominor.yy2 = sqlite3Expr(TK_NOT, yygotominor.yy2, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy2,&yymsp[-4].minor.yy2->span,&yymsp[0].minor.yy2->span);
+  yygotominor.yy44 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy44, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy44->span);
 }
-#line 2755 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2795 "parse.c"
         break;
       case 224:
-#line 722 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 751 "parse.y"
 {
-    yygotominor.yy2 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy2, 0, 0);
-    if( yygotominor.yy2 ){
-      yygotominor.yy2->pList = yymsp[-1].minor.yy82;
+  ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy44, 0);
+  pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy44, 0);
+  yygotominor.yy44 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy44, 0, 0);
+  if( yygotominor.yy44 ) yygotominor.yy44->pList = pList;
+  if( yymsp[-3].minor.yy58 ) yygotominor.yy44 = sqlite3Expr(TK_NOT, yygotominor.yy44, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy44,&yymsp[-4].minor.yy44->span,&yymsp[0].minor.yy44->span);
+}
+#line 2807 "parse.c"
+        break;
+      case 227:
+#line 763 "parse.y"
+{
+    yygotominor.yy44 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy44, 0, 0);
+    if( yygotominor.yy44 ){
+      yygotominor.yy44->pList = yymsp[-1].minor.yy412;
     }else{
-      sqlite3ExprListDelete(yymsp[-1].minor.yy82);
+      sqlite3ExprListDelete(yymsp[-1].minor.yy412);
     }
-    if( yymsp[-3].minor.yy412 ) yygotominor.yy2 = sqlite3Expr(TK_NOT, yygotominor.yy2, 0, 0);
-    sqlite3ExprSpan(yygotominor.yy2,&yymsp[-4].minor.yy2->span,&yymsp[0].minor.yy0);
+    if( yymsp[-3].minor.yy58 ) yygotominor.yy44 = sqlite3Expr(TK_NOT, yygotominor.yy44, 0, 0);
+    sqlite3ExprSpan(yygotominor.yy44,&yymsp[-4].minor.yy44->span,&yymsp[0].minor.yy0);
   }
-#line 2769 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2821 "parse.c"
         break;
-      case 225:
-#line 732 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 228:
+#line 773 "parse.y"
 {
-    yygotominor.yy2 = sqlite3Expr(TK_SELECT, 0, 0, 0);
-    if( yygotominor.yy2 ) yygotominor.yy2->pSelect = yymsp[-1].minor.yy459;
-    if( !yygotominor.yy2 ) sqlite3SelectDelete(yymsp[-1].minor.yy459);
-    sqlite3ExprSpan(yygotominor.yy2,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+    yygotominor.yy44 = sqlite3Expr(TK_SELECT, 0, 0, 0);
+    if( yygotominor.yy44 ) yygotominor.yy44->pSelect = yymsp[-1].minor.yy99;
+    if( !yygotominor.yy44 ) sqlite3SelectDelete(yymsp[-1].minor.yy99);
+    sqlite3ExprSpan(yygotominor.yy44,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
   }
-#line 2779 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2831 "parse.c"
         break;
-      case 226:
-#line 738 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 229:
+#line 779 "parse.y"
 {
-    yygotominor.yy2 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy2, 0, 0);
-    if( yygotominor.yy2 ) yygotominor.yy2->pSelect = yymsp[-1].minor.yy459;
-    if( !yygotominor.yy2 ) sqlite3SelectDelete(yymsp[-1].minor.yy459);
-    if( yymsp[-3].minor.yy412 ) yygotominor.yy2 = sqlite3Expr(TK_NOT, yygotominor.yy2, 0, 0);
-    sqlite3ExprSpan(yygotominor.yy2,&yymsp[-4].minor.yy2->span,&yymsp[0].minor.yy0);
+    yygotominor.yy44 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy44, 0, 0);
+    if( yygotominor.yy44 ) yygotominor.yy44->pSelect = yymsp[-1].minor.yy99;
+    if( !yygotominor.yy44 ) sqlite3SelectDelete(yymsp[-1].minor.yy99);
+    if( yymsp[-3].minor.yy58 ) yygotominor.yy44 = sqlite3Expr(TK_NOT, yygotominor.yy44, 0, 0);
+    sqlite3ExprSpan(yygotominor.yy44,&yymsp[-4].minor.yy44->span,&yymsp[0].minor.yy0);
   }
-#line 2790 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2842 "parse.c"
         break;
-      case 227:
-#line 745 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 230:
+#line 786 "parse.y"
 {
-    SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy258,&yymsp[0].minor.yy258);
-    yygotominor.yy2 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy2, 0, 0);
-    if( yygotominor.yy2 ) yygotominor.yy2->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0);
-    if( yymsp[-2].minor.yy412 ) yygotominor.yy2 = sqlite3Expr(TK_NOT, yygotominor.yy2, 0, 0);
-    sqlite3ExprSpan(yygotominor.yy2,&yymsp[-3].minor.yy2->span,yymsp[0].minor.yy258.z?&yymsp[0].minor.yy258:&yymsp[-1].minor.yy258);
+    SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy144,&yymsp[0].minor.yy144);
+    yygotominor.yy44 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy44, 0, 0);
+    if( yygotominor.yy44 ) yygotominor.yy44->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0);
+    if( yymsp[-2].minor.yy58 ) yygotominor.yy44 = sqlite3Expr(TK_NOT, yygotominor.yy44, 0, 0);
+    sqlite3ExprSpan(yygotominor.yy44,&yymsp[-3].minor.yy44->span,yymsp[0].minor.yy144.z?&yymsp[0].minor.yy144:&yymsp[-1].minor.yy144);
   }
-#line 2801 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2853 "parse.c"
         break;
-      case 228:
-#line 752 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 231:
+#line 793 "parse.y"
 {
-    Expr *p = yygotominor.yy2 = sqlite3Expr(TK_EXISTS, 0, 0, 0);
+    Expr *p = yygotominor.yy44 = sqlite3Expr(TK_EXISTS, 0, 0, 0);
     if( p ){
-      p->pSelect = yymsp[-1].minor.yy459;
+      p->pSelect = yymsp[-1].minor.yy99;
       sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
     }
-    if( !p ) sqlite3SelectDelete(yymsp[-1].minor.yy459);
+    if( !p ) sqlite3SelectDelete(yymsp[-1].minor.yy99);
   }
-#line 2813 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2865 "parse.c"
         break;
-      case 229:
-#line 763 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 232:
+#line 804 "parse.y"
 {
-  yygotominor.yy2 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy2, yymsp[-1].minor.yy2, 0);
-  if( yygotominor.yy2 ) yygotominor.yy2->pList = yymsp[-2].minor.yy82;
-  sqlite3ExprSpan(yygotominor.yy2, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
+  yygotominor.yy44 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy44, yymsp[-1].minor.yy44, 0);
+  if( yygotominor.yy44 ) yygotominor.yy44->pList = yymsp[-2].minor.yy412;
+  sqlite3ExprSpan(yygotominor.yy44, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
 }
-#line 2822 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2874 "parse.c"
         break;
-      case 230:
-#line 770 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 233:
+#line 811 "parse.y"
 {
-  yygotominor.yy82 = sqlite3ExprListAppend(yymsp[-4].minor.yy82, yymsp[-2].minor.yy2, 0);
-  yygotominor.yy82 = sqlite3ExprListAppend(yygotominor.yy82, yymsp[0].minor.yy2, 0);
+  yygotominor.yy412 = sqlite3ExprListAppend(yymsp[-4].minor.yy412, yymsp[-2].minor.yy44, 0);
+  yygotominor.yy412 = sqlite3ExprListAppend(yygotominor.yy412, yymsp[0].minor.yy44, 0);
 }
-#line 2830 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2882 "parse.c"
         break;
-      case 231:
-#line 774 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 234:
+#line 815 "parse.y"
 {
-  yygotominor.yy82 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy2, 0);
-  yygotominor.yy82 = sqlite3ExprListAppend(yygotominor.yy82, yymsp[0].minor.yy2, 0);
+  yygotominor.yy412 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy44, 0);
+  yygotominor.yy412 = sqlite3ExprListAppend(yygotominor.yy412, yymsp[0].minor.yy44, 0);
 }
-#line 2838 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2890 "parse.c"
         break;
-      case 240:
-#line 799 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 243:
+#line 840 "parse.y"
 {
-  if( yymsp[-9].minor.yy412!=OE_None ) yymsp[-9].minor.yy412 = yymsp[0].minor.yy412;
-  if( yymsp[-9].minor.yy412==OE_Default) yymsp[-9].minor.yy412 = OE_Abort;
-  sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy258, &yymsp[-6].minor.yy258, sqlite3SrcListAppend(0,&yymsp[-4].minor.yy258,0),yymsp[-2].minor.yy82,yymsp[-9].minor.yy412, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0);
+  if( yymsp[-9].minor.yy58!=OE_None ) yymsp[-9].minor.yy58 = yymsp[0].minor.yy58;
+  if( yymsp[-9].minor.yy58==OE_Default) yymsp[-9].minor.yy58 = OE_Abort;
+  sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy144, &yymsp[-6].minor.yy144, sqlite3SrcListAppend(0,&yymsp[-4].minor.yy144,0),yymsp[-2].minor.yy412,yymsp[-9].minor.yy58, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0);
 }
-#line 2847 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2899 "parse.c"
         break;
-      case 241:
-      case 288:
-#line 806 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = OE_Abort;}
-#line 2853 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 242:
-#line 807 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = OE_None;}
-#line 2858 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 244:
+      case 291:
+#line 847 "parse.y"
+{yygotominor.yy58 = OE_Abort;}
+#line 2905 "parse.c"
         break;
       case 245:
-#line 817 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 848 "parse.y"
+{yygotominor.yy58 = OE_None;}
+#line 2910 "parse.c"
+        break;
+      case 248:
+#line 858 "parse.y"
 {
   Expr *p = 0;
-  if( yymsp[-1].minor.yy258.n>0 ){
+  if( yymsp[-1].minor.yy144.n>0 ){
     p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
-    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy258.z, yymsp[-1].minor.yy258.n);
+    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy144.z, yymsp[-1].minor.yy144.n);
   }
-  yygotominor.yy82 = sqlite3ExprListAppend(yymsp[-4].minor.yy82, p, &yymsp[-2].minor.yy258);
+  yygotominor.yy412 = sqlite3ExprListAppend(yymsp[-4].minor.yy412, p, &yymsp[-2].minor.yy144);
 }
-#line 2870 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2922 "parse.c"
         break;
-      case 246:
-#line 825 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 249:
+#line 866 "parse.y"
 {
   Expr *p = 0;
-  if( yymsp[-1].minor.yy258.n>0 ){
+  if( yymsp[-1].minor.yy144.n>0 ){
     p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
-    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy258.z, yymsp[-1].minor.yy258.n);
+    if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy144.z, yymsp[-1].minor.yy144.n);
   }
-  yygotominor.yy82 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy258);
+  yygotominor.yy412 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy144);
 }
-#line 2882 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 248:
-#line 838 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy67);}
-#line 2887 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 249:
-      case 250:
-#line 842 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Vacuum(pParse,0);}
-#line 2893 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2934 "parse.c"
         break;
       case 251:
-      case 253:
-#line 848 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-3].minor.yy258,&yymsp[-2].minor.yy258,&yymsp[0].minor.yy258,0);}
-#line 2899 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 879 "parse.y"
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy367);}
+#line 2939 "parse.c"
         break;
       case 252:
-#line 849 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-3].minor.yy258,&yymsp[-2].minor.yy258,&yymsp[0].minor.yy0,0);}
-#line 2904 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 253:
+#line 883 "parse.y"
+{sqlite3Vacuum(pParse,0);}
+#line 2945 "parse.c"
         break;
       case 254:
-#line 851 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 256:
+#line 889 "parse.y"
+{sqlite3Pragma(pParse,&yymsp[-3].minor.yy144,&yymsp[-2].minor.yy144,&yymsp[0].minor.yy144,0);}
+#line 2951 "parse.c"
+        break;
+      case 255:
+#line 890 "parse.y"
+{sqlite3Pragma(pParse,&yymsp[-3].minor.yy144,&yymsp[-2].minor.yy144,&yymsp[0].minor.yy0,0);}
+#line 2956 "parse.c"
+        break;
+      case 257:
+#line 892 "parse.y"
 {
-  sqlite3Pragma(pParse,&yymsp[-3].minor.yy258,&yymsp[-2].minor.yy258,&yymsp[0].minor.yy258,1);
+  sqlite3Pragma(pParse,&yymsp[-3].minor.yy144,&yymsp[-2].minor.yy144,&yymsp[0].minor.yy144,1);
 }
-#line 2911 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2963 "parse.c"
         break;
-      case 255:
-#line 854 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-4].minor.yy258,&yymsp[-3].minor.yy258,&yymsp[-1].minor.yy258,0);}
-#line 2916 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 258:
+#line 895 "parse.y"
+{sqlite3Pragma(pParse,&yymsp[-4].minor.yy144,&yymsp[-3].minor.yy144,&yymsp[-1].minor.yy144,0);}
+#line 2968 "parse.c"
         break;
-      case 256:
-#line 855 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-1].minor.yy258,&yymsp[0].minor.yy258,0,0);}
-#line 2921 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 259:
+#line 896 "parse.y"
+{sqlite3Pragma(pParse,&yymsp[-1].minor.yy144,&yymsp[0].minor.yy144,0,0);}
+#line 2973 "parse.c"
         break;
-      case 263:
-#line 868 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 266:
+#line 909 "parse.y"
 {
   Token all;
-  all.z = yymsp[-3].minor.yy258.z;
-  all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy258.z) + yymsp[0].minor.yy0.n;
-  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy347, &all);
+  all.z = yymsp[-3].minor.yy144.z;
+  all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy144.z) + yymsp[0].minor.yy0.n;
+  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy203, &all);
 }
-#line 2931 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2983 "parse.c"
         break;
-      case 264:
-#line 877 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 267:
+#line 918 "parse.y"
 {
-  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy258, &yymsp[-6].minor.yy258, yymsp[-5].minor.yy412, yymsp[-4].minor.yy210.a, yymsp[-4].minor.yy210.b, yymsp[-2].minor.yy67, yymsp[-1].minor.yy412, yymsp[0].minor.yy2, yymsp[-9].minor.yy412);
-  yygotominor.yy258 = (yymsp[-6].minor.yy258.n==0?yymsp[-7].minor.yy258:yymsp[-6].minor.yy258);
+  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy144, &yymsp[-6].minor.yy144, yymsp[-5].minor.yy58, yymsp[-4].minor.yy234.a, yymsp[-4].minor.yy234.b, yymsp[-2].minor.yy367, yymsp[-1].minor.yy58, yymsp[0].minor.yy44, yymsp[-9].minor.yy58);
+  yygotominor.yy144 = (yymsp[-6].minor.yy144.n==0?yymsp[-7].minor.yy144:yymsp[-6].minor.yy144);
 }
-#line 2939 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 2991 "parse.c"
         break;
-      case 265:
       case 268:
-#line 883 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = TK_BEFORE; }
-#line 2945 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 266:
-#line 884 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = TK_AFTER;  }
-#line 2950 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 267:
-#line 885 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = TK_INSTEAD;}
-#line 2955 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 271:
+#line 924 "parse.y"
+{ yygotominor.yy58 = TK_BEFORE; }
+#line 2997 "parse.c"
         break;
       case 269:
+#line 925 "parse.y"
+{ yygotominor.yy58 = TK_AFTER;  }
+#line 3002 "parse.c"
+        break;
       case 270:
-      case 271:
-#line 890 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210.a = yymsp[0].major; yygotominor.yy210.b = 0;}
-#line 2962 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 926 "parse.y"
+{ yygotominor.yy58 = TK_INSTEAD;}
+#line 3007 "parse.c"
         break;
       case 272:
-#line 893 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210.a = TK_UPDATE; yygotominor.yy210.b = yymsp[0].minor.yy240;}
-#line 2967 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 273:
       case 274:
-#line 896 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = TK_ROW; }
-#line 2973 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 931 "parse.y"
+{yygotominor.yy234.a = yymsp[0].major; yygotominor.yy234.b = 0;}
+#line 3014 "parse.c"
         break;
       case 275:
-#line 898 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy412 = TK_STATEMENT; }
-#line 2978 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 934 "parse.y"
+{yygotominor.yy234.a = TK_UPDATE; yygotominor.yy234.b = yymsp[0].minor.yy258;}
+#line 3019 "parse.c"
         break;
       case 276:
-#line 901 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy2 = 0; }
-#line 2983 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
       case 277:
-#line 902 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy2 = yymsp[0].minor.yy2; }
-#line 2988 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 937 "parse.y"
+{ yygotominor.yy58 = TK_ROW; }
+#line 3025 "parse.c"
         break;
       case 278:
-#line 906 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{
-  yymsp[-2].minor.yy347->pNext = yymsp[0].minor.yy347;
-  yygotominor.yy347 = yymsp[-2].minor.yy347;
-}
-#line 2996 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 939 "parse.y"
+{ yygotominor.yy58 = TK_STATEMENT; }
+#line 3030 "parse.c"
         break;
       case 279:
-#line 910 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy347 = 0; }
-#line 3001 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 942 "parse.y"
+{ yygotominor.yy44 = 0; }
+#line 3035 "parse.c"
         break;
       case 280:
-#line 916 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy347 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy258, yymsp[-1].minor.yy82, yymsp[0].minor.yy2, yymsp[-4].minor.yy412); }
-#line 3006 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 943 "parse.y"
+{ yygotominor.yy44 = yymsp[0].minor.yy44; }
+#line 3040 "parse.c"
         break;
       case 281:
-#line 921 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy347 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy258, yymsp[-4].minor.yy240, yymsp[-1].minor.yy82, 0, yymsp[-7].minor.yy412);}
-#line 3011 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 947 "parse.y"
+{
+  yymsp[-2].minor.yy203->pNext = yymsp[0].minor.yy203;
+  yygotominor.yy203 = yymsp[-2].minor.yy203;
+}
+#line 3048 "parse.c"
         break;
       case 282:
-#line 924 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy347 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy258, yymsp[-1].minor.yy240, 0, yymsp[0].minor.yy459, yymsp[-4].minor.yy412);}
-#line 3016 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 951 "parse.y"
+{ yygotominor.yy203 = 0; }
+#line 3053 "parse.c"
         break;
       case 283:
-#line 928 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy347 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy258, yymsp[0].minor.yy2);}
-#line 3021 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 957 "parse.y"
+{ yygotominor.yy203 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy144, yymsp[-1].minor.yy412, yymsp[0].minor.yy44, yymsp[-4].minor.yy58); }
+#line 3058 "parse.c"
         break;
       case 284:
-#line 931 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy347 = sqlite3TriggerSelectStep(yymsp[0].minor.yy459); }
-#line 3026 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 962 "parse.y"
+{yygotominor.yy203 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy144, yymsp[-4].minor.yy258, yymsp[-1].minor.yy412, 0, yymsp[-7].minor.yy58);}
+#line 3063 "parse.c"
         break;
       case 285:
-#line 934 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{
-  yygotominor.yy2 = sqlite3Expr(TK_RAISE, 0, 0, 0); 
-  yygotominor.yy2->iColumn = OE_Ignore;
-  sqlite3ExprSpan(yygotominor.yy2, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 3035 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 965 "parse.y"
+{yygotominor.yy203 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy144, yymsp[-1].minor.yy258, 0, yymsp[0].minor.yy99, yymsp[-4].minor.yy58);}
+#line 3068 "parse.c"
         break;
       case 286:
-#line 939 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{
-  yygotominor.yy2 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy258); 
-  yygotominor.yy2->iColumn = yymsp[-3].minor.yy412;
-  sqlite3ExprSpan(yygotominor.yy2, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 3044 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 969 "parse.y"
+{yygotominor.yy203 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy144, yymsp[0].minor.yy44);}
+#line 3073 "parse.c"
         break;
       case 287:
-#line 947 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = OE_Rollback;}
-#line 3049 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 972 "parse.y"
+{yygotominor.yy203 = sqlite3TriggerSelectStep(yymsp[0].minor.yy99); }
+#line 3078 "parse.c"
         break;
-      case 289:
-#line 949 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy412 = OE_Fail;}
-#line 3054 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 290:
-#line 954 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 288:
+#line 975 "parse.y"
 {
-  sqlite3DropTrigger(pParse,yymsp[0].minor.yy67);
+  yygotominor.yy44 = sqlite3Expr(TK_RAISE, 0, 0, 0); 
+  yygotominor.yy44->iColumn = OE_Ignore;
+  sqlite3ExprSpan(yygotominor.yy44, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
 }
-#line 3061 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 3087 "parse.c"
         break;
-      case 291:
-#line 960 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 289:
+#line 980 "parse.y"
 {
-  sqlite3Attach(pParse, &yymsp[-3].minor.yy258, &yymsp[-1].minor.yy258, yymsp[0].minor.yy132.type, &yymsp[0].minor.yy132.key);
+  yygotominor.yy44 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy144); 
+  yygotominor.yy44->iColumn = yymsp[-3].minor.yy58;
+  sqlite3ExprSpan(yygotominor.yy44, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
 }
-#line 3068 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 3096 "parse.c"
+        break;
+      case 290:
+#line 988 "parse.y"
+{yygotominor.yy58 = OE_Rollback;}
+#line 3101 "parse.c"
         break;
       case 292:
-#line 964 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy132.type = 0; }
-#line 3073 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 990 "parse.y"
+{yygotominor.yy58 = OE_Fail;}
+#line 3106 "parse.c"
         break;
       case 293:
-#line 965 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy132.type=1; yygotominor.yy132.key = yymsp[0].minor.yy258; }
-#line 3078 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 995 "parse.y"
+{
+  sqlite3DropTrigger(pParse,yymsp[0].minor.yy367);
+}
+#line 3113 "parse.c"
         break;
       case 294:
-#line 966 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy132.type=2; yygotominor.yy132.key = yymsp[0].minor.yy0; }
-#line 3083 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
-        break;
-      case 297:
-#line 972 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 1001 "parse.y"
 {
-  sqlite3Detach(pParse, &yymsp[0].minor.yy258);
+  sqlite3Attach(pParse, &yymsp[-3].minor.yy144, &yymsp[-1].minor.yy144, yymsp[0].minor.yy300.type, &yymsp[0].minor.yy300.key);
 }
-#line 3090 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 3120 "parse.c"
         break;
-      case 298:
-#line 978 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Reindex(pParse, 0, 0);}
-#line 3095 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 295:
+#line 1005 "parse.y"
+{ yygotominor.yy300.type = 0; }
+#line 3125 "parse.c"
         break;
-      case 299:
-#line 979 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Reindex(pParse, &yymsp[-1].minor.yy258, &yymsp[0].minor.yy258);}
-#line 3100 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+      case 296:
+#line 1006 "parse.y"
+{ yygotominor.yy300.type=1; yygotominor.yy300.key = yymsp[0].minor.yy144; }
+#line 3130 "parse.c"
+        break;
+      case 297:
+#line 1007 "parse.y"
+{ yygotominor.yy300.type=2; yygotominor.yy300.key = yymsp[0].minor.yy0; }
+#line 3135 "parse.c"
         break;
       case 300:
-#line 984 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 1013 "parse.y"
 {
-  sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy67,&yymsp[0].minor.yy258);
+  sqlite3Detach(pParse, &yymsp[0].minor.yy144);
 }
-#line 3107 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 3142 "parse.c"
         break;
       case 301:
-#line 987 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 1019 "parse.y"
+{sqlite3Reindex(pParse, 0, 0);}
+#line 3147 "parse.c"
+        break;
+      case 302:
+#line 1020 "parse.y"
+{sqlite3Reindex(pParse, &yymsp[-1].minor.yy144, &yymsp[0].minor.yy144);}
+#line 3152 "parse.c"
+        break;
+      case 303:
+#line 1025 "parse.y"
+{sqlite3Analyze(pParse, 0, 0);}
+#line 3157 "parse.c"
+        break;
+      case 304:
+#line 1026 "parse.y"
+{sqlite3Analyze(pParse, &yymsp[-1].minor.yy144, &yymsp[0].minor.yy144);}
+#line 3162 "parse.c"
+        break;
+      case 305:
+#line 1031 "parse.y"
 {
-  sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy258);
+  sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy367,&yymsp[0].minor.yy144);
 }
-#line 3114 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 3169 "parse.c"
         break;
-      case 302:
-#line 990 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+      case 306:
+#line 1034 "parse.y"
+{
+  sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy144);
+}
+#line 3176 "parse.c"
+        break;
+      case 307:
+#line 1037 "parse.y"
 {
-  sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy67);
+  sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy367);
 }
-#line 3121 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 3183 "parse.c"
         break;
   };
   yygoto = yyRuleInfo[yyruleno].lhs;
@@ -3173,7 +3235,7 @@ static void yy_syntax_error(
 ){
   sqlite3ParserARG_FETCH;
 #define TOKEN (yyminor.yy0)
-#line 23 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.y"
+#line 34 "parse.y"
 
   if( pParse->zErrMsg==0 ){
     if( TOKEN.z[0] ){
@@ -3182,7 +3244,7 @@ static void yy_syntax_error(
       sqlite3ErrorMsg(pParse, "incomplete SQL statement");
     }
   }
-#line 3188 "/home/rei/php_dev/php5.1/ext/pdo_sqlite/sqlite/src/parse.c"
+#line 3250 "parse.c"
   sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
 }
 
index 9dc0a15f9f18f0c7445ae574cf22b2a04f191f93..c351d4025d18ba2f7a99c6bb222c6693f60dfd6b 100644 (file)
 #define TK_ID                             27
 #define TK_ABORT                          28
 #define TK_AFTER                          29
-#define TK_ASC                            30
-#define TK_ATTACH                         31
-#define TK_BEFORE                         32
-#define TK_CASCADE                        33
-#define TK_CONFLICT                       34
-#define TK_DATABASE                       35
-#define TK_DESC                           36
-#define TK_DETACH                         37
-#define TK_EACH                           38
-#define TK_FAIL                           39
-#define TK_FOR                            40
-#define TK_IGNORE                         41
-#define TK_INITIALLY                      42
-#define TK_INSTEAD                        43
-#define TK_LIKE_KW                        44
-#define TK_MATCH                          45
-#define TK_KEY                            46
-#define TK_OF                             47
-#define TK_OFFSET                         48
-#define TK_PRAGMA                         49
-#define TK_RAISE                          50
-#define TK_REPLACE                        51
-#define TK_RESTRICT                       52
-#define TK_ROW                            53
-#define TK_STATEMENT                      54
-#define TK_TRIGGER                        55
-#define TK_VACUUM                         56
-#define TK_VIEW                           57
-#define TK_REINDEX                        58
-#define TK_RENAME                         59
-#define TK_CTIME_KW                       60
-#define TK_ALTER                          61
-#define TK_OR                             62
-#define TK_AND                            63
-#define TK_NOT                            64
-#define TK_IS                             65
-#define TK_BETWEEN                        66
-#define TK_IN                             67
-#define TK_ISNULL                         68
-#define TK_NOTNULL                        69
-#define TK_NE                             70
-#define TK_EQ                             71
-#define TK_GT                             72
-#define TK_LE                             73
-#define TK_LT                             74
-#define TK_GE                             75
-#define TK_ESCAPE                         76
-#define TK_BITAND                         77
-#define TK_BITOR                          78
-#define TK_LSHIFT                         79
-#define TK_RSHIFT                         80
-#define TK_PLUS                           81
-#define TK_MINUS                          82
-#define TK_STAR                           83
-#define TK_SLASH                          84
-#define TK_REM                            85
-#define TK_CONCAT                         86
-#define TK_UMINUS                         87
-#define TK_UPLUS                          88
-#define TK_BITNOT                         89
-#define TK_STRING                         90
-#define TK_JOIN_KW                        91
-#define TK_CONSTRAINT                     92
-#define TK_DEFAULT                        93
-#define TK_NULL                           94
-#define TK_PRIMARY                        95
-#define TK_UNIQUE                         96
-#define TK_CHECK                          97
-#define TK_REFERENCES                     98
-#define TK_COLLATE                        99
-#define TK_AUTOINCR                       100
-#define TK_ON                             101
-#define TK_DELETE                         102
-#define TK_UPDATE                         103
-#define TK_INSERT                         104
-#define TK_SET                            105
-#define TK_DEFERRABLE                     106
-#define TK_FOREIGN                        107
-#define TK_DROP                           108
-#define TK_UNION                          109
-#define TK_ALL                            110
-#define TK_INTERSECT                      111
-#define TK_EXCEPT                         112
-#define TK_SELECT                         113
-#define TK_DISTINCT                       114
-#define TK_DOT                            115
-#define TK_FROM                           116
-#define TK_JOIN                           117
-#define TK_USING                          118
-#define TK_ORDER                          119
-#define TK_BY                             120
-#define TK_GROUP                          121
-#define TK_HAVING                         122
-#define TK_LIMIT                          123
-#define TK_WHERE                          124
-#define TK_INTO                           125
-#define TK_VALUES                         126
-#define TK_INTEGER                        127
-#define TK_FLOAT                          128
-#define TK_BLOB                           129
-#define TK_REGISTER                       130
-#define TK_VARIABLE                       131
-#define TK_EXISTS                         132
-#define TK_CASE                           133
-#define TK_WHEN                           134
-#define TK_THEN                           135
-#define TK_ELSE                           136
-#define TK_INDEX                          137
-#define TK_TO                             138
-#define TK_ADD                            139
-#define TK_COLUMNKW                       140
+#define TK_ANALYZE                        30
+#define TK_ASC                            31
+#define TK_ATTACH                         32
+#define TK_BEFORE                         33
+#define TK_CASCADE                        34
+#define TK_CAST                           35
+#define TK_CONFLICT                       36
+#define TK_DATABASE                       37
+#define TK_DESC                           38
+#define TK_DETACH                         39
+#define TK_EACH                           40
+#define TK_FAIL                           41
+#define TK_FOR                            42
+#define TK_IGNORE                         43
+#define TK_INITIALLY                      44
+#define TK_INSTEAD                        45
+#define TK_LIKE_KW                        46
+#define TK_MATCH                          47
+#define TK_KEY                            48
+#define TK_OF                             49
+#define TK_OFFSET                         50
+#define TK_PRAGMA                         51
+#define TK_RAISE                          52
+#define TK_REPLACE                        53
+#define TK_RESTRICT                       54
+#define TK_ROW                            55
+#define TK_STATEMENT                      56
+#define TK_TRIGGER                        57
+#define TK_VACUUM                         58
+#define TK_VIEW                           59
+#define TK_REINDEX                        60
+#define TK_RENAME                         61
+#define TK_CTIME_KW                       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
+#define TK_ADD                            141
+#define TK_COLUMNKW                       142
index e5203fdf91f9fad58cfe512e4729f163ff6e7cd1..c7b661652a909abafb67c091773544db8d97d2b0 100644 (file)
 **
 ** @(#) $Id$
 */
+
+// All token codes are small integers with #defines that begin with "TK_"
 %token_prefix TK_
+
+// The type of the data attached to each token is Token.  This is also the
+// default type for non-terminals.
+//
 %token_type {Token}
 %default_type {Token}
+
+// The generated parser function takes a 4th argument as follows:
 %extra_argument {Parse *pParse}
+
+// This code runs whenever there is a syntax error
+//
 %syntax_error {
   if( pParse->zErrMsg==0 ){
     if( TOKEN.z[0] ){
     }
   }
 }
+
+// The name of the generated procedure that implements the parser
+// is as follows:
 %name sqlite3Parser
+
+// The following text is included near the beginning of the C source
+// code file that implements the parser.
+//
 %include {
 #include "sqliteInt.h"
 #include "parse.h"
@@ -126,9 +144,10 @@ create_table_args ::= AS select(S). {
 columnlist ::= columnlist COMMA column.
 columnlist ::= column.
 
-// About the only information used for a column is the name of the
-// column.  The type is always just "text".  But the code will accept
-// an elaborate typename.  Perhaps someday we'll do something with it.
+// A "column" is a complete description of a single column in a
+// CREATE TABLE statement.  This includes the column name, its
+// datatype, and other keywords such as PRIMARY KEY, UNIQUE, REFERENCES,
+// NOT NULL and so forth.
 //
 column(A) ::= columnid(X) type carglist. {
   A.z = X.z;
@@ -151,7 +170,7 @@ id(A) ::= ID(X).         {A = X;}
 // This obviates the need for the "id" nonterminal.
 //
 %fallback ID
-  ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CONFLICT
+  ABORT AFTER ANALYZE ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT
   DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
   IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH KEY
   OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
@@ -198,22 +217,38 @@ nm(A) ::= ID(X).         {A = X;}
 nm(A) ::= STRING(X).     {A = X;}
 nm(A) ::= JOIN_KW(X).    {A = X;}
 
+// A typetoken is really one or more tokens that form a type name such
+// as can be found after the column name in a CREATE TABLE statement.
+// Multiple tokens are concatenated to form the value of the typetoken.
+//
+%type typetoken {Token}
 type ::= .
-type ::= typename(X).                    {sqlite3AddColumnType(pParse,&X,&X);}
-type ::= typename(X) LP signed RP(Y).    {sqlite3AddColumnType(pParse,&X,&Y);}
-type ::= typename(X) LP signed COMMA signed RP(Y).
-                                         {sqlite3AddColumnType(pParse,&X,&Y);}
+type ::= typetoken(X).                   {sqlite3AddColumnType(pParse,&X);}
+typetoken(A) ::= typename(X).   {A = X;}
+typetoken(A) ::= typename(X) LP signed RP(Y). {
+  A.z = X.z;
+  A.n = &Y.z[Y.n] - X.z;
+}
+typetoken(A) ::= typename(X) LP signed COMMA signed RP(Y). {
+  A.z = X.z;
+  A.n = &Y.z[Y.n] - X.z;
+}
 %type typename {Token}
 typename(A) ::= ids(X).             {A = X;}
 typename(A) ::= typename(X) ids(Y). {A.z=X.z; A.n=Y.n+(Y.z-X.z);}
 %type signed {int}
 signed(A) ::= plus_num(X).    { A = atoi(X.z); }
 signed(A) ::= minus_num(X).   { A = -atoi(X.z); }
+
+// "carglist" is a list of additional constraints that come after the
+// column name and column type in a CREATE TABLE statement.
+//
 carglist ::= carglist carg.
 carglist ::= .
 carg ::= CONSTRAINT nm ccons.
 carg ::= ccons.
 carg ::= DEFAULT term(X).            {sqlite3AddDefaultValue(pParse,X);}
+carg ::= DEFAULT LP expr(X) RP.      {sqlite3AddDefaultValue(pParse,X);}
 carg ::= DEFAULT PLUS term(X).       {sqlite3AddDefaultValue(pParse,X);}
 carg ::= DEFAULT MINUS term(X).      {
   Expr *p = sqlite3Expr(TK_UMINUS, X, 0, 0);
@@ -619,6 +654,12 @@ expr(A) ::= VARIABLE(X).     {
   Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
   sqlite3ExprAssignVarNumber(pParse, pExpr);
 }
+%ifndef SQLITE_OMIT_CAST
+expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). {
+  A = sqlite3Expr(TK_CAST, E, 0, &T);
+  sqlite3ExprSpan(A,&X,&Y);
+}
+%endif // SQLITE_OMIT_CAST
 expr(A) ::= ID(X) LP exprlist(Y) RP(E). {
   A = sqlite3ExprFunction(Y, &X);
   sqlite3ExprSpan(A,&X,&E);
@@ -979,6 +1020,12 @@ cmd ::= REINDEX.                {sqlite3Reindex(pParse, 0, 0);}
 cmd ::= REINDEX nm(X) dbnm(Y).  {sqlite3Reindex(pParse, &X, &Y);}
 %endif
 
+/////////////////////////////////// ANALYZE ///////////////////////////////////
+%ifndef SQLITE_OMIT_ANALYZE
+cmd ::= ANALYZE.                {sqlite3Analyze(pParse, 0, 0);}
+cmd ::= ANALYZE nm(X) dbnm(Y).  {sqlite3Analyze(pParse, &X, &Y);}
+%endif
+
 //////////////////////// ALTER TABLE table ... ////////////////////////////////
 %ifndef SQLITE_OMIT_ALTERTABLE
 cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
index 226c1829ae3c1699fd9c6febfa50627ffb008540..839488e862591e8dc1b20585d918937fbcfc56e2 100644 (file)
@@ -583,12 +583,13 @@ void sqlite3Pragma(
         while(pFK){
           int j;
           for(j=0; j<pFK->nCol; j++){
+            char *zCol = pFK->aCol[j].zCol;
             sqlite3VdbeAddOp(v, OP_Integer, i, 0);
             sqlite3VdbeAddOp(v, OP_Integer, j, 0);
             sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->zTo, 0);
             sqlite3VdbeOp3(v, OP_String8, 0, 0,
                              pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
-            sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->aCol[j].zCol, 0);
+            sqlite3VdbeOp3(v, zCol ? OP_String8 : OP_Null, 0, 0, zCol, 0);
             sqlite3VdbeAddOp(v, OP_Callback, 5, 0);
           }
           ++i;
@@ -602,14 +603,25 @@ void sqlite3Pragma(
 #ifndef NDEBUG
   if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
     extern void sqlite3ParserTrace(FILE*, char *);
-    if( getBoolean(zRight) ){
-      sqlite3ParserTrace(stdout, "parser: ");
-    }else{
-      sqlite3ParserTrace(0, 0);
+    if( zRight ){
+      if( getBoolean(zRight) ){
+        sqlite3ParserTrace(stderr, "parser: ");
+      }else{
+        sqlite3ParserTrace(0, 0);
+      }
     }
   }else
 #endif
 
+  /* Reinstall the LIKE and GLOB functions.  The variant of LIKE
+  ** used will be case sensitive or not depending on the RHS.
+  */
+  if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
+    if( zRight ){
+      sqlite3RegisterLikeFunctions(db, getBoolean(zRight));
+    }
+  }else
+
 #ifndef SQLITE_OMIT_INTEGRITY_CHECK
   if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
     int i, j, addr;
index d1fec1b8444966dc84bd99d372a0687d1b4e8245..628afbd991105940456366d108a97290c4e0e7fe 100644 (file)
@@ -294,6 +294,11 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
     rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
     sqlite3SafetyOn(db);
     sqliteFree(zSql);
+#ifndef SQLITE_OMIT_ANALYZE
+    if( rc==SQLITE_OK ){
+      sqlite3AnalysisLoad(db, iDb);
+    }
+#endif
     sqlite3BtreeCloseCursor(curMain);
   }
   if( sqlite3_malloc_failed ){
@@ -370,7 +375,7 @@ int sqlite3ReadSchema(Parse *pParse){
       rc = sqlite3Init(db, &pParse->zErrMsg);
     }
   }
-  assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized)||db->init.busy );
+  assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized) || db->init.busy );
   if( rc!=SQLITE_OK ){
     pParse->rc = rc;
     pParse->nErr++;
@@ -526,4 +531,3 @@ int sqlite3_prepare16(
   return rc;
 }
 #endif /* SQLITE_OMIT_UTF16 */
-
index 6e700771b4ba2e34ef6129d67a1748abc47bde2d..d4cb66499fb57ccd827c446ac579a1d95dab04da 100644 (file)
@@ -111,6 +111,7 @@ static const char aPrefix[] = "-x0\000X0";
 static const et_info fmtinfo[] = {
   {  'd', 10, 1, etRADIX,      0,  0 },
   {  's',  0, 4, etSTRING,     0,  0 },
+  {  'g',  0, 1, etGENERIC,    30, 0 },
   {  'z',  0, 6, etDYNSTRING,  0,  0 },
   {  'q',  0, 4, etSQLESCAPE,  0,  0 },
   {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
@@ -122,7 +123,6 @@ static const et_info fmtinfo[] = {
   {  'f',  0, 1, etFLOAT,      0,  0 },
   {  'e',  0, 1, etEXP,        30, 0 },
   {  'E',  0, 1, etEXP,        14, 0 },
-  {  'g',  0, 1, etGENERIC,    30, 0 },
   {  'G',  0, 1, etGENERIC,    14, 0 },
   {  'i', 10, 1, etRADIX,      0,  0 },
   {  'n',  0, 0, etSIZE,       0,  0 },
@@ -210,9 +210,11 @@ static int vxprintf(
   etByte flag_plussign;      /* True if "+" flag is present */
   etByte flag_blanksign;     /* True if " " flag is present */
   etByte flag_alternateform; /* True if "#" flag is present */
+  etByte flag_altform2;      /* True if "!" flag is present */
   etByte flag_zeropad;       /* True if field width constant starts with zero */
   etByte flag_long;          /* True if "l" flag is present */
   etByte flag_longlong;      /* True if the "ll" flag is present */
+  etByte done;               /* Loop termination flag */
   UINT64_TYPE longvalue;     /* Value for integer types */
   LONGDOUBLE_TYPE realvalue; /* Value for real types */
   const et_info *infop;      /* Pointer to the appropriate info structure */
@@ -225,7 +227,7 @@ static int vxprintf(
    "                                                                         ";
 #define etSPACESIZE (sizeof(spaces)-1)
 #ifndef etNOFLOATINGPOINT
-  int  exp;                  /* exponent of real numbers */
+  int  exp, e2;              /* exponent of real numbers */
   double rounder;            /* Used for rounding floating point values */
   etByte flag_dp;            /* True if decimal point should be shown */
   etByte flag_rtz;           /* True if trailing zeros should be removed */
@@ -254,17 +256,19 @@ static int vxprintf(
     }
     /* Find out what flags are present */
     flag_leftjustify = flag_plussign = flag_blanksign = 
-     flag_alternateform = flag_zeropad = 0;
+     flag_alternateform = flag_altform2 = flag_zeropad = 0;
+    done = 0;
     do{
       switch( c ){
-        case '-':   flag_leftjustify = 1;     c = 0;   break;
-        case '+':   flag_plussign = 1;        c = 0;   break;
-        case ' ':   flag_blanksign = 1;       c = 0;   break;
-        case '#':   flag_alternateform = 1;   c = 0;   break;
-        case '0':   flag_zeropad = 1;         c = 0;   break;
-        default:                                       break;
+        case '-':   flag_leftjustify = 1;     break;
+        case '+':   flag_plussign = 1;        break;
+        case ' ':   flag_blanksign = 1;       break;
+        case '#':   flag_alternateform = 1;   break;
+        case '!':   flag_altform2 = 1;        break;
+        case '0':   flag_zeropad = 1;         break;
+        default:    done = 1;                 break;
       }
-    }while( c==0 && (c=(*++fmt))!=0 );
+    }while( !done && (c=(*++fmt))!=0 );
     /* Get the field width */
     width = 0;
     if( c=='*' ){
@@ -336,6 +340,7 @@ static int vxprintf(
     ** At this point, variables are initialized as follows:
     **
     **   flag_alternateform          TRUE if a '#' is present.
+    **   flag_altform2               TRUE if a '!' is present.
     **   flag_plussign               TRUE if a '+' is present.
     **   flag_leftjustify            TRUE if a '-' is present or if the
     **                               field width was negative.
@@ -414,7 +419,7 @@ static int vxprintf(
         realvalue = va_arg(ap,double);
 #ifndef etNOFLOATINGPOINT
         if( precision<0 ) precision = 6;         /* Set default precision */
-        if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10;
+        if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
         if( realvalue<0.0 ){
           realvalue = -realvalue;
           prefix = '-';
@@ -423,8 +428,7 @@ static int vxprintf(
           else if( flag_blanksign )    prefix = ' ';
           else                         prefix = 0;
         }
-        if( infop->type==etGENERIC && precision>0 ) precision--;
-        rounder = 0.0;
+        if( xtype==etGENERIC && precision>0 ) precision--;
 #if 0
         /* Rounding works like BSD when the constant 0.4999 is used.  Wierd! */
         for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
@@ -432,12 +436,13 @@ static int vxprintf(
         /* It makes more sense to use 0.5 */
         for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1);
 #endif
-        if( infop->type==etFLOAT ) realvalue += rounder;
+        if( xtype==etFLOAT ) realvalue += rounder;
         /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
         exp = 0;
         if( realvalue>0.0 ){
-          while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
-          while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
+          while( realvalue>1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
+          while( realvalue>1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
+          while( realvalue>10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
           while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
           while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
           if( exp>350 || exp<-350 ){
@@ -467,51 +472,67 @@ static int vxprintf(
         }else{
           flag_rtz = 0;
         }
-        /*
-        ** The "exp+precision" test causes output to be of type etEXP if
-        ** the precision is too large to fit in buf[].
-        */
+        if( xtype==etEXP ){
+          e2 = 0;
+        }else{
+          e2 = exp;
+        }
         nsd = 0;
-        if( xtype==etFLOAT && exp+precision<etBUFSIZE-30 ){
-          flag_dp = (precision>0 || flag_alternateform);
-          if( prefix ) *(bufpt++) = prefix;         /* Sign */
-          if( exp<0 )  *(bufpt++) = '0';            /* Digits before "." */
-          else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd);
-          if( flag_dp ) *(bufpt++) = '.';           /* The decimal point */
-          for(exp++; exp<0 && precision>0; precision--, exp++){
-            *(bufpt++) = '0';
+        flag_dp = (precision>0) | flag_alternateform | flag_altform2;
+        /* The sign in front of the number */
+        if( prefix ){
+          *(bufpt++) = prefix;
+        }
+        /* Digits prior to the decimal point */
+        if( e2<0 ){
+          *(bufpt++) = '0';
+        }else{
+          for(; e2>=0; e2--){
+            *(bufpt++) = et_getdigit(&realvalue,&nsd);
           }
-          while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
-          *(bufpt--) = 0;                           /* Null terminate */
-          if( flag_rtz && flag_dp ){     /* Remove trailing zeros and "." */
-            while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
-            if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
+        }
+        /* The decimal point */
+        if( flag_dp ){
+          *(bufpt++) = '.';
+        }
+        /* "0" digits after the decimal point but before the first
+        ** significant digit of the number */
+        for(e2++; e2<0 && precision>0; precision--, e2++){
+          *(bufpt++) = '0';
+        }
+        /* Significant digits after the decimal point */
+        while( (precision--)>0 ){
+          *(bufpt++) = et_getdigit(&realvalue,&nsd);
+        }
+        /* Remove trailing zeros and the "." if no digits follow the "." */
+        if( flag_rtz && flag_dp ){
+          while( bufpt[-1]=='0' ) *(--bufpt) = 0;
+          assert( bufpt>buf );
+          if( bufpt[-1]=='.' ){
+            if( flag_altform2 ){
+              *(bufpt++) = '0';
+            }else{
+              *(--bufpt) = 0;
+            }
           }
-          bufpt++;                            /* point to next free slot */
-        }else{    /* etEXP or etGENERIC */
-          flag_dp = (precision>0 || flag_alternateform);
-          if( prefix ) *(bufpt++) = prefix;   /* Sign */
-          *(bufpt++) = et_getdigit(&realvalue,&nsd);  /* First digit */
-          if( flag_dp ) *(bufpt++) = '.';     /* Decimal point */
-          while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
-          bufpt--;                            /* point to last digit */
-          if( flag_rtz && flag_dp ){          /* Remove tail zeros */
-            while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
-            if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
+        }
+        /* Add the "eNNN" suffix */
+        if( flag_exp || (xtype==etEXP && exp) ){
+          *(bufpt++) = aDigits[infop->charset];
+          if( exp<0 ){
+            *(bufpt++) = '-'; exp = -exp;
+          }else{
+            *(bufpt++) = '+';
           }
-          bufpt++;                            /* point to next free slot */
-          if( exp || flag_exp ){
-            *(bufpt++) = aDigits[infop->charset];
-            if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
-            else       { *(bufpt++) = '+'; }
-            if( exp>=100 ){
-              *(bufpt++) = (exp/100)+'0';                /* 100's digit */
-              exp %= 100;
-            }
-            *(bufpt++) = exp/10+'0';                     /* 10's digit */
-            *(bufpt++) = exp%10+'0';                     /* 1's digit */
+          if( exp>=100 ){
+            *(bufpt++) = (exp/100)+'0';                /* 100's digit */
+            exp %= 100;
           }
+          *(bufpt++) = exp/10+'0';                     /* 10's digit */
+          *(bufpt++) = exp%10+'0';                     /* 1's digit */
         }
+        *bufpt = 0;
+
         /* The converted number is in buf[] and zero terminated. Output it.
         ** Note that the number is in the usual order, not reversed as with
         ** integer conversions. */
@@ -564,36 +585,35 @@ static int vxprintf(
         if( precision>=0 && precision<length ) length = precision;
         break;
       case etSQLESCAPE:
-      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++;
-          }
-          needQuote = !isnull && xtype==etSQLESCAPE2;
-          n += i + 1 + needQuote*2;
-          if( n>etBUFSIZE ){
-            bufpt = zExtra = sqliteMalloc( n );
-            if( bufpt==0 ) return -1;
-          }else{
-            bufpt = buf;
-          }
-          j = 0;
-          if( needQuote ) bufpt[j++] = '\'';
-          for(i=0; (c=arg[i])!=0; i++){
-            bufpt[j++] = c;
-            if( c=='\'' ) bufpt[j++] = c;
-          }
-          if( needQuote ) bufpt[j++] = '\'';
-          bufpt[j] = 0;
-          length = j;
-          if( precision>=0 && precision<length ) length = precision;
+      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++;
+        }
+        needQuote = !isnull && xtype==etSQLESCAPE2;
+        n += i + 1 + needQuote*2;
+        if( n>etBUFSIZE ){
+          bufpt = zExtra = sqliteMalloc( n );
+          if( bufpt==0 ) return -1;
+        }else{
+          bufpt = buf;
         }
+        j = 0;
+        if( needQuote ) bufpt[j++] = '\'';
+        for(i=0; (c=arg[i])!=0; i++){
+          bufpt[j++] = c;
+          if( c=='\'' ) bufpt[j++] = c;
+        }
+        if( needQuote ) bufpt[j++] = '\'';
+        bufpt[j] = 0;
+        length = j;
+        if( precision>=0 && precision<length ) length = precision;
         break;
+      }
       case etTOKEN: {
         Token *pToken = va_arg(ap, Token*);
         if( pToken && pToken->z ){
index 4c2a71723944075096e4bc5b83cd09d8dc040a9b..a4eb3fca4a8369d881360eeb23e6e459f363c552 100644 (file)
@@ -85,7 +85,7 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
   Token *apAll[3];
   Token *p;
   static const struct {
-    const char *zKeyword;
+    const char zKeyword[8];
     u8 nChar;
     u8 code;
   } keywords[] = {
@@ -155,6 +155,15 @@ static void setToken(Token *p, const char *z){
   p->dyn = 0;
 }
 
+/*
+** Create an expression node for an identifier with the name of zName
+*/
+static Expr *createIdExpr(const char *zName){
+  Token dummy;
+  setToken(&dummy, zName);
+  return sqlite3Expr(TK_ID, 0, 0, &dummy);
+}
+
 
 /*
 ** Add a term to the WHERE expression in *ppExpr that requires the
@@ -168,24 +177,20 @@ static void addWhereTerm(
   const char *zAlias2,     /* Alias for second table.  May be NULL */
   Expr **ppExpr            /* Add the equality term to this expression */
 ){
-  Token dummy;
   Expr *pE1a, *pE1b, *pE1c;
   Expr *pE2a, *pE2b, *pE2c;
   Expr *pE;
 
-  setToken(&dummy, zCol);
-  pE1a = sqlite3Expr(TK_ID, 0, 0, &dummy);
-  pE2a = sqlite3Expr(TK_ID, 0, 0, &dummy);
+  pE1a = createIdExpr(zCol);
+  pE2a = createIdExpr(zCol);
   if( zAlias1==0 ){
     zAlias1 = pTab1->zName;
   }
-  setToken(&dummy, zAlias1);
-  pE1b = sqlite3Expr(TK_ID, 0, 0, &dummy);
+  pE1b = createIdExpr(zAlias1);
   if( zAlias2==0 ){
     zAlias2 = pTab2->zName;
   }
-  setToken(&dummy, zAlias2);
-  pE2b = sqlite3Expr(TK_ID, 0, 0, &dummy);
+  pE2b = createIdExpr(zAlias2);
   pE1c = sqlite3Expr(TK_DOT, pE1b, pE1a, 0);
   pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0);
   pE = sqlite3Expr(TK_EQ, pE1c, pE2c, 0);
@@ -321,10 +326,7 @@ void sqlite3SelectDelete(Select *p){
 ** stack into the sorter.
 */
 static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
-  int i;
-  for(i=0; i<pOrderBy->nExpr; i++){
-    sqlite3ExprCode(pParse, pOrderBy->a[i].pExpr);
-  }
+  sqlite3ExprCodeExprList(pParse, pOrderBy);
   sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr, 0);
   sqlite3VdbeAddOp(v, OP_SortInsert, 0, 0);
 }
@@ -402,9 +404,7 @@ static int selectInnerLoop(
     }
   }else{
     nColumn = pEList->nExpr;
-    for(i=0; i<pEList->nExpr; i++){
-      sqlite3ExprCode(pParse, pEList->a[i].pExpr);
-    }
+    sqlite3ExprCodeExprList(pParse, pEList);
   }
 
   /* If the DISTINCT keyword was present on the SELECT statement
@@ -412,14 +412,15 @@ static int selectInnerLoop(
   ** part of the result.
   */
   if( hasDistinct ){
+    int n = pEList->nExpr;
 #if NULL_ALWAYS_DISTINCT
     sqlite3VdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqlite3VdbeCurrentAddr(v)+7);
 #endif
     /* Deliberately leave the affinity string off of the following
     ** OP_MakeRecord */
-    sqlite3VdbeAddOp(v, OP_MakeRecord, pEList->nExpr * -1, 0);
+    sqlite3VdbeAddOp(v, OP_MakeRecord, -n, 0);
     sqlite3VdbeAddOp(v, OP_Distinct, distinct, sqlite3VdbeCurrentAddr(v)+3);
-    sqlite3VdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
+    sqlite3VdbeAddOp(v, OP_Pop, n+1, 0);
     sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);
     VdbeComment((v, "# skip indistinct records"));
     sqlite3VdbeAddOp(v, OP_IdxInsert, distinct, 0);
@@ -511,33 +512,25 @@ static int selectInnerLoop(
     }
 #endif /* #ifndef SQLITE_OMIT_SUBQUERY */
 
-    /* Send the data to the callback function.
+    /* Send the data to the callback function or to a subroutine.  In the
+    ** case of a subroutine, the subroutine itself is responsible for
+    ** popping the data from the stack.
     */
+    case SRT_Subroutine:
     case SRT_Callback:
     case SRT_Sorter: {
       if( pOrderBy ){
         sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
         pushOntoSorter(pParse, v, pOrderBy);
+      }else if( eDest==SRT_Subroutine ){
+        sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);
       }else{
-        assert( eDest==SRT_Callback );
+        assert( eDest!=SRT_Sorter );
         sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);
       }
       break;
     }
 
-    /* Invoke a subroutine to handle the results.  The subroutine itself
-    ** is responsible for popping the results off of the stack.
-    */
-    case SRT_Subroutine: {
-      if( pOrderBy ){
-        sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
-        pushOntoSorter(pParse, v, pOrderBy);
-      }else{
-        sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);
-      }
-      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
@@ -1322,9 +1315,9 @@ static void computeLimitRegisters(Parse *pParse, Select *p){
 ** DISTINCT, UNION, INTERSECT and EXCEPT select statements (but not 
 ** UNION ALL).
 **
-** The value returned is the address of the OP_OpenTemp instruction.
+** The value returned is the address of the OP_OpenVirtual instruction.
 */
-static int openTempIndex(Parse *pParse, Select *p, int iTab){
+static int openVirtualIndex(Parse *pParse, Select *p, int iTab){
   KeyInfo *pKeyInfo;
   int nColumn;
   sqlite3 *db = pParse->db;
@@ -1346,18 +1339,18 @@ static int openTempIndex(Parse *pParse, Select *p, int iTab){
       pKeyInfo->aColl[i] = db->pDfltColl;
     }
   }
-  addr = sqlite3VdbeOp3(v, OP_OpenTemp, iTab, 0, 
+  addr = sqlite3VdbeOp3(v, OP_OpenVirtual, iTab, 0, 
       (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
   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.
+** Add the address "addr" to the set of all OpenVirtual opcode addresses
+** that are being accumulated in p->ppOpenVirtual.
 */
-static int multiSelectOpenTempAddr(Select *p, int addr){
-  IdList *pList = *p->ppOpenTemp = sqlite3IdListAppend(*p->ppOpenTemp, 0);
+static int multiSelectOpenVirtualAddr(Select *p, int addr){
+  IdList *pList = *p->ppOpenVirtual = sqlite3IdListAppend(*p->ppOpenVirtual, 0);
   if( pList==0 ){
     return SQLITE_NOMEM;
   }
@@ -1430,7 +1423,7 @@ static int multiSelect(
   int rc = SQLITE_OK;   /* Success code from a subroutine */
   Select *pPrior;       /* Another SELECT immediately to our left */
   Vdbe *v;              /* Generate code to this VDBE */
-  IdList *pOpenTemp = 0;/* OP_OpenTemp opcodes that need a KeyInfo */
+  IdList *pOpenVirtual = 0;/* OP_OpenVirtual opcodes that need a KeyInfo */
   int aAddr[5];         /* Addresses of SetNumColumns operators */
   int nAddr = 0;        /* Number used */
   int nCol;             /* Number of columns in the result set */
@@ -1465,21 +1458,21 @@ static int multiSelect(
   }
 
   /* If *p this is the right-most select statement, then initialize
-  ** p->ppOpenTemp to point to pOpenTemp.  If *p is not the right most
-  ** statement then p->ppOpenTemp will have already been initialized
-  ** by a prior call to this same procedure.  Pass along the pOpenTemp
+  ** p->ppOpenVirtual to point to pOpenVirtual.  If *p is not the right most
+  ** statement then p->ppOpenVirtual will have already been initialized
+  ** by a prior call to this same procedure.  Pass along the pOpenVirtual
   ** pointer to pPrior, the next statement to our left.
   */
-  if( p->ppOpenTemp==0 ){
-    p->ppOpenTemp = &pOpenTemp;
+  if( p->ppOpenVirtual==0 ){
+    p->ppOpenVirtual = &pOpenVirtual;
   }
-  pPrior->ppOpenTemp = p->ppOpenTemp;
+  pPrior->ppOpenVirtual = p->ppOpenVirtual;
 
   /* Create the destination temporary table if necessary
   */
   if( eDest==SRT_TempTable ){
     assert( p->pEList );
-    sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0);
+    sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 0);
     assert( nAddr==0 );
     aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, 0);
     eDest = SRT_Table;
@@ -1536,9 +1529,9 @@ static int multiSelect(
           rc = 1;
           goto multi_select_end;
         }
-        addr = sqlite3VdbeAddOp(v, OP_OpenTemp, unionTab, 0);
+        addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, unionTab, 0);
         if( p->op!=TK_ALL ){
-          rc = multiSelectOpenTempAddr(p, addr);
+          rc = multiSelectOpenVirtualAddr(p, addr);
           if( rc!=SQLITE_OK ){
             goto multi_select_end;
           }
@@ -1628,8 +1621,8 @@ static int multiSelect(
         goto multi_select_end;
       }
 
-      addr = sqlite3VdbeAddOp(v, OP_OpenTemp, tab1, 0);
-      rc = multiSelectOpenTempAddr(p, addr);
+      addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab1, 0);
+      rc = multiSelectOpenVirtualAddr(p, addr);
       if( rc!=SQLITE_OK ){
         goto multi_select_end;
       }
@@ -1646,8 +1639,8 @@ static int multiSelect(
 
       /* Code the current SELECT into temporary table "tab2"
       */
-      addr = sqlite3VdbeAddOp(v, OP_OpenTemp, tab2, 0);
-      rc = multiSelectOpenTempAddr(p, addr);
+      addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab2, 0);
+      rc = multiSelectOpenVirtualAddr(p, addr);
       if( rc!=SQLITE_OK ){
         goto multi_select_end;
       }
@@ -1725,11 +1718,11 @@ static int multiSelect(
   ** SELECT might also skip this part if it has no ORDER BY clause and
   ** no temp tables are required.
   */
-  if( p->pOrderBy || (pOpenTemp && pOpenTemp->nId>0) ){
+  if( p->pOrderBy || (pOpenVirtual && pOpenVirtual->nId>0) ){
     int i;                        /* Loop counter */
     KeyInfo *pKeyInfo;            /* Collating sequence for the result set */
 
-    assert( p->ppOpenTemp == &pOpenTemp );
+    assert( p->ppOpenVirtual == &pOpenVirtual );
     pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*sizeof(CollSeq*));
     if( !pKeyInfo ){
       rc = SQLITE_NOMEM;
@@ -1746,9 +1739,9 @@ static int multiSelect(
       }
     }
 
-    for(i=0; pOpenTemp && i<pOpenTemp->nId; i++){
+    for(i=0; pOpenVirtual && i<pOpenVirtual->nId; i++){
       int p3type = (i==0?P3_KEYINFO_HANDOFF:P3_KEYINFO);
-      int addr = pOpenTemp->a[i].idx;
+      int addr = pOpenVirtual->a[i].idx;
       sqlite3VdbeChangeP3(v, addr, (char *)pKeyInfo, p3type);
     }
 
@@ -1768,17 +1761,17 @@ static int multiSelect(
       generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm);
     }
 
-    if( !pOpenTemp ){
+    if( !pOpenVirtual ){
       /* This happens for UNION ALL ... ORDER BY */
       sqliteFree(pKeyInfo);
     }
   }
 
 multi_select_end:
-  if( pOpenTemp ){
-    sqlite3IdListDelete(pOpenTemp);
+  if( pOpenVirtual ){
+    sqlite3IdListDelete(pOpenVirtual);
   }
-  p->ppOpenTemp = 0;
+  p->ppOpenVirtual = 0;
   return rc;
 }
 #endif /* SQLITE_OMIT_COMPOUND_SELECT */
@@ -2183,7 +2176,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
   /* If the output is destined for a temporary table, open that table.
   */
   if( eDest==SRT_TempTable ){
-    sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0);
+    sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 0);
     sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, 1);
   }
 
@@ -2653,7 +2646,7 @@ int sqlite3Select(
   /* If the output is destined for a temporary table, open that table.
   */
   if( eDest==SRT_TempTable ){
-    sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0);
+    sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 0);
     sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr);
   }
 
@@ -2737,7 +2730,7 @@ int sqlite3Select(
   */
   if( isDistinct ){
     distinct = pParse->nTab++;
-    openTempIndex(pParse, p, distinct);
+    openVirtualIndex(pParse, p, distinct);
   }else{
     distinct = -1;
   }
@@ -2766,9 +2759,7 @@ int sqlite3Select(
     int lbl1 = 0;
     pParse->fillAgg = 1;
     if( pGroupBy ){
-      for(i=0; i<pGroupBy->nExpr; i++){
-        sqlite3ExprCode(pParse, pGroupBy->a[i].pExpr);
-      }
+      sqlite3ExprCodeExprList(pParse, pGroupBy);
       /* No affinity string is attached to the following OP_MakeRecord 
       ** because we do not need to do any coercion of datatypes. */
       sqlite3VdbeAddOp(v, OP_MakeRecord, pGroupBy->nExpr, 0);
index e6411fc363cbcca83ef3af9c51995fa803fc9586..cd32a9e17228c28ce30965c7533e25e4de64e0aa 100644 (file)
@@ -984,10 +984,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
       p->showHeader = 1;
       memset(p->colWidth,0,ArraySize(p->colWidth));
       p->colWidth[0] = 4;
-      p->colWidth[1] = 12;
+      p->colWidth[1] = 14;
       p->colWidth[2] = 10;
       p->colWidth[3] = 10;
-      p->colWidth[4] = 35;
+      p->colWidth[4] = 33;
     }else if (p->explainPrev.valid) {
       p->explainPrev.valid = 0;
       p->mode = p->explainPrev.mode;
@@ -1093,6 +1093,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
           }
         }
       }
+      *z = 0;
       if( i+1!=nCol ){
         fprintf(stderr,"%s line %d: expected %d columns of data but found %d\n",
            zFile, lineno, nCol, i+1);
index ecd337199ad1c6b8cb7b454737153d09f6cf3637..ceed1f8249bedfed4eeeafd37244b765dd6fa297 100644 (file)
@@ -158,7 +158,7 @@ int sqlite3_exec(
 */
 #define SQLITE_OK           0   /* Successful result */
 #define SQLITE_ERROR        1   /* SQL error or missing database */
-#define SQLITE_INTERNAL     2   /* An internal logic error in SQLite */
+#define SQLITE_INTERNAL     2   /* NOT USED. Internal logic error in SQLite */
 #define SQLITE_PERM         3   /* Access permission denied */
 #define SQLITE_ABORT        4   /* Callback routine requested an abort */
 #define SQLITE_BUSY         5   /* The database file is locked */
@@ -168,13 +168,13 @@ int sqlite3_exec(
 #define SQLITE_INTERRUPT    9   /* Operation terminated by sqlite3_interrupt()*/
 #define SQLITE_IOERR       10   /* Some kind of disk I/O error occurred */
 #define SQLITE_CORRUPT     11   /* The database disk image is malformed */
-#define SQLITE_NOTFOUND    12   /* (Internal Only) Table or record not found */
+#define SQLITE_NOTFOUND    12   /* NOT USED. Table or record not found */
 #define SQLITE_FULL        13   /* Insertion failed because database is full */
 #define SQLITE_CANTOPEN    14   /* Unable to open the database file */
 #define SQLITE_PROTOCOL    15   /* Database lock protocol error */
 #define SQLITE_EMPTY       16   /* Database is empty */
 #define SQLITE_SCHEMA      17   /* The database schema changed */
-#define SQLITE_TOOBIG      18   /* Too much data for one row of a table */
+#define SQLITE_TOOBIG      18   /* NOT USED. Too much data for one row */
 #define SQLITE_CONSTRAINT  19   /* Abort due to contraint violation */
 #define SQLITE_MISMATCH    20   /* Data type mismatch */
 #define SQLITE_MISUSE      21   /* Library used incorrectly */
@@ -452,6 +452,7 @@ int sqlite3_set_authorizer(
 #define SQLITE_DETACH               25   /* Database Name   NULL            */
 #define SQLITE_ALTER_TABLE          26   /* Database Name   Table Name      */
 #define SQLITE_REINDEX              27   /* Index Name      NULL            */
+#define SQLITE_ANALYZE              28   /* Table Name      NULL            */
 
 
 /*
@@ -1002,10 +1003,9 @@ int sqlite3_value_type(sqlite3_value*);
 void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
 
 /*
-** The pUserData parameter to the sqlite3_create_function() and
-** sqlite3_create_aggregate() routines used to register user functions
-** is available to the implementation of the function using this
-** call.
+** The pUserData parameter to the sqlite3_create_function()
+** routine used to register user functions is available to
+** the implementation of the function using this call.
 */
 void *sqlite3_user_data(sqlite3_context*);
 
index f0ffbd2e85ec5fd7b178ad2c2b40ca1d01f7b7f7..a5245015ebd37469515963b59457867b1a3d204f 100644 (file)
@@ -39,7 +39,6 @@
 # define _LARGEFILE_SOURCE 1
 #endif
 
-#include "config.h"
 #include "sqlite3.h"
 #include "hash.h"
 #include "parse.h"
@@ -209,6 +208,7 @@ typedef struct BusyHandler BusyHandler;
 struct BusyHandler {
   int (*xFunc)(void *,int);  /* The busy callback */
   void *pArg;                /* First arg to busy callback */
+  int nBusy;                 /* Incremented with each busy call */
 };
 
 /*
@@ -298,30 +298,30 @@ extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */
 /*
 ** Forward references to structures
 */
+typedef struct AggExpr AggExpr;
+typedef struct AuthContext AuthContext;
+typedef struct CollSeq CollSeq;
 typedef struct Column Column;
-typedef struct Table Table;
-typedef struct Index Index;
+typedef struct Db Db;
 typedef struct Expr Expr;
 typedef struct ExprList ExprList;
-typedef struct Parse Parse;
-typedef struct Token Token;
-typedef struct IdList IdList;
-typedef struct SrcList SrcList;
-typedef struct WhereInfo WhereInfo;
-typedef struct WhereLevel WhereLevel;
-typedef struct Select Select;
-typedef struct AggExpr AggExpr;
-typedef struct FuncDef FuncDef;
-typedef struct Trigger Trigger;
-typedef struct TriggerStep TriggerStep;
-typedef struct TriggerStack TriggerStack;
 typedef struct FKey FKey;
-typedef struct Db Db;
-typedef struct AuthContext AuthContext;
+typedef struct FuncDef FuncDef;
+typedef struct IdList IdList;
+typedef struct Index Index;
 typedef struct KeyClass KeyClass;
-typedef struct CollSeq CollSeq;
 typedef struct KeyInfo KeyInfo;
 typedef struct NameContext NameContext;
+typedef struct Parse Parse;
+typedef struct Select Select;
+typedef struct SrcList SrcList;
+typedef struct Table Table;
+typedef struct Token Token;
+typedef struct TriggerStack TriggerStack;
+typedef struct TriggerStep TriggerStep;
+typedef struct Trigger Trigger;
+typedef struct WhereInfo WhereInfo;
+typedef struct WhereLevel WhereLevel;
 
 /*
 ** Each database file to be accessed by the system is an instance
@@ -496,17 +496,23 @@ struct sqlite3 {
 ** points to a linked list of these structures.
 */
 struct FuncDef {
-  char *zName;         /* SQL name of the function */
-  int nArg;            /* Number of arguments.  -1 means unlimited */
+  i16 nArg;            /* Number of arguments.  -1 means unlimited */
   u8 iPrefEnc;         /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */
+  u8 needCollSeq;      /* True if sqlite3GetFuncCollSeq() might be called */
+  u8 flags;            /* Some combination of SQLITE_FUNC_* */
   void *pUserData;     /* User data parameter */
   FuncDef *pNext;      /* Next function with same name */
   void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */
   void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */
   void (*xFinalize)(sqlite3_context*);                /* Aggregate finializer */
-  u8 needCollSeq;      /* True if sqlite3GetFuncCollSeq() might be called */
+  char zName[1];       /* SQL name of the function.  MUST BE LAST */
 };
 
+/*
+** Possible values for FuncDef.flags
+*/
+#define SQLITE_FUNC_LIKEOPT  0x01    /* Candidate for the LIKE optimization */
+
 /*
 ** information about each column of an SQL table is held in an instance
 ** of this structure.
@@ -745,6 +751,7 @@ struct Index {
   char *zName;     /* Name of this index */
   int nColumn;     /* Number of columns in the table used by this index */
   int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
+  unsigned *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
   Table *pTable;   /* The SQL table being indexed */
   int tnum;        /* Page containing root of this index in database file */
   u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
@@ -839,12 +846,13 @@ 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 */
+#define EP_FromJoin     0x01  /* Originated in ON or USING clause of a join */
+#define EP_Agg          0x02  /* Contains one or more aggregate functions */
+#define EP_Resolved     0x04  /* IDs have been resolved to COLUMNs */
+#define EP_Error        0x08  /* Expression contains one or more errors */
+#define EP_Not          0x10  /* Operator preceeded by NOT */
+#define EP_VarSelect    0x20  /* pSelect is correlated, not constant */
+#define EP_Dequoted     0x40  /* True if the string has been dequoted */
 
 /*
 ** These macros can be used to test, set, or clear bits in the 
@@ -924,8 +932,8 @@ struct SrcList {
     char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
     Table *pTab;      /* An SQL table corresponding to zName */
     Select *pSelect;  /* A SELECT statement used in place of a table name */
-    int jointype;     /* Type of join between this table and the next */
-    int iCursor;      /* The VDBE cursor number used to access this table */
+    u8 jointype;      /* Type of join between this table and the next */
+    i16 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 */
@@ -949,18 +957,20 @@ struct SrcList {
 ** access or modified by other modules.
 */
 struct WhereLevel {
-  int iMem;            /* Memory cell used by this level */
-  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 */
-  int iLeftJoin;       /* Memory cell used to implement LEFT OUTER JOIN */
-  int top;             /* First instruction of interior of the loop */
-  int inOp, inP1, inP2;/* Opcode used to implement an IN operator */
-  int bRev;            /* Do the scan in the reverse direction */
+  int iFrom;            /* Which entry in the FROM clause */
+  int flags;            /* Flags associated with this level */
+  int iMem;             /* First memory cell used by this level */
+  int iLeftJoin;        /* Memory cell used to implement LEFT OUTER JOIN */
+  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 brk;              /* Jump here to break out of the loop */
+  int cont;             /* Jump here to continue with the next loop cycle */
+  int top;              /* First instruction of interior of the loop */
+  int op, p1, p2;       /* Opcode used to terminate the loop */
+  int nEq;              /* Number of == or IN constraints on this loop */
+  int nIn;              /* Number of IN operators constraining this loop */
+  int *aInLoop;         /* Loop terminators for IN operators */
 };
 
 /*
@@ -1036,7 +1046,7 @@ struct Select {
   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 */
-  IdList **ppOpenTemp;   /* OP_OpenTemp addresses used by multi-selects */
+  IdList **ppOpenVirtual;/* OP_OpenVirtual addresses used by multi-selects */
   u8 isResolved;         /* True once sqlite3SelectResolve() has run. */
   u8 isAgg;              /* True if this is an aggregate query */
 };
@@ -1345,6 +1355,7 @@ void *sqlite3TextToPtr(const char*);
 void sqlite3SetString(char **, ...);
 void sqlite3ErrorMsg(Parse*, const char*, ...);
 void sqlite3Dequote(char*);
+void sqlite3DequoteExpr(Expr*);
 int sqlite3KeywordCode(const char*, int);
 int sqlite3RunParser(Parse*, const char*, char **);
 void sqlite3FinishCoding(Parse*);
@@ -1370,7 +1381,7 @@ void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int);
 void sqlite3AddColumn(Parse*,Token*);
 void sqlite3AddNotNull(Parse*, int);
 void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int);
-void sqlite3AddColumnType(Parse*,Token*,Token*);
+void sqlite3AddColumnType(Parse*,Token*);
 void sqlite3AddDefaultValue(Parse*,Expr*);
 void sqlite3AddCollateType(Parse*, const char*, int);
 void sqlite3EndTable(Parse*,Token*,Token*,Select*);
@@ -1437,6 +1448,7 @@ void sqlite3BeginTransaction(Parse*, int);
 void sqlite3CommitTransaction(Parse*);
 void sqlite3RollbackTransaction(Parse*);
 int sqlite3ExprIsConstant(Expr*);
+int sqlite3ExprIsConstantOrFunction(Expr*);
 int sqlite3ExprIsInteger(Expr*, int*);
 int sqlite3IsRowid(const char*);
 void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int);
@@ -1509,7 +1521,7 @@ int sqlite3FixSelect(DbFixer*, Select*);
 int sqlite3FixExpr(DbFixer*, Expr*);
 int sqlite3FixExprList(DbFixer*, ExprList*);
 int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
-double sqlite3AtoF(const char *z, const char **);
+int sqlite3AtoF(const char *z, double*);
 char *sqlite3_snprintf(int,char*,const char*,...);
 int sqlite3GetInt32(const char *, int*);
 int sqlite3FitsIn64Bits(const char *);
@@ -1564,6 +1576,14 @@ void sqlite3AlterFinishAddColumn(Parse *, Token *);
 void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
 const char *sqlite3TestErrorName(int);
 CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char *, int);
+char sqlite3AffinityType(const Token*);
+void sqlite3Analyze(Parse*, Token*, Token*);
+int sqlite3InvokeBusyHandler(BusyHandler*);
+int sqlite3FindDb(sqlite3*, Token*);
+void sqlite3AnalysisLoad(sqlite3*,int iDB);
+void sqlite3DefaultRowEst(Index*);
+void sqlite3RegisterLikeFunctions(sqlite3*, int);
+int sqlite3IsLikeFunction(sqlite3*,Expr*,char*);
 
 #ifdef SQLITE_SSE
 #include "sseInt.h"
index a443a7746711b9fb4e6dff512e3b8cee499d6afa..d3a116877f2b99ae852b0bc259cee548be0128f2 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <ctype.h>
 
 #define NUM_PREPARED_STMTS 10
 #define MAX_PREPARED_STMTS 100
@@ -42,7 +43,9 @@
 typedef struct SqlFunc SqlFunc;
 struct SqlFunc {
   Tcl_Interp *interp;   /* The TCL interpret to execute the function */
-  char *zScript;        /* The script to be run */
+  Tcl_Obj *pScript;     /* The Tcl_Obj representation of the script */
+  int useEvalObjv;      /* True if it is safe to use Tcl_EvalObjv */
+  char *zName;          /* Name of this function */
   SqlFunc *pNext;       /* Next function on the list of them all */
 };
 
@@ -54,7 +57,7 @@ typedef struct SqlCollate SqlCollate;
 struct SqlCollate {
   Tcl_Interp *interp;   /* The TCL interpret to execute the function */
   char *zScript;        /* The script to be run */
-  SqlCollate *pNext;       /* Next function on the list of them all */
+  SqlCollate *pNext;    /* Next function on the list of them all */
 };
 
 /*
@@ -76,24 +79,76 @@ struct SqlPreparedStmt {
 */
 typedef struct SqliteDb SqliteDb;
 struct SqliteDb {
-  sqlite3 *db;          /* The "real" database structure */
-  Tcl_Interp *interp;   /* The interpreter used for this database */
-  char *zBusy;          /* The busy callback routine */
-  char *zCommit;        /* The commit hook callback routine */
-  char *zTrace;         /* The trace callback routine */
-  char *zProgress;      /* The progress callback routine */
-  char *zAuth;          /* The authorization callback routine */
-  char *zNull;          /* Text to substitute for an SQL NULL value */
-  SqlFunc *pFunc;       /* List of SQL functions */
-  SqlCollate *pCollate; /* List of SQL collation functions */
-  int rc;               /* Return code of most recent sqlite3_exec() */
-  Tcl_Obj *pCollateNeeded;  /* Collation needed script */
+  sqlite3 *db;               /* The "real" database structure */
+  Tcl_Interp *interp;        /* The interpreter used for this database */
+  char *zBusy;               /* The busy callback routine */
+  char *zCommit;             /* The commit hook callback routine */
+  char *zTrace;              /* The trace callback routine */
+  char *zProgress;           /* The progress callback routine */
+  char *zAuth;               /* The authorization callback routine */
+  char *zNull;               /* Text to substitute for an SQL NULL value */
+  SqlFunc *pFunc;            /* List of SQL functions */
+  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 */
 };
 
+/*
+** Look at the script prefix in pCmd.  We will be executing this script
+** after first appending one or more arguments.  This routine analyzes
+** the script to see if it is safe to use Tcl_EvalObjv() on the script
+** rather than the more general Tcl_EvalEx().  Tcl_EvalObjv() is much
+** faster.
+**
+** Scripts that are safe to use with Tcl_EvalObjv() consists of a
+** command name followed by zero or more arguments with no [...] or $
+** or {...} or ; to be seen anywhere.  Most callback scripts consist
+** of just a single procedure name and they meet this requirement.
+*/
+static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){
+  /* We could try to do something with Tcl_Parse().  But we will instead
+  ** just do a search for forbidden characters.  If any of the forbidden
+  ** characters appear in pCmd, we will report the string as unsafe.
+  */
+  const char *z;
+  int n;
+  z = Tcl_GetStringFromObj(pCmd, &n);
+  while( n-- > 0 ){
+    int c = *(z++);
+    if( c=='$' || c=='[' || c==';' ) return 0;
+  }
+  return 1;
+}
+
+/*
+** Find an SqlFunc structure with the given name.  Or create a new
+** one if an existing one cannot be found.  Return a pointer to the
+** structure.
+*/
+static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
+  SqlFunc *p, *pNew;
+  int i;
+  pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + strlen(zName) + 1 );
+  pNew->zName = (char*)&pNew[1];
+  for(i=0; zName[i]; i++){ pNew->zName[i] = tolower(zName[i]); }
+  pNew->zName[i] = 0;
+  for(p=pDb->pFunc; p; p=p->pNext){ 
+    if( strcmp(p->zName, pNew->zName)==0 ){
+      Tcl_Free((char*)pNew);
+      return p;
+    }
+  }
+  pNew->interp = pDb->interp;
+  pNew->pScript = 0;
+  pNew->pNext = pDb->pFunc;
+  pDb->pFunc = pNew;
+  return pNew;
+}
+
 /*
 ** Finalize and free a list of prepared statements
 */
@@ -121,6 +176,7 @@ static void DbDeleteCmd(void *db){
   while( pDb->pFunc ){
     SqlFunc *pFunc = pDb->pFunc;
     pDb->pFunc = pFunc->pNext;
+    Tcl_DecrRefCount(pFunc->pScript);
     Tcl_Free((char*)pFunc);
   }
   while( pDb->pCollate ){
@@ -151,16 +207,9 @@ static int DbBusyHandler(void *cd, int nTries){
   SqliteDb *pDb = (SqliteDb*)cd;
   int rc;
   char zVal[30];
-  char *zCmd;
-  Tcl_DString cmd;
 
-  Tcl_DStringInit(&cmd);
-  Tcl_DStringAppend(&cmd, pDb->zBusy, -1);
   sprintf(zVal, "%d", nTries);
-  Tcl_DStringAppendElement(&cmd, zVal);
-  zCmd = Tcl_DStringValue(&cmd);
-  rc = Tcl_Eval(pDb->interp, zCmd);
-  Tcl_DStringFree(&cmd);
+  rc = Tcl_VarEval(pDb->interp, pDb->zBusy, " ", zVal, (char*)0);
   if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
     return 0;
   }
@@ -247,7 +296,7 @@ static int tclSqlCollate(
   Tcl_IncrRefCount(pCmd);
   Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA));
   Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB));
-  Tcl_EvalObjEx(p->interp, pCmd, 0);
+  Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
   Tcl_DecrRefCount(pCmd);
   return (atoi(Tcl_GetStringResult(p->interp)));
 }
@@ -258,22 +307,88 @@ static int tclSqlCollate(
 */
 static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
   SqlFunc *p = sqlite3_user_data(context);
-  Tcl_DString cmd;
+  Tcl_Obj *pCmd;
   int i;
   int rc;
 
-  Tcl_DStringInit(&cmd);
-  Tcl_DStringAppend(&cmd, p->zScript, -1);
-  for(i=0; i<argc; i++){
-    if( SQLITE_NULL==sqlite3_value_type(argv[i]) ){
-      Tcl_DStringAppendElement(&cmd, "");
-    }else{
-      Tcl_DStringAppendElement(&cmd, sqlite3_value_text(argv[i]));
+  if( argc==0 ){
+    /* If there are no arguments to the function, call Tcl_EvalObjEx on the
+    ** script object directly.  This allows the TCL compiler to generate
+    ** bytecode for the command on the first invocation and thus make
+    ** subsequent invocations much faster. */
+    pCmd = p->pScript;
+    Tcl_IncrRefCount(pCmd);
+    rc = Tcl_EvalObjEx(p->interp, pCmd, 0);
+    Tcl_DecrRefCount(pCmd);
+  }else{
+    /* If there are arguments to the function, make a shallow copy of the
+    ** script object, lappend the arguments, then evaluate the copy.
+    **
+    ** By "shallow" copy, we mean a only the outer list Tcl_Obj is duplicated.
+    ** The new Tcl_Obj contains pointers to the original list elements. 
+    ** That way, when Tcl_EvalObjv() is run and shimmers the first element
+    ** of the list to tclCmdNameType, that alternate representation will
+    ** be preserved and reused on the next invocation.
+    */
+    Tcl_Obj **aArg;
+    int nArg;
+    if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){
+      sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); 
+      return;
+    }     
+    pCmd = Tcl_NewListObj(nArg, aArg);
+    Tcl_IncrRefCount(pCmd);
+    for(i=0; i<argc; i++){
+      sqlite3_value *pIn = argv[i];
+      Tcl_Obj *pVal;
+            
+      /* Set pVal to contain the i'th column of this row. */
+      switch( sqlite3_value_type(pIn) ){
+        case SQLITE_BLOB: {
+          int bytes = sqlite3_value_bytes(pIn);
+          pVal = Tcl_NewByteArrayObj(sqlite3_value_blob(pIn), bytes);
+          break;
+        }
+        case SQLITE_INTEGER: {
+          sqlite_int64 v = sqlite3_value_int64(pIn);
+          if( v>=-2147483647 && v<=2147483647 ){
+            pVal = Tcl_NewIntObj(v);
+          }else{
+            pVal = Tcl_NewWideIntObj(v);
+          }
+          break;
+        }
+        case SQLITE_FLOAT: {
+          double r = sqlite3_value_double(pIn);
+          pVal = Tcl_NewDoubleObj(r);
+          break;
+        }
+        case SQLITE_NULL: {
+          pVal = Tcl_NewStringObj("", 0);
+          break;
+        }
+        default: {
+          int bytes = sqlite3_value_bytes(pIn);
+          pVal = Tcl_NewStringObj(sqlite3_value_text(pIn), bytes);
+          break;
+        }
+      }
+      rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal);
+      if( rc ){
+        Tcl_DecrRefCount(pCmd);
+        sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); 
+        return;
+      }
+    }
+    if( !p->useEvalObjv ){
+      /* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd
+      ** is a list without a string representation.  To prevent this from
+      ** happening, make sure pCmd has a valid string representation */
+      Tcl_GetString(pCmd);
     }
+    rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
+    Tcl_DecrRefCount(pCmd);
   }
-  rc = Tcl_EvalEx(p->interp, Tcl_DStringValue(&cmd), Tcl_DStringLength(&cmd),
-                  TCL_EVAL_DIRECT);
-  Tcl_DStringFree(&cmd);
 
   if( rc && rc!=TCL_RETURN ){
     sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); 
@@ -283,7 +398,9 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
     u8 *data;
     char *zType = pVar->typePtr ? pVar->typePtr->name : "";
     char c = zType[0];
-    if( c=='b' && strcmp(zType,"bytearray")==0 ){
+    if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
+      /* Only return a BLOB type if the Tcl variable is a bytearray and
+      ** has no string representation. */
       data = Tcl_GetByteArrayFromObj(pVar, &n);
       sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);
     }else if( (c=='b' && strcmp(zType,"boolean")==0) ||
@@ -294,6 +411,10 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
       double r;
       Tcl_GetDoubleFromObj(0, pVar, &r);
       sqlite3_result_double(context, r);
+    }else if( c=='w' && strcmp(zType,"wideInt")==0 ){
+      Tcl_WideInt v;
+      Tcl_GetWideIntFromObj(0, pVar, &v);
+      sqlite3_result_int64(context, v);
     }else{
       data = Tcl_GetStringFromObj(pVar, &n);
       sqlite3_result_text(context, data, n, SQLITE_TRANSIENT);
@@ -351,6 +472,7 @@ static int auth_callback(
     case SQLITE_DETACH            : zCode="SQLITE_DETACH"; break;
     case SQLITE_ALTER_TABLE       : zCode="SQLITE_ALTER_TABLE"; break;
     case SQLITE_REINDEX           : zCode="SQLITE_REINDEX"; break;
+    case SQLITE_ANALYZE           : zCode="SQLITE_ANALYZE"; break;
     default                       : zCode="????"; break;
   }
   Tcl_DStringInit(&str);
@@ -469,8 +591,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     "function",           "last_insert_rowid", "nullvalue",
     "onecolumn",          "progress",          "rekey",
     "timeout",            "total_changes",     "trace",
-    "version",
-    0                    
+    "transaction",        "version",           0
   };
   enum DB_enum {
     DB_AUTHORIZER,        DB_BUSY,             DB_CACHE,
@@ -480,7 +601,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     DB_FUNCTION,          DB_LAST_INSERT_ROWID,DB_NULLVALUE,
     DB_ONECOLUMN,         DB_PROGRESS,         DB_REKEY,
     DB_TIMEOUT,           DB_TOTAL_CHANGES,    DB_TRACE,
-    DB_VERSION
+    DB_TRANSACTION,       DB_VERSION,          
   };
   /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
 
@@ -924,7 +1045,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
             u8 *data;
             char *zType = pVar->typePtr ? pVar->typePtr->name : "";
             char c = zType[0];
-            if( c=='b' && strcmp(zType,"bytearray")==0 ){
+            if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
+              /* Only load a BLOB type if the Tcl variable is a bytearray and
+              ** has no string representation. */
               data = Tcl_GetByteArrayFromObj(pVar, &n);
               sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC);
               Tcl_IncrRefCount(pVar);
@@ -937,6 +1060,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
               double r;
               Tcl_GetDoubleFromObj(interp, pVar, &r);
               sqlite3_bind_double(pStmt, i, r);
+            }else if( c=='w' && strcmp(zType,"wideInt")==0 ){
+              Tcl_WideInt v;
+              Tcl_GetWideIntFromObj(interp, pVar, &v);
+              sqlite3_bind_int64(pStmt, i, v);
             }else{
               data = Tcl_GetStringFromObj(pVar, &n);
               sqlite3_bind_text(pStmt, i, data, n, SQLITE_STATIC);
@@ -1146,22 +1273,22 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
   */
   case DB_FUNCTION: {
     SqlFunc *pFunc;
+    Tcl_Obj *pScript;
     char *zName;
-    char *zScript;
-    int nScript;
     if( objc!=4 ){
       Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
       return TCL_ERROR;
     }
     zName = Tcl_GetStringFromObj(objv[2], 0);
-    zScript = Tcl_GetStringFromObj(objv[3], &nScript);
-    pFunc = (SqlFunc*)Tcl_Alloc( sizeof(*pFunc) + nScript + 1 );
+    pScript = objv[3];
+    pFunc = findSqlFunc(pDb, zName);
     if( pFunc==0 ) return TCL_ERROR;
-    pFunc->interp = interp;
-    pFunc->pNext = pDb->pFunc;
-    pFunc->zScript = (char*)&pFunc[1];
-    pDb->pFunc = pFunc;
-    strcpy(pFunc->zScript, zScript);
+    if( pFunc->pScript ){
+      Tcl_DecrRefCount(pFunc->pScript);
+    }
+    pFunc->pScript = pScript;
+    Tcl_IncrRefCount(pScript);
+    pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
     rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8,
         pFunc, tclSqlFunc, 0, 0);
     if( rc!=SQLITE_OK ){
@@ -1362,6 +1489,63 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     break;
   }
 
+  /*    $db transaction [-deferred|-immediate|-exclusive] SCRIPT
+  **
+  ** Start a new transaction (if we are not already in the midst of a
+  ** transaction) and execute the TCL script SCRIPT.  After SCRIPT
+  ** completes, either commit the transaction or roll it back if SCRIPT
+  ** throws an exception.  Or if no new transation was started, do nothing.
+  ** pass the exception on up the stack.
+  **
+  ** This command was inspired by Dave Thomas's talk on Ruby at the
+  ** 2005 O'Reilly Open Source Convention (OSCON).
+  */
+  case DB_TRANSACTION: {
+    int inTrans;
+    Tcl_Obj *pScript;
+    const char *zBegin = "BEGIN";
+    if( objc!=3 && objc!=4 ){
+      Tcl_WrongNumArgs(interp, 2, objv, "[TYPE] SCRIPT");
+      return TCL_ERROR;
+    }
+    if( objc==3 ){
+      pScript = objv[2];
+    } else {
+      static const char *TTYPE_strs[] = {
+        "deferred",   "exclusive",  "immediate", 0
+      };
+      enum TTYPE_enum {
+        TTYPE_DEFERRED, TTYPE_EXCLUSIVE, TTYPE_IMMEDIATE
+      };
+      int ttype;
+      if( Tcl_GetIndexFromObj(interp, objv[2], TTYPE_strs, "transaction type",
+                              0, &ttype) ){
+        return TCL_ERROR;
+      }
+      switch( (enum TTYPE_enum)ttype ){
+        case TTYPE_DEFERRED:    /* no-op */;                 break;
+        case TTYPE_EXCLUSIVE:   zBegin = "BEGIN EXCLUSIVE";  break;
+        case TTYPE_IMMEDIATE:   zBegin = "BEGIN IMMEDIATE";  break;
+      }
+      pScript = objv[3];
+    }
+    inTrans = !sqlite3_get_autocommit(pDb->db);
+    if( !inTrans ){
+      sqlite3_exec(pDb->db, zBegin, 0, 0, 0);
+    }
+    rc = Tcl_EvalObjEx(interp, pScript, 0);
+    if( !inTrans ){
+      const char *zEnd;
+      if( rc==TCL_ERROR ){
+        zEnd = "ROLLBACK";
+      } else {
+        zEnd = "COMMIT";
+      }
+      sqlite3_exec(pDb->db, zEnd, 0, 0, 0);
+    }
+    break;
+  }
+
   /*    $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
   **
   ** Copy data into table from filename, optionally using SEPARATOR
index de1df80e1d5d3e50cd13044662d91d73832f5e85..8cb4bf2bcae953bece4a494519469d6a5953d763 100644 (file)
@@ -26,7 +26,6 @@ const char *sqlite3TestErrorName(int rc){
   switch( rc ){
     case SQLITE_OK:         zName = "SQLITE_OK";          break;
     case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
-    case SQLITE_INTERNAL:   zName = "SQLITE_INTERNAL";    break;
     case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
     case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
     case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
@@ -36,13 +35,11 @@ const char *sqlite3TestErrorName(int rc){
     case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
     case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
     case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
-    case SQLITE_NOTFOUND:   zName = "SQLITE_NOTFOUND";    break;
     case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
     case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
     case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
     case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
     case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break;
-    case SQLITE_TOOBIG:     zName = "SQLITE_TOOBIG";      break;
     case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break;
     case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break;
     case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break;
@@ -2759,12 +2756,24 @@ static void set_options(Tcl_Interp *interp){
   Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
 #endif
 
+#ifdef SQLITE_CASE_SENSITIVE_LIKE
+  Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","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_ANALYZE
+  Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY);
+#endif
+
 #ifdef SQLITE_OMIT_AUTHORIZATION
   Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
 #else
@@ -2788,12 +2797,24 @@ static void set_options(Tcl_Interp *interp){
   Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
 #endif
 
+#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
+  Tcl_SetVar2(interp, "sqlite_options", "between_opt", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "between_opt", "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_CAST
+  Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY);
+#endif
+
 #ifdef SQLITE_OMIT_COMPLETE
   Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY);
 #else
@@ -2854,12 +2875,24 @@ static void set_options(Tcl_Interp *interp){
   Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
 #endif
 
+#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
+  Tcl_SetVar2(interp, "sqlite_options", "like_opt", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "like_opt", "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_OR_OPTIMIZATION
+  Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY);
+#endif
+
 #ifdef SQLITE_OMIT_PAGER_PRAGMAS
   Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
 #else
@@ -3073,8 +3106,17 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
   static int bitmask_size = sizeof(Bitmask)*8;
   int i;
   extern int sqlite3_os_trace;
+  extern int sqlite3_where_trace;
   extern int sqlite3_sync_count, sqlite3_fullsync_count;
   extern int sqlite3_opentemp_count;
+  extern int sqlite3_memUsed;
+  extern int sqlite3_memMax;
+  extern char sqlite3_query_plan[];
+  extern int sqlite3_like_count;
+#ifdef SQLITE_DEBUG
+  extern int sqlite3_vdbe_addop_trace;
+#endif
+  static char *query_plan = sqlite3_query_plan;
 
   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
     Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
@@ -3087,6 +3129,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
       (char*)&sqlite3_search_count, TCL_LINK_INT);
   Tcl_LinkVar(interp, "sqlite_sort_count", 
       (char*)&sqlite3_sort_count, TCL_LINK_INT);
+  Tcl_LinkVar(interp, "sqlite_like_count", 
+      (char*)&sqlite3_like_count, TCL_LINK_INT);
   Tcl_LinkVar(interp, "sqlite_interrupt_count", 
       (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
   Tcl_LinkVar(interp, "sqlite_open_file_count", 
@@ -3095,6 +3139,20 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
       (char*)&sqlite3_current_time, TCL_LINK_INT);
   Tcl_LinkVar(interp, "sqlite_os_trace",
       (char*)&sqlite3_os_trace, TCL_LINK_INT);
+  Tcl_LinkVar(interp, "sqlite_where_trace",
+      (char*)&sqlite3_where_trace, TCL_LINK_INT);
+#ifdef SQLITE_DEBUG
+  Tcl_LinkVar(interp, "sqlite_addop_trace",
+      (char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT);
+#endif
+#ifdef SQLITE_MEMDEBUG
+  Tcl_LinkVar(interp, "sqlite_memused",
+      (char*)&sqlite3_memUsed, TCL_LINK_INT | TCL_LINK_READ_ONLY);
+  Tcl_LinkVar(interp, "sqlite_memmax",
+      (char*)&sqlite3_memMax, TCL_LINK_INT | TCL_LINK_READ_ONLY);
+#endif
+  Tcl_LinkVar(interp, "sqlite_query_plan",
+      (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
 #ifndef SQLITE_OMIT_DISKIO
   Tcl_LinkVar(interp, "sqlite_opentemp_count",
       (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
index f06685606c932648e38d71f0ac29638a1f9830df..768811ffe5ca537e2e1033feee52b1b4dca08f82 100644 (file)
@@ -30,7 +30,6 @@ static char *errorName(int rc){
   switch( rc ){
     case SQLITE_OK:         zName = "SQLITE_OK";          break;
     case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
-    case SQLITE_INTERNAL:   zName = "SQLITE_INTERNAL";    break;
     case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
     case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
     case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
@@ -39,13 +38,11 @@ static char *errorName(int rc){
     case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
     case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
     case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
-    case SQLITE_NOTFOUND:   zName = "SQLITE_NOTFOUND";    break;
     case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
     case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
     case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
     case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
     case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break;
-    case SQLITE_TOOBIG:     zName = "SQLITE_TOOBIG";      break;
     case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break;
     case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break;
     case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break;
index a3edd8740c4c38ef782ccc033e865b2589f8e504..6b973a14783b81e16d7ca31be249a52fe5f5827b 100644 (file)
@@ -30,7 +30,6 @@ static char *errorName(int rc){
   switch( rc ){
     case SQLITE_OK:         zName = "SQLITE_OK";          break;
     case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
-    case SQLITE_INTERNAL:   zName = "SQLITE_INTERNAL";    break;
     case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
     case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
     case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
@@ -39,7 +38,6 @@ static char *errorName(int rc){
     case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
     case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
     case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
-    case SQLITE_NOTFOUND:   zName = "SQLITE_NOTFOUND";    break;
     case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
     case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
     case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
index 47a407a4b517b5961970e49045c26f8fcf63b147..45991ba3a3fc922451790291ff4e974b4d50c2eb 100644 (file)
@@ -375,7 +375,6 @@ static int tcl_thread_result(
   switch( threadset[i].rc ){
     case SQLITE_OK:         zName = "SQLITE_OK";          break;
     case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
-    case SQLITE_INTERNAL:   zName = "SQLITE_INTERNAL";    break;
     case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
     case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
     case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
@@ -385,13 +384,11 @@ static int tcl_thread_result(
     case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
     case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
     case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
-    case SQLITE_NOTFOUND:   zName = "SQLITE_NOTFOUND";    break;
     case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
     case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
     case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
     case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
     case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break;
-    case SQLITE_TOOBIG:     zName = "SQLITE_TOOBIG";      break;
     case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break;
     case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break;
     case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break;
index 578a60bda7b6d13e3c2474d80fce8927ba16ee1c..7346f5b54ca52d394062cbcc28529279e87b4657 100644 (file)
@@ -38,9 +38,9 @@
 
 /*
 ** If X is a character that can be used in an identifier and
-** X&0x80==0 then isIdChar[X] will be 1.  If X&0x80==0x80 then
+** X&0x80==0 then sqlite3IsIdChar[X] will be 1.  If X&0x80==0x80 then
 ** X is always an identifier character.  (Hence all UTF-8
-** characters can be part of an identifier).  isIdChar[X] will
+** characters can be part of an identifier).  sqlite3IsIdChar[X] will
 ** be 0 for every character in the lower 128 ASCII characters
 ** that cannot be used as part of an identifier.
 **
@@ -55,7 +55,7 @@
 ** SQLite will allow '$' in identifiers for compatibility.
 ** But the feature is undocumented.
 */
-static const char isIdChar[] = {
+const char sqlite3IsIdChar[] = {
 /* 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 */
@@ -65,7 +65,7 @@ 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>0x1f && isIdChar[c-0x20]))
+#define IdChar(C)  (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20]))
 
 /*
 ** Return the length of the token that begins at z[0]. 
@@ -183,12 +183,9 @@ static int getToken(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 '"': {
+    case '`':
+    case '\'':
+    case '"': {
       int delim = z[0];
       for(i=1; (c=z[i])!=0; i++){
         if( c==delim ){
@@ -204,16 +201,23 @@ static int getToken(const unsigned char *z, int *tokenType){
       return i;
     }
     case '.': {
-      *tokenType = TK_DOT;
-      return 1;
+#ifndef SQLITE_OMIT_FLOATING_POINT
+      if( !isdigit(z[1]) )
+#endif
+      {
+        *tokenType = TK_DOT;
+        return 1;
+      }
+      /* If the next character is a digit, this is a floating point
+      ** number that begins with ".".  Fall thru into the next case */
     }
     case '0': case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9': {
       *tokenType = TK_INTEGER;
-      for(i=1; isdigit(z[i]); i++){}
+      for(i=0; isdigit(z[i]); i++){}
 #ifndef SQLITE_OMIT_FLOATING_POINT
-      if( z[i]=='.' && isdigit(z[i+1]) ){
-        i += 2;
+      if( z[i]=='.' ){
+        i++;
         while( isdigit(z[i]) ){ i++; }
         *tokenType = TK_FLOAT;
       }
@@ -239,50 +243,47 @@ static int getToken(const unsigned char *z, int *tokenType){
       for(i=1; isdigit(z[i]); i++){}
       return i;
     }
-    case ':': {
-      for(i=1; IdChar(z[i]); i++){}
-      *tokenType = i>1 ? TK_VARIABLE : TK_ILLEGAL;
-      return i;
+    case '#': {
+      for(i=1; isdigit(z[i]); i++){}
+      if( i>1 ){
+        /* Parameters of the form #NNN (where NNN is a number) are used
+        ** internally by sqlite3NestedParse.  */
+        *tokenType = TK_REGISTER;
+        return i;
+      }
+      /* Fall through into the next case if the '#' is not followed by
+      ** a digit. Try to match #AAAA where AAAA is a parameter name. */
     }
 #ifndef SQLITE_OMIT_TCL_VARIABLE
-    case '$': {
+    case '$':
+#endif
+    case ':': {
+      int n = 0;
       *tokenType = TK_VARIABLE;
-      if( z[1]=='{' ){
-        int nBrace = 1;
-        for(i=2; (c=z[i])!=0 && nBrace; i++){
-          if( c=='{' ){
-            nBrace++;
-          }else if( c=='}' ){
-            nBrace--;
-          }
-        }
-        if( c==0 ) *tokenType = TK_ILLEGAL;
-      }else{
-        int n = 0;
-        for(i=1; (c=z[i])!=0; i++){
-          if( isalnum(c) || c=='_' ){
-            n++;
-          }else if( c=='(' && n>0 ){
-            do{
-              i++;
-            }while( (c=z[i])!=0 && !isspace(c) && c!=')' );
-            if( c==')' ){
-              i++;
-            }else{
-              *tokenType = TK_ILLEGAL;
-            }
-            break;
-          }else if( c==':' && z[i+1]==':' ){
+      for(i=1; (c=z[i])!=0; i++){
+        if( IdChar(c) ){
+          n++;
+#ifndef SQLITE_OMIT_TCL_VARIABLE
+        }else if( c=='(' && n>0 ){
+          do{
+            i++;
+          }while( (c=z[i])!=0 && !isspace(c) && c!=')' );
+          if( c==')' ){
             i++;
           }else{
-            break;
+            *tokenType = TK_ILLEGAL;
           }
+          break;
+        }else if( c==':' && z[i+1]==':' ){
+          i++;
+#endif
+        }else{
+          break;
         }
-        if( n==0 ) *tokenType = TK_ILLEGAL;
       }
+      if( n==0 ) *tokenType = TK_ILLEGAL;
       return i;
     }
-#endif
 #ifndef SQLITE_OMIT_BLOB_LITERAL
     case 'x': case 'X': {
       if( (c=z[1])=='\'' || c=='"' ){
@@ -430,241 +431,3 @@ abort_parse:
   }
   return nErr;
 }
-
-/* The sqlite3_complete() API may be omitted (to save code space) by
-** defining the following symbol.
-*/
-#ifndef SQLITE_OMIT_COMPLETE
-
-/*
-** Token types used by the sqlite3_complete() routine.  See the header
-** comments on that procedure for additional information.
-*/
-#define tkSEMI    0
-#define tkWS      1
-#define tkOTHER   2
-#define tkEXPLAIN 3
-#define tkCREATE  4
-#define tkTEMP    5
-#define tkTRIGGER 6
-#define tkEND     7
-
-/*
-** Return TRUE if the given SQL string ends in a semicolon.
-**
-** Special handling is require for CREATE TRIGGER statements.
-** Whenever the CREATE TRIGGER keywords are seen, the statement
-** must end with ";END;".
-**
-** This implementation uses a state machine with 7 states:
-**
-**   (0) START     At the beginning or end of an SQL statement.  This routine
-**                 returns 1 if it ends in the START state and 0 if it ends
-**                 in any other state.
-**
-**   (1) NORMAL    We are in the middle of statement which ends with a single
-**                 semicolon.
-**
-**   (2) EXPLAIN   The keyword EXPLAIN has been seen at the beginning of 
-**                 a statement.
-**
-**   (3) CREATE    The keyword CREATE has been seen at the beginning of a
-**                 statement, possibly preceeded by EXPLAIN and/or followed by
-**                 TEMP or TEMPORARY
-**
-**   (4) TRIGGER   We are in the middle of a trigger definition that must be
-**                 ended by a semicolon, the keyword END, and another semicolon.
-**
-**   (5) SEMI      We've seen the first semicolon in the ";END;" that occurs at
-**                 the end of a trigger definition.
-**
-**   (6) END       We've seen the ";END" of the ";END;" that occurs at the end
-**                 of a trigger difinition.
-**
-** Transitions between states above are determined by tokens extracted
-** from the input.  The following tokens are significant:
-**
-**   (0) tkSEMI      A semicolon.
-**   (1) tkWS        Whitespace
-**   (2) tkOTHER     Any other SQL token.
-**   (3) tkEXPLAIN   The "explain" keyword.
-**   (4) tkCREATE    The "create" keyword.
-**   (5) tkTEMP      The "temp" or "temporary" keyword.
-**   (6) tkTRIGGER   The "trigger" keyword.
-**   (7) tkEND       The "end" keyword.
-**
-** Whitespace never causes a state transition and is always ignored.
-**
-** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
-** to recognize the end of a trigger can be omitted.  All we have to do
-** is look for a semicolon that is not part of an string or comment.
-*/
-int sqlite3_complete(const char *zSql){
-  u8 state = 0;   /* Current state, using numbers defined in header comment */
-  u8 token;       /* Value of the next token */
-
-#ifndef SQLITE_OMIT_TRIGGER
-  /* A complex statement machine used to detect the end of a CREATE TRIGGER
-  ** statement.  This is the normal case.
-  */
-  static const u8 trans[7][8] = {
-                     /* Token:                                                */
-     /* State:       **  SEMI  WS  OTHER EXPLAIN  CREATE  TEMP  TRIGGER  END  */
-     /* 0   START: */ {    0,  0,     1,      2,      3,    1,       1,   1,  },
-     /* 1  NORMAL: */ {    0,  1,     1,      1,      1,    1,       1,   1,  },
-     /* 2 EXPLAIN: */ {    0,  2,     1,      1,      3,    1,       1,   1,  },
-     /* 3  CREATE: */ {    0,  3,     1,      1,      1,    3,       4,   1,  },
-     /* 4 TRIGGER: */ {    5,  4,     4,      4,      4,    4,       4,   4,  },
-     /* 5    SEMI: */ {    5,  5,     4,      4,      4,    4,       4,   6,  },
-     /* 6     END: */ {    0,  6,     4,      4,      4,    4,       4,   4,  },
-  };
-#else
-  /* If triggers are not suppored by this compile then the statement machine
-  ** used to detect the end of a statement is much simplier
-  */
-  static const u8 trans[2][3] = {
-                     /* Token:           */
-     /* State:       **  SEMI  WS  OTHER */
-     /* 0   START: */ {    0,  0,     1, },
-     /* 1  NORMAL: */ {    0,  1,     1, },
-  };
-#endif /* SQLITE_OMIT_TRIGGER */
-
-  while( *zSql ){
-    switch( *zSql ){
-      case ';': {  /* A semicolon */
-        token = tkSEMI;
-        break;
-      }
-      case ' ':
-      case '\r':
-      case '\t':
-      case '\n':
-      case '\f': {  /* White space is ignored */
-        token = tkWS;
-        break;
-      }
-      case '/': {   /* C-style comments */
-        if( zSql[1]!='*' ){
-          token = tkOTHER;
-          break;
-        }
-        zSql += 2;
-        while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
-        if( zSql[0]==0 ) return 0;
-        zSql++;
-        token = tkWS;
-        break;
-      }
-      case '-': {   /* SQL-style comments from "--" to end of line */
-        if( zSql[1]!='-' ){
-          token = tkOTHER;
-          break;
-        }
-        while( *zSql && *zSql!='\n' ){ zSql++; }
-        if( *zSql==0 ) return state==0;
-        token = tkWS;
-        break;
-      }
-      case '[': {   /* Microsoft-style identifiers in [...] */
-        zSql++;
-        while( *zSql && *zSql!=']' ){ zSql++; }
-        if( *zSql==0 ) return 0;
-        token = tkOTHER;
-        break;
-      }
-      case '"':     /* single- and double-quoted strings */
-      case '\'': {
-        int c = *zSql;
-        zSql++;
-        while( *zSql && *zSql!=c ){ zSql++; }
-        if( *zSql==0 ) return 0;
-        token = tkOTHER;
-        break;
-      }
-      default: {
-        int c;
-        if( IdChar((u8)*zSql) ){
-          /* Keywords and unquoted identifiers */
-          int nId;
-          for(nId=1; IdChar(zSql[nId]); nId++){}
-#ifdef SQLITE_OMIT_TRIGGER
-          token = tkOTHER;
-#else
-          switch( *zSql ){
-            case 'c': case 'C': {
-              if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
-                token = tkCREATE;
-              }else{
-                token = tkOTHER;
-              }
-              break;
-            }
-            case 't': case 'T': {
-              if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){
-                token = tkTRIGGER;
-              }else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){
-                token = tkTEMP;
-              }else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){
-                token = tkTEMP;
-              }else{
-                token = tkOTHER;
-              }
-              break;
-            }
-            case 'e':  case 'E': {
-              if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
-                token = tkEND;
-              }else
-#ifndef SQLITE_OMIT_EXPLAIN
-              if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
-                token = tkEXPLAIN;
-              }else
-#endif
-              {
-                token = tkOTHER;
-              }
-              break;
-            }
-            default: {
-              token = tkOTHER;
-              break;
-            }
-          }
-#endif /* SQLITE_OMIT_TRIGGER */
-          zSql += nId-1;
-        }else{
-          /* Operators and special symbols */
-          token = tkOTHER;
-        }
-        break;
-      }
-    }
-    state = trans[state][token];
-    zSql++;
-  }
-  return state==0;
-}
-
-#ifndef SQLITE_OMIT_UTF16
-/*
-** This routine is the same as the sqlite3_complete() routine described
-** above, except that the parameter is required to be UTF-16 encoded, not
-** UTF-8.
-*/
-int sqlite3_complete16(const void *zSql){
-  sqlite3_value *pVal;
-  char const *zSql8;
-  int rc = 0;
-
-  pVal = sqlite3ValueNew();
-  sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
-  zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
-  if( zSql8 ){
-    rc = sqlite3_complete(zSql8);
-  }
-  sqlite3ValueFree(pVal);
-  return rc;
-}
-#endif /* SQLITE_OMIT_UTF16 */
-#endif /* SQLITE_OMIT_COMPLETE */
index 9d96bec182f3c4dab43d561546ebe4af1f24e5ed..b1f28ad8cf69885d33dd818a05384e902236dc11 100644 (file)
@@ -47,7 +47,11 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
     u8 enc = sqlite3VdbeDb(v)->enc;
     Column *pCol = &pTab->aCol[i];
     sqlite3ValueFromExpr(pCol->pDflt, enc, pCol->affinity, &pValue);
-    sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
+    if( pValue ){
+      sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
+    }else{
+      VdbeComment((v, "# %s.%s", pTab->zName, pCol->zName));
+    }
   }
 }
 
@@ -273,7 +277,7 @@ void sqlite3Update(
   /* Remember the index of every item to be updated.
   */
   sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
-  sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
+  sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
 
   /* End the database scan loop.
   */
@@ -295,8 +299,7 @@ void sqlite3Update(
 
     /* The top of the update loop for when there are triggers.
     */
-    sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
-    addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0);
+    addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
 
     if( !isView ){
       sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
@@ -389,8 +392,7 @@ void sqlite3Update(
     ** So make the cursor point at the old record.
     */
     if( !triggers_exist ){
-      sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
-      addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0);
+      addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
       sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
     }
     sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);
@@ -468,7 +470,6 @@ void sqlite3Update(
   */
   sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
   sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
-  sqlite3VdbeAddOp(v, OP_ListReset, 0, 0);
 
   /* Close all tables if there were no FOR EACH ROW triggers */
   if( !triggers_exist ){
index 90edb98a09975dc1cca8184c2b5f79ac7bb5044d..a35a43fce3d7f51908112adc396c956685a7dda2 100644 (file)
@@ -58,6 +58,8 @@ int sqlite3_malloc_failed = 0;
 */
 int sqlite3_nMalloc;         /* Number of sqliteMalloc() calls */
 int sqlite3_nFree;           /* Number of sqliteFree() calls */
+int sqlite3_memUsed;         /* Total memory obtained from malloc */
+int sqlite3_memMax;          /* Mem usage high-water mark */
 int sqlite3_iMallocFail;     /* Fail sqliteMalloc() after this many calls */
 int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */
 #if SQLITE_MEMDEBUG>1
@@ -72,13 +74,10 @@ static int memcnt = 0;
 #define N_GUARD 2
 
 /*
-** Allocate new memory and set it to zero.  Return NULL if
-** no memory is available.
+** Check for a simulated memory allocation failure.  Return true if
+** the failure should be simulated.  Return false to proceed as normal.
 */
-void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
-  void *p;
-  int *pi;
-  int i, k;
+static int simulatedMallocFailure(int n, char *zFile, int line){
   if( sqlite3_iMallocFail>=0 ){
     sqlite3_iMallocFail--;
     if( sqlite3_iMallocFail==0 ){
@@ -88,10 +87,28 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
               n, zFile,line);
 #endif
       sqlite3_iMallocFail = sqlite3_iMallocReset;
-      return 0;
+      return 1;
     }
   }
-  if( n==0 ) return 0;
+  return 0;
+}
+
+/*
+** Allocate new memory and set it to zero.  Return NULL if
+** no memory is available.
+*/
+void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
+  void *p;
+  int *pi;
+  int i, k;
+  if( n==0 ){
+    return 0;
+  }
+  if( simulatedMallocFailure(n, zFile, line) ){
+    return 0;
+  }
+  sqlite3_memUsed += n;
+  if( sqlite3_memMax<sqlite3_memUsed ) sqlite3_memMax = sqlite3_memUsed;
   k = (n+sizeof(int)-1)/sizeof(int);
   pi = malloc( (N_GUARD*2+1+k)*sizeof(int));
   if( pi==0 ){
@@ -157,6 +174,7 @@ void sqlite3Free_(void *p, char *zFile, int line){
       }
     }
     n = pi[N_GUARD];
+    sqlite3_memUsed -= n;
     k = (n+sizeof(int)-1)/sizeof(int);
     for(i=0; i<N_GUARD; i++){
       if( pi[k+N_GUARD+1+i]!=0xdead3344 ){
@@ -188,6 +206,9 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
     sqlite3Free_(oldP,zFile,line);
     return 0;
   }
+  if( simulatedMallocFailure(n, zFile, line) ){
+    return 0;
+  }
   oldPi = oldP;
   oldPi -= N_GUARD+1;
   if( oldPi[0]!=0xdead1122 ){
@@ -195,6 +216,7 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
     return 0;
   }
   oldN = oldPi[N_GUARD];
+  sqlite3_memUsed -= oldN;
   oldK = (oldN+sizeof(int)-1)/sizeof(int);
   for(i=0; i<N_GUARD; i++){
     if( oldPi[oldK+N_GUARD+1+i]!=0xdead3344 ){
@@ -211,6 +233,8 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
   }
   for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122;
   pi[N_GUARD] = n;
+  sqlite3_memUsed += n;
+  if( sqlite3_memMax<sqlite3_memUsed ) sqlite3_memMax = sqlite3_memUsed;
   for(i=0; i<N_GUARD; i++) pi[k+N_GUARD+1+i] = 0xdead3344;
   p = &pi[N_GUARD+1];
   memcpy(p, oldP, n>oldN ? oldN : n);
@@ -268,6 +292,7 @@ void sqlite3FreeX(void *p){
 */
 void *sqlite3Malloc(int n){
   void *p;
+  if( n==0 ) return 0;
   if( (p = malloc(n))==0 ){
     if( n>0 ) sqlite3_malloc_failed++;
   }else{
@@ -282,6 +307,7 @@ void *sqlite3Malloc(int n){
 */
 void *sqlite3MallocRaw(int n){
   void *p;
+  if( n==0 ) return 0;
   if( (p = malloc(n))==0 ){
     if( n>0 ) sqlite3_malloc_failed++;
   }
@@ -372,8 +398,8 @@ void sqlite3SetString(char **pz, ...){
     zResult += strlen(zResult);
   }
   va_end(ap);
-#ifdef SQLITE_DEBUG
-#if SQLITE_DEBUG>1
+#ifdef SQLITE_MEMDEBUG
+#if SQLITE_MEMDEBUG>1
   fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz);
 #endif
 #endif
@@ -460,7 +486,8 @@ void sqlite3Dequote(char *z){
   switch( quote ){
     case '\'':  break;
     case '"':   break;
-    case '[':   quote = ']';  break;
+    case '`':   break;                /* For MySQL compatibility */
+    case '[':   quote = ']';  break;  /* For MS SqlServer compatibility */
     default:    return;
   }
   for(i=1, j=0; z[i]; i++){
@@ -565,8 +592,9 @@ int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
 ** of "." depending on how locale is set.  But that would cause problems
 ** for SQL.  So this routine always uses "." regardless of locale.
 */
-double sqlite3AtoF(const char *z, const char **pzEnd){
+int sqlite3AtoF(const char *z, double *pResult){
   int sign = 1;
+  const char *zBegin = z;
   LONGDOUBLE_TYPE v1 = 0.0;
   if( *z=='-' ){
     sign = -1;
@@ -613,8 +641,8 @@ double sqlite3AtoF(const char *z, const char **pzEnd){
       v1 *= scale;
     }
   }
-  if( pzEnd ) *pzEnd = z;
-  return sign<0 ? -v1 : v1;
+  *pResult = sign<0 ? -v1 : v1;
+  return z - zBegin;
 }
 
 /*
@@ -720,7 +748,7 @@ int sqlite3SafetyOn(sqlite3 *db){
   if( db->magic==SQLITE_MAGIC_OPEN ){
     db->magic = SQLITE_MAGIC_BUSY;
     return 0;
-  }else if( db->magic==SQLITE_MAGIC_BUSY || db->magic==SQLITE_MAGIC_ERROR ){
+  }else if( db->magic==SQLITE_MAGIC_BUSY ){
     db->magic = SQLITE_MAGIC_ERROR;
     db->flags |= SQLITE_Interrupt;
   }
@@ -736,7 +764,7 @@ int sqlite3SafetyOff(sqlite3 *db){
   if( db->magic==SQLITE_MAGIC_BUSY ){
     db->magic = SQLITE_MAGIC_OPEN;
     return 0;
-  }else if( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ERROR ){
+  }else if( db->magic==SQLITE_MAGIC_OPEN ){
     db->magic = SQLITE_MAGIC_ERROR;
     db->flags |= SQLITE_Interrupt;
   }
index fe44eed405c0bff0728cb533ead0a7597bb76708..ae33e39961a24d0571683f8097411c64daf0f815 100644 (file)
@@ -454,7 +454,6 @@ int sqlite3VdbeExec(
   int rc = SQLITE_OK;        /* Value to return */
   sqlite3 *db = p->db;       /* The database */
   Mem *pTos;                 /* Top entry in the operand stack */
-  char zBuf[100];            /* Space to sprintf() an integer */
 #ifdef VDBE_PROFILE
   unsigned long long start;  /* CPU clock count at start of opcode */
   int origPc;                /* Program counter at start of opcode */
@@ -478,6 +477,7 @@ int sqlite3VdbeExec(
     p->popStack = 0;
   }
   p->resOnStack = 0;
+  db->busyHandler.nBusy = 0;
   CHECK_FOR_INTERRUPT;
   for(pc=p->pc; rc==SQLITE_OK; pc++){
     assert( pc>=0 && pc<p->nOp );
@@ -633,7 +633,7 @@ case OP_Return: {           /* no-push */
   break;
 }
 
-/* Opcode:  Halt P1 P2 *
+/* Opcode:  Halt P1 P2 P3
 **
 ** Exit immediately.  All open cursors, Lists, Sorts, etc are closed
 ** automatically.
@@ -646,6 +646,8 @@ case OP_Return: {           /* no-push */
 ** then back out all changes that have occurred during this execution of the
 ** VDBE, but do not rollback the transaction. 
 **
+** If P3 is not null then it is an error message string.
+**
 ** There is an implied "Halt 0 0 0" instruction inserted at the very end of
 ** every program.  So a jump past the last instruction of the program
 ** is the same as executing Halt.
@@ -667,28 +669,31 @@ case OP_Halt: {            /* no-push */
   return p->rc ? SQLITE_ERROR : SQLITE_DONE;
 }
 
-/* Opcode: Integer P1 * P3
-**
-** 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.
+/* Opcode: Integer P1 * *
 **
-** If the value cannot be represented as a 32-bits then its value
-** will be in P3.
+** The 32-bit integer value P1 is pushed onto the stack.
 */
 case OP_Integer: {
   pTos++;
-  if( pOp->p3==0 ){
-    pTos->flags = MEM_Int;
-    pTos->i = pOp->p1;
-  }else{
-    pTos->flags = MEM_Str|MEM_Static|MEM_Term;
-    pTos->z = pOp->p3;
-    pTos->n = strlen(pTos->z);
-    pTos->enc = SQLITE_UTF8;
-    pTos->i = sqlite3VdbeIntValue(pTos);
-    pTos->flags |= MEM_Int;
-  }
+  pTos->flags = MEM_Int;
+  pTos->i = pOp->p1;
+  break;
+}
+
+/* Opcode: Int64 * * P3
+**
+** P3 is a string representation of an integer.  Convert that integer
+** to a 64-bit value and push it onto the stack.
+*/
+case OP_Int64: {
+  pTos++;
+  assert( pOp->p3!=0 );
+  pTos->flags = MEM_Str|MEM_Static|MEM_Term;
+  pTos->z = pOp->p3;
+  pTos->n = strlen(pTos->z);
+  pTos->enc = SQLITE_UTF8;
+  pTos->i = sqlite3VdbeIntValue(pTos);
+  pTos->flags |= MEM_Int;
   break;
 }
 
@@ -1000,7 +1005,7 @@ case OP_Concat: {           /* same as TK_CONCAT */
     pTerm = &pTos[1-nField];
     for(i=j=0; i<nField; i++, pTerm++){
       int n = pTerm->n;
-      assert( pTerm->flags & MEM_Str );
+      assert( pTerm->flags & (MEM_Str|MEM_Blob) );
       memcpy(&zNew[j], pTerm->z, n);
       j += n;
     }
@@ -1377,6 +1382,94 @@ case OP_MustBeInt: {            /* no-push */
   break;
 }
 
+#ifndef SQLITE_OMIT_CAST
+/* Opcode: ToInt * * *
+**
+** Force the value on the top of the stack to be an integer.  If
+** The value is currently a real number, drop its fractional part.
+** If the value is text or blob, try to convert it to an integer using the
+** equivalent of atoi() and store 0 if no such conversion is possible.
+**
+** A NULL value is not changed by this routine.  It remains NULL.
+*/
+case OP_ToInt: {                  /* no-push */
+  assert( pTos>=p->aStack );
+  if( pTos->flags & MEM_Null ) break;
+  assert( MEM_Str==(MEM_Blob>>3) );
+  pTos->flags |= (pTos->flags&MEM_Blob)>>3;
+  applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
+  sqlite3VdbeMemIntegerify(pTos);
+  break;
+}
+
+/* Opcode: ToNumeric * * *
+**
+** Force the value on the top of the stack to be numeric (either an
+** integer or a floating-point number.
+** If the value is text or blob, try to convert it to an using the
+** equivalent of atoi() or atof() and store 0 if no such conversion 
+** is possible.
+**
+** A NULL value is not changed by this routine.  It remains NULL.
+*/
+case OP_ToNumeric: {                  /* no-push */
+  assert( pTos>=p->aStack );
+  if( pTos->flags & MEM_Null ) break;
+  assert( MEM_Str==(MEM_Blob>>3) );
+  pTos->flags |= (pTos->flags&MEM_Blob)>>3;
+  applyAffinity(pTos, SQLITE_AFF_NUMERIC, db->enc);
+  if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){
+    sqlite3VdbeMemRealify(pTos);
+  }else{
+    sqlite3VdbeMemRelease(pTos);
+  }
+  assert( (pTos->flags & MEM_Dyn)==0 );
+  pTos->flags &= (MEM_Int|MEM_Real);
+  break;
+}
+
+/* Opcode: ToText * * *
+**
+** Force the value on the top of the stack to be text.
+** If the value is numeric, convert it to an using the
+** equivalent of printf().  Blob values are unchanged and
+** are afterwards simply interpreted as text.
+**
+** A NULL value is not changed by this routine.  It remains NULL.
+*/
+case OP_ToText: {                  /* no-push */
+  assert( pTos>=p->aStack );
+  if( pTos->flags & MEM_Null ) break;
+  assert( MEM_Str==(MEM_Blob>>3) );
+  pTos->flags |= (pTos->flags&MEM_Blob)>>3;
+  applyAffinity(pTos, SQLITE_AFF_TEXT, db->enc);
+  assert( pTos->flags & MEM_Str );
+  pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
+  break;
+}
+
+/* Opcode: ToBlob * * *
+**
+** Force the value on the top of the stack to be a BLOB.
+** If the value is numeric, convert it to a string first.
+** Strings are simply reinterpreted as blobs with no change
+** to the underlying data.
+**
+** A NULL value is not changed by this routine.  It remains NULL.
+*/
+case OP_ToBlob: {                  /* no-push */
+  assert( pTos>=p->aStack );
+  if( pTos->flags & MEM_Null ) break;
+  if( (pTos->flags & MEM_Blob)==0 ){
+    applyAffinity(pTos, SQLITE_AFF_TEXT, db->enc);
+    assert( pTos->flags & MEM_Str );
+    pTos->flags |= MEM_Blob;
+  }
+  pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Str);
+  break;
+}
+#endif /* SQLITE_OMIT_CAST */
+
 /* Opcode: Eq P1 P2 P3
 **
 ** Pop the top two elements from the stack.  If they are equal, then
@@ -1737,6 +1830,13 @@ case OP_SetNumColumns: {       /* no-push */
 ** just a pointer into the record which is stored further down on the
 ** stack.  The column value is not copied. The number of columns in the
 ** record is stored on the stack just above the record itself.
+**
+** If the column contains fewer than P2 fields, then push a NULL.  Or
+** if P3 is of type P3_MEM, then push the P3 value.  The P3 value will
+** be default value for a column that has been added using the ALTER TABLE
+** ADD COLUMN command.  If P3 is an ordinary string, just push a NULL.
+** When P3 is a string it is really just a comment describing the value
+** to be pushed, not a default value.
 */
 case OP_Column: {
   u32 payloadSize;   /* Number of bytes in the record */
@@ -1937,7 +2037,8 @@ case OP_Column: {
   /* 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.
+  ** request.  In this case, set the value NULL or to P3 if P3 is
+  ** a pointer to a Mem object.
   */
   if( aOffset[p2] ){
     assert( rc==SQLITE_OK );
@@ -1954,7 +2055,7 @@ case OP_Column: {
     sqlite3VdbeSerialGet(zData, aType[p2], pTos);
     pTos->enc = db->enc;
   }else{
-    if( pOp->p3 ){
+    if( pOp->p3type==P3_MEM ){
       sqlite3VdbeMemShallowCopy(pTos, (Mem *)(pOp->p3), MEM_Static);
     }else{
       pTos->flags = MEM_Null;
@@ -2000,12 +2101,9 @@ op_column_out:
 ** The original stack entries are popped from the stack if P1>0 but
 ** remain on the stack if P1<0.
 **
-** The P2 argument is divided into two 16-bit words before it is processed.
-** If the hi-word is non-zero, then an extra integer is read from the stack
-** and appended to the record as a varint.  If the low-word of P2 is not
-** zero and one or more of the entries are NULL, then jump to the value of
-** the low-word of P2.  This feature can be used to skip a uniqueness test
-** on indices.
+** If P2 is not zero and one or more of the entries are NULL, then jump
+** to the address given by P2.  This feature can be used to skip a
+** uniqueness test on indices.
 **
 ** P3 may be a string that is P1 characters long.  The nth character of the
 ** string indicates the column affinity that should be used for the nth
@@ -2019,7 +2117,17 @@ op_column_out:
 **    'o' = NONE.
 **
 ** If P3 is NULL then all index fields have the affinity NONE.
+**
+** See also OP_MakeIdxRec
+*/
+/* Opcode: MakeRecordI P1 P2 P3
+**
+** This opcode works just OP_MakeRecord except that it reads an extra
+** integer from the stack (thus reading a total of abs(P1+1) entries)
+** and appends that extra integer to the end of the record as a varint.
+** This results in an index key.
 */
+case OP_MakeIdxRec:
 case OP_MakeRecord: {
   /* Assuming the record contains N fields, the record format looks
   ** like this:
@@ -2057,8 +2165,8 @@ case OP_MakeRecord: {
 
   leaveOnStack = ((pOp->p1<0)?1:0);
   nField = pOp->p1 * (leaveOnStack?-1:1);
-  jumpIfNull = (pOp->p2 & 0x00FFFFFF);
-  addRowid = ((pOp->p2>>24) & 0x0000FFFF)?1:0;
+  jumpIfNull = pOp->p2;
+  addRowid = pOp->opcode==OP_MakeIdxRec;
   zAffinity = pOp->p3;
 
   pData0 = &pTos[1-nField];
@@ -2145,6 +2253,7 @@ case OP_MakeRecord: {
     pTos->flags = MEM_Blob | MEM_Dyn;
     pTos->xDel = 0;
   }
+  pTos->enc = SQLITE_UTF8;  /* In case the blob is ever converted to text */
 
   /* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */
   if( jumpIfNull && containsNull ){
@@ -2429,11 +2538,7 @@ case OP_OpenWrite: {       /* no-push */
     p2 = pTos->i;
     assert( (pTos->flags & MEM_Dyn)==0 );
     pTos--;
-    if( p2<2 ){
-      sqlite3SetString(&p->zErrMsg, "root page number less than 2", (char*)0);
-      rc = SQLITE_INTERNAL;
-      break;
-    }
+    assert( p2>=2 );
   }
   assert( i>=0 );
   pCur = allocateCursor(p, i);
@@ -2498,25 +2603,18 @@ case OP_OpenWrite: {       /* no-push */
   break;
 }
 
-/* Opcode: OpenTemp P1 * P3
+/* Opcode: OpenVirtual P1 * P3
 **
-** Open a new cursor to a transient table.
-** The transient cursor is always opened read/write even if 
-** the main database is read-only.  The transient table is deleted
-** automatically when the cursor is closed.
+** Open a new cursor to a transient or virtual table.
+** The cursor is always opened read/write even if 
+** the main database is read-only.  The transient or virtual
+** table is deleted automatically when the cursor is closed.
 **
 ** The cursor points to a BTree table if P3==0 and to a BTree index
 ** if P3 is not 0.  If P3 is not NULL, it points to a KeyInfo structure
 ** that defines the format of keys in the index.
-**
-** This opcode is used for tables that exist for the duration of a single
-** SQL statement only.  Tables created using CREATE TEMPORARY TABLE
-** are opened using OP_OpenRead or OP_OpenWrite.  "Temporary" in the
-** context of this opcode means for the duration of a single SQL statement
-** whereas "Temporary" in the context of CREATE TABLE means for the duration
-** of the connection to the database.  Same word; different meanings.
 */
-case OP_OpenTemp: {       /* no-push */
+case OP_OpenVirtual: {       /* no-push */
   int i = pOp->p1;
   Cursor *pCx;
   assert( i>=0 );
@@ -3280,6 +3378,7 @@ case OP_RowData: {
   }else{
     pTos->flags = MEM_Null;
   }
+  pTos->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
   break;
 }
 
@@ -3444,17 +3543,12 @@ case OP_Next: {        /* no-push */
   break;
 }
 
-/* Opcode: IdxInsert P1 P2 P3
+/* Opcode: IdxInsert P1 * *
 **
 ** The top of the stack holds a SQL index key made using the
 ** MakeIdxKey instruction.  This opcode writes that key into the
 ** index P1.  Data for the entry is nil.
 **
-** If P2==1, then the key must be unique.  If the key is not unique,
-** the program aborts with a SQLITE_CONSTRAINT error and the database
-** is rolled back.  If P3 is not null, then it becomes part of the
-** error message returned with the SQLITE_CONSTRAINT.
-**
 ** This instruction only works for indices.  The equivalent instruction
 ** for tables is OP_Insert.
 */
@@ -3466,35 +3560,10 @@ case OP_IdxInsert: {        /* no-push */
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
   assert( pTos->flags & MEM_Blob );
+  assert( pOp->p2==0 );
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     int nKey = pTos->n;
     const char *zKey = pTos->z;
-    if( pOp->p2 ){
-      int res;
-      int len;
-   
-      /* 'len' is the length of the key minus the rowid at the end */
-      len = nKey - sqlite3VdbeIdxRowidLen(nKey, zKey);
-
-      rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
-      if( rc!=SQLITE_OK ) goto abort_due_to_error;
-      while( res!=0 && !sqlite3BtreeEof(pCrsr) ){
-        int c;
-        if( sqlite3VdbeIdxKeyCompare(pC, len, zKey, &c)==SQLITE_OK && c==0 ){
-          rc = SQLITE_CONSTRAINT;
-          if( pOp->p3 && pOp->p3[0] ){
-            sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0);
-          }
-          goto abort_due_to_error;
-        }
-        if( res<0 ){
-          sqlite3BtreeNext(pCrsr, &res);
-          res = +1;
-        }else{
-          break;
-        }
-      }
-    }
     assert( pC->isTable==0 );
     rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0);
     assert( pC->deferredMoveto==0 );
@@ -3815,6 +3884,21 @@ case OP_ParseSchema: {        /* no-push */
   break;  
 }
 
+#ifndef SQLITE_OMIT_ANALYZE
+/* Opcode: LoadAnalysis P1 * *
+**
+** Read the sqlite_stat1 table for database P1 and load the content
+** of that table into the internal index hash table.  This will cause
+** the analysis to be used when preparing all subsequent queries.
+*/
+case OP_LoadAnalysis: {        /* no-push */
+  int iDb = pOp->p1;
+  assert( iDb>=0 && iDb<db->nDb );
+  sqlite3AnalysisLoad(db, iDb);
+  break;  
+}
+#endif /* SQLITE_OMIT_ANALYZE */
+
 /* Opcode: DropTable P1 * P3
 **
 ** Remove the internal (in-memory) data structures that describe
@@ -3906,86 +3990,35 @@ case OP_IntegrityCk: {
 }
 #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
 
-/* Opcode: ListWrite * * *
+/* Opcode: FifoWrite * * *
 **
 ** Write the integer on the top of the stack
-** into the temporary storage list.
+** into the Fifo.
 */
-case OP_ListWrite: {        /* no-push */
-  Keylist *pKeylist;
+case OP_FifoWrite: {        /* no-push */
   assert( pTos>=p->aStack );
-  pKeylist = p->pList;
-  if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){
-    pKeylist = sqliteMallocRaw( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) );
-    if( pKeylist==0 ) goto no_mem;
-    pKeylist->nKey = 1000;
-    pKeylist->nRead = 0;
-    pKeylist->nUsed = 0;
-    pKeylist->pNext = p->pList;
-    p->pList = pKeylist;
-  }
   Integerify(pTos);
-  pKeylist->aKey[pKeylist->nUsed++] = pTos->i;
+  sqlite3VdbeFifoPush(&p->sFifo, pTos->i);
   assert( (pTos->flags & MEM_Dyn)==0 );
   pTos--;
   break;
 }
 
-/* Opcode: ListRewind * * *
-**
-** Rewind the temporary buffer back to the beginning.
-*/
-case OP_ListRewind: {        /* no-push */
-  /* What this opcode codes, really, is reverse the order of the
-  ** linked list of Keylist structures so that they are read out
-  ** in the same order that they were read in. */
-  Keylist *pRev, *pTop;
-  pRev = 0;
-  while( p->pList ){
-    pTop = p->pList;
-    p->pList = pTop->pNext;
-    pTop->pNext = pRev;
-    pRev = pTop;
-  }
-  p->pList = pRev;
-  break;
-}
-
-/* Opcode: ListRead * P2 *
+/* Opcode: FifoRead * P2 *
 **
-** Attempt to read an integer from the temporary storage buffer
-** and push it onto the stack.  If the storage buffer is empty, 
+** Attempt to read a single integer from the Fifo
+** and push it onto the stack.  If the Fifo is empty
 ** push nothing but instead jump to P2.
 */
-case OP_ListRead: {
-  Keylist *pKeylist;
+case OP_FifoRead: {
+  i64 v;
   CHECK_FOR_INTERRUPT;
-  pKeylist = p->pList;
-  if( pKeylist!=0 ){
-    assert( pKeylist->nRead>=0 );
-    assert( pKeylist->nRead<pKeylist->nUsed );
-    assert( pKeylist->nRead<pKeylist->nKey );
+  if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){
+    pc = pOp->p2 - 1;
+  }else{
     pTos++;
-    pTos->i = pKeylist->aKey[pKeylist->nRead++];
+    pTos->i = v;
     pTos->flags = MEM_Int;
-    if( pKeylist->nRead>=pKeylist->nUsed ){
-      p->pList = pKeylist->pNext;
-      sqliteFree(pKeylist);
-    }
-  }else{
-    pc = pOp->p2 - 1;
-  }
-  break;
-}
-
-/* Opcode: ListReset * * *
-**
-** Reset the temporary storage buffer so that it holds nothing.
-*/
-case OP_ListReset: {        /* no-push */
-  if( p->pList ){
-    sqlite3VdbeKeylistFree(p->pList);
-    p->pList = 0;
   }
   break;
 }
@@ -4036,8 +4069,8 @@ case OP_ContextPush: {        /* no-push */
   pContext = &p->contextStack[i];
   pContext->lastRowid = db->lastRowid;
   pContext->nChange = p->nChange;
-  pContext->pList = p->pList;
-  p->pList = 0;
+  pContext->sFifo = p->sFifo;
+  sqlite3VdbeFifoInit(&p->sFifo);
   break;
 }
 
@@ -4052,8 +4085,8 @@ case OP_ContextPop: {        /* no-push */
   assert( p->contextStackTop>=0 );
   db->lastRowid = pContext->lastRowid;
   p->nChange = pContext->nChange;
-  sqlite3VdbeKeylistFree(p->pList);
-  p->pList = pContext->pList;
+  sqlite3VdbeFifoClear(&p->sFifo);
+  p->sFifo = pContext->sFifo;
   break;
 }
 #endif /* #ifndef SQLITE_OMIT_TRIGGER */
@@ -4567,9 +4600,7 @@ case OP_Expire: {        /* no-push */
 /* An other opcode is illegal...
 */
 default: {
-  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",pOp->opcode);
-  sqlite3SetString(&p->zErrMsg, "unknown opcode ", zBuf, (char*)0);
-  rc = SQLITE_INTERNAL;
+  assert( 0 );
   break;
 }
 
@@ -4606,10 +4637,7 @@ default: {
     if( pTos>=p->aStack ){
       sqlite3VdbeMemSanity(pTos, db->enc);
     }
-    if( pc<-1 || pc>=p->nOp ){
-      sqlite3SetString(&p->zErrMsg, "jump destination out of range", (char*)0);
-      rc = SQLITE_INTERNAL;
-    }
+    assert( pc>=-1 && pc<p->nOp );
 #ifdef SQLITE_DEBUG
     /* Code for tracing the vdbe stack. */
     if( p->trace && pTos>=p->aStack ){
index c88a75c134900d7b8363a4b3dd16fc997afa72c8..77695d1cdaa3ed22d658c78817ed2ebeb3e15869 100644 (file)
@@ -105,8 +105,6 @@ int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
 void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
 void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
 void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
-void sqlite3VdbeDequoteP3(Vdbe*, int addr);
-int sqlite3VdbeFindOp(Vdbe*, int, int, int);
 VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
 int sqlite3VdbeMakeLabel(Vdbe*);
 void sqlite3VdbeDelete(Vdbe*);
index 1feb9bab45e76fffa21e3c58e5aadcd136b78114..7bf2a0ec5dc4c7c5bb30588504a40555a9129f1f 100644 (file)
@@ -260,17 +260,29 @@ struct Set {
 };
 
 /*
-** A Keylist is a bunch of keys into a table.  The keylist can
-** grow without bound.  The keylist stores the ROWIDs of database
-** records that need to be deleted or updated.
+** A FifoPage structure holds a single page of valves.  Pages are arranged
+** in a list.
 */
-typedef struct Keylist Keylist;
-struct Keylist {
-  int nKey;         /* Number of slots in aKey[] */
-  int nUsed;        /* Next unwritten slot in aKey[] */
-  int nRead;        /* Next unread slot in aKey[] */
-  Keylist *pNext;   /* Next block of keys */
-  i64 aKey[1];      /* One or more keys.  Extra space allocated as needed */
+typedef struct FifoPage FifoPage;
+struct FifoPage {
+  int nSlot;         /* Number of entries aSlot[] */
+  int iWrite;        /* Push the next value into this entry in aSlot[] */
+  int iRead;         /* Read the next value from this entry in aSlot[] */
+  FifoPage *pNext;   /* Next page in the fifo */
+  i64 aSlot[1];      /* One or more slots for rowid values */
+};
+
+/*
+** The Fifo structure is typedef-ed in vdbeInt.h.  But the implementation
+** of that structure is private to this file.
+**
+** The Fifo structure describes the entire fifo.  
+*/
+typedef struct Fifo Fifo;
+struct Fifo {
+  int nEntry;         /* Total number of entries */
+  FifoPage *pFirst;   /* First page on the list */
+  FifoPage *pLast;    /* Last page on the list */
 };
 
 /*
@@ -286,7 +298,7 @@ typedef struct Context Context;
 struct Context {
   int lastRowid;    /* Last insert rowid (sqlite3.lastRowid) */
   int nChange;      /* Statement changes (Vdbe.nChanges)     */
-  Keylist *pList;   /* Records that will participate in a DELETE or UPDATE */
+  Fifo sFifo;       /* Records that will participate in a DELETE or UPDATE */
 };
 
 /*
@@ -325,7 +337,7 @@ struct Vdbe {
   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 */
+  Fifo sFifo;             /* A list of ROWIDs */
   int contextStackTop;    /* Index of top element in the context stack */
   int contextStackDepth;  /* The size of the "context" stack */
   Context *contextStack;  /* Stack used by opcodes ContextPush & ContextPop*/
@@ -362,7 +374,6 @@ struct Vdbe {
 void sqlite3VdbeFreeCursor(Cursor*);
 void sqlite3VdbeSorterReset(Vdbe*);
 int sqlite3VdbeAggReset(sqlite3*, Agg *, KeyInfo *);
-void sqlite3VdbeKeylistFree(Keylist*);
 void sqliteVdbePopStack(Vdbe*,int);
 int sqlite3VdbeCursorMoveto(Cursor*);
 #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
@@ -411,3 +422,7 @@ int sqlite3VdbeOpcodeNoPush(u8);
 int sqlite3VdbeMemTranslate(Mem*, u8);
 void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf);
 int sqlite3VdbeMemHandleBom(Mem *pMem);
+void sqlite3VdbeFifoInit(Fifo*);
+int sqlite3VdbeFifoPush(Fifo*, i64);
+int sqlite3VdbeFifoPop(Fifo*, i64*);
+void sqlite3VdbeFifoClear(Fifo*);
index f07bc889924be2fc43caffd72f95206f903db3d8..dfe8f12c418e6df091ce554317fe89f857f623c3 100644 (file)
@@ -84,7 +84,7 @@ void sqlite3_result_blob(
   int n, 
   void (*xDel)(void *)
 ){
-  assert( n>0 );
+  assert( n>=0 );
   sqlite3VdbeMemSetStr(&pCtx->s, z, n, 0, xDel);
 }
 void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
@@ -213,7 +213,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
     rc = SQLITE_MISUSE;
   }
 
-  sqlite3Error(p->db, rc, p->zErrMsg);
+  sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
   return rc;
 }
 
@@ -230,10 +230,6 @@ void *sqlite3_user_data(sqlite3_context *p){
 ** Allocate or return the aggregate context for a user function.  A new
 ** context is allocated on the first call.  Subsequent calls return the
 ** same context that was returned on prior calls.
-**
-** This routine is defined here in vdbe.c because it depends on knowing
-** the internals of the sqlite3_context structure which is only defined in
-** this source file.
 */
 void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
   assert( p && p->pFunc && p->pFunc->xStep );
@@ -369,6 +365,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) );
 }
+#if 0
+sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
+  return columnMem(pStmt, i);
+}
+#endif
 #ifndef SQLITE_OMIT_UTF16
 const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
   return sqlite3_value_text16( columnMem(pStmt,i) );
index e64831e7545275589cb7ae6c9bd7b6c9f7d25728..d9541a3fee9926099b0bdd510733bb96833218b0 100644 (file)
@@ -25,7 +25,7 @@
 ** set the sqlite3_vdbe_addop_trace to 1 and all opcodes will be printed
 ** as they are added to the instruction stream.
 */
-#ifndef NDEBUG
+#ifdef SQLITE_DEBUG
 int sqlite3_vdbe_addop_trace = 0;
 #endif
 
@@ -109,6 +109,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
   pOp->p2 = p2;
   pOp->p3 = 0;
   pOp->p3type = P3_NOTUSED;
+  p->expired = 0;
 #ifdef SQLITE_DEBUG
   if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
 #endif
@@ -442,47 +443,6 @@ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
 }
 #endif
 
-/*
-** If the P3 operand to the specified instruction appears
-** to be a quoted string token, then this procedure removes 
-** the quotes.
-**
-** The quoting operator can be either a grave ascent (ASCII 0x27)
-** or a double quote character (ASCII 0x22).  Two quotes in a row
-** resolve to be a single actual quote character within the string.
-*/
-void sqlite3VdbeDequoteP3(Vdbe *p, int addr){
-  Op *pOp;
-  assert( p->magic==VDBE_MAGIC_INIT );
-  if( p->aOp==0 ) return;
-  if( addr<0 || addr>=p->nOp ){
-    addr = p->nOp - 1;
-    if( addr<0 ) return;
-  }
-  pOp = &p->aOp[addr];
-  if( pOp->p3==0 || pOp->p3[0]==0 ) return;
-  if( pOp->p3type==P3_STATIC ){
-    pOp->p3 = sqliteStrDup(pOp->p3);
-    pOp->p3type = P3_DYNAMIC;
-  }
-  assert( pOp->p3type==P3_DYNAMIC );
-  sqlite3Dequote(pOp->p3);
-}
-
-/*
-** Search the current program starting at instruction addr for the given
-** opcode and P2 value.  Return the address plus 1 if found and 0 if not
-** found.
-*/
-int sqlite3VdbeFindOp(Vdbe *p, int addr, int op, int p2){
-  int i;
-  assert( p->magic==VDBE_MAGIC_INIT );
-  for(i=addr; i<p->nOp; i++){
-    if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1;
-  }
-  return 0;
-}
-
 /*
 ** Return the opcode for a given address.
 */
@@ -952,18 +912,6 @@ int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
   return SQLITE_OK;
 }
 
-
-/*
-** Delete a keylist
-*/
-void sqlite3VdbeKeylistFree(Keylist *p){
-  while( p ){
-    Keylist *pNext = p->pNext;
-    sqliteFree(p);
-    p = pNext;
-  }
-}
-
 /*
 ** Close a cursor and release all the resources that cursor happens
 ** to hold.
@@ -1010,13 +958,10 @@ static void Cleanup(Vdbe *p){
   }
   closeAllCursors(p);
   releaseMemArray(p->aMem, p->nMem);
-  if( p->pList ){
-    sqlite3VdbeKeylistFree(p->pList);
-    p->pList = 0;
-  }
+  sqlite3VdbeFifoClear(&p->sFifo);
   if( p->contextStack ){
     for(i=0; i<p->contextStackTop; i++){
-      sqlite3VdbeKeylistFree(p->contextStack[i].pList);
+      sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);
     }
     sqliteFree(p->contextStack);
   }
@@ -1145,6 +1090,7 @@ static int vdbeCommit(sqlite3 *db){
   */
 #ifndef SQLITE_OMIT_DISKIO
   else{
+    int needSync = 0;
     char *zMaster = 0;   /* File-name for the master journal */
     char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
     OsFile master;
@@ -1180,6 +1126,9 @@ static int vdbeCommit(sqlite3 *db){
       if( pBt && sqlite3BtreeIsInTrans(pBt) ){
         char const *zFile = sqlite3BtreeGetJournalname(pBt);
         if( zFile[0]==0 ) continue;  /* Ignore :memory: databases */
+        if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
+          needSync = 1;
+        }
         rc = sqlite3OsWrite(&master, zFile, strlen(zFile)+1);
         if( rc!=SQLITE_OK ){
           sqlite3OsClose(&master);
@@ -1196,7 +1145,7 @@ static int vdbeCommit(sqlite3 *db){
     */
     zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
     rc = sqlite3OsOpenDirectory(zMainFile, &master);
-    if( rc!=SQLITE_OK || (rc = sqlite3OsSync(&master))!=SQLITE_OK ){
+    if( rc!=SQLITE_OK || (needSync && (rc=sqlite3OsSync(&master))!=SQLITE_OK) ){
       sqlite3OsClose(&master);
       sqlite3OsDelete(zMaster);
       sqliteFree(zMaster);
@@ -1763,7 +1712,7 @@ int sqlite3VdbeSerialGet(
       pMem->flags = MEM_Int;
       return 6;
     }
-    case 6:   /* 6-byte signed integer */
+    case 6:   /* 8-byte signed integer */
     case 7: { /* IEEE floating point */
       u64 x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
       u32 y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
diff --git a/ext/pdo_sqlite/sqlite/src/vdbefifo.c b/ext/pdo_sqlite/sqlite/src/vdbefifo.c
new file mode 100644 (file)
index 0000000..7ea6c05
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+** 2005 June 16
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements a FIFO queue of rowids used for processing
+** UPDATE and DELETE statements.
+*/
+#include "sqliteInt.h"
+#include "vdbeInt.h"
+
+/*
+** Allocate a new FifoPage and return a pointer to it.  Return NULL if
+** we run out of memory.  Leave space on the page for nEntry entries.
+*/
+static FifoPage *allocatePage(int nEntry){
+  FifoPage *pPage;
+  if( nEntry>32767 ){
+    nEntry = 32767;
+  }
+  pPage = sqliteMallocRaw( sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
+  if( pPage ){
+    pPage->nSlot = nEntry;
+    pPage->iWrite = 0;
+    pPage->iRead = 0;
+    pPage->pNext = 0;
+  }
+  return pPage;
+}
+
+/*
+** Initialize a Fifo structure.
+*/
+void sqlite3VdbeFifoInit(Fifo *pFifo){
+  memset(pFifo, 0, sizeof(*pFifo));
+}
+
+/*
+** Push a single 64-bit integer value into the Fifo.  Return SQLITE_OK
+** normally.   SQLITE_NOMEM is returned if we are unable to allocate
+** memory.
+*/
+int sqlite3VdbeFifoPush(Fifo *pFifo, i64 val){
+  FifoPage *pPage;
+  pPage = pFifo->pLast;
+  if( pPage==0 ){
+    pPage = pFifo->pLast = pFifo->pFirst = allocatePage(20);
+    if( pPage==0 ){
+      return SQLITE_NOMEM;
+    }
+  }else if( pPage->iWrite>=pPage->nSlot ){
+    pPage->pNext = allocatePage(pFifo->nEntry);
+    if( pPage->pNext==0 ){
+      return SQLITE_NOMEM;
+    }
+    pPage = pFifo->pLast = pPage->pNext;
+  }
+  pPage->aSlot[pPage->iWrite++] = val;
+  pFifo->nEntry++;
+  return SQLITE_OK;
+}
+
+/*
+** Extract a single 64-bit integer value from the Fifo.  The integer
+** extracted is the one least recently inserted.  If the Fifo is empty
+** return SQLITE_DONE.
+*/
+int sqlite3VdbeFifoPop(Fifo *pFifo, i64 *pVal){
+  FifoPage *pPage;
+  if( pFifo->nEntry==0 ){
+    return SQLITE_DONE;
+  }
+  assert( pFifo->nEntry>0 );
+  pPage = pFifo->pFirst;
+  assert( pPage!=0 );
+  assert( pPage->iWrite>pPage->iRead );
+  assert( pPage->iWrite<=pPage->nSlot );
+  assert( pPage->iRead<pPage->nSlot );
+  assert( pPage->iRead>=0 );
+  *pVal = pPage->aSlot[pPage->iRead++];
+  pFifo->nEntry--;
+  if( pPage->iRead>=pPage->iWrite ){
+    pFifo->pFirst = pPage->pNext;
+    sqliteFree(pPage);
+    if( pFifo->nEntry==0 ){
+      assert( pFifo->pLast==pPage );
+      pFifo->pLast = 0;
+    }else{
+      assert( pFifo->pFirst!=0 );
+    }
+  }else{
+    assert( pFifo->nEntry>0 );
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Delete all information from a Fifo object.   Free all memory held
+** by the Fifo.
+*/
+void sqlite3VdbeFifoClear(Fifo *pFifo){
+  FifoPage *pPage, *pNextPage;
+  for(pPage=pFifo->pFirst; pPage; pPage=pNextPage){
+    pNextPage = pPage->pNext;
+    sqliteFree(pPage);
+  }
+  sqlite3VdbeFifoInit(pFifo);
+}
index f08671f249c473e9b92f783347857018134578a9..416beb6c785c15b7558983b497eb13d04821ab4e 100644 (file)
@@ -174,7 +174,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
   ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
   */
   if( fg & MEM_Real ){
-    sqlite3_snprintf(NBFS, z, "%.15g", pMem->r);
+    sqlite3_snprintf(NBFS, z, "%!.15g", pMem->r);
   }else{
     assert( fg & MEM_Int );
     sqlite3_snprintf(NBFS, z, "%lld", pMem->i);
@@ -256,12 +256,14 @@ double sqlite3VdbeRealValue(Mem *pMem){
   }else if( pMem->flags & MEM_Int ){
     return (double)pMem->i;
   }else if( pMem->flags & (MEM_Str|MEM_Blob) ){
+    double val = 0.0;
     if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8)
        || sqlite3VdbeMemNulTerminate(pMem) ){
       return SQLITE_NOMEM;
     }
     assert( pMem->z );
-    return sqlite3AtoF(pMem->z, 0);
+    sqlite3AtoF(pMem->z, &val);
+    return val;
   }else{
     return 0.0;
   }
@@ -406,6 +408,7 @@ int sqlite3VdbeMemSetStr(
   switch( enc ){
     case 0:
       pMem->flags |= MEM_Blob;
+      pMem->enc = SQLITE_UTF8;
       break;
 
     case SQLITE_UTF8:
@@ -666,9 +669,9 @@ void sqlite3VdbeMemSanity(Mem *pMem, u8 db_enc){
   /* MEM_Null excludes all other types */
   assert( (pMem->flags&(MEM_Str|MEM_Int|MEM_Real|MEM_Blob))==0
           || (pMem->flags&MEM_Null)==0 );
-  if( (pMem->flags & (MEM_Int|MEM_Real))==(MEM_Int|MEM_Real) ){
-    assert( pMem->r==pMem->i );
-  }
+  /* If the MEM is both real and integer, the values are equal */
+  assert( (pMem->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) 
+          || pMem->r==pMem->i );
 }
 #endif
 
index 553de70a25df7a91682e38b2b4256aa87ee8a9b1..fddc1f0155bd484c1f002725dac6986568391fd7 100644 (file)
 */
 #include "sqliteInt.h"
 
+/*
+** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
+*/
+#define BMS  (sizeof(Bitmask)*8)
+
+/*
+** Determine the number of elements in an array.
+*/
+#define ARRAYSIZE(X)  (sizeof(X)/sizeof(X[0]))
+
+/*
+** Trace output macros
+*/
+#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
+int sqlite3_where_trace = 0;
+# define TRACE(X)  if(sqlite3_where_trace) sqlite3DebugPrintf X
+#else
+# define TRACE(X)
+#endif
+
+/* Forward reference
+*/
+typedef struct WhereClause WhereClause;
+
 /*
 ** 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.  
+** All WhereTerms are collected into a single WhereClause structure.  
+** The following identity holds:
+**
+**        WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm
+**
+** When a term is of the form:
 **
-** 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.
+**              X <op> <expr>
 **
-** prereqLeft, prereqRight, and prereqAll record sets of cursor numbers,
+** where X is a column name and <op> is one of certain operators,
+** then WhereTerm.leftCursor and WhereTerm.leftColumn record the
+** cursor number and column number for X.  WhereTerm.operator records
+** the <op> using a bitmask encoding defined by WO_xxx below.  The
+** use of a bitmask encoding for the operator allows us to search
+** quickly for terms that match any of several different operators.
+**
+** 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
 ** 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 {
-  Expr *p;                /* Pointer to the subexpression */
-  u8 indexable;           /* True if this subexprssion is usable by an index */
-  short int idxLeft;      /* p->pLeft is a column in this table number. -1 if
-                          ** 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 */
-  Bitmask prereqLeft;     /* Bitmask of tables referenced by p->pLeft */
-  Bitmask prereqRight;    /* Bitmask of tables referenced by p->pRight */
+typedef struct WhereTerm WhereTerm;
+struct WhereTerm {
+  Expr *pExpr;            /* Pointer to the subexpression */
+  i16 iParent;            /* Disable pWC->a[iParent] when this term disabled */
+  i16 leftCursor;         /* Cursor number of X in "X <op> <expr>" */
+  i16 leftColumn;         /* Column number of X in "X <op> <expr>" */
+  u16 operator;           /* A WO_xx value describing <op> */
+  u8 flags;               /* Bit flags.  See below */
+  u8 nChild;              /* Number of children that must disable us */
+  WhereClause *pWC;       /* The clause this term is part of */
+  Bitmask prereqRight;    /* Bitmask of tables used by pRight */
   Bitmask prereqAll;      /* Bitmask of tables referenced by p */
 };
 
+/*
+** Allowed values of WhereTerm.flags
+*/
+#define TERM_DYNAMIC    0x01   /* Need to call sqlite3ExprDelete(pExpr) */
+#define TERM_VIRTUAL    0x02   /* Added by the optimizer.  Do not code */
+#define TERM_CODED      0x04   /* This term is already coded */
+#define TERM_COPIED     0x08   /* Has a child */
+#define TERM_OR_OK      0x10   /* Used during OR-clause processing */
+
+/*
+** An instance of the following structure holds all information about a
+** WHERE clause.  Mostly this is a container for one or more WhereTerms.
+*/
+struct WhereClause {
+  Parse *pParse;           /* The parser context */
+  int nTerm;               /* Number of terms */
+  int nSlot;               /* Number of entries in a[] */
+  WhereTerm *a;            /* Each a[] describes a term of the WHERE cluase */
+  WhereTerm aStatic[10];   /* Initial static space for a[] */
+};
+
 /*
 ** An instance of the following structure keeps track of a mapping
-** between VDBE cursor numbers and bits of the bitmasks in ExprInfo.
+** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
 **
 ** The VDBE cursor numbers are small integers contained in 
 ** SrcList_item.iCursor and Expr.iTable fields.  For any given WHERE 
@@ -107,43 +144,117 @@ struct ExprMaskSet {
   int ix[sizeof(Bitmask)*8];    /* Cursor assigned to each bit */
 };
 
+
 /*
-** Determine the number of elements in an array.
+** Bitmasks for the operators that indices are able to exploit.  An
+** OR-ed combination of these values can be used when searching for
+** terms in the where clause.
 */
-#define ARRAYSIZE(X)  (sizeof(X)/sizeof(X[0]))
+#define WO_IN     1
+#define WO_EQ     2
+#define WO_LT     (WO_EQ<<(TK_LT-TK_EQ))
+#define WO_LE     (WO_EQ<<(TK_LE-TK_EQ))
+#define WO_GT     (WO_EQ<<(TK_GT-TK_EQ))
+#define WO_GE     (WO_EQ<<(TK_GE-TK_EQ))
+
+/*
+** Value for flags returned by bestIndex()
+*/
+#define WHERE_ROWID_EQ       0x0001   /* rowid=EXPR or rowid IN (...) */
+#define WHERE_ROWID_RANGE    0x0002   /* rowid<EXPR and/or rowid>EXPR */
+#define WHERE_COLUMN_EQ      0x0010   /* x=EXPR or x IN (...) */
+#define WHERE_COLUMN_RANGE   0x0020   /* x<EXPR and/or x>EXPR */
+#define WHERE_COLUMN_IN      0x0040   /* x IN (...) */
+#define WHERE_TOP_LIMIT      0x0100   /* x<EXPR or x<=EXPR constraint */
+#define WHERE_BTM_LIMIT      0x0200   /* x>EXPR or x>=EXPR constraint */
+#define WHERE_IDX_ONLY       0x0800   /* Use index only - omit table */
+#define WHERE_ORDERBY        0x1000   /* Output will appear in correct order */
+#define WHERE_REVERSE        0x2000   /* Scan in reverse order */
+#define WHERE_UNIQUE         0x4000   /* Selects no more than one row */
+
+/*
+** Initialize a preallocated WhereClause structure.
+*/
+static void whereClauseInit(WhereClause *pWC, Parse *pParse){
+  pWC->pParse = pParse;
+  pWC->nTerm = 0;
+  pWC->nSlot = ARRAYSIZE(pWC->aStatic);
+  pWC->a = pWC->aStatic;
+}
+
+/*
+** Deallocate a WhereClause structure.  The WhereClause structure
+** itself is not freed.  This routine is the inverse of whereClauseInit().
+*/
+static void whereClauseClear(WhereClause *pWC){
+  int i;
+  WhereTerm *a;
+  for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
+    if( a->flags & TERM_DYNAMIC ){
+      sqlite3ExprDelete(a->pExpr);
+    }
+  }
+  if( pWC->a!=pWC->aStatic ){
+    sqliteFree(pWC->a);
+  }
+}
+
+/*
+** Add a new entries to the WhereClause structure.  Increase the allocated
+** space as necessary.
+**
+** WARNING:  This routine might reallocate the space used to store
+** WhereTerms.  All pointers to WhereTerms should be invalided after
+** calling this routine.  Such pointers may be reinitialized by referencing
+** the pWC->a[] array.
+*/
+static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){
+  WhereTerm *pTerm;
+  int idx;
+  if( pWC->nTerm>=pWC->nSlot ){
+    WhereTerm *pOld = pWC->a;
+    pWC->a = sqliteMalloc( sizeof(pWC->a[0])*pWC->nSlot*2 );
+    if( pWC->a==0 ) return 0;
+    memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
+    if( pOld!=pWC->aStatic ){
+      sqliteFree(pOld);
+    }
+    pWC->nSlot *= 2;
+  }
+  pTerm = &pWC->a[idx = pWC->nTerm];
+  pWC->nTerm++;
+  pTerm->pExpr = p;
+  pTerm->flags = flags;
+  pTerm->pWC = pWC;
+  pTerm->iParent = -1;
+  return idx;
+}
 
 /*
 ** 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:
+** each subexpression is separate by the AND operator or some other
+** operator specified in the op parameter.  The WhereClause structure
+** is filled with pointers to 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.
+** does is make slot[] entries point to substructure within pExpr.
 **
-** 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.
+** In the previous sentence and in the diagram, "slot[]" refers to
+** the WhereClause.a[] array.  This array grows as needed to contain
+** all terms of the WHERE clause.
 */
-static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){
-  int cnt = 0;
-  if( pExpr==0 || nSlot<1 ) return 0;
-  if( nSlot==1 || pExpr->op!=TK_AND ){
-    aSlot[0].p = pExpr;
-    return 1;
-  }
-  if( pExpr->pLeft->op!=TK_AND ){
-    aSlot[0].p = pExpr->pLeft;
-    cnt = 1 + exprSplit(nSlot-1, &aSlot[1], pExpr->pRight);
+static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
+  if( pExpr==0 ) return;
+  if( pExpr->op!=op ){
+    whereClauseInsert(pWC, pExpr, 0);
   }else{
-    cnt = exprSplit(nSlot, aSlot, pExpr->pLeft);
-    cnt += exprSplit(nSlot-cnt, &aSlot[cnt], pExpr->pRight);
+    whereSplit(pWC, pExpr->pLeft, op);
+    whereSplit(pWC, pExpr->pRight, op);
   }
-  return cnt;
 }
 
 /*
@@ -167,18 +278,17 @@ static Bitmask getMask(ExprMaskSet *pMaskSet, int iCursor){
 
 /*
 ** Create a new mask for cursor iCursor.
+**
+** There is one cursor per table in the FROM clause.  The number of
+** tables in the FROM clause is limited by a test early in the
+** sqlite3WhereBegin() routien.  So we know that the pMaskSet->ix[]
+** array will never overflow.
 */
 static void createMask(ExprMaskSet *pMaskSet, int iCursor){
-  if( pMaskSet->n<ARRAYSIZE(pMaskSet->ix) ){
-    pMaskSet->ix[pMaskSet->n++] = iCursor;
-  }
+  assert( pMaskSet->n < ARRAYSIZE(pMaskSet->ix) );
+  pMaskSet->ix[pMaskSet->n++] = iCursor;
 }
 
-/*
-** Destroy an expression mask set
-*/
-#define freeMaskSet(P)   /* NO-OP */
-
 /*
 ** This routine walks (recursively) an expression tree and generates
 ** a bitmask indicating which tables are used in that expression
@@ -189,7 +299,9 @@ static void createMask(ExprMaskSet *pMaskSet, int iCursor){
 ** the header comment on that routine for additional information.
 ** 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.
+** the VDBE cursor number of the table.  This routine just has to
+** translate the cursor numbers into bitmask values and OR all
+** the bitmasks together.
 */
 static Bitmask exprListTableUsage(ExprMaskSet *, ExprList *);
 static Bitmask exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
@@ -229,7 +341,10 @@ static Bitmask exprListTableUsage(ExprMaskSet *pMaskSet, ExprList *pList){
 ** "=", "<", ">", "<=", ">=", and "IN".
 */
 static int allowedOp(int op){
-  assert( TK_GT==TK_LE-1 && TK_LE==TK_LT-1 && TK_LT==TK_GE-1 && TK_EQ==TK_GT-1);
+  assert( TK_GT>TK_EQ && TK_GT<TK_GE );
+  assert( TK_LT>TK_EQ && TK_LT<TK_GE );
+  assert( TK_LE>TK_EQ && TK_LE<TK_GE );
+  assert( TK_GE==TK_EQ+4 );
   return op==TK_IN || (op>=TK_EQ && op<=TK_GE);
 }
 
@@ -239,76 +354,349 @@ static int allowedOp(int op){
 #define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
 
 /*
-** Return the index in the SrcList that uses cursor iCur.  If iCur is
-** used by the first entry in SrcList return 0.  If iCur is used by
-** the second entry return 1.  And so forth.
+** Commute a comparision operator.  Expressions of the form "X op Y"
+** are converted into "Y op X".
+*/
+static void exprCommute(Expr *pExpr){
+  assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
+  SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
+  SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
+  if( pExpr->op>=TK_GT ){
+    assert( TK_LT==TK_GT+2 );
+    assert( TK_GE==TK_LE+2 );
+    assert( TK_GT>TK_EQ );
+    assert( TK_GT<TK_LE );
+    assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
+    pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
+  }
+}
+
+/*
+** Translate from TK_xx operator to WO_xx bitmask.
+*/
+static int operatorMask(int op){
+  int c;
+  assert( allowedOp(op) );
+  if( op==TK_IN ){
+    c = WO_IN;
+  }else{
+    c = WO_EQ<<(op-TK_EQ);
+  }
+  assert( op!=TK_IN || c==WO_IN );
+  assert( op!=TK_EQ || c==WO_EQ );
+  assert( op!=TK_LT || c==WO_LT );
+  assert( op!=TK_LE || c==WO_LE );
+  assert( op!=TK_GT || c==WO_GT );
+  assert( op!=TK_GE || c==WO_GE );
+  return c;
+}
+
+/*
+** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
+** where X is a reference to the iColumn of table iCur and <op> is one of
+** the WO_xx operator codes specified by the op parameter.
+** Return a pointer to the term.  Return 0 if not found.
+*/
+static WhereTerm *findTerm(
+  WhereClause *pWC,     /* The WHERE clause to be searched */
+  int iCur,             /* Cursor number of LHS */
+  int iColumn,          /* Column number of LHS */
+  Bitmask notReady,     /* RHS must not overlap with this mask */
+  u16 op,               /* Mask of WO_xx values describing operator */
+  Index *pIdx           /* Must be compatible with this index, if not NULL */
+){
+  WhereTerm *pTerm;
+  int k;
+  for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
+    if( pTerm->leftCursor==iCur
+       && (pTerm->prereqRight & notReady)==0
+       && pTerm->leftColumn==iColumn
+       && (pTerm->operator & op)!=0
+    ){
+      if( iCur>=0 && pIdx ){
+        Expr *pX = pTerm->pExpr;
+        CollSeq *pColl;
+        char idxaff;
+        int k;
+        Parse *pParse = pWC->pParse;
+
+        idxaff = pIdx->pTable->aCol[iColumn].affinity;
+        if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
+        pColl = sqlite3ExprCollSeq(pParse, pX->pLeft);
+        if( !pColl ){
+          if( pX->pRight ){
+            pColl = sqlite3ExprCollSeq(pParse, pX->pRight);
+          }
+          if( !pColl ){
+            pColl = pParse->db->pDfltColl;
+          }
+        }
+        for(k=0; k<pIdx->nColumn && pIdx->aiColumn[k]!=iColumn; k++){}
+        assert( k<pIdx->nColumn );
+        if( pColl!=pIdx->keyInfo.aColl[k] ) continue;
+      }
+      return pTerm;
+    }
+  }
+  return 0;
+}
+
+/* Forward reference */
+static void exprAnalyze(SrcList*, ExprMaskSet*, WhereClause*, int);
+
+/*
+** Call exprAnalyze on all terms in a WHERE clause.  
+**
 **
-** SrcList is the set of tables in the FROM clause in the order that
-** they will be processed.  The value returned here gives us an index
-** of which tables will be processed first.
 */
-static int tableOrder(SrcList *pList, int iCur){
+static void exprAnalyzeAll(
+  SrcList *pTabList,       /* the FROM clause */
+  ExprMaskSet *pMaskSet,   /* table masks */
+  WhereClause *pWC         /* the WHERE clause to be analyzed */
+){
   int i;
-  struct SrcList_item *pItem;
-  for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
-    if( pItem->iCursor==iCur ) return i;
+  for(i=pWC->nTerm-1; i>=0; i--){
+    exprAnalyze(pTabList, pMaskSet, pWC, i);
   }
-  return -1;
 }
 
+#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
 /*
-** The input to this routine is an ExprInfo structure with only the
-** "p" field filled in.  The job of this routine is to analyze the
-** subexpression and populate all the other fields of the ExprInfo
+** Check to see if the given expression is a LIKE or GLOB operator that
+** can be optimized using inequality constraints.  Return TRUE if it is
+** so and false if not.
+**
+** In order for the operator to be optimizible, the RHS must be a string
+** literal that does not begin with a wildcard.  
+*/
+static int isLikeOrGlob(
+  sqlite3 *db,      /* The database */
+  Expr *pExpr,      /* Test this expression */
+  int *pnPattern,   /* Number of non-wildcard prefix characters */
+  int *pisComplete  /* True if the only wildcard is % in the last character */
+){
+  const char *z;
+  Expr *pRight, *pLeft;
+  ExprList *pList;
+  int c, cnt;
+  char wc[3];
+  if( !sqlite3IsLikeFunction(db, pExpr, wc) ){
+    return 0;
+  }
+  pList = pExpr->pList;
+  pRight = pList->a[0].pExpr;
+  if( pRight->op!=TK_STRING ){
+    return 0;
+  }
+  pLeft = pList->a[1].pExpr;
+  if( pLeft->op!=TK_COLUMN ){
+    return 0;
+  }
+  sqlite3DequoteExpr(pRight);
+  z = pRight->token.z;
+  for(cnt=0; (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2]; cnt++){}
+  if( cnt==0 || 255==(u8)z[cnt] ){
+    return 0;
+  }
+  *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
+  *pnPattern = cnt;
+  return 1;
+}
+#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
+
+/*
+** The input to this routine is an WhereTerm structure with only the
+** "pExpr" field filled in.  The job of this routine is to analyze the
+** subexpression and populate all the other fields of the WhereTerm
 ** structure.
+**
+** If the expression is of the form "<expr> <op> X" it gets commuted
+** to the standard form of "X <op> <expr>".  If the expression is of
+** the form "X <op> Y" where both X and Y are columns, then the original
+** expression is unchanged and a new virtual expression of the form
+** "Y <op> X" is added to the WHERE clause.  
 */
-static void exprAnalyze(SrcList *pSrc, ExprMaskSet *pMaskSet, ExprInfo *pInfo){
-  Expr *pExpr = pInfo->p;
-  pInfo->prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
-  pInfo->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);
-  pInfo->prereqAll = exprTableUsage(pMaskSet, pExpr);
-  pInfo->indexable = 0;
-  pInfo->idxLeft = -1;
-  pInfo->idxRight = -1;
-  if( allowedOp(pExpr->op) && (pInfo->prereqRight & pInfo->prereqLeft)==0 ){
-    if( pExpr->pRight && pExpr->pRight->op==TK_COLUMN ){
-      pInfo->idxRight = pExpr->pRight->iTable;
-      pInfo->indexable = 1;
+static void exprAnalyze(
+  SrcList *pSrc,            /* the FROM clause */
+  ExprMaskSet *pMaskSet,    /* table masks */
+  WhereClause *pWC,         /* the WHERE clause */
+  int idxTerm               /* Index of the term to be analyzed */
+){
+  WhereTerm *pTerm = &pWC->a[idxTerm];
+  Expr *pExpr = pTerm->pExpr;
+  Bitmask prereqLeft;
+  Bitmask prereqAll;
+  int idxRight;
+  int nPattern;
+  int isComplete;
+
+  if( sqlite3_malloc_failed ) return;
+  prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
+  pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);
+  pTerm->prereqAll = prereqAll = exprTableUsage(pMaskSet, pExpr);
+  pTerm->leftCursor = -1;
+  pTerm->iParent = -1;
+  pTerm->operator = 0;
+  idxRight = -1;
+  if( allowedOp(pExpr->op) && (pTerm->prereqRight & prereqLeft)==0 ){
+    Expr *pLeft = pExpr->pLeft;
+    Expr *pRight = pExpr->pRight;
+    if( pLeft->op==TK_COLUMN ){
+      pTerm->leftCursor = pLeft->iTable;
+      pTerm->leftColumn = pLeft->iColumn;
+      pTerm->operator = operatorMask(pExpr->op);
     }
-    if( pExpr->pLeft->op==TK_COLUMN ){
-      pInfo->idxLeft = pExpr->pLeft->iTable;
-      pInfo->indexable = 1;
+    if( pRight && pRight->op==TK_COLUMN ){
+      WhereTerm *pNew;
+      Expr *pDup;
+      if( pTerm->leftCursor>=0 ){
+        int idxNew;
+        pDup = sqlite3ExprDup(pExpr);
+        idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
+        if( idxNew==0 ) return;
+        pNew = &pWC->a[idxNew];
+        pNew->iParent = idxTerm;
+        pTerm = &pWC->a[idxTerm];
+        pTerm->nChild = 1;
+        pTerm->flags |= TERM_COPIED;
+      }else{
+        pDup = pExpr;
+        pNew = pTerm;
+      }
+      exprCommute(pDup);
+      pLeft = pDup->pLeft;
+      pNew->leftCursor = pLeft->iTable;
+      pNew->leftColumn = pLeft->iColumn;
+      pNew->prereqRight = prereqLeft;
+      pNew->prereqAll = prereqAll;
+      pNew->operator = operatorMask(pDup->op);
     }
   }
-  if( pInfo->indexable ){
-    assert( pInfo->idxLeft!=pInfo->idxRight );
-
-    /* We want the expression to be of the form "X = expr", not "expr = X".
-    ** So flip it over if necessary.  If the expression is "X = Y", then
-    ** we want Y to come from an earlier table than X.
-    **
-    ** The collating sequence rule is to always choose the left expression.
-    ** So if we do a flip, we also have to move the collating sequence.
-    */
-    if( tableOrder(pSrc,pInfo->idxLeft)<tableOrder(pSrc,pInfo->idxRight) ){
-      assert( pExpr->op!=TK_IN );
-      SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
-      SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
-      if( pExpr->op>=TK_GT ){
-        assert( TK_LT==TK_GT+2 );
-        assert( TK_GE==TK_LE+2 );
-        assert( TK_GT>TK_EQ );
-        assert( TK_GT<TK_LE );
-        assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
-        pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
+
+#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION
+  /* If a term is the BETWEEN operator, create two new virtual terms
+  ** that define the range that the BETWEEN implements.
+  */
+  else if( pExpr->op==TK_BETWEEN ){
+    ExprList *pList = pExpr->pList;
+    int i;
+    static const u8 ops[] = {TK_GE, TK_LE};
+    assert( pList!=0 );
+    assert( pList->nExpr==2 );
+    for(i=0; i<2; i++){
+      Expr *pNewExpr;
+      int idxNew;
+      pNewExpr = sqlite3Expr(ops[i], sqlite3ExprDup(pExpr->pLeft),
+                             sqlite3ExprDup(pList->a[i].pExpr), 0);
+      idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
+      exprAnalyze(pSrc, pMaskSet, pWC, idxNew);
+      pTerm = &pWC->a[idxTerm];
+      pWC->a[idxNew].iParent = idxTerm;
+    }
+    pTerm->nChild = 2;
+  }
+#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */
+
+#ifndef SQLITE_OMIT_OR_OPTIMIZATION
+  /* Attempt to convert OR-connected terms into an IN operator so that
+  ** they can make use of indices.
+  */
+  else if( pExpr->op==TK_OR ){
+    int ok;
+    int i, j;
+    int iColumn, iCursor;
+    WhereClause sOr;
+    WhereTerm *pOrTerm;
+
+    assert( (pTerm->flags & TERM_DYNAMIC)==0 );
+    whereClauseInit(&sOr, pWC->pParse);
+    whereSplit(&sOr, pExpr, TK_OR);
+    exprAnalyzeAll(pSrc, pMaskSet, &sOr);
+    assert( sOr.nTerm>0 );
+    j = 0;
+    do{
+      iColumn = sOr.a[j].leftColumn;
+      iCursor = sOr.a[j].leftCursor;
+      ok = iCursor>=0;
+      for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0 && ok; i--, pOrTerm++){
+        if( pOrTerm->operator!=WO_EQ ){
+          goto or_not_possible;
+        }
+        if( pOrTerm->leftCursor==iCursor && pOrTerm->leftColumn==iColumn ){
+          pOrTerm->flags |= TERM_OR_OK;
+        }else if( (pOrTerm->flags & TERM_COPIED)!=0 ||
+                    ((pOrTerm->flags & TERM_VIRTUAL)!=0 &&
+                     (sOr.a[pOrTerm->iParent].flags & TERM_OR_OK)!=0) ){
+          pOrTerm->flags &= ~TERM_OR_OK;
+        }else{
+          ok = 0;
+        }
+      }
+    }while( !ok && (sOr.a[j++].flags & TERM_COPIED)!=0 && j<sOr.nTerm );
+    if( ok ){
+      ExprList *pList = 0;
+      Expr *pNew, *pDup;
+      for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0 && ok; i--, pOrTerm++){
+        if( (pOrTerm->flags & TERM_OR_OK)==0 ) continue;
+        pDup = sqlite3ExprDup(pOrTerm->pExpr->pRight);
+        pList = sqlite3ExprListAppend(pList, pDup, 0);
+      }
+      pDup = sqlite3Expr(TK_COLUMN, 0, 0, 0);
+      if( pDup ){
+        pDup->iTable = iCursor;
+        pDup->iColumn = iColumn;
       }
-      SWAP(unsigned, pInfo->prereqLeft, pInfo->prereqRight);
-      SWAP(short int, pInfo->idxLeft, pInfo->idxRight);
+      pNew = sqlite3Expr(TK_IN, pDup, 0, 0);
+      if( pNew ) pNew->pList = pList;
+      pTerm->pExpr = pNew;
+      pTerm->flags |= TERM_DYNAMIC;
+      exprAnalyze(pSrc, pMaskSet, pWC, idxTerm);
+      pTerm = &pWC->a[idxTerm];
     }
-  }      
+or_not_possible:
+    whereClauseClear(&sOr);
+  }
+#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
 
+#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
+  /* Add constraints to reduce the search space on a LIKE or GLOB
+  ** operator.
+  */
+  if( isLikeOrGlob(pWC->pParse->db, pExpr, &nPattern, &isComplete) ){
+    Expr *pLeft, *pRight;
+    Expr *pStr1, *pStr2;
+    Expr *pNewExpr1, *pNewExpr2;
+    int idxNew1, idxNew2;
+
+    pLeft = pExpr->pList->a[1].pExpr;
+    pRight = pExpr->pList->a[0].pExpr;
+    pStr1 = sqlite3Expr(TK_STRING, 0, 0, 0);
+    if( pStr1 ){
+      sqlite3TokenCopy(&pStr1->token, &pRight->token);
+      pStr1->token.n = nPattern;
+    }
+    pStr2 = sqlite3ExprDup(pStr1);
+    if( pStr2 ){
+      assert( pStr2->token.dyn );
+      ++*(u8*)&pStr2->token.z[nPattern-1];
+    }
+    pNewExpr1 = sqlite3Expr(TK_GE, sqlite3ExprDup(pLeft), pStr1, 0);
+    idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
+    exprAnalyze(pSrc, pMaskSet, pWC, idxNew1);
+    pNewExpr2 = sqlite3Expr(TK_LT, sqlite3ExprDup(pLeft), pStr2, 0);
+    idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
+    exprAnalyze(pSrc, pMaskSet, pWC, idxNew2);
+    pTerm = &pWC->a[idxTerm];
+    if( isComplete ){
+      pWC->a[idxNew1].iParent = idxTerm;
+      pWC->a[idxNew2].iParent = idxTerm;
+      pTerm->nChild = 2;
+    }
+  }
+#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
 }
 
+
 /*
 ** 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
@@ -322,10 +710,6 @@ static void exprAnalyze(SrcList *pSrc, ExprMaskSet *pMaskSet, ExprInfo *pInfo){
 ** constraints.  Any of these columns may be missing from the ORDER BY
 ** clause and the match can still be a success.
 **
-** 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 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
@@ -394,10 +778,9 @@ static int isSortingIndex(
   }
 
   /* 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.
+  ** are covered.
   */
-  if( j>=nTerm || (i>=pIdx->nColumn && pIdx->onError!=OE_None) ){
+  if( j>=nTerm ){
     *pbRev = sortOrder==SQLITE_SO_DESC;
     return 1;
   }
@@ -426,6 +809,249 @@ static int sortableByRowid(
   return 0;
 }
 
+/*
+** Prepare a crude estimate of the logorithm of the input value.
+** The results need not be exact.  This is only used for estimating
+** the total cost of performing operatings with O(logN) or O(NlogN)
+** complexity.  Because N is just a guess, it is no great tragedy if
+** logN is a little off.
+*/
+static double estLog(double N){
+  double logN = 1.0;
+  double x = 10.0;
+  while( N>x ){
+    logN += 1.0;
+    x *= 10;
+  }
+  return logN;
+}
+
+/*
+** Find the best index for accessing a particular table.  Return a pointer
+** to the index, flags that describe how the index should be used, the
+** number of equality constraints, and the "cost" for this index.
+**
+** The lowest cost index wins.  The cost is an estimate of the amount of
+** CPU and disk I/O need to process the request using the selected index.
+** Factors that influence cost include:
+**
+**    *  The estimated number of rows that will be retrieved.  (The
+**       fewer the better.)
+**
+**    *  Whether or not sorting must occur.
+**
+**    *  Whether or not there must be separate lookups in the
+**       index and in the main table.
+**
+*/
+static double bestIndex(
+  Parse *pParse,              /* The parsing context */
+  WhereClause *pWC,           /* The WHERE clause */
+  struct SrcList_item *pSrc,  /* The FROM clause term to search */
+  Bitmask notReady,           /* Mask of cursors that are not available */
+  ExprList *pOrderBy,         /* The order by clause */
+  Index **ppIndex,            /* Make *ppIndex point to the best index */
+  int *pFlags,                /* Put flags describing this choice in *pFlags */
+  int *pnEq                   /* Put the number of == or IN constraints here */
+){
+  WhereTerm *pTerm;
+  Index *bestIdx = 0;         /* Index that gives the lowest cost */
+  double lowestCost = 1.0e99; /* The cost of using bestIdx */
+  int bestFlags = 0;          /* Flags associated with bestIdx */
+  int bestNEq = 0;            /* Best value for nEq */
+  int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
+  Index *pProbe;              /* An index we are evaluating */
+  int rev;                    /* True to scan in reverse order */
+  int flags;                  /* Flags associated with pProbe */
+  int nEq;                    /* Number of == or IN constraints */
+  double cost;                /* Cost of using pProbe */
+
+  TRACE(("bestIndex: tbl=%s notReady=%x\n", pSrc->pTab->zName, notReady));
+
+  /* Check for a rowid=EXPR or rowid IN (...) constraints
+  */
+  pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
+  if( pTerm ){
+    Expr *pExpr;
+    *ppIndex = 0;
+    bestFlags = WHERE_ROWID_EQ;
+    if( pTerm->operator & WO_EQ ){
+      /* Rowid== is always the best pick.  Look no further.  Because only
+      ** a single row is generated, output is always in sorted order */
+      *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
+      *pnEq = 1;
+      TRACE(("... best is rowid\n"));
+      return 0.0;
+    }else if( (pExpr = pTerm->pExpr)->pList!=0 ){
+      /* Rowid IN (LIST): cost is NlogN where N is the number of list
+      ** elements.  */
+      lowestCost = pExpr->pList->nExpr;
+      lowestCost *= estLog(lowestCost);
+    }else{
+      /* Rowid IN (SELECT): cost is NlogN where N is the number of rows
+      ** in the result of the inner select.  We have no way to estimate
+      ** that value so make a wild guess. */
+      lowestCost = 200.0;
+    }
+    TRACE(("... rowid IN cost: %.9g\n", lowestCost));
+  }
+
+  /* Estimate the cost of a table scan.  If we do not know how many
+  ** entries are in the table, use 1 million as a guess.
+  */
+  pProbe = pSrc->pTab->pIndex;
+  cost = pProbe ? pProbe->aiRowEst[0] : 1000000.0;
+  TRACE(("... table scan base cost: %.9g\n", cost));
+  flags = WHERE_ROWID_RANGE;
+
+  /* Check for constraints on a range of rowids in a table scan.
+  */
+  pTerm = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE|WO_GT|WO_GE, 0);
+  if( pTerm ){
+    if( findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0) ){
+      flags |= WHERE_TOP_LIMIT;
+      cost *= 0.333;  /* Guess that rowid<EXPR eliminates two-thirds or rows */
+    }
+    if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){
+      flags |= WHERE_BTM_LIMIT;
+      cost *= 0.333;  /* Guess that rowid>EXPR eliminates two-thirds of rows */
+    }
+    TRACE(("... rowid range reduces cost to %.9g\n", cost));
+  }else{
+    flags = 0;
+  }
+
+  /* If the table scan does not satisfy the ORDER BY clause, increase
+  ** the cost by NlogN to cover the expense of sorting. */
+  if( pOrderBy ){
+    if( sortableByRowid(iCur, pOrderBy, &rev) ){
+      flags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
+      if( rev ){
+        flags |= WHERE_REVERSE;
+      }
+    }else{
+      cost += cost*estLog(cost);
+      TRACE(("... sorting increases cost to %.9g\n", cost));
+    }
+  }
+  if( cost<lowestCost ){
+    lowestCost = cost;
+    bestFlags = flags;
+  }
+
+  /* Look at each index.
+  */
+  for(; pProbe; pProbe=pProbe->pNext){
+    int i;                       /* Loop counter */
+    double inMultiplier = 1.0;
+
+    TRACE(("... index %s:\n", pProbe->zName));
+
+    /* Count the number of columns in the index that are satisfied
+    ** by x=EXPR constraints or x IN (...) constraints.
+    */
+    flags = 0;
+    for(i=0; i<pProbe->nColumn; i++){
+      int j = pProbe->aiColumn[i];
+      pTerm = findTerm(pWC, iCur, j, notReady, WO_EQ|WO_IN, pProbe);
+      if( pTerm==0 ) break;
+      flags |= WHERE_COLUMN_EQ;
+      if( pTerm->operator & WO_IN ){
+        Expr *pExpr = pTerm->pExpr;
+        flags |= WHERE_COLUMN_IN;
+        if( pExpr->pSelect!=0 ){
+          inMultiplier *= 100.0;
+        }else if( pExpr->pList!=0 ){
+          inMultiplier *= pExpr->pList->nExpr + 1.0;
+        }
+      }
+    }
+    cost = pProbe->aiRowEst[i] * inMultiplier * estLog(inMultiplier);
+    nEq = i;
+    if( pProbe->onError!=OE_None && (flags & WHERE_COLUMN_IN)==0
+         && nEq==pProbe->nColumn ){
+      flags |= WHERE_UNIQUE;
+    }
+    TRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n", nEq, inMultiplier, cost));
+
+    /* Look for range constraints
+    */
+    if( nEq<pProbe->nColumn ){
+      int j = pProbe->aiColumn[nEq];
+      pTerm = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pProbe);
+      if( pTerm ){
+        flags |= WHERE_COLUMN_RANGE;
+        if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pProbe) ){
+          flags |= WHERE_TOP_LIMIT;
+          cost *= 0.333;
+        }
+        if( findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pProbe) ){
+          flags |= WHERE_BTM_LIMIT;
+          cost *= 0.333;
+        }
+        TRACE(("...... range reduces cost to %.9g\n", cost));
+      }
+    }
+
+    /* Add the additional cost of sorting if that is a factor.
+    */
+    if( pOrderBy ){
+      if( (flags & WHERE_COLUMN_IN)==0 &&
+           isSortingIndex(pParse,pProbe,pSrc->pTab,iCur,pOrderBy,nEq,&rev) ){
+        if( flags==0 ){
+          flags = WHERE_COLUMN_RANGE;
+        }
+        flags |= WHERE_ORDERBY;
+        if( rev ){
+          flags |= WHERE_REVERSE;
+        }
+      }else{
+        cost += cost*estLog(cost);
+        TRACE(("...... orderby increases cost to %.9g\n", cost));
+      }
+    }
+
+    /* Check to see if we can get away with using just the index without
+    ** ever reading the table.  If that is the case, then halve the
+    ** cost of this index.
+    */
+    if( flags && pSrc->colUsed < (((Bitmask)1)<<(BMS-1)) ){
+      Bitmask m = pSrc->colUsed;
+      int j;
+      for(j=0; j<pProbe->nColumn; j++){
+        int x = pProbe->aiColumn[j];
+        if( x<BMS-1 ){
+          m &= ~(((Bitmask)1)<<x);
+        }
+      }
+      if( m==0 ){
+        flags |= WHERE_IDX_ONLY;
+        cost *= 0.5;
+        TRACE(("...... idx-only reduces cost to %.9g\n", cost));
+      }
+    }
+
+    /* If this index has achieved the lowest cost so far, then use it.
+    */
+    if( cost < lowestCost ){
+      bestIdx = pProbe;
+      lowestCost = cost;
+      assert( flags!=0 );
+      bestFlags = flags;
+      bestNEq = nEq;
+    }
+  }
+
+  /* Report the best result
+  */
+  *ppIndex = bestIdx;
+  TRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n",
+        bestIdx ? bestIdx->zName : "(none)", lowestCost, bestFlags, bestNEq));
+  *pFlags = bestFlags;
+  *pnEq = bestNEq;
+  return lowestCost;
+}
+
 
 /*
 ** Disable a term in the WHERE clause.  Except, do not disable the term
@@ -449,10 +1075,18 @@ static int sortableByRowid(
 ** too much.  If we disabled in (1), we'd get the wrong answer.
 ** See ticket #813.
 */
-static void disableTerm(WhereLevel *pLevel, Expr **ppExpr){
-  Expr *pExpr = *ppExpr;
-  if( pLevel->iLeftJoin==0 || ExprHasProperty(pExpr, EP_FromJoin) ){
-    *ppExpr = 0;
+static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
+  if( pTerm
+      && (pTerm->flags & TERM_CODED)==0
+      && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
+  ){
+    pTerm->flags |= TERM_CODED;
+    if( pTerm->iParent>=0 ){
+      WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
+      if( (--pOther->nChild)==0 ){
+        disableTerm(pLevel, pOther);
+      }
+    }
   }
 }
 
@@ -475,41 +1109,138 @@ static void buildIndexProbe(Vdbe *v, int nColumn, int brk, Index *pIdx){
   sqlite3IndexAffinityStr(v, pIdx);
 }
 
+
 /*
-** Generate code for an equality term of the WHERE clause.  An equality
-** term can be either X=expr  or X IN (...).   pTerm is the X.  
+** Generate code for a single equality term of the WHERE clause.  An equality
+** term can be either X=expr or X IN (...).   pTerm is the term to be 
+** coded.
+**
+** The current value for the constraint is left on the top of the stack.
+**
+** For a constraint of the form X=expr, the expression is evaluated and its
+** result is left on the stack.  For constraints of the form X IN (...)
+** this routine sets up a loop that will iterate over all values of X.
 */
 static void codeEqualityTerm(
   Parse *pParse,      /* The parsing context */
-  ExprInfo *pTerm,    /* The term of the WHERE clause to be coded */
+  WhereTerm *pTerm,   /* The term of the WHERE clause to be coded */
   int brk,            /* Jump here to abandon the loop */
   WhereLevel *pLevel  /* When level of the FROM clause we are working on */
 ){
-  Expr *pX = pTerm->p;
+  Expr *pX = pTerm->pExpr;
   if( pX->op!=TK_IN ){
     assert( pX->op==TK_EQ );
     sqlite3ExprCode(pParse, pX->pRight);
 #ifndef SQLITE_OMIT_SUBQUERY
   }else{
     int iTab;
+    int *aIn;
     Vdbe *v = pParse->pVdbe;
 
     sqlite3CodeSubselect(pParse, pX);
     iTab = pX->iTable;
     sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk);
     VdbeComment((v, "# %.*s", pX->span.n, pX->span.z));
-    pLevel->inP2 = sqlite3VdbeAddOp(v, OP_Column, iTab, 0);
-    pLevel->inOp = OP_Next;
-    pLevel->inP1 = iTab;
+    pLevel->nIn++;
+    pLevel->aInLoop = aIn = sqliteRealloc(pLevel->aInLoop,
+                                 sizeof(pLevel->aInLoop[0])*3*pLevel->nIn);
+    if( aIn ){
+      aIn += pLevel->nIn*3 - 3;
+      aIn[0] = OP_Next;
+      aIn[1] = iTab;
+      aIn[2] = sqlite3VdbeAddOp(v, OP_Column, iTab, 0);
+    }else{
+      pLevel->nIn = 0;
+    }
 #endif
   }
-  disableTerm(pLevel, &pTerm->p);
+  disableTerm(pLevel, pTerm);
 }
 
 /*
-** The number of bits in a Bitmask
+** Generate code that will evaluate all == and IN constraints for an
+** index.  The values for all constraints are left on the stack.
+**
+** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
+** Suppose the WHERE clause is this:  a==5 AND b IN (1,2,3) AND c>5 AND c<10
+** The index has as many as three equality constraints, but in this
+** example, the third "c" value is an inequality.  So only two 
+** constraints are coded.  This routine will generate code to evaluate
+** a==5 and b IN (1,2,3).  The current values for a and b will be left
+** on the stack - a is the deepest and b the shallowest.
+**
+** In the example above nEq==2.  But this subroutine works for any value
+** of nEq including 0.  If nEq==0, this routine is nearly a no-op.
+** The only thing it does is allocate the pLevel->iMem memory cell.
+**
+** This routine always allocates at least one memory cell and puts
+** the address of that memory cell in pLevel->iMem.  The code that
+** calls this routine will use pLevel->iMem to store the termination
+** key value of the loop.  If one or more IN operators appear, then
+** this routine allocates an additional nEq memory cells for internal
+** use.
 */
-#define BMS  (sizeof(Bitmask)*8-1)
+static void codeAllEqualityTerms(
+  Parse *pParse,        /* Parsing context */
+  WhereLevel *pLevel,   /* Which nested loop of the FROM we are coding */
+  WhereClause *pWC,     /* The WHERE clause */
+  Bitmask notReady,     /* Which parts of FROM have not yet been coded */
+  int brk               /* Jump here to end the loop */
+){
+  int nEq = pLevel->nEq;        /* The number of == or IN constraints to code */
+  int termsInMem = 0;           /* If true, store value in mem[] cells */
+  Vdbe *v = pParse->pVdbe;      /* The virtual machine under construction */
+  Index *pIdx = pLevel->pIdx;   /* The index being used for this loop */
+  int iCur = pLevel->iTabCur;   /* The cursor of the table */
+  WhereTerm *pTerm;             /* A single constraint term */
+  int j;                        /* Loop counter */
+
+  /* Figure out how many memory cells we will need then allocate them.
+  ** We always need at least one used to store the loop terminator
+  ** value.  If there are IN operators we'll need one for each == or
+  ** IN constraint.
+  */
+  pLevel->iMem = pParse->nMem++;
+  if( pLevel->flags & WHERE_COLUMN_IN ){
+    pParse->nMem += pLevel->nEq;
+    termsInMem = 1;
+  }
+
+  /* Evaluate the equality constraints
+  */
+  for(j=0; j<pIdx->nColumn; j++){
+    int k = pIdx->aiColumn[j];
+    pTerm = findTerm(pWC, iCur, k, notReady, WO_EQ|WO_IN, pIdx);
+    if( pTerm==0 ) break;
+    assert( (pTerm->flags & TERM_CODED)==0 );
+    codeEqualityTerm(pParse, pTerm, brk, pLevel);
+    if( termsInMem ){
+      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem+j+1, 1);
+    }
+  }
+  assert( j==nEq );
+
+  /* Make sure all the constraint values are on the top of the stack
+  */
+  if( termsInMem ){
+    for(j=0; j<nEq; j++){
+      sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem+j+1, 0);
+    }
+  }
+}
+
+#ifdef SQLITE_TEST
+/*
+** The following variable holds a text description of query plan generated
+** by the most recent call to sqlite3WhereBegin().  Each call to WhereBegin
+** overwrites the previous.  This information is used for testing and
+** analysis only.
+*/
+char sqlite3_query_plan[BMS*2*40];  /* Text of the join */
+static int nQPlan = 0;              /* Next free slow in _query_plan[] */
+
+#endif /* SQLITE_TEST */
+
 
 
 /*
@@ -538,6 +1269,12 @@ static void codeEqualityTerm(
 **        end                        |-- by sqlite3WhereEnd()
 **      end                         /
 **
+** Note that the loops might not be nested in the order in which they
+** appear in the FROM clause if a different order is better able to make
+** use of indices.  Note also that when the IN operator appears in
+** the WHERE clause, it might result in additional nested loops for
+** scanning through all values on the right-hand side of the IN.
+**
 ** There are Btree cursors associated with each table.  t1 uses cursor
 ** number pTabList->a[0].iCursor.  t2 uses the cursor pTabList->a[1].iCursor.
 ** And so forth.  This routine generates code to open those VDBE cursors
@@ -604,47 +1341,36 @@ WhereInfo *sqlite3WhereBegin(
   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 */
-  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[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 */
+  Bitmask notReady;          /* Cursors that are not yet positioned */
+  WhereTerm *pTerm;          /* A single term in the WHERE clause */
+  ExprMaskSet maskSet;       /* The expression mask set */
+  WhereClause wc;            /* 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 */
+  int iFrom;                      /* First unused FROM clause element */
+  int andFlags;              /* AND-ed combination of all wc.a[].flags */
 
-  /* The number of terms in the FROM clause is limited by the number of
+  /* The number of tables in the FROM clause is limited by the number of
   ** bits in a Bitmask 
   */
-  if( pTabList->nSrc>sizeof(Bitmask)*8 ){
-    sqlite3ErrorMsg(pParse, "at most %d tables in a join",
-       sizeof(Bitmask)*8);
+  if( pTabList->nSrc>BMS ){
+    sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
     return 0;
   }
 
   /* Split the WHERE clause into separate subexpressions where each
-  ** subexpression is separated by an AND operator.  If the aExpr[]
-  ** array fills up, the last entry might point to an expression which
-  ** contains additional unfactored AND operators.
+  ** subexpression is separated by an AND operator.
   */
   initMaskSet(&maskSet);
-  memset(aExpr, 0, sizeof(aExpr));
-  nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere);
-  if( nExpr==ARRAYSIZE(aExpr) ){
-    sqlite3ErrorMsg(pParse, "WHERE clause too complex - no more "
-       "than %d terms allowed", (int)ARRAYSIZE(aExpr)-1);
-    return 0;
-  }
+  whereClauseInit(&wc, pParse);
+  whereSplit(&wc, pWhere, TK_AND);
     
   /* Allocate and initialize the WhereInfo structure that will become the
   ** return value.
   */
   pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
   if( sqlite3_malloc_failed ){
-    sqliteFree(pWInfo); /* Avoid leaking memory when malloc fails */
-    return 0;
+    goto whereBeginNoMem;
   }
   pWInfo->pParse = pParse;
   pWInfo->pTabList = pTabList;
@@ -658,272 +1384,95 @@ WhereInfo *sqlite3WhereBegin(
     pWhere = 0;
   }
 
-  /* Analyze all of the subexpressions.
+  /* Analyze all of the subexpressions.  Note that exprAnalyze() might
+  ** add new virtual terms onto the end of the WHERE clause.  We do not
+  ** want to analyze these virtual terms, so start analyzing at the end
+  ** and work forward so that they added virtual terms are never processed.
   */
   for(i=0; i<pTabList->nSrc; i++){
     createMask(&maskSet, pTabList->a[i].iCursor);
   }
-  for(pTerm=aExpr, i=0; i<nExpr; i++, pTerm++){
-    exprAnalyze(pTabList, &maskSet, pTerm);
+  exprAnalyzeAll(pTabList, &maskSet, &wc);
+  if( sqlite3_malloc_failed ){
+    goto whereBeginNoMem;
   }
 
-  /* Figure out what index to use (if any) for each nested loop.
-  ** Make pWInfo->a[i].pIdx point to the index to use for the i-th nested
-  ** loop where i==0 is the outer loop and i==pTabList->nSrc-1 is the inner
-  ** loop. 
+  /* Chose the best index to use for each table in the FROM clause.
   **
-  ** If terms exist that use the ROWID of any table, then set the
-  ** iDirectEq[], iDirectLt[], or iDirectGt[] elements for that table
-  ** to the index of the term containing the ROWID.  We always prefer
-  ** to use a ROWID which can directly access a table rather than an
-  ** index which requires reading an index first to get the rowid then
-  ** doing a second read of the actual database table.
+  ** This loop fills in the following fields:
   **
-  ** Actually, if there are more than 32 tables in the join, only the
-  ** first 32 tables are candidates for indices.  This is (again) due
-  ** to the limit of 32 bits in an integer bitmask.
+  **   pWInfo->a[].pIdx      The index to use for this level of the loop.
+  **   pWInfo->a[].flags     WHERE_xxx flags associated with pIdx
+  **   pWInfo->a[].nEq       The number of == and IN constraints
+  **   pWInfo->a[].iFrom     When term of the FROM clause is being coded
+  **   pWInfo->a[].iTabCur   The VDBE cursor for the database table
+  **   pWInfo->a[].iIdxCur   The VDBE cursor for the index
+  **
+  ** This loop also figures out the nesting order of tables in the FROM
+  ** clause.
   */
-  loopMask = 0;
+  notReady = ~(Bitmask)0;
   pTabItem = pTabList->a;
   pLevel = pWInfo->a;
-  for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++,pTabItem++,pLevel++){
-    int j;
-    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
-    ** set iDirectEq[i] to the index of the term.  For terms of the
-    ** form ROWID<expr or ROWID<=expr set iDirectLt[i] to the term index.
-    ** For terms like ROWID>expr or ROWID>=expr set iDirectGt[i].
-    **
-    ** (Added:) Treat ROWID IN expr like ROWID=expr.
-    */
-    pLevel->iIdxCur = -1;
-    iDirectEq[i] = -1;
-    iDirectLt[i] = -1;
-    iDirectGt[i] = -1;
-    for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){
-      Expr *pX = pTerm->p;
-      if( pTerm->idxLeft==iCur && pX->pLeft->iColumn<0
-            && (pTerm->prereqRight & loopMask)==pTerm->prereqRight ){
-        switch( pX->op ){
-          case TK_IN:
-          case TK_EQ: iDirectEq[i] = j; break;
-          case TK_LE:
-          case TK_LT: iDirectLt[i] = j; break;
-          case TK_GE:
-          case TK_GT: iDirectGt[i] = j;  break;
-        }
-      }
-    }
-
-    /* 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;
-      continue;
-    }
-
-    /* Do a search for usable indices.  Leave pBestIdx pointing to
-    ** the "best" index.  pBestIdx is left set to NULL if no indices
-    ** are usable.
-    **
-    ** 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
-    ** 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&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&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
-    ** an equality comparison except that it can only be used on the
-    ** left-most column of an index and other terms of the WHERE clause
-    ** cannot be used in conjunction with the IN operator to help satisfy
-    ** other columns of the index.
-    */
-    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
-      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>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);
-        if( !pColl && pX->pRight ){
-          pColl = sqlite3ExprCollSeq(pParse, pX->pRight);
-        }
-        if( !pColl ){
-          pColl = pParse->db->pDfltColl;
-        }
-        if( pTerm->idxLeft==iCur 
-             && (pTerm->prereqRight & loopMask)==pTerm->prereqRight ){
-          int iColumn = pX->pLeft->iColumn;
-          int k;
-          char idxaff = iColumn>=0 ? pIdx->pTable->aCol[iColumn].affinity : 0; 
-          for(k=0; k<pIdx->nColumn; k++){
-            /* If the collating sequences or affinities don't match, 
-            ** ignore this index.  */
-            if( pColl!=pIdx->keyInfo.aColl[k] ) continue;
-            if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
-            if( pIdx->aiColumn[k]==iColumn ){
-              switch( pX->op ){
-                case TK_IN: {
-                  if( k==0 ) inMask |= 1;
-                  break;
-                }
-                case TK_EQ: {
-                  eqMask |= ((Bitmask)1)<<k;
-                  break;
-                }
-                case TK_LE:
-                case TK_LT: {
-                  ltMask |= ((Bitmask)1)<<k;
-                  break;
-                }
-                case TK_GE:
-                case TK_GT: {
-                  gtMask |= ((Bitmask)1)<<k;
-                  break;
-                }
-                default: {
-                  /* CANT_HAPPEN */
-                  assert( 0 );
-                  break;
-                }
-              }
-              break;
-            }
-          }
-        }
-      }
-
-      /* The following loop ends with nEq set to the number of columns
-      ** on the left of the index with == constraints.
-      */
-      for(nEq=0; nEq<pIdx->nColumn; nEq++){
-        m = (((Bitmask)1)<<(nEq+1))-1;
-        if( (m & eqMask)!=m ) break;
+  andFlags = ~0;
+  for(i=iFrom=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
+    Index *pIdx;                /* Index for FROM table at pTabItem */
+    int flags;                  /* Flags asssociated with pIdx */
+    int nEq;                    /* Number of == or IN constraints */
+    double cost;                /* The cost for pIdx */
+    int j;                      /* For looping over FROM tables */
+    Index *pBest = 0;           /* The best index seen so far */
+    int bestFlags = 0;          /* Flags associated with pBest */
+    int bestNEq = 0;            /* nEq associated with pBest */
+    double lowestCost = 1.0e99; /* Cost of the pBest */
+    int bestJ;                  /* The value of j */
+    Bitmask m;                  /* Bitmask value for j or bestJ */
+
+    for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){
+      m = getMask(&maskSet, pTabItem->iCursor);
+      if( (m & notReady)==0 ){
+        if( j==iFrom ) iFrom++;
+        continue;
       }
-
-      /* 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;
-        }
+      cost = bestIndex(pParse, &wc, pTabItem, notReady,
+                       (j==0 && ppOrderBy) ? *ppOrderBy : 0,
+                       &pIdx, &flags, &nEq);
+      if( cost<lowestCost ){
+        lowestCost = cost;
+        pBest = pIdx;
+        bestFlags = flags;
+        bestNEq = nEq;
+        bestJ = j;
       }
-
-      /* 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;
+      if( (pTabItem->jointype & JT_LEFT)!=0
+         || (j>0 && (pTabItem[-1].jointype & JT_LEFT)!=0)
+      ){
+        break;
       }
     }
-    pLevel->pIdx = pBestIdx;
-    pLevel->score = bestScore;
-    pLevel->bRev = bestRev;
-    loopMask |= mask;
-    if( pBestIdx ){
+    if( (bestFlags & WHERE_ORDERBY)!=0 ){
+      *ppOrderBy = 0;
+    }
+    andFlags &= bestFlags;
+    pLevel->flags = bestFlags;
+    pLevel->pIdx = pBest;
+    pLevel->nEq = bestNEq;
+    pLevel->aInLoop = 0;
+    pLevel->nIn = 0;
+    if( pBest ){
       pLevel->iIdxCur = pParse->nTab++;
+    }else{
+      pLevel->iIdxCur = -1;
     }
+    notReady &= ~getMask(&maskSet, pTabList->a[bestJ].iCursor);
+    pLevel->iFrom = bestJ;
   }
 
-  /* Check to see if the ORDER BY clause is or can be satisfied by the
-  ** use of an index on the first table.
+  /* If the total query only selects a single row, then the ORDER BY
+  ** clause is irrelevant.
   */
-  if( ppOrderBy && *ppOrderBy && pTabList->nSrc>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;
-    }
+  if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){
+    *ppOrderBy = 0;
   }
 
   /* Open all tables in the pTabList and any indices selected for
@@ -931,55 +1480,64 @@ WhereInfo *sqlite3WhereBegin(
   */
   sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
   pLevel = pWInfo->a;
-  for(i=0, pTabItem=pTabList->a; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
+  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
     Table *pTab;
     Index *pIx;
     int iIdxCur = pLevel->iIdxCur;
 
+    pTabItem = &pTabList->a[pLevel->iFrom];
     pTab = pTabItem->pTab;
     if( pTab->isTransient || pTab->pSelect ) continue;
-    if( (pLevel->score & 1)==0 ){
+    if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
       sqlite3OpenTableForReading(v, pTabItem->iCursor, pTab);
     }
     pLevel->iTabCur = pTabItem->iCursor;
     if( (pIx = pLevel->pIdx)!=0 ){
       sqlite3VdbeAddOp(v, OP_Integer, pIx->iDb, 0);
+      VdbeComment((v, "# %s", pIx->zName));
       sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum,
                      (char*)&pIx->keyInfo, P3_KEYINFO);
     }
-    if( (pLevel->score & 1)!=0 ){
+    if( (pLevel->flags & WHERE_IDX_ONLY)!=0 ){
       sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
     }
     sqlite3CodeVerifySchema(pParse, pTab->iDb);
   }
   pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
 
-  /* Generate the code to do the search
+  /* Generate the code to do the search.  Each iteration of the for
+  ** loop below generates code for a single nested loop of the VM
+  ** program.
   */
-  loopMask = 0;
-  pLevel = pWInfo->a;
-  pTabItem = pTabList->a;
-  for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
-    int j, k;
+  notReady = ~(Bitmask)0;
+  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
+    int j;
     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 */
+    int bRev;          /* True if we need to scan in reverse order */
 
+    pTabItem = &pTabList->a[pLevel->iFrom];
+    iCur = pTabItem->iCursor;
     pIdx = pLevel->pIdx;
     iIdxCur = pLevel->iIdxCur;
-    pLevel->inOp = OP_Noop;
+    bRev = (pLevel->flags & WHERE_REVERSE)!=0;
+    omitTable = (pLevel->flags & WHERE_IDX_ONLY)!=0;
 
-    /* Check to see if it is appropriate to omit the use of the table
-    ** here and use its index instead.
+    /* Create labels for the "break" and "continue" instructions
+    ** for the current loop.  Jump to brk to break out of a loop.
+    ** Jump to cont to go immediately to the next iteration of the
+    ** loop.
     */
-    omitTable = (pLevel->score&1)!=0;
+    brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
+    cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
 
     /* If this is the right table of a LEFT OUTER JOIN, allocate and
     ** initialize a memory cell that records if this table matches any
     ** row of the left table of the join.
     */
-    if( i>0 && (pTabList->a[i-1].jointype & JT_LEFT)!=0 ){
+    if( pLevel->iFrom>0 && (pTabItem[-1].jointype & JT_LEFT)!=0 ){
       if( !pParse->nMem ) pParse->nMem++;
       pLevel->iLeftJoin = pParse->nMem++;
       sqlite3VdbeAddOp(v, OP_Null, 0, 0);
@@ -987,122 +1545,55 @@ WhereInfo *sqlite3WhereBegin(
       VdbeComment((v, "# init LEFT JOIN no-match flag"));
     }
 
-    if( i<ARRAYSIZE(iDirectEq) && (k = iDirectEq[i])>=0 ){
+    if( pLevel->flags & WHERE_ROWID_EQ ){
       /* Case 1:  We can directly reference a single row using an
       **          equality comparison against the ROWID field.  Or
       **          we reference multiple rows using a "rowid IN (...)"
       **          construct.
       */
-      assert( k<nExpr );
-      pTerm = &aExpr[k];
-      assert( pTerm->p!=0 );
-      assert( pTerm->idxLeft==iCur );
+      pTerm = findTerm(&wc, iCur, -1, notReady, WO_EQ|WO_IN, 0);
+      assert( pTerm!=0 );
+      assert( pTerm->pExpr!=0 );
+      assert( pTerm->leftCursor==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);
       sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk);
       VdbeComment((v, "pk"));
       pLevel->op = OP_Noop;
-    }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 using the "==" or "IN" operators.
-      */
-      int start;
-      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
-      ** constraints that column.  If the WHERE clause term is X=expr, then
-      ** evaluation expr and leave the result on the stack */
-      for(j=0; j<nColumn; j++){
-        for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){
-          Expr *pX = pTerm->p;
-          if( pX==0 ) continue;
-          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) ){
-              codeEqualityTerm(pParse, pTerm, brk, pLevel);
-              break;
-            }
-          }
-        }
-      }
-      pLevel->iMem = pParse->nMem++;
-      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
-      buildIndexProbe(v, nColumn, brk, pIdx);
-      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
-
-      /* Generate code (1) to move to the first matching element of the table.
-      ** Then generate code (2) that jumps to "brk" after the cursor is past
-      ** the last matching element of the table.  The code (1) is executed
-      ** once to initialize the search, the code (2) is executed before each
-      ** iteration of the scan to see if the scan has finished. */
-      if( pLevel->bRev ){
-        /* Scan in reverse order */
-        sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, brk);
-        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
-        sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, brk);
-        pLevel->op = OP_Prev;
-      }else{
-        /* Scan in the forward order */
-        sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, brk);
-        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
-        sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, brk, "+", P3_STATIC);
-        pLevel->op = OP_Next;
-      }
-      sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
-      sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
-      if( !omitTable ){
-        sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
-        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
-      }
-      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.
+    }else if( pLevel->flags & WHERE_ROWID_RANGE ){
+      /* Case 2:  We have an inequality comparison against the ROWID field.
       */
       int testOp = OP_Noop;
       int start;
-      int bRev = pLevel->bRev;
+      WhereTerm *pStart, *pEnd;
 
       assert( omitTable==0 );
-      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
-      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
+      pStart = findTerm(&wc, iCur, -1, notReady, WO_GT|WO_GE, 0);
+      pEnd = findTerm(&wc, iCur, -1, notReady, WO_LT|WO_LE, 0);
       if( bRev ){
-        int t = iDirectGt[i];
-        iDirectGt[i] = iDirectLt[i];
-        iDirectLt[i] = t;
+        pTerm = pStart;
+        pStart = pEnd;
+        pEnd = pTerm;
       }
-      if( iDirectGt[i]>=0 ){
+      if( pStart ){
         Expr *pX;
-        k = iDirectGt[i];
-        assert( k<nExpr );
-        pTerm = &aExpr[k];
-        pX = pTerm->p;
+        pX = pStart->pExpr;
         assert( pX!=0 );
-        assert( pTerm->idxLeft==iCur );
+        assert( pStart->leftCursor==iCur );
         sqlite3ExprCode(pParse, pX->pRight);
         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);
+        disableTerm(pLevel, pStart);
       }else{
         sqlite3VdbeAddOp(v, bRev ? OP_Last : OP_Rewind, iCur, brk);
       }
-      if( iDirectLt[i]>=0 ){
+      if( pEnd ){
         Expr *pX;
-        k = iDirectLt[i];
-        assert( k<nExpr );
-        pTerm = &aExpr[k];
-        pX = pTerm->p;
+        pX = pEnd->pExpr;
         assert( pX!=0 );
-        assert( pTerm->idxLeft==iCur );
+        assert( pEnd->leftCursor==iCur );
         sqlite3ExprCode(pParse, pX->pRight);
         pLevel->iMem = pParse->nMem++;
         sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
@@ -1111,7 +1602,7 @@ WhereInfo *sqlite3WhereBegin(
         }else{
           testOp = bRev ? OP_Lt : OP_Gt;
         }
-        disableTerm(pLevel, &pTerm->p);
+        disableTerm(pLevel, pEnd);
       }
       start = sqlite3VdbeCurrentAddr(v);
       pLevel->op = bRev ? OP_Prev : OP_Next;
@@ -1122,77 +1613,38 @@ WhereInfo *sqlite3WhereBegin(
         sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
         sqlite3VdbeAddOp(v, testOp, 'n', brk);
       }
-    }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);
-      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->p1 = iCur;
-      pLevel->p2 = start;
-    }else{
-      /* Case 5: The WHERE clause term that refers to the right-most
+    }else if( pLevel->flags & WHERE_COLUMN_RANGE ){
+      /* Case 3: The WHERE clause term that refers to the right-most
       **         column of the index is an inequality.  For example, if
       **         the index is on (x,y,z) and the WHERE clause is of the
       **         form "x=5 AND y<10" then this case is used.  Only the
       **         right-most column can be an inequality - the rest must
-      **         use the "==" operator.
+      **         use the "==" and "IN" operators.
       **
       **         This case is also used when there are no WHERE clause
       **         constraints but an index is selected anyway, in order
       **         to force the output order to conform to an ORDER BY.
       */
-      int score = pLevel->score;
-      int nEqColumn = score/32;
       int start;
+      int nEq = pLevel->nEq;
       int leFlag=0, geFlag=0;
       int testOp;
+      int topLimit = (pLevel->flags & WHERE_TOP_LIMIT)!=0;
+      int btmLimit = (pLevel->flags & WHERE_BTM_LIMIT)!=0;
 
-      /* Evaluate the equality constraints
+      /* Generate code to evaluate all constraint terms using == or IN
+      ** and level the values of those terms on the stack.
       */
-      for(j=0; j<nEqColumn; j++){
-        int iIdxCol = pIdx->aiColumn[j];
-        for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){
-          Expr *pX = pTerm->p;
-          if( pX==0 ) continue;
-          if( pTerm->idxLeft==iCur
-             && pX->op==TK_EQ
-             && (pTerm->prereqRight & loopMask)==pTerm->prereqRight 
-             && pX->pLeft->iColumn==iIdxCol
-          ){
-            sqlite3ExprCode(pParse, pX->pRight);
-            disableTerm(pLevel, &pTerm->p);
-            break;
-          }
-        }
-      }
+      codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk);
 
       /* Duplicate the equality term values because they will all be
       ** used twice: once to make the termination key and once to make the
       ** start key.
       */
-      for(j=0; j<nEqColumn; j++){
-        sqlite3VdbeAddOp(v, OP_Dup, nEqColumn-1, 0);
+      for(j=0; j<nEq; j++){
+        sqlite3VdbeAddOp(v, OP_Dup, nEq-1, 0);
       }
 
-      /* Labels for the beginning and end of the loop
-      */
-      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
-      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
-
       /* Generate the termination key.  This is the key value that
       ** will end the search.  There is no termination key if there
       ** are no equality terms and no "X<..." term.
@@ -1200,37 +1652,32 @@ 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 & 4)!=0 ){
-        for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){
-          Expr *pX = pTerm->p;
-          if( pX==0 ) continue;
-          if( pTerm->idxLeft==iCur
-             && (pX->op==TK_LT || pX->op==TK_LE)
-             && (pTerm->prereqRight & loopMask)==pTerm->prereqRight 
-             && pX->pLeft->iColumn==pIdx->aiColumn[j]
-          ){
-            sqlite3ExprCode(pParse, pX->pRight);
-            leFlag = pX->op==TK_LE;
-            disableTerm(pLevel, &pTerm->p);
-            break;
-          }
-        }
+      if( topLimit ){
+        Expr *pX;
+        int k = pIdx->aiColumn[j];
+        pTerm = findTerm(&wc, iCur, k, notReady, WO_LT|WO_LE, pIdx);
+        assert( pTerm!=0 );
+        pX = pTerm->pExpr;
+        assert( (pTerm->flags & TERM_CODED)==0 );
+        sqlite3ExprCode(pParse, pX->pRight);
+        leFlag = pX->op==TK_LE;
+        disableTerm(pLevel, pTerm);
         testOp = OP_IdxGE;
       }else{
-        testOp = nEqColumn>0 ? OP_IdxGE : OP_Noop;
+        testOp = nEq>0 ? OP_IdxGE : OP_Noop;
         leFlag = 1;
       }
       if( testOp!=OP_Noop ){
-        int nCol = nEqColumn + ((score & 4)!=0);
+        int nCol = nEq + topLimit;
         pLevel->iMem = pParse->nMem++;
         buildIndexProbe(v, nCol, brk, pIdx);
-        if( pLevel->bRev ){
+        if( bRev ){
           int op = leFlag ? OP_MoveLe : OP_MoveLt;
           sqlite3VdbeAddOp(v, op, iIdxCur, brk);
         }else{
           sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
         }
-      }else if( pLevel->bRev ){
+      }else if( bRev ){
         sqlite3VdbeAddOp(v, OP_Last, iIdxCur, brk);
       }
 
@@ -1243,28 +1690,23 @@ 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 & 8)!=0 ){
-        for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){
-          Expr *pX = pTerm->p;
-          if( pX==0 ) continue;
-          if( pTerm->idxLeft==iCur
-             && (pX->op==TK_GT || pX->op==TK_GE)
-             && (pTerm->prereqRight & loopMask)==pTerm->prereqRight 
-             && pX->pLeft->iColumn==pIdx->aiColumn[j]
-          ){
-            sqlite3ExprCode(pParse, pX->pRight);
-            geFlag = pX->op==TK_GE;
-            disableTerm(pLevel, &pTerm->p);
-            break;
-          }
-        }
+      if( btmLimit ){
+        Expr *pX;
+        int k = pIdx->aiColumn[j];
+        pTerm = findTerm(&wc, iCur, k, notReady, WO_GT|WO_GE, pIdx);
+        assert( pTerm!=0 );
+        pX = pTerm->pExpr;
+        assert( (pTerm->flags & TERM_CODED)==0 );
+        sqlite3ExprCode(pParse, pX->pRight);
+        geFlag = pX->op==TK_GE;
+        disableTerm(pLevel, pTerm);
       }else{
         geFlag = 1;
       }
-      if( nEqColumn>0 || (score&8)!=0 ){
-        int nCol = nEqColumn + ((score&8)!=0);
+      if( nEq>0 || btmLimit ){
+        int nCol = nEq + btmLimit;
         buildIndexProbe(v, nCol, brk, pIdx);
-        if( pLevel->bRev ){
+        if( bRev ){
           pLevel->iMem = pParse->nMem++;
           sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
           testOp = OP_IdxLT;
@@ -1272,7 +1714,7 @@ WhereInfo *sqlite3WhereBegin(
           int op = geFlag ? OP_MoveGe : OP_MoveGt;
           sqlite3VdbeAddOp(v, op, iIdxCur, brk);
         }
-      }else if( pLevel->bRev ){
+      }else if( bRev ){
         testOp = OP_Noop;
       }else{
         sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, brk);
@@ -1286,12 +1728,12 @@ WhereInfo *sqlite3WhereBegin(
       if( testOp!=OP_Noop ){
         sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
         sqlite3VdbeAddOp(v, testOp, iIdxCur, brk);
-        if( (leFlag && !pLevel->bRev) || (!geFlag && pLevel->bRev) ){
+        if( (leFlag && !bRev) || (!geFlag && bRev) ){
           sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
         }
       }
       sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
-      sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + ((score&4)!=0), cont);
+      sqlite3VdbeAddOp(v, OP_IdxIsNull, nEq + topLimit, cont);
       if( !omitTable ){
         sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
         sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
@@ -1299,25 +1741,80 @@ WhereInfo *sqlite3WhereBegin(
 
       /* Record the instruction used to terminate the loop.
       */
-      pLevel->op = pLevel->bRev ? OP_Prev : OP_Next;
+      pLevel->op = bRev ? OP_Prev : OP_Next;
+      pLevel->p1 = iIdxCur;
+      pLevel->p2 = start;
+    }else if( pLevel->flags & WHERE_COLUMN_EQ ){
+      /* Case 4:  There is an index and all terms of the WHERE clause that
+      **          refer to the index using the "==" or "IN" operators.
+      */
+      int start;
+      int nEq = pLevel->nEq;
+
+      /* Generate code to evaluate all constraint terms using == or IN
+      ** and leave the values of those terms on the stack.
+      */
+      codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk);
+
+      /* Generate a single key that will be used to both start and terminate
+      ** the search
+      */
+      buildIndexProbe(v, nEq, brk, pIdx);
+      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
+
+      /* Generate code (1) to move to the first matching element of the table.
+      ** Then generate code (2) that jumps to "brk" after the cursor is past
+      ** the last matching element of the table.  The code (1) is executed
+      ** once to initialize the search, the code (2) is executed before each
+      ** iteration of the scan to see if the scan has finished. */
+      if( bRev ){
+        /* Scan in reverse order */
+        sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, brk);
+        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
+        sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, brk);
+        pLevel->op = OP_Prev;
+      }else{
+        /* Scan in the forward order */
+        sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, brk);
+        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
+        sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, brk, "+", P3_STATIC);
+        pLevel->op = OP_Next;
+      }
+      sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
+      sqlite3VdbeAddOp(v, OP_IdxIsNull, nEq, cont);
+      if( !omitTable ){
+        sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
+        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
+      }
       pLevel->p1 = iIdxCur;
       pLevel->p2 = start;
+    }else{
+      /* Case 5:  There is no usable index.  We must do a complete
+      **          scan of the entire table.
+      */
+      assert( omitTable==0 );
+      assert( bRev==0 );
+      pLevel->op = OP_Next;
+      pLevel->p1 = iCur;
+      pLevel->p2 = 1 + sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
     }
-    loopMask |= getMask(&maskSet, iCur);
+    notReady &= ~getMask(&maskSet, iCur);
 
     /* Insert code to test every subexpression that can be completely
     ** computed using the current set of tables.
     */
-    for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){
-      if( pTerm->p==0 ) continue;
-      if( (pTerm->prereqAll & loopMask)!=pTerm->prereqAll ) continue;
-      if( pLevel->iLeftJoin && !ExprHasProperty(pTerm->p,EP_FromJoin) ){
+    for(pTerm=wc.a, j=wc.nTerm; j>0; j--, pTerm++){
+      Expr *pE;
+      if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+      if( (pTerm->prereqAll & notReady)!=0 ) continue;
+      pE = pTerm->pExpr;
+      assert( pE!=0 );
+      if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
         continue;
       }
-      sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1);
-      pTerm->p = 0;
+      sqlite3ExprIfFalse(pParse, pE, cont, 1);
+      pTerm->flags |= TERM_CODED;
     }
-    brk = cont;
 
     /* For a LEFT OUTER JOIN, generate code that will record the fact that
     ** at least one row of the right table has matched the left table.  
@@ -1327,17 +1824,75 @@ WhereInfo *sqlite3WhereBegin(
       sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
       sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
       VdbeComment((v, "# record LEFT JOIN hit"));
-      for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){
-        if( pTerm->p==0 ) continue;
-        if( (pTerm->prereqAll & loopMask)!=pTerm->prereqAll ) continue;
-        sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1);
-        pTerm->p = 0;
+      for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){
+        if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+        if( (pTerm->prereqAll & notReady)!=0 ) continue;
+        assert( pTerm->pExpr );
+        sqlite3ExprIfFalse(pParse, pTerm->pExpr, cont, 1);
+        pTerm->flags |= TERM_CODED;
+      }
+    }
+  }
+
+#ifdef SQLITE_TEST  /* For testing and debugging use only */
+  /* Record in the query plan information about the current table
+  ** and the index used to access it (if any).  If the table itself
+  ** is not used, its name is just '{}'.  If no index is used
+  ** the index is listed as "{}".  If the primary key is used the
+  ** index name is '*'.
+  */
+  for(i=0; i<pTabList->nSrc; i++){
+    char *z;
+    int n;
+    pLevel = &pWInfo->a[i];
+    pTabItem = &pTabList->a[pLevel->iFrom];
+    z = pTabItem->zAlias;
+    if( z==0 ) z = pTabItem->pTab->zName;
+    n = strlen(z);
+    if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
+      if( pLevel->flags & WHERE_IDX_ONLY ){
+        strcpy(&sqlite3_query_plan[nQPlan], "{}");
+        nQPlan += 2;
+      }else{
+        strcpy(&sqlite3_query_plan[nQPlan], z);
+        nQPlan += n;
+      }
+      sqlite3_query_plan[nQPlan++] = ' ';
+    }
+    if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+      strcpy(&sqlite3_query_plan[nQPlan], "* ");
+      nQPlan += 2;
+    }else if( pLevel->pIdx==0 ){
+      strcpy(&sqlite3_query_plan[nQPlan], "{} ");
+      nQPlan += 3;
+    }else{
+      n = strlen(pLevel->pIdx->zName);
+      if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
+        strcpy(&sqlite3_query_plan[nQPlan], pLevel->pIdx->zName);
+        nQPlan += n;
+        sqlite3_query_plan[nQPlan++] = ' ';
       }
     }
   }
+  while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){
+    sqlite3_query_plan[--nQPlan] = 0;
+  }
+  sqlite3_query_plan[nQPlan] = 0;
+  nQPlan = 0;
+#endif /* SQLITE_TEST // Testing and debugging use only */
+
+  /* Record the continuation address in the WhereInfo structure.  Then
+  ** clean up and return.
+  */
   pWInfo->iContinue = cont;
-  freeMaskSet(&maskSet);
+  whereClauseClear(&wc);
   return pWInfo;
+
+  /* Jump here if malloc fails */
+whereBeginNoMem:
+  whereClauseClear(&wc);
+  sqliteFree(pWInfo);
+  return 0;
 }
 
 /*
@@ -1349,7 +1904,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
   int i;
   WhereLevel *pLevel;
   SrcList *pTabList = pWInfo->pTabList;
-  struct SrcList_item *pTabItem;
 
   /* Generate loop termination code.
   */
@@ -1360,8 +1914,13 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
       sqlite3VdbeAddOp(v, pLevel->op, pLevel->p1, pLevel->p2);
     }
     sqlite3VdbeResolveLabel(v, pLevel->brk);
-    if( pLevel->inOp!=OP_Noop ){
-      sqlite3VdbeAddOp(v, pLevel->inOp, pLevel->inP1, pLevel->inP2);
+    if( pLevel->nIn ){
+      int *a;
+      int j;
+      for(j=pLevel->nIn, a=&pLevel->aInLoop[j*3-3]; j>0; j--, a-=3){
+        sqlite3VdbeAddOp(v, a[0], a[1], a[2]);
+      }
+      sqliteFree(pLevel->aInLoop);
     }
     if( pLevel->iLeftJoin ){
       int addr;
@@ -1380,15 +1939,14 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
   */
   sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
 
-  /* Close all of the cursors that were opend by sqlite3WhereBegin.
+  /* Close all of the cursors that were opened by sqlite3WhereBegin.
   */
-  pLevel = pWInfo->a;
-  pTabItem = pTabList->a;
-  for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
+  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
+    struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
     Table *pTab = pTabItem->pTab;
     assert( pTab!=0 );
     if( pTab->isTransient || pTab->pSelect ) continue;
-    if( (pLevel->score & 1)==0 ){
+    if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
       sqlite3VdbeAddOp(v, OP_Close, pTabItem->iCursor, 0);
     }
     if( pLevel->pIdx!=0 ){
@@ -1404,7 +1962,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
     ** that reference the table and converts them into opcodes that
     ** reference the index.
     */
-    if( pLevel->score & 1 ){
+    if( pLevel->flags & WHERE_IDX_ONLY ){
       int i, j, last;
       VdbeOp *pOp;
       Index *pIdx = pLevel->pIdx;
index 708b3538d724588078f9fece6dc1e8316eb04f6c..8f6e87330a53107940d7f586afb7c1b3c200f502 100644 (file)
@@ -1606,12 +1606,11 @@ int k;
 FILE *err;
 {
   int spcnt, i;
-  spcnt = 0;
   if( argv[0] ) fprintf(err,"%s",argv[0]);
   spcnt = strlen(argv[0]) + 1;
   for(i=1; i<n && argv[i]; i++){
     fprintf(err," %s",argv[i]);
-    spcnt += strlen(argv[i]+1);
+    spcnt += strlen(argv[i])+1;
   }
   spcnt += k;
   for(; argv[i]; i++) fprintf(err," %s",argv[i]);
@@ -2305,7 +2304,7 @@ to follow the previous rule.");
 ** macros.  This routine looks for "%ifdef" and "%ifndef" and "%endif" and
 ** comments them out.  Text in between is also commented out as appropriate.
 */
-static preprocess_input(char *z){
+static void preprocess_input(char *z){
   int i, j, k, n;
   int exclude = 0;
   int start;
@@ -3664,6 +3663,20 @@ int mhflag;     /* Output in makeheaders format if true */
       fprintf(out,"      break;\n"); lineno++;
     }
   }
+  if( lemp->vardest ){
+    struct symbol *dflt_sp = 0;
+    for(i=0; i<lemp->nsymbol; i++){
+      struct symbol *sp = lemp->symbols[i];
+      if( sp==0 || sp->type==TERMINAL ||
+          sp->index<=0 || sp->destructor!=0 ) continue;
+      fprintf(out,"    case %d:\n",sp->index); lineno++;
+      dflt_sp = sp;
+    }
+    if( dflt_sp!=0 ){
+      emit_destructor_code(out,dflt_sp,lemp,&lineno);
+      fprintf(out,"      break;\n"); lineno++;
+    }
+  }
   for(i=0; i<lemp->nsymbol; i++){
     struct symbol *sp = lemp->symbols[i];
     if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
@@ -3683,20 +3696,6 @@ int mhflag;     /* Output in makeheaders format if true */
     emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
     fprintf(out,"      break;\n"); lineno++;
   }
-  if( lemp->vardest ){
-    struct symbol *dflt_sp = 0;
-    for(i=0; i<lemp->nsymbol; i++){
-      struct symbol *sp = lemp->symbols[i];
-      if( sp==0 || sp->type==TERMINAL ||
-          sp->index<=0 || sp->destructor!=0 ) continue;
-      fprintf(out,"    case %d:\n",sp->index); lineno++;
-      dflt_sp = sp;
-    }
-    if( dflt_sp!=0 ){
-      emit_destructor_code(out,dflt_sp,lemp,&lineno);
-      fprintf(out,"      break;\n"); lineno++;
-    }
-  }
   tplt_xfer(lemp->name,in,out,&lineno);
 
   /* Generate code which executes whenever the parser stack overflows */
index aac842f10cfab6e2d7e4626009d444aac2bfecc6..57ec97f6a87c7cd894e966235e899514d17efe5d 100644 (file)
@@ -364,11 +364,11 @@ static int yy_find_shift_action(
 ** return YY_NO_ACTION.
 */
 static int yy_find_reduce_action(
-  yyParser *pParser,        /* The parser */
+  int stateno,              /* Current state number */
   int iLookAhead            /* The look-ahead token */
 ){
   int i;
-  int stateno = pParser->yystack[pParser->yyidx].stateno;
+  /* int stateno = pParser->yystack[pParser->yyidx].stateno; */
  
   i = yy_reduce_ofst[stateno];
   if( i==YY_REDUCE_USE_DFLT ){
@@ -462,6 +462,18 @@ static void yy_reduce(
   }
 #endif /* NDEBUG */
 
+#ifndef NDEBUG
+  /* Silence complaints from purify about yygotominor being uninitialized
+  ** in some cases when it is copied into the stack after the following
+  ** switch.  yygotominor is uninitialized when a rule reduces that does
+  ** not set the value of its left-hand side nonterminal.  Leaving the
+  ** value of the nonterminal uninitialized is utterly harmless as long
+  ** as the value is never used.  So really the only thing this code
+  ** accomplishes is to quieten purify.  
+  */
+  memset(&yygotominor, 0, sizeof(yygotominor));
+#endif
+
   switch( yyruleno ){
   /* Beginning here are the reduction cases.  A typical example
   ** follows:
@@ -476,9 +488,24 @@ static void yy_reduce(
   yygoto = yyRuleInfo[yyruleno].lhs;
   yysize = yyRuleInfo[yyruleno].nrhs;
   yypParser->yyidx -= yysize;
-  yyact = yy_find_reduce_action(yypParser,yygoto);
+  yyact = yy_find_reduce_action(yymsp[-yysize].stateno,yygoto);
   if( yyact < YYNSTATE ){
-    yy_shift(yypParser,yyact,yygoto,&yygotominor);
+#ifdef NDEBUG
+    /* If we are not debugging and the reduce action popped at least
+    ** one element off the stack, then we can push the new element back
+    ** onto the stack here, and skip the stack overflow test in yy_shift().
+    ** That gives a significant speed improvement. */
+    if( yysize ){
+      yypParser->yyidx++;
+      yymsp -= yysize-1;
+      yymsp->stateno = yyact;
+      yymsp->major = yygoto;
+      yymsp->minor = yygotominor;
+    }else
+#endif
+    {
+      yy_shift(yypParser,yyact,yygoto,&yygotominor);
+    }
   }else if( yyact == YYNSTATE + YYNRULE + 1 ){
     yy_accept(yypParser);
   }
@@ -570,7 +597,7 @@ void Parse(
   /* (re)initialize the parser, if necessary */
   yypParser = (yyParser*)yyp;
   if( yypParser->yyidx<0 ){
-    if( yymajor==0 ) return;
+    /* if( yymajor==0 ) return; // not sure why this was here... */
     yypParser->yyidx = 0;
     yypParser->yyerrcnt = -1;
     yypParser->yystack[0].stateno = 0;
index 185f1748971b6c91eab4095b3758501a82fa1241..928d3b69dc78090d5ad7319142b3794e0c6b8c5e 100644 (file)
@@ -1,6 +1,6 @@
 #
 # This script looks for memory leaks by analyzing the output of "sqlite" 
-# when compiled with the MEMORY_DEBUG=2 option.
+# when compiled with the SQLITE_DEBUG=2 option.
 #
 /[0-9]+ malloc / {
   mem[$6] = $0
index 69bc4ae88edba23aa26e3f524ca353ce88fe8675..2e3f43bc13673145ff23d8f7f0570840f1ae4479 100644 (file)
@@ -13,7 +13,8 @@ exec `which tclsh` $0 "$@"
 set doco "
 This script is a tool to help track down memory leaks in the sqlite
 library. The library must be compiled with the preprocessor symbol
-SQLITE_DEBUG set to at least 2. It must be set to 3 to enable stack traces.
+SQLITE_MEMDEBUG set to at least 2. It must be set to 3 to enable stack 
+traces.
 
 To use, run the leaky application and save the standard error output.
 Then, execute this program with the first argument the name of the
@@ -24,29 +25,88 @@ If all goes well a summary of unfreed allocations is printed out. If the
 GNU C library is in use and SQLITE_DEBUG is 3 or greater a stack trace is
 printed out for each unmatched allocation.
 
+If the \"-r <n>\" option is passed, then the program stops and prints out
+the state of the heap immediately after the <n>th call to malloc() or
+realloc().
+
 Example:
 
 $ ./testfixture ../sqlite/test/select1.test 2> memtrace.out
-$ tclsh $argv0 ./testfixture memtrace.out
+$ tclsh $argv0 ?-r <malloc-number>? ./testfixture memtrace.out
 "
 
-# If stack traces are enabled, the 'addr2line' program is called to
-# translate a binary stack address into a human-readable form.
-set addr2line addr2line
 
-if { [llength $argv]!=2 } {
-  puts "Usage: $argv0 <binary file> <mem trace file>"
+proc usage {} {
+  set prg [file tail $::argv0]
+  puts "Usage: $prg ?-r <malloc-number>? <binary file> <mem trace file>"
   puts ""
-  puts [string trim $doco]
+  puts [string trim $::doco]
   exit -1
 }
 
+proc shift {listvar} {
+  upvar $listvar l
+  set ret [lindex $l 0]
+  set l [lrange $l 1 end]
+  return $ret
+}
+
+# Argument handling. The following vars are set:
+#
+# $exe       - the name of the executable (i.e. "testfixture" or "./sqlite3")
+# $memfile   - the name of the file containing the trace output.
+# $report_at - The malloc number to stop and report at. Or -1 to read 
+#              all of $memfile.
+#
+set report_at -1
+while {[llength $argv]>2} {
+  set arg [shift argv]
+  switch -- $arg {
+    "-r" {
+      set report_at [shift argv]
+    }
+    default {
+      usage
+    }
+  }
+}
+if {[llength $argv]!=2} usage
+set exe [lindex $argv 0]
+set memfile [lindex $argv 1]
+
+# If stack traces are enabled, the 'addr2line' program is called to
+# translate a binary stack address into a human-readable form.
+set addr2line addr2line
+
+# When the SQLITE_MEMDEBUG is set as described above, SQLite prints
+# out a line for each malloc(), realloc() or free() call that the
+# library makes. If SQLITE_MEMDEBUG is 3, then a stack trace is printed
+# out before each malloc() and realloc() line.
+#
+# This program parses each line the SQLite library outputs and updates
+# the following global Tcl variables to reflect the "current" state of
+# the heap used by SQLite.
+#
+set nBytes 0               ;# Total number of bytes currently allocated.
+set nMalloc 0              ;# Total number of malloc()/realloc() calls.
+set nPeak 0                ;# Peak of nBytes.
+set iPeak 0                ;# nMalloc when nPeak was set.
+#
+# More detailed state information is stored in the $memmap array. 
+# Each key in the memmap array is the address of a chunk of memory
+# currently allocated from the heap. The value is a list of the 
+# following form
+# 
+#     {<number-of-bytes> <malloc id> <stack trace>}
+#
+array unset memmap
 
 proc process_input {input_file array_name} {
   upvar $array_name mem 
   set input [open $input_file]
 
   set MALLOC {([[:digit:]]+) malloc ([[:digit:]]+) bytes at 0x([[:xdigit:]]+)}
+  # set STACK {^[[:digit:]]+: STACK: (.*)$}
   set STACK {^STACK: (.*)$}
   set FREE {[[:digit:]]+ free ([[:digit:]]+) bytes at 0x([[:xdigit:]]+)}
   set REALLOC {([[:digit:]]+) realloc ([[:digit:]]+) to ([[:digit:]]+)}
@@ -66,6 +126,17 @@ proc process_input {input_file array_name} {
       set mem($addr) [list $bytes "malloc $mallocid" $stack]
       set stack ""
 
+      # Increase the current heap usage
+      incr ::nBytes $bytes
+
+      # Increase the number of malloc() calls
+      incr ::nMalloc
+
+      if {$::nBytes > $::nPeak} {
+        set ::nPeak $::nBytes
+        set ::iPeak $::nMalloc
+      }
+
     } elseif { [regexp $FREE $line dummy bytes addr] } {
       # If this is a 'free' line, remove the entry from the mem array. If the 
       # entry does not exist, or is the wrong number of bytes, announce a
@@ -76,31 +147,86 @@ proc process_input {input_file array_name} {
       }
       unset mem($addr) 
 
+      # Decrease the current heap usage
+      incr ::nBytes [expr -1 * $bytes]
+
     } elseif { [regexp $REALLOC $line dummy mallocid ob b oa a] } {
-      # If it is a realloc line, remove the old mem entry and add a new one.
+      # "free" the old allocation in the internal model:
+      incr ::nBytes [expr -1 * $ob]
       unset mem($oa);
+
+      # "malloc" the new allocation
       set mem($a) [list $b "realloc $mallocid" $stack]
+      incr ::nBytes $b
       set stack ""
+
+      # Increase the number of malloc() calls
+      incr ::nMalloc
+
+      if {$::nBytes > $::nPeak} {
+        set ::nPeak $::nBytes
+        set ::iPeak $::nMalloc
+      }
+
     } else {
       # puts "REJECT: $line"
     }
+
+    if {$::nMalloc==$::report_at} report
   }
 
   close $input
 }
 
-process_input [lindex $argv 1] mem
-set exe [lindex $argv 0]
-
-foreach key [array names mem] {
-  set bytes [lindex $mem($key) 0]
-  set mallocid [lindex $mem($key) 1]
-  set stack [lindex $mem($key) 2]
-  puts "Leaked $bytes bytes at 0x$key: $mallocid"
-  foreach frame [lrange $stack 1 10] {
-    foreach {f l} [split [exec $addr2line -f --exe=$exe $frame] \n] {}
+proc printstack {stack} {
+  set fcount 10
+  if {[llength $stack]<10} {
+    set fcount [llength $stack]
+  }
+  foreach frame [lrange $stack 1 $fcount] {
+    foreach {f l} [split [exec $::addr2line -f --exe=$::exe $frame] \n] {}
     puts [format "%-30s %s" $f $l]
   }
   if {[llength $stack]>0 } {puts ""}
 }
 
+proc report {} {
+
+  foreach key [array names ::memmap] {
+    set stack [lindex $::memmap($key) 2]
+    set bytes [lindex $::memmap($key) 0]
+    lappend summarymap($stack) $bytes
+  }
+
+  foreach stack [array names summarymap] {
+    set allocs $summarymap($stack)
+    set sum 0
+    foreach a $allocs {
+      incr sum $a
+    }
+    lappend sorted [list $sum $stack]
+  }
+
+  set sorted [lsort -integer -index 0 $sorted]
+  foreach s $sorted {
+    set sum [lindex $s 0]
+    set stack [lindex $s 1]
+    set allocs $summarymap($stack)
+    puts "$sum bytes in [llength $allocs] chunks ($allocs)"
+    printstack $stack
+  }
+
+  # Print out summary statistics
+  puts "Total allocations            : $::nMalloc"
+  puts "Total outstanding allocations: [array size ::memmap]" 
+  puts "Current heap usage           : $::nBytes bytes"
+  puts "Peak heap usage              : $::nPeak bytes (malloc #$::iPeak)"
+
+  exit
+}
+
+process_input $memfile memmap
+report
+
+
+
index 265e3d1ea2de73516f19c261c316b6c9be32c4e5..58d4b9cb78a3c91f4e79041b570b5517f8b6b8b8 100644 (file)
@@ -32,68 +32,78 @@ struct Keyword {
 #ifdef SQLITE_OMIT_ALTERTABLE
 #  define ALTER      0
 #else
-#  define ALTER      1
+#  define ALTER      0x00000001
+#endif
+#define ALWAYS       0x00000002
+#ifdef SQLITE_OMIT_ANALYZE
+#  define ANALYZE    0
+#else
+#  define ANALYZE    0x00000004
 #endif
-#define ALWAYS     2
 #ifdef SQLITE_OMIT_ATTACH
 #  define ATTACH     0
 #else
-#  define ATTACH     4
+#  define ATTACH     0x00000008
 #endif
 #ifdef SQLITE_OMIT_AUTOINCREMENT
 #  define AUTOINCR   0
 #else
-#  define AUTOINCR   8
+#  define AUTOINCR   0x00000010
+#endif
+#ifdef SQLITE_OMIT_CAST
+#  define CAST       0
+#else
+#  define CAST       0x00000020
 #endif
 #ifdef SQLITE_OMIT_COMPOUND_SELECT
 #  define COMPOUND   0
 #else
-#  define COMPOUND   16
+#  define COMPOUND   0x00000040
 #endif
 #ifdef SQLITE_OMIT_CONFLICT_CLAUSE
 #  define CONFLICT   0
 #else
-#  define CONFLICT   32
+#  define CONFLICT   0x00000080
 #endif
 #ifdef SQLITE_OMIT_EXPLAIN
 #  define EXPLAIN    0
 #else
-#  define EXPLAIN    128
+#  define EXPLAIN    0x00000100
 #endif
 #ifdef SQLITE_OMIT_FOREIGN_KEY
 #  define FKEY       0
 #else
-#  define FKEY       256
+#  define FKEY       0x00000200
 #endif
 #ifdef SQLITE_OMIT_PRAGMA
 #  define PRAGMA     0
 #else
-#  define PRAGMA     512
+#  define PRAGMA     0x00000400
 #endif
 #ifdef SQLITE_OMIT_REINDEX
 #  define REINDEX    0
 #else
-#  define REINDEX    1024
+#  define REINDEX    0x00000800
 #endif
 #ifdef SQLITE_OMIT_SUBQUERY
 #  define SUBQUERY   0
 #else
-#  define SUBQUERY   2048
+#  define SUBQUERY   0x00001000
 #endif
 #ifdef SQLITE_OMIT_TRIGGER
 #  define TRIGGER    0
 #else
-#  define TRIGGER    4096
+#  define TRIGGER    0x00002000
 #endif
 #ifdef SQLITE_OMIT_VACUUM
 #  define VACUUM     0
 #else
-#  define VACUUM     8192
+#  define VACUUM     0x00004000
 #endif
 #ifdef SQLITE_OMIT_VIEW
 #  define VIEW       0
 #else
-#  define VIEW       16384
+#  define VIEW       0x00008000
 #endif
 
 
@@ -102,9 +112,11 @@ struct Keyword {
 */
 static Keyword aKeywordTable[] = {
   { "ABORT",            "TK_ABORT",        CONFLICT|TRIGGER       },
+  { "ADD",              "TK_ADD",          ALTER                  },
   { "AFTER",            "TK_AFTER",        TRIGGER                },
   { "ALL",              "TK_ALL",          ALWAYS                 },
   { "ALTER",            "TK_ALTER",        ALTER                  },
+  { "ANALYZE",          "TK_ANALYZE",      ANALYZE                },
   { "AND",              "TK_AND",          ALWAYS                 },
   { "AS",               "TK_AS",           ALWAYS                 },
   { "ASC",              "TK_ASC",          ALWAYS                 },
@@ -116,16 +128,18 @@ static Keyword aKeywordTable[] = {
   { "BY",               "TK_BY",           ALWAYS                 },
   { "CASCADE",          "TK_CASCADE",      FKEY                   },
   { "CASE",             "TK_CASE",         ALWAYS                 },
+  { "CAST",             "TK_CAST",         CAST                   },
   { "CHECK",            "TK_CHECK",        ALWAYS                 },
   { "COLLATE",          "TK_COLLATE",      ALWAYS                 },
+  { "COLUMN",           "TK_COLUMNKW",     ALTER                  },
   { "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                 },
+  { "CURRENT_DATE",     "TK_CTIME_KW",     ALWAYS                 },
+  { "CURRENT_TIME",     "TK_CTIME_KW",     ALWAYS                 },
+  { "CURRENT_TIMESTAMP","TK_CTIME_KW",     ALWAYS                 },
   { "DATABASE",         "TK_DATABASE",     ATTACH                 },
   { "DEFAULT",          "TK_DEFAULT",      ALWAYS                 },
   { "DEFERRED",         "TK_DEFERRED",     ALWAYS                 },
@@ -148,7 +162,7 @@ static Keyword aKeywordTable[] = {
   { "FOREIGN",          "TK_FOREIGN",      FKEY                   },
   { "FROM",             "TK_FROM",         ALWAYS                 },
   { "FULL",             "TK_JOIN_KW",      ALWAYS                 },
-  { "GLOB",             "TK_GLOB",         ALWAYS                 },
+  { "GLOB",             "TK_LIKE_KW",      ALWAYS                 },
   { "GROUP",            "TK_GROUP",        ALWAYS                 },
   { "HAVING",           "TK_HAVING",       ALWAYS                 },
   { "IGNORE",           "TK_IGNORE",       CONFLICT|TRIGGER       },
@@ -166,7 +180,7 @@ static Keyword aKeywordTable[] = {
   { "JOIN",             "TK_JOIN",         ALWAYS                 },
   { "KEY",              "TK_KEY",          ALWAYS                 },
   { "LEFT",             "TK_JOIN_KW",      ALWAYS                 },
-  { "LIKE",             "TK_LIKE",         ALWAYS                 },
+  { "LIKE",             "TK_LIKE_KW",      ALWAYS                 },
   { "LIMIT",            "TK_LIMIT",        ALWAYS                 },
   { "MATCH",            "TK_MATCH",        ALWAYS                 },
   { "NATURAL",          "TK_JOIN_KW",      ALWAYS                 },
@@ -183,6 +197,7 @@ static Keyword aKeywordTable[] = {
   { "PRIMARY",          "TK_PRIMARY",      ALWAYS                 },
   { "RAISE",            "TK_RAISE",        TRIGGER                },
   { "REFERENCES",       "TK_REFERENCES",   FKEY                   },
+  { "REGEXP",           "TK_LIKE_KW",      ALWAYS                 },
   { "REINDEX",          "TK_REINDEX",      REINDEX                },
   { "RENAME",           "TK_RENAME",       ALTER                  },
   { "REPLACE",          "TK_REPLACE",      CONFLICT               },
index e42fb28de4e98c5b918b4e813569ed432ea14515..c9b8f92e252576c590ae39bb568e7157fd3d5549 100644 (file)
@@ -5,7 +5,7 @@
 
 # Get the name of the database to analyze
 #
-set argv $argv0
+#set argv $argv0
 if {[llength $argv]!=1} {
   puts stderr "Usage: $argv0 database-name"
   exit 1
@@ -29,7 +29,10 @@ if {[file size $file_to_analyze]<512} {
 sqlite3 db [lindex $argv 0]
 set DB [btree_open [lindex $argv 0] 1000 0]
 
-# In-memory database for collecting statistics
+# In-memory database for collecting statistics. This script loops through
+# the tables and indices in the database being analyzed, adding a row for each
+# to an in-memory database (for which the schema is shown below). It then
+# queries the in-memory db to produce the space-analysis report.
 #
 sqlite3 mem :memory:
 set tabledef\
@@ -52,32 +55,80 @@ set tabledef\
 );}
 mem eval $tabledef
 
-# This query will be used to find the root page number for every table
-# in the database.
-#
-set sql {
-  SELECT name, rootpage 
-    FROM sqlite_master WHERE type='table'
-  UNION ALL
-  SELECT 'sqlite_master', 1
-  ORDER BY 1
+proc integerify {real} {
+  return [expr int($real)]
 }
+mem function int integerify
 
-# Quote a string for SQL
+# Quote a string for use in an SQL query. Examples:
 #
-proc quote txt {
+# [quote {hello world}]   == {'hello world'}
+# [quote {hello world's}] == {'hello world''s'}
+#
+proc quote {txt} {
   regsub -all ' $txt '' q
   return '$q'
 }
 
-# Analyze every table in the database, one at a time.
+# This proc is a wrapper around the btree_cursor_info command. The
+# second argument is an open btree cursor returned by [btree_cursor].
+# The first argument is the name of an array variable that exists in
+# the scope of the caller. If the third argument is non-zero, then
+# info is returned for the page that lies $up entries upwards in the
+# tree-structure. (i.e. $up==1 returns the parent page, $up==2 the 
+# grandparent etc.)
+#
+# The following entries in that array are filled in with information retrieved
+# using [btree_cursor_info]:
+#
+#   $arrayvar(page_no)             =  The page number
+#   $arrayvar(entry_no)            =  The entry number
+#   $arrayvar(page_entries)        =  Total number of entries on this page
+#   $arrayvar(cell_size)           =  Cell size (local payload + header)
+#   $arrayvar(page_freebytes)      =  Number of free bytes on this page
+#   $arrayvar(page_freeblocks)     =  Number of free blocks on the page
+#   $arrayvar(payload_bytes)       =  Total payload size (local + overflow)
+#   $arrayvar(header_bytes)        =  Header size in bytes
+#   $arrayvar(local_payload_bytes) =  Local payload size
+#   $arrayvar(parent)              =  Parent page number
+# 
+proc cursor_info {arrayvar csr {up 0}} {
+  upvar $arrayvar a
+  foreach [list a(page_no) \
+                a(entry_no) \
+                a(page_entries) \
+                a(cell_size) \
+                a(page_freebytes) \
+                a(page_freeblocks) \
+                a(payload_bytes) \
+                a(header_bytes) \
+                a(local_payload_bytes) \
+                a(parent) ] [btree_cursor_info $csr $up] {}
+}
+
+# Determine the page-size of the database. This global variable is used
+# throughout the script.
 #
 set pageSize [db eval {PRAGMA page_size}]
+
+# Analyze every table in the database, one at a time.
+#
+# The following query returns the name and root-page of each table in the
+# database, including the sqlite_master table.
+#
+set sql {
+  SELECT name, rootpage FROM sqlite_master WHERE type='table'
+  UNION ALL
+  SELECT 'sqlite_master', 1
+  ORDER BY 1
+}
 foreach {name rootpage} [db eval $sql] {
   puts stderr "Analyzing table $name..."
-  set cursor [btree_cursor $DB $rootpage 0]
-  set go [btree_first $cursor]
-  catch {unset seen}
+
+  # Code below traverses the table being analyzed (table name $name), using the
+  # btree cursor $cursor. Statistics related to table $name are accumulated in
+  # the following variables:
+  #
   set total_payload 0        ;# Payload space used by all entries
   set total_ovfl 0           ;# Payload space on overflow pages
   set unused_int 0           ;# Unused space on interior nodes
@@ -90,14 +141,35 @@ foreach {name rootpage} [db eval $sql] {
   set ovfl_pages 0           ;# Number of overflow pages used
   set leaf_pages 0           ;# Number of leaf pages
   set int_pages 0            ;# Number of interior pages
-  while {$go==0} {
+
+  # As the btree is traversed, the array variable $seen($pgno) is set to 1
+  # the first time page $pgno is encountered.
+  #
+  catch {unset seen}
+
+  # The following loop runs once for each entry in table $name. The table
+  # is traversed using the btree cursor stored in variable $csr
+  #
+  set csr [btree_cursor $DB $rootpage 0]
+  for {btree_first $csr} {![btree_eof $csr]} {btree_next $csr} {
     incr cnt_leaf_entry
-    set stat [btree_cursor_info $cursor]
-    set payload [lindex $stat 6]
-    if {$payload>$mx_payload} {set mx_payload $payload}
-    incr total_payload $payload
-    set local [lindex $stat 8]    
-    set ovfl [expr {$payload-$local}]
+
+    # Retrieve information about the entry the btree-cursor points to into
+    # the array variable $ci (cursor info).
+    #
+    cursor_info ci $csr
+
+    # Check if the payload of this entry is greater than the current 
+    # $mx_payload statistic for the table. Also increase the $total_payload
+    # statistic.
+    #
+    if {$ci(payload_bytes)>$mx_payload} {set mx_payload $ci(payload_bytes)}
+    incr total_payload $ci(payload_bytes)
+
+    # If this entry uses overflow pages, then update the $cnt_ovfl, 
+    # $total_ovfl, $ovfl_pages and $unused_ovfl statistics.
+    #
+    set ovfl [expr {$ci(payload_bytes)-$ci(local_payload_bytes)}]
     if {$ovfl} {
       incr cnt_ovfl
       incr total_ovfl $ovfl
@@ -105,33 +177,59 @@ foreach {name rootpage} [db eval $sql] {
       incr ovfl_pages $n
       incr unused_ovfl [expr {$n*($pageSize-4) - $ovfl}]
     }
-    set pgno [lindex $stat 0]
-    if {![info exists seen($pgno)]} {
-      set seen($pgno) 1
+
+    # If this is the first table entry analyzed for the page, then update
+    # the page-related statistics $leaf_pages and $unused_leaf. Also, if
+    # this page has a parent page that has not been analyzed, retrieve
+    # info for the parent and update statistics for it too.
+    #
+    if {![info exists seen($ci(page_no))]} {
+      set seen($ci(page_no)) 1
       incr leaf_pages
-      incr unused_leaf [lindex $stat 4]
-      set parent [lindex $stat 9]
-      set up 0
-      while {$parent!=0 && ![info exists seen($parent)]} {
-        incr up
-        set stat [btree_cursor_info $cursor $up]
-        set seen($parent) 1
+      incr unused_leaf $ci(page_freebytes)
+
+      # Now check if the page has a parent that has not been analyzed. If
+      # so, update the $int_pages, $cnt_int_entry and $unused_int statistics
+      # accordingly. Then check if the parent page has a parent that has
+      # not yet been analyzed etc.
+      #
+      # set parent $ci(parent_page_no)
+      for {set up 1} \
+          {$ci(parent)!=0 && ![info exists seen($ci(parent))]} {incr up} \
+      {
+        # Mark the parent as seen.
+        #
+        set seen($ci(parent)) 1
+
+        # Retrieve info for the parent and update statistics.
+        cursor_info ci $csr $up
         incr int_pages
-        incr cnt_int_entry [lindex $stat 2]
-        incr unused_int [lindex $stat 4]
-        set parent [lindex $stat 9]
+        incr cnt_int_entry $ci(page_entries)
+        incr unused_int $ci(page_freebytes)
       }
     }
-    set go [btree_next $cursor]
   }
-  btree_close_cursor $cursor
+  btree_close_cursor $csr
+
+  # Handle the special case where a table contains no data. In this case
+  # all statistics are zero, except for the number of leaf pages (1) and
+  # the unused bytes on leaf pages ($pageSize - 8).
+  #
+  # An exception to the above is the sqlite_master table. If it is empty
+  # then all statistics are zero except for the number of leaf pages (1),
+  # and the number of unused bytes on leaf pages ($pageSize - 112).
+  #
   if {[llength [array names seen]]==0} {
     set leaf_pages 1
-    set unused_leaf [expr {$pageSize-8}]
-  } elseif {$rootpage==1 && ![info exists seen(1)]} {
-    incr int_pages
-    incr unused_int [expr {$pageSize-112}]
+    if {$rootpage==1} {
+      set unused_leaf [expr {$pageSize-112}]
+    } else {
+      set unused_leaf [expr {$pageSize-8}]
+    }
   }
+
+  # Insert the statistics for the table analyzed into the in-memory database.
+  #
   set sql "INSERT INTO space_used VALUES("
   append sql [quote $name]
   append sql ",[quote $name]"
@@ -152,23 +250,22 @@ foreach {name rootpage} [db eval $sql] {
   mem eval $sql
 }
 
-# This query will be used to find the root page number for every index
-# in the database.
+# Analyze every index in the database, one at a time.
+#
+# The query below returns the name, associated table and root-page number 
+# for every index in the database.
 #
 set sql {
-  SELECT name, tbl_name, rootpage 
-    FROM sqlite_master WHERE type='index'
+  SELECT name, tbl_name, rootpage FROM sqlite_master WHERE type='index'
   ORDER BY 2, 1
 }
-
-# Analyze every index in the database, one at a time.
-#
-set pageSize [db eval {PRAGMA page_size}]
 foreach {name tbl_name rootpage} [db eval $sql] {
   puts stderr "Analyzing index $name of table $tbl_name..."
-  set cursor [btree_cursor $DB $rootpage 0]
-  set go [btree_first $cursor]
-  catch {unset seen}
+
+  # Code below traverses the index being analyzed (index name $name), using the
+  # btree cursor $cursor. Statistics related to index $name are accumulated in
+  # the following variables:
+  #
   set total_payload 0        ;# Payload space used by all entries
   set total_ovfl 0           ;# Payload space on overflow pages
   set unused_leaf 0          ;# Unused space on leaf nodes
@@ -178,14 +275,36 @@ foreach {name tbl_name rootpage} [db eval $sql] {
   set mx_payload 0           ;# Maximum payload size
   set ovfl_pages 0           ;# Number of overflow pages used
   set leaf_pages 0           ;# Number of leaf pages
-  while {$go==0} {
+
+  # As the btree is traversed, the array variable $seen($pgno) is set to 1
+  # the first time page $pgno is encountered.
+  #
+  catch {unset seen}
+
+  # The following loop runs once for each entry in index $name. The index
+  # is traversed using the btree cursor stored in variable $csr
+  #
+  set csr [btree_cursor $DB $rootpage 0]
+  for {btree_first $csr} {![btree_eof $csr]} {btree_next $csr} {
     incr cnt_leaf_entry
-    set stat [btree_cursor_info $cursor]
-    set payload [btree_keysize $cursor]
+
+    # Retrieve information about the entry the btree-cursor points to into
+    # the array variable $ci (cursor info).
+    #
+    cursor_info ci $csr
+
+    # Check if the payload of this entry is greater than the current 
+    # $mx_payload statistic for the table. Also increase the $total_payload
+    # statistic.
+    #
+    set payload [btree_keysize $csr]
     if {$payload>$mx_payload} {set mx_payload $payload}
     incr total_payload $payload
-    set local [lindex $stat 8]    
-    set ovfl [expr {$payload-$local}]
+
+    # If this entry uses overflow pages, then update the $cnt_ovfl, 
+    # $total_ovfl, $ovfl_pages and $unused_ovfl statistics.
+    #
+    set ovfl [expr {$payload-$ci(local_payload_bytes)}]
     if {$ovfl} {
       incr cnt_ovfl
       incr total_ovfl $ovfl
@@ -193,19 +312,29 @@ foreach {name tbl_name rootpage} [db eval $sql] {
       incr ovfl_pages $n
       incr unused_ovfl [expr {$n*($pageSize-4) - $ovfl}]
     }
-    set pgno [lindex $stat 0]
-    if {![info exists seen($pgno)]} {
-      set seen($pgno) 1
+
+    # If this is the first table entry analyzed for the page, then update
+    # the page-related statistics $leaf_pages and $unused_leaf.
+    #
+    if {![info exists seen($ci(page_no))]} {
+      set seen($ci(page_no)) 1
       incr leaf_pages
-      incr unused_leaf [lindex $stat 4]
+      incr unused_leaf $ci(page_freebytes)
     }
-    set go [btree_next $cursor]
   }
-  btree_close_cursor $cursor
+  btree_close_cursor $csr
+
+  # Handle the special case where a index contains no data. In this case
+  # all statistics are zero, except for the number of leaf pages (1) and
+  # the unused bytes on leaf pages ($pageSize - 8).
+  #
   if {[llength [array names seen]]==0} {
     set leaf_pages 1
     set unused_leaf [expr {$pageSize-8}]
   }
+
+  # Insert the statistics for the index analyzed into the in-memory database.
+  #
   set sql "INSERT INTO space_used VALUES("
   append sql [quote $name]
   append sql ",[quote $tbl_name]"
@@ -246,7 +375,7 @@ proc percent {num denom {of {}}} {
   if {$denom==0.0} {return ""}
   set v [expr {$num*100.0/$denom}]
   set of {}
-  if {$v==1.0 || $v==0.0 || ($v>1.0 && $v<99.0)} {
+  if {$v==100.0 || $v<0.001 || ($v>1.0 && $v<99.0)} {
     return [format {%5.1f%% %s} $v $of]
   } elseif {$v<0.1 || $v>99.9} {
     return [format {%7.3f%% %s} $v $of]
@@ -255,63 +384,106 @@ proc percent {num denom {of {}}} {
   }
 }
 
+proc divide {num denom} {
+  if {$denom==0} {return 0.0}
+  return [format %.2f [expr double($num)/double($denom)]]
+}
+
 # Generate a subreport that covers some subset of the database.
 # the $where clause determines which subset to analyze.
 #
 proc subreport {title where} {
-  global pageSize
-  set hit 0
+  global pageSize file_pgcnt
+
+  # Query the in-memory database for the sum of various statistics 
+  # for the subset of tables/indices identified by the WHERE clause in
+  # $where. Note that even if the WHERE clause matches no rows, the
+  # following query returns exactly one row (because it is an aggregate).
+  #
+  # The results of the query are stored directly by SQLite into local 
+  # variables (i.e. $nentry, $nleaf etc.).
+  #
   mem eval "
     SELECT
-      sum(nentry) AS nentry,
-      sum(leaf_entries) AS nleaf,
-      sum(payload) AS payload,
-      sum(ovfl_payload) AS ovfl_payload,
+      int(sum(nentry)) AS nentry,
+      int(sum(leaf_entries)) AS nleaf,
+      int(sum(payload)) AS payload,
+      int(sum(ovfl_payload)) AS ovfl_payload,
       max(mx_payload) AS mx_payload,
-      sum(ovfl_cnt) as ovfl_cnt,
-      sum(leaf_pages) AS leaf_pages,
-      sum(int_pages) AS int_pages,
-      sum(ovfl_pages) AS ovfl_pages,
-      sum(leaf_unused) AS leaf_unused,
-      sum(int_unused) AS int_unused,
-      sum(ovfl_unused) AS ovfl_unused
-    FROM space_used WHERE $where" {} {set hit 1}
-  if {!$hit} {return 0}
+      int(sum(ovfl_cnt)) as ovfl_cnt,
+      int(sum(leaf_pages)) AS leaf_pages,
+      int(sum(int_pages)) AS int_pages,
+      int(sum(ovfl_pages)) AS ovfl_pages,
+      int(sum(leaf_unused)) AS leaf_unused,
+      int(sum(int_unused)) AS int_unused,
+      int(sum(ovfl_unused)) AS ovfl_unused
+    FROM space_used WHERE $where" {} {}
+
+  # Output the sub-report title, nicely decorated with * characters.
+  #
   puts ""
   set len [string length $title]
-  incr len 5
-  set stars "***********************************"
-  append stars $stars
-  set stars [string range $stars $len end]
+  set stars [string repeat * [expr 65-$len]]
   puts "*** $title $stars"
   puts ""
+
+  # Calculate statistics and store the results in TCL variables, as follows:
+  #
+  # total_pages: Database pages consumed.
+  # total_pages_percent: Pages consumed as a percentage of the file.
+  # storage: Bytes consumed.
+  # payload_percent: Payload bytes used as a percentage of $storage.
+  # total_unused: Unused bytes on pages.
+  # avg_payload: Average payload per btree entry.
+  # avg_fanout: Average fanout for internal pages.
+  # avg_unused: Average unused bytes per btree entry.
+  # ovfl_cnt_percent: Percentage of btree entries that use overflow pages.
+  #
   set total_pages [expr {$leaf_pages+$int_pages+$ovfl_pages}]
-  statline "Percentage of total database" [percent $total_pages $::file_pgcnt]
-  statline "Number of entries" $nleaf
-  set total_unused [expr {$ovfl_unused+$int_unused+$leaf_unused}]
+  set total_pages_percent [percent $total_pages $file_pgcnt]
   set storage [expr {$total_pages*$pageSize}]
-  statline "Bytes of storage consumed" $storage
-  statline "Bytes of payload" $payload \
-       [percent $payload $storage {of storage consumed}]
-  statline "Average payload per entry" [expr {$nleaf>0?$payload/$nleaf:0}]
-  set avgunused [expr {$nleaf>0?$total_unused/$nleaf:0}]
-  statline "Average unused bytes per entry" $avgunused
-  set nint [expr {$nentry-$nleaf}]
+  set payload_percent [percent $payload $storage {of storage consumed}]
+  set total_unused [expr {$ovfl_unused+$int_unused+$leaf_unused}]
+  set avg_payload [divide $payload $nleaf]
+  set avg_unused [divide $total_unused $nleaf]
   if {$int_pages>0} {
-    statline "Average fanout" [format %.2f [expr {($nint+0.0)/$int_pages}]]
+    # TODO: Is this formula correct?
+    set nTab [mem eval "
+      SELECT count(*) FROM (
+          SELECT DISTINCT tblname FROM space_used WHERE $where AND is_index=0
+      )
+    "]
+    set avg_fanout [mem eval "
+      SELECT (sum(leaf_pages+int_pages)-$nTab)/sum(int_pages) FROM space_used
+          WHERE $where AND is_index = 0
+    "]
+    set avg_fanout [format %.2f $avg_fanout]
+  }
+  set ovfl_cnt_percent [percent $ovfl_cnt $nleaf {of all entries}]
+
+  # Print out the sub-report statistics.
+  #
+  statline {Percentage of total database} $total_pages_percent
+  statline {Number of entries} $nleaf
+  statline {Bytes of storage consumed} $storage
+  statline {Bytes of payload} $payload $payload_percent
+  statline {Average payload per entry} $avg_payload
+  statline {Average unused bytes per entry} $avg_unused
+  if {[info exists avg_fanout]} {
+    statline {Average fanout} $avg_fanout
   }
-  statline "Maximum payload per entry" $mx_payload
-  statline "Entries that use overflow" $ovfl_cnt \
-        [percent $ovfl_cnt $nleaf {of all entries}]
+  statline {Maximum payload per entry} $mx_payload
+  statline {Entries that use overflow} $ovfl_cnt $ovfl_cnt_percent
   if {$int_pages>0} {
-    statline "Index pages used" $int_pages
+    statline {Index pages used} $int_pages
   }
-  statline "Primary pages used" $leaf_pages
-  statline "Overflow pages used" $ovfl_pages
-  statline "Total pages used" $total_pages
+  statline {Primary pages used} $leaf_pages
+  statline {Overflow pages used} $ovfl_pages
+  statline {Total pages used} $total_pages
   if {$int_unused>0} {
-    statline "Unused bytes on index pages" $int_unused \
+    set int_unused_percent \
          [percent $int_unused [expr {$int_pages*$pageSize}] {of index space}]
+    statline "Unused bytes on index pages" $int_unused $int_unused_percent
   }
   statline "Unused bytes on primary pages" $leaf_unused \
      [percent $leaf_unused [expr {$leaf_pages*$pageSize}] {of primary space}]
@@ -322,42 +494,106 @@ proc subreport {title where} {
   return 1
 }
 
-# Output summary statistics:
+# Calculate the overhead in pages caused by auto-vacuum. 
+#
+# This procedure calculates and returns the number of pages used by the 
+# auto-vacuum 'pointer-map'. If the database does not support auto-vacuum,
+# then 0 is returned. The two arguments are the size of the database file in
+# pages and the page size used by the database (in bytes).
+proc autovacuum_overhead {filePages pageSize} {
+
+  # Read the value of meta 4. If non-zero, then the database supports
+  # auto-vacuum. It would be possible to use "PRAGMA auto_vacuum" instead,
+  # but that would not work if the SQLITE_OMIT_PRAGMA macro was defined
+  # when the library was built.
+  set meta4 [lindex [btree_get_meta $::DB] 4]
+
+  # If the database is not an auto-vacuum database or the file consists
+  # of one page only then there is no overhead for auto-vacuum. Return zero.
+  if {0==$meta4 || $filePages==1} {
+    return 0
+  }
+
+  # The number of entries on each pointer map page. The layout of the
+  # database file is one pointer-map page, followed by $ptrsPerPage other
+  # pages, followed by a pointer-map page etc. The first pointer-map page
+  # is the second page of the file overall.
+  set ptrsPerPage [expr double($pageSize/5)]
+
+  # Return the number of pointer map pages in the database.
+  return [expr int(ceil( ($filePages-1.0)/($ptrsPerPage+1.0) ))]
+}
+
+
+# Calculate the summary statistics for the database and store the results
+# in TCL variables. They are output below. Variables are as follows:
+#
+# pageSize:      Size of each page in bytes.
+# file_bytes:    File size in bytes.
+# file_pgcnt:    Number of pages in the file.
+# file_pgcnt2:   Number of pages in the file (calculated).
+# av_pgcnt:      Pages consumed by the auto-vacuum pointer-map.
+# av_percent:    Percentage of the file consumed by auto-vacuum pointer-map.
+# inuse_pgcnt:   Data pages in the file.
+# inuse_percent: Percentage of pages used to store data.
+# free_pgcnt:    Free pages calculated as (<total pages> - <in-use pages>)
+# free_pgcnt2:   Free pages in the file according to the file header.
+# free_percent:  Percentage of file consumed by free pages (calculated).
+# free_percent2: Percentage of file consumed by free pages (header).
+# ntable:        Number of tables in the db.
+# nindex:        Number of indices in the db.
+# nautoindex:    Number of indices created automatically.
+# nmanindex:     Number of indices created manually.
+# user_payload:  Number of bytes of payload in table btrees 
+#                (not including sqlite_master)
+# user_percent:  $user_payload as a percentage of total file size.
+
+set file_bytes  [file size $file_to_analyze]
+set file_pgcnt  [expr {$file_bytes/$pageSize}]
+
+set av_pgcnt    [autovacuum_overhead $file_pgcnt $pageSize]
+set av_percent  [percent $av_pgcnt $file_pgcnt]
+
+set sql {SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM space_used}
+set inuse_pgcnt   [expr int([mem eval $sql])]
+set inuse_percent [percent $inuse_pgcnt $file_pgcnt]
+
+set free_pgcnt    [expr $file_pgcnt-$inuse_pgcnt-$av_pgcnt]
+set free_percent  [percent $free_pgcnt $file_pgcnt]
+set free_pgcnt2   [lindex [btree_get_meta $DB] 0]
+set free_percent2 [percent $free_pgcnt2 $file_pgcnt]
+
+set file_pgcnt2 [expr {$inuse_pgcnt+$free_pgcnt2+$av_pgcnt}]
+
+set ntable [db eval {SELECT count(*)+1 FROM sqlite_master WHERE type='table'}]
+set nindex [db eval {SELECT count(*) FROM sqlite_master WHERE type='index'}]
+set sql {SELECT count(*) FROM sqlite_master WHERE name LIKE 'sqlite_autoindex%'}
+set nautoindex [db eval $sql]
+set nmanindex [expr {$nindex-$nautoindex}]
+
+# set total_payload [mem eval "SELECT sum(payload) FROM space_used"]
+set user_payload [mem one {SELECT int(sum(payload)) FROM space_used
+     WHERE NOT is_index AND name NOT LIKE 'sqlite_master'}]
+set user_percent [percent $user_payload $file_bytes]
+
+# Output the summary statistics calculated above.
 #
 puts "/** Disk-Space Utilization Report For $file_to_analyze"
 puts "*** As of [clock format [clock seconds] -format {%Y-%b-%d %H:%M:%S}]"
 puts ""
 statline {Page size in bytes} $pageSize
-set fsize [file size $file_to_analyze]
-set file_pgcnt [expr {$fsize/$pageSize}]
-set usedcnt [mem eval \
-              {SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM space_used}]
-set freecnt [expr {$file_pgcnt-$usedcnt}]
-set freecnt2 [lindex [btree_get_meta $DB] 0]
 statline {Pages in the whole file (measured)} $file_pgcnt
-set file_pgcnt2 [expr {$usedcnt+$freecnt2}]
 statline {Pages in the whole file (calculated)} $file_pgcnt2
-statline {Pages that store data} $usedcnt [percent $usedcnt $file_pgcnt]
-statline {Pages on the freelist (per header)}\
-   $freecnt2 [percent $freecnt2 $file_pgcnt]
-statline {Pages on the freelist (calculated)}\
-   $freecnt [percent $freecnt $file_pgcnt]
-
-set ntable [db eval {SELECT count(*)+1 FROM sqlite_master WHERE type='table'}]
+statline {Pages that store data} $inuse_pgcnt $inuse_percent
+statline {Pages on the freelist (per header)} $free_pgcnt2 $free_percent2
+statline {Pages on the freelist (calculated)} $free_pgcnt $free_percent
+statline {Pages of auto-vacuum overhead} $av_pgcnt $av_percent
 statline {Number of tables in the database} $ntable
-set nindex [db eval {SELECT count(*) FROM sqlite_master WHERE type='index'}]
-set autoindex [db eval {SELECT count(*) FROM sqlite_master
-                        WHERE type='index' AND name LIKE '(% autoindex %)'}]
-set manindex [expr {$nindex-$autoindex}]
 statline {Number of indices} $nindex
-statline {Number of named indices} $manindex
-statline {Automatically generated indices} $autoindex
-set total_payload [mem eval "SELECT sum(payload) FROM space_used"]
-statline "Size of the file in bytes" $fsize
-set user_payload [mem one {SELECT sum(payload) FROM space_used
-     WHERE NOT is_index AND name NOT LIKE 'sqlite_master'}]
-statline "Bytes of user payload stored" $user_payload \
-    [percent $user_payload $fsize]
+statline {Number of named indices} $nmanindex
+statline {Automatically generated indices} $nautoindex
+statline {Size of the file in bytes} $file_bytes
+statline {Bytes of user payload stored} $user_payload $user_percent
 
 # Output table rankings
 #
@@ -365,8 +601,8 @@ puts ""
 puts "*** Page counts for all tables with their indices ********************"
 puts ""
 mem eval {SELECT tblname, count(*) AS cnt, 
-              sum(int_pages+leaf_pages+ovfl_pages) AS size
-          FROM space_used GROUP BY tblname ORDER BY size DESC, tblname} {} {
+              int(sum(int_pages+leaf_pages+ovfl_pages)) AS size
+          FROM space_used GROUP BY tblname ORDER BY size+0 DESC, tblname} {} {
   statline [string toupper $tblname] $size [percent $size $file_pgcnt]
 }
 
@@ -422,6 +658,11 @@ Pages on the freelist
     future use.  The percentage at the right is the number of freelist pages
     divided by the total number of pages in the file.
 
+Pages of auto-vacuum overhead
+
+    The number of pages that store data used by the database to facilitate
+    auto-vacuum. This is zero for databases that do not support auto-vacuum.
+
 Number of tables in the database
 
     The number of tables in the database, including the SQLITE_MASTER table
@@ -535,7 +776,8 @@ Unused bytes on all pages
     divided by the total number of bytes.
 }
 
-# Output the database
+# Output a dump of the in-memory database. This can be used for more
+# complex offline analysis.
 #
 puts "**********************************************************************"
 puts "The entire text of this report can be sourced into any SQL database"