open-plc-utils: moved to github
open-plc-utils: moved to github

Signed-off-by: Florian Fainelli <florian@openwrt.org>

git-svn-id: svn://svn.openwrt.org/openwrt/packages@43424 3c298f89-4303-0410-b956-a3cf2f4a3e73

file:a/devel/perf/Makefile (deleted)
--- a/devel/perf/Makefile
+++ /dev/null
@@ -1,67 +1,1 @@
-#
-# Copyright (C) 2011-2013 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
 
-include $(TOPDIR)/rules.mk
-include $(INCLUDE_DIR)/kernel.mk
-
-PKG_NAME:=perf
-PKG_VERSION:=$(LINUX_VERSION)
-PKG_RELEASE:=2
-
-PKG_USE_MIPS16:=0
-
-include $(INCLUDE_DIR)/package.mk
-
-define Package/perf
-  SECTION:=devel
-  CATEGORY:=Development
-  DEPENDS:= +libelf1 +libdw +libpthread +librt +binutils
-  TITLE:=Linux performance monitoring tool
-  VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE)
-  URL:=http://www.kernel.org
-endef
-
-define Package/perf/description
-  perf is the Linux performance monitoring tool
-endef
-
-# Perf's makefile and headers are not relocatable and must be built from the
-# Linux sources directory
-define Build/Prepare
-	$(RM) -r $(PKG_BUILD_DIR)
-	ln -s $(LINUX_DIR)/tools/perf $(PKG_BUILD_DIR)
-endef
-
-# MAKE_FLAGS should be passed again upon cleaning because Perf's makefile
-# always performs checks before processing any rule
-define Build/Clean
-	-$(MAKE) -C $(PKG_BUILD_DIR) \
-		NO_DWARF=1 \
-		$(MAKE_FLAGS) \
-		clean
-endef
-
-MAKE_FLAGS = \
-	ARCH="$(LINUX_KARCH)" \
-	NO_LIBPERL=1 \
-	NO_LIBPYTHON=1 \
-	NO_NEWT=1 \
-	CROSS_COMPILE="$(TARGET_CROSS)" \
-	CC="$(TARGET_CC)" \
-	LD="$(TARGET_CROSS)ld" \
-	CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
-	LDFLAGS="$(TARGET_LDFLAGS)" \
-	V=1 \
-	prefix=/usr
-
-define Package/perf/install
-	$(INSTALL_DIR) $(1)/usr/bin
-	$(INSTALL_BIN) $(LINUX_DIR)/tools/perf/perf $(1)/usr/bin/
-endef
-
-$(eval $(call BuildPackage,perf))
-

file:a/lang/php5/Makefile (deleted)
--- a/lang/php5/Makefile
+++ /dev/null
@@ -1,535 +1,1 @@
-#
-# Copyright (C) 2006-2014 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
 
-include $(TOPDIR)/rules.mk
-
-PKG_NAME:=php
-PKG_VERSION:=5.4.27
-PKG_RELEASE:=1
-
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
-PKG_SOURCE_URL:=http://www.php.net/distributions/
-PKG_MD5SUM:=1c6e99187d25023411b663ea09f145ee
-
-PKG_FIXUP:=libtool no-autoreconf
-PKG_BUILD_PARALLEL:=1
-
-PHP5_MODULES = \
-	calendar ctype curl \
-	fileinfo \
-	dom \
-	exif \
-	ftp \
-	gettext gd gmp \
-	hash \
-	iconv \
-	json \
-	ldap \
-	mbstring mcrypt mysql mysqli \
-	openssl \
-	pcntl pdo pdo-mysql pdo-pgsql pdo-sqlite pgsql \
-	session shmop simplexml soap sockets sqlite sqlite3 sysvmsg sysvsem sysvshm \
-	tokenizer \
-	xml xmlreader xmlwriter zip \
-
-PKG_CONFIG_DEPENDS:= \
-	$(patsubst %,CONFIG_PACKAGE_php5-mod-%,$(PHP5_MODULES)) \
-	CONFIG_PHP5_FILTER CONFIG_PHP5_LIBXML CONFIG_PHP5_SYSTEMTZDATA
-
-include $(INCLUDE_DIR)/package.mk
-include $(INCLUDE_DIR)/nls.mk
-
-define Package/php5/Default
-  SUBMENU:=PHP
-  SECTION:=lang
-  CATEGORY:=Languages
-  TITLE:=PHP5 Hypertext preprocessor
-  URL:=http://www.php.net/
-  MAINTAINER:=Michael Heimpold <mhei@heimpold.de>
-  DEPENDS:=php5
-endef
-
-define Package/php5/Default/description
-  PHP is a widely-used general-purpose scripting language that is especially
-  suited for Web development and can be embedded into HTML.
-endef
-
-define Package/php5/config
-	config PHP5_FILTER
-		bool "PHP5 Filter support"
-		depends on PACKAGE_php5-cli || PACKAGE_php5-cgi
-
-	config PHP5_LIBXML
-		bool "PHP5 LIBXML support"
-		depends on PACKAGE_php5-cli || PACKAGE_php5-cgi
-
-	config PHP5_SYSTEMTZDATA
-		bool "Use system timezone data instead of php's built-in database"
-		depends on PACKAGE_php5-cli || PACKAGE_php5-cgi
-		select PACKAGE_zoneinfo-core
-		default y
-		help
-			Enabling this feature automatically selects the zoneinfo-core package
-			which contains data for UTC timezone. To use other timezones you have
-			to install the corresponding zoneinfo-... package(s).
-endef
-
-define Package/php5
-  $(call Package/php5/Default)
-
-  DEPENDS:=+libpcre +zlib \
-           +PHP5_LIBXML:libxml2
-endef
-
-define Package/php5/description
-  $(call Package/php5/Default/description)
-  This package contains only the PHP config file. You must actually choose
-  your PHP flavour (cli, cgi or fastcgi).
-endef
-
-define Package/php5-cli
-  $(call Package/php5/Default)
-  TITLE+= (CLI)
-endef
-
-define Package/php5-cli/description
-  $(call Package/php5/Default/description)
-  This package contains the CLI version of the PHP5 interpreter.
-endef
-
-define Package/php5-cgi
-  $(call Package/php5/Default)
-  TITLE+= (CGI & FastCGI)
-endef
-
-define Package/php5-cgi/description
-  $(call Package/php5/Default/description)
-  This package contains the CGI version of the PHP5 interpreter.
-endef
-
-define Package/php5-fastcgi
-  $(call Package/php5/Default)
-  DEPENDS+= +php5-cgi
-  TITLE:=FastCGI startup script
-endef
-
-define Package/php5-fastcgi/description
-  As FastCGI support is now a core feature the php5-fastcgi package now depends
-  on the php5-cgi package, containing just the startup script.
-endef
-
-CONFIGURE_ARGS+= \
-	--enable-cli \
-	--enable-cgi \
-	--enable-shared \
-	--disable-static \
-	--disable-rpath \
-	--disable-debug \
-	--without-pear \
-	\
-	--with-config-file-path=/etc \
-	--with-config-file-scan-dir=/etc/php5 \
-	--disable-short-tags \
-	\
-	--with-zlib="$(STAGING_DIR)/usr" \
-	  --with-zlib-dir="$(STAGING_DIR)/usr" \
-	--with-pcre-regex="$(STAGING_DIR)/usr" \
-	--disable-phar
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-calendar),)
-  CONFIGURE_ARGS+= --enable-calendar=shared
-else
-  CONFIGURE_ARGS+= --disable-calendar
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-ctype),)
-  CONFIGURE_ARGS+= --enable-ctype=shared
-else
-  CONFIGURE_ARGS+= --disable-ctype
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-curl),)
-  CONFIGURE_ARGS+= --with-curl=shared,"$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --without-curl
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-fileinfo),)
-  CONFIGURE_ARGS+= --enable-fileinfo=shared
-else
-  CONFIGURE_ARGS+= --disable-fileinfo
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-gettext),)
-  CONFIGURE_ARGS+= --with-gettext=shared,"$(STAGING_DIR)/usr/lib/libintl-full"
-else
-  CONFIGURE_ARGS+= --without-gettext
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-dom),)
-  CONFIGURE_ARGS+= --enable-dom=shared
-else
-  CONFIGURE_ARGS+= --disable-dom
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-exif),)
-  CONFIGURE_ARGS+= --enable-exif=shared
-else
-  CONFIGURE_ARGS+= --disable-exif
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-ftp),)
-  CONFIGURE_ARGS+= --enable-ftp=shared
-else
-  CONFIGURE_ARGS+= --disable-ftp
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-gd),)
-  CONFIGURE_ARGS+= \
-	--with-gd=shared \
-	--without-freetype-dir \
-	--with-jpeg-dir="$(STAGING_DIR)/usr" \
-	--with-png-dir="$(STAGING_DIR)/usr" \
-	--without-xpm-dir \
-	--without-t1lib \
-	--enable-gd-native-ttf \
-	--disable-gd-jis-conv
-else
-  CONFIGURE_ARGS+= --without-gd
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-gmp),)
-  CONFIGURE_ARGS+= --with-gmp=shared,"$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --without-gmp
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-hash),)
-  CONFIGURE_ARGS+= --enable-hash=shared
-else
-  CONFIGURE_ARGS+= --disable-hash
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-iconv),)
-  CONFIGURE_ARGS+= --with-iconv=shared,"$(ICONV_PREFIX)"
-else
-  CONFIGURE_ARGS+= --without-iconv
-endif
-
-ifneq ($(CONFIG_PACKAGE_php5-mod-json),)
-  CONFIGURE_ARGS+= --enable-json=shared
-else
-  CONFIGURE_ARGS+= --disable-json
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-ldap),)
-  CONFIGURE_ARGS+= \
-	--with-ldap=shared,"$(STAGING_DIR)/usr" \
-	--with-ldap-sasl="$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --without-ldap
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-mbstring),)
-  CONFIGURE_ARGS+= --enable-mbstring=shared --enable-mbregex
-else
-  CONFIGURE_ARGS+= --disable-mbstring
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-mcrypt),)
-  CONFIGURE_ARGS+=  --with-mcrypt=shared,"$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --without-mcrypt
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-mysql),)
-  CONFIGURE_ARGS+= --with-mysql=shared,"$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --without-mysql
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-mysqli),)
-  CONFIGURE_ARGS+= --with-mysqli=shared,"$(STAGING_DIR)/usr/bin/mysql_config"
-else
-  CONFIGURE_ARGS+= --without-mysqli
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-openssl),)
-  CONFIGURE_ARGS+= \
-	--with-openssl=shared,"$(STAGING_DIR)/usr" \
-	--with-kerberos=no \
-	--with-openssl-dir="$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --without-openssl
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-pcntl),)
-  CONFIGURE_ARGS+= --enable-pcntl=shared
-else
-  CONFIGURE_ARGS+= --disable-pcntl
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-pdo),)
-  CONFIGURE_ARGS+= --enable-pdo=shared
-  ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-pdo-mysql),)
-    CONFIGURE_ARGS+= --with-pdo-mysql=shared,"$(STAGING_DIR)/usr"
-  else
-    CONFIGURE_ARGS+= --without-pdo-mysql
-  endif
-  ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-pdo-pgsql),)
-    CONFIGURE_ARGS+= --with-pdo-pgsql=shared,"$(STAGING_DIR)/usr"
-  else
-    CONFIGURE_ARGS+= --without-pdo-pgsql
-  endif
-  ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-pdo-sqlite),)
-    CONFIGURE_ARGS+= --with-pdo-sqlite=shared,"$(STAGING_DIR)/usr"
-  else
-    CONFIGURE_ARGS+= --without-pdo-sqlite
-  endif
-else
-  CONFIGURE_ARGS+= --disable-pdo
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-pgsql),)
-  CONFIGURE_ARGS+= --with-pgsql=shared,"$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --without-pgsql
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-session),)
-  CONFIGURE_ARGS+= --enable-session=shared
-else
-  CONFIGURE_ARGS+= --disable-session
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-shmop),)
-  CONFIGURE_ARGS+= --enable-shmop=shared
-else
-  CONFIGURE_ARGS+= --disable-shmop
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-simplexml),)
-  CONFIGURE_ARGS+= --enable-simplexml=shared
-else
-  CONFIGURE_ARGS+= --disable-simplexml
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-soap),)
-  CONFIGURE_ARGS+= --enable-soap=shared
-else
-  CONFIGURE_ARGS+= --disable-soap
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-sockets),)
-  CONFIGURE_ARGS+= --enable-sockets=shared
-else
-  CONFIGURE_ARGS+= --disable-sockets
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-sqlite),)
-  CONFIGURE_ARGS+= --with-sqlite=shared,"$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --without-sqlite
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-sqlite3),)
-  CONFIGURE_ARGS+= --with-sqlite3=shared,"$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --without-sqlite3
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-sysvmsg),)
-  CONFIGURE_ARGS+= --enable-sysvmsg=shared
-else
-  CONFIGURE_ARGS+= --disable-sysvmsg
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-sysvsem),)
-  CONFIGURE_ARGS+= --enable-sysvsem=shared
-else
-  CONFIGURE_ARGS+= --disable-sysvsem
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-sysvshm),)
-  CONFIGURE_ARGS+= --enable-sysvshm=shared
-else
-  CONFIGURE_ARGS+= --disable-sysvshm
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-tokenizer),)
-  CONFIGURE_ARGS+= --enable-tokenizer=shared
-else
-  CONFIGURE_ARGS+= --disable-tokenizer
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-xml),)
-  CONFIGURE_ARGS+= --enable-xml=shared,"$(STAGING_DIR)/usr"
-  ifneq ($(CONFIG_PHP5_LIBXML),)
-    CONFIGURE_ARGS+= --with-libxml-dir="$(STAGING_DIR)/usr/include/libxml2"
-  else
-    CONFIGURE_ARGS+= --with-libexpat-dir="$(STAGING_DIR)/usr"
-  endif
-else
-  CONFIGURE_ARGS+= --disable-xml
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-xmlreader),)
-  CONFIGURE_ARGS+= --enable-xmlreader=shared,"$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --disable-xmlreader
-endif
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-xmlwriter),)
-  CONFIGURE_ARGS+= --enable-xmlwriter=shared,"$(STAGING_DIR)/usr"
-else
-  CONFIGURE_ARGS+= --disable-xmlwriter
-endif
-
-ifneq ($(CONFIG_PACKAGE_php5-mod-zip),)
-  CONFIGURE_ARGS+= --enable-zip=shared
-else
-  CONFIGURE_ARGS+= --disable-zip
-endif
-
-ifneq ($(SDK)$(CONFIG_PHP5_FILTER),)
-  CONFIGURE_ARGS+= --enable-filter
-else
-  CONFIGURE_ARGS+= --disable-filter
-endif
-
-ifneq ($(SDK)$(CONFIG_PHP5_LIBXML),)
-  CONFIGURE_ARGS+= --enable-libxml
-  CONFIGURE_ARGS+= --with-libxml-dir="$(STAGING_DIR)/usr/include/libxml2"
-else
-  CONFIGURE_ARGS+= --disable-libxml
-endif
-
-ifneq ($(CONFIG_PHP5_SYSTEMTZDATA),)
-  CONFIGURE_ARGS+= --with-system-tzdata
-else
-  CONFIGURE_ARGS+= --without-system-tzdata
-endif
-
-CONFIGURE_VARS+= \
-	ac_cv_c_bigendian_php=$(if $(CONFIG_BIG_ENDIAN),yes,no) \
-	php_cv_cc_rpath="no" \
-	iconv_impl_name="gnu_libiconv" \
-	ac_cv_php_xml2_config_path="$(STAGING_DIR)/host/bin/xml2-config" \
-
-define Package/php5/conffiles
-/etc/php.ini
-endef
-
-define Package/php5/install
-	$(INSTALL_DIR) $(1)/etc
-	$(INSTALL_DATA) ./files/php.ini $(1)/etc/
-endef
-
-define Package/php5-cli/install
-	$(INSTALL_DIR) $(1)/usr/bin
-	$(CP) $(PKG_BUILD_DIR)/sapi/cli/php $(1)/usr/bin/php-cli
-endef
-
-define Package/php5-cgi/install
-	$(INSTALL_DIR) $(1)/usr/bin
-	$(CP) $(PKG_BUILD_DIR)/sapi/cgi/php-cgi $(1)/usr/bin/php-cgi
-	ln -sf php-cgi $(1)/usr/bin/php-fcgi
-endef
-
-define Package/php5-fastcgi/install
-	$(INSTALL_DIR) $(1)/etc/config
-	$(INSTALL_DATA) ./files/php5-fastcgi.config $(1)/etc/config/php5-fastcgi
-
-	$(INSTALL_DIR) $(1)/etc/init.d
-	$(INSTALL_BIN) ./files/php5-fastcgi.init $(1)/etc/init.d/php5-fastcgi
-endef
-
-define Build/Prepare
-	$(call Build/Prepare/Default)
-	( cd $(PKG_BUILD_DIR); touch configure.in; ./buildconf --force )
-endef
-
-define Build/InstallDev
-	mkdir -p $(PKG_BUILD_DIR)/staging/usr/bin
-	make -C $(PKG_BUILD_DIR) install INSTALL_ROOT=$(PKG_BUILD_DIR)/staging
-	rm -f $(PKG_BUILD_DIR)/staging/usr/bin/php
-	$(CP) $(PKG_BUILD_DIR)/staging/* $(STAGING_DIR_HOST)
-	sed -i -e "s#prefix='/usr'#prefix='$(STAGING_DIR_HOST)/usr'#" $(STAGING_DIR_HOST)/usr/bin/phpize
-	sed -i -e "s#exec_prefix=\"\`eval echo /usr\`\"#exec_prefix='$(STAGING_DIR_HOST)/usr'#" $(STAGING_DIR_HOST)/usr/bin/phpize
-	sed -i -e "s#prefix=\"/usr\"#prefix=\"$(STAGING_DIR_HOST)/usr\"#" $(STAGING_DIR_HOST)/usr/bin/php-config
-endef
-
-define BuildModule
-
-  define Package/php5-mod-$(1)
-    $(call Package/php5/Default)
-
-    ifneq ($(3),)
-      DEPENDS+=$(3)
-    endif
-
-    TITLE:=$(2) shared module
-  endef
-
-  define Package/php5-mod-$(1)/install
-	$(INSTALL_DIR) $$(1)/usr/lib/php
-	$(INSTALL_BIN) $(PKG_BUILD_DIR)/modules/$(subst -,_,$(1)).so $$(1)/usr/lib/php/
-	$(INSTALL_DIR) $$(1)/etc/php5
-	echo "extension=$(subst -,_,$(1)).so" > $$(1)/etc/php5/$(subst -,_,$(1)).ini
-  endef
-
-  $$(eval $$(call BuildPackage,php5-mod-$(1)))
-
-endef
-
-$(eval $(call BuildPackage,php5))
-$(eval $(call BuildPackage,php5-cli))
-$(eval $(call BuildPackage,php5-cgi))
-$(eval $(call BuildPackage,php5-fastcgi))
-
-#$(eval $(call BuildModule,NAME,TITLE[,PKG DEPENDS]))
-$(eval $(call BuildModule,calendar,Calendar))
-$(eval $(call BuildModule,ctype,Ctype))
-$(eval $(call BuildModule,curl,cURL,+PACKAGE_php5-mod-curl:libcurl))
-$(eval $(call BuildModule,fileinfo,Fileinfo,+PACKAGE_php5-mod-fileinfo:libmagic))
-$(eval $(call BuildModule,dom,DOM,+@PHP5_LIBXML +PACKAGE_php5-mod-dom:libxml2))
-$(eval $(call BuildModule,exif,EXIF))
-$(eval $(call BuildModule,ftp,FTP,+PACKAGE_php5-mod-ftp:libopenssl))
-$(eval $(call BuildModule,gettext,Gettext,+PACKAGE_php5-mod-gettext:libintl-full))
-$(eval $(call BuildModule,gd,GD graphics,+PACKAGE_php5-mod-gd:libjpeg +PACKAGE_php5-mod-gd:libpng))
-$(eval $(call BuildModule,gmp,GMP,+PACKAGE_php5-mod-gmp:libgmp))
-$(eval $(call BuildModule,hash,Hash))
-$(eval $(call BuildModule,iconv,iConv,+PACKAGE_php5-mod-iconv:libiconv))
-$(eval $(call BuildModule,json,JSON))
-$(eval $(call BuildModule,ldap,LDAP,+PACKAGE_php5-mod-ldap:libopenldap +PACKAGE_php5-mod-ldap:libsasl2))
-$(eval $(call BuildModule,mbstring,MBString))
-$(eval $(call BuildModule,mcrypt,Mcrypt,+PACKAGE_php5-mod-mcrypt:libmcrypt +PACKAGE_php5-mod-mcrypt:libltdl))
-$(eval $(call BuildModule,mysql,MySQL,+PACKAGE_php5-mod-mysql:libmysqlclient))
-$(eval $(call BuildModule,mysqli,MySQL Improved Extension,+PACKAGE_php5-mod-mysqli:libmysqlclient))
-$(eval $(call BuildModule,openssl,OpenSSL,+PACKAGE_php5-mod-openssl:libopenssl))
-$(eval $(call BuildModule,pcntl,PCNTL))
-$(eval $(call BuildModule,pdo,PHP Data Objects))
-$(eval $(call BuildModule,pdo-mysql,PDO driver for MySQL,+php5-mod-pdo +PACKAGE_php5-mod-pdo-mysql:libmysqlclient))
-$(eval $(call BuildModule,pdo-pgsql,PDO driver for PostgreSQL,+php5-mod-pdo +PACKAGE_php5-mod-pdo-pgsql:libpq))
-$(eval $(call BuildModule,pdo-sqlite,PDO driver for SQLite 3.x,+php5-mod-pdo +PACKAGE_php5-mod-pdo-sqlite:libsqlite3 +PACKAGE_php5-mod-pdo-sqlite:libpthread +PACKAGE_php5-mod-pdo-sqlite:librt))
-$(eval $(call BuildModule,pgsql,PostgreSQL,+PACKAGE_php5-mod-pgsql:libpq))
-$(eval $(call BuildModule,session,Session))
-$(eval $(call BuildModule,shmop,Shared Memory))
-$(eval $(call BuildModule,simplexml,SimpleXML,+@PHP5_LIBXML +PACKAGE_php5-mod-simplexml:libxml2))
-$(eval $(call BuildModule,soap,SOAP,+@PHP5_LIBXML +PACKAGE_php5-mod-soap:libxml2))
-$(eval $(call BuildModule,sockets,Sockets))
-$(eval $(call BuildModule,sqlite,SQLite 2.x,+PACKAGE_php5-mod-sqlite:libsqlite2))
-$(eval $(call BuildModule,sqlite3,SQLite3,+PACKAGE_php5-mod-sqlite3:libsqlite3 +PACKAGE_php5-mod-sqlite3:libpthread))
-$(eval $(call BuildModule,sysvmsg,System V messages))
-$(eval $(call BuildModule,sysvsem,System V shared memory))
-$(eval $(call BuildModule,sysvshm,System V semaphore))
-$(eval $(call BuildModule,tokenizer,Tokenizer))
-$(eval $(call BuildModule,xml,XML,+PHP5_LIBXML:libxml2 +!PHP5_LIBXML:libexpat))
-$(eval $(call BuildModule,xmlreader,XMLReader,+@PHP5_LIBXML +PACKAGE_php5-mod-xmlreader:libxml2 +PACKAGE_php5-mod-xmlreader:libiconv))
-$(eval $(call BuildModule,xmlwriter,XMLWriter,+@PHP5_LIBXML +PACKAGE_php5-mod-xmlwriter:libxml2 +PACKAGE_php5-mod-xmlwriter:libiconv))
-$(eval $(call BuildModule,zip,ZIP,+PACKAGE_php5-mod-zip:zlib))
-

file:a/lang/php5/files/php.ini (deleted)
--- a/lang/php5/files/php.ini
+++ /dev/null
@@ -1,312 +1,1 @@
-[PHP]
 
-zend.ze1_compatibility_mode = Off
-
-; Language Options
-
-engine = On
-;short_open_tag = Off
-precision    =  12
-y2k_compliance = On
-output_buffering = Off
-;output_handler =
-zlib.output_compression = Off
-;zlib.output_compression_level = -1
-;zlib.output_handler =
-implicit_flush = Off
-unserialize_callback_func =
-serialize_precision = 100
-
-;open_basedir =
-disable_functions =
-disable_classes =
-
-; Colors for Syntax Highlighting mode.  Anything that's acceptable in
-; <span style="color: ???????"> would work.
-;highlight.string  = #DD0000
-;highlight.comment = #FF9900
-;highlight.keyword = #007700
-;highlight.bg      = #FFFFFF
-;highlight.default = #0000BB
-;highlight.html    = #000000
-
-;ignore_user_abort = On
-;realpath_cache_size = 16k
-;realpath_cache_ttl = 120
-
-; Miscellaneous
-
-expose_php = On
-
-; Resource Limits
-
-max_execution_time = 30	; Maximum execution time of each script, in seconds.
-max_input_time = 60	; Maximum amount of time each script may spend parsing request data.
-;max_input_nesting_level = 64
-memory_limit = 8M	; Maximum amount of memory a script may consume.
-
-; Error handling and logging
-
-; Error Level Constants:
-; E_ALL             - All errors and warnings (includes E_STRICT as of PHP 6.0.0)
-; E_ERROR           - fatal run-time errors
-; E_RECOVERABLE_ERROR  - almost fatal run-time errors
-; E_WARNING         - run-time warnings (non-fatal errors)
-; E_PARSE           - compile-time parse errors
-; E_NOTICE          - run-time notices (these are warnings which often result
-;                     from a bug in your code, but it's possible that it was
-;                     intentional (e.g., using an uninitialized variable and
-;                     relying on the fact it's automatically initialized to an
-;                     empty string)
-; E_STRICT			- run-time notices, enable to have PHP suggest changes
-;                     to your code which will ensure the best interoperability
-;                     and forward compatibility of your code
-; E_CORE_ERROR      - fatal errors that occur during PHP's initial startup
-; E_CORE_WARNING    - warnings (non-fatal errors) that occur during PHP's
-;                     initial startup
-; E_COMPILE_ERROR   - fatal compile-time errors
-; E_COMPILE_WARNING - compile-time warnings (non-fatal errors)
-; E_USER_ERROR      - user-generated error message
-; E_USER_WARNING    - user-generated warning message
-; E_USER_NOTICE     - user-generated notice message
-; E_DEPRECATED      - warn about code that will not work in future versions
-;                     of PHP
-; E_USER_DEPRECATED - user-generated deprecation warnings
-;
-; Common Values:
-;   E_ALL & ~E_NOTICE  (Show all errors, except for notices and coding standards warnings.)
-;   E_ALL & ~E_NOTICE | E_STRICT  (Show all errors, except for notices)
-;   E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR  (Show only errors)
-;   E_ALL | E_STRICT  (Show all errors, warnings and notices including coding standards.)
-; Default Value: E_ALL & ~E_NOTICE
-error_reporting  =  E_ALL & ~E_NOTICE & ~E_STRICT
-
-display_errors = On
-display_startup_errors = Off
-log_errors = Off
-log_errors_max_len = 1024
-ignore_repeated_errors = Off
-ignore_repeated_source = Off
-report_memleaks = On
-;report_zend_debug = 0
-track_errors = Off
-;html_errors = Off
-;docref_root = "/phpmanual/"
-;docref_ext = .html
-;error_prepend_string = "<font color=#ff0000>"
-;error_append_string = "</font>"
-; Log errors to specified file.
-;error_log = /var/log/php_errors.log
-; Log errors to syslog.
-;error_log = syslog
-
-; Data Handling
-
-;arg_separator.output = "&amp;"
-;arg_separator.input = ";&"
-variables_order = "EGPCS"
-request_order = "GP"
-register_globals = Off
-register_long_arrays = Off
-register_argc_argv = On
-auto_globals_jit = On
-post_max_size = 8M
-;magic_quotes_gpc = Off
-magic_quotes_runtime = Off
-magic_quotes_sybase = Off
-auto_prepend_file =
-auto_append_file =
-default_mimetype = "text/html"
-;default_charset = "iso-8859-1"
-;always_populate_raw_post_data = On
-
-; Paths and Directories
-
-; UNIX: "/path1:/path2"
-;include_path = ".:/php/includes"
-doc_root = "/www"
-user_dir =
-extension_dir = "/usr/lib/php"
-enable_dl = On
-;cgi.force_redirect = 1
-;cgi.nph = 1
-;cgi.redirect_status_env = ;
-cgi.fix_pathinfo=1
-;fastcgi.impersonate = 1;
-;fastcgi.logging = 0
-;cgi.rfc2616_headers = 0
-
-; File Uploads
-
-file_uploads = On
-upload_tmp_dir = "/tmp"
-upload_max_filesize = 2M
-max_file_uploads = 20
-
-; Fopen wrappers
-
-allow_url_fopen = On
-allow_url_include = Off
-;from="john@doe.com"
-;user_agent="PHP"
-default_socket_timeout = 60
-;auto_detect_line_endings = Off
-
-; Dynamic Extensions
-
-;extension=ctype.so
-;extension=curl.so
-;extension=dom.so
-;extension=exif.so
-;extension=ftp.so
-;extension=gd.so
-;extension=gmp.so
-;extension=hash.so
-;extension=iconv.so
-;extension=json.so
-;extension=ldap.so
-;extension=mbstring.so
-;extension=mcrypt.so
-;extension=mysql.so
-;extension=openssl.so
-;extension=pcre.so
-;extension=pdo.so
-;extension=pdo-mysql.so
-;extension=pdo-pgsql.so
-;extension=pdo_sqlite.so
-;extension=pgsql.so
-;extension=session.so
-;extension=soap.so
-;extension=sockets.so
-;extension=sqlite.so
-;extension=sqlite3.so
-;extension=tokenizer.so
-;extension=xml.so
-;extension=xmlreader.so
-;extension=xmlwriter.so
-
-; Module Settings
-
-[APC]
-apc.enabled = 1
-apc.shm_segments = 1	;The number of shared memory segments to allocate for the compiler cache.
-apc.shm_size = 4M	;The size of each shared memory segment.
-
-[Date]
-;date.timezone =
-;date.default_latitude = 31.7667
-;date.default_longitude = 35.2333
-;date.sunrise_zenith = 90.583333
-;date.sunset_zenith = 90.583333
-
-[filter]
-;filter.default = unsafe_raw
-;filter.default_flags =
-
-[iconv]
-;iconv.input_encoding = ISO-8859-1
-;iconv.internal_encoding = ISO-8859-1
-;iconv.output_encoding = ISO-8859-1
-
-[sqlite]
-;sqlite.assoc_case = 0
-
-[sqlite3]
-;sqlite3.extension_dir =
-
-[Pdo_mysql]
-pdo_mysql.cache_size = 2000
-pdo_mysql.default_socket=
-
-[MySQL]
-mysql.allow_local_infile = On
-mysql.allow_persistent = On
-mysql.cache_size = 2000
-mysql.max_persistent = -1
-mysql.max_links = -1
-mysql.default_port =
-mysql.default_socket =
-mysql.default_host =
-mysql.default_user =
-mysql.default_password =
-mysql.connect_timeout = 60
-mysql.trace_mode = Off
-
-[PostgresSQL]
-pgsql.allow_persistent = On
-pgsql.auto_reset_persistent = Off
-pgsql.max_persistent = -1
-pgsql.max_links = -1
-pgsql.ignore_notice = 0
-pgsql.log_notice = 0
-
-[Session]
-session.save_handler = files
-session.save_path = "/tmp"
-session.use_cookies = 1
-;session.cookie_secure =
-session.use_only_cookies = 1
-session.name = PHPSESSID
-session.auto_start = 0
-session.cookie_lifetime = 0
-session.cookie_path = /
-session.cookie_domain =
-session.cookie_httponly =
-session.serialize_handler = php
-session.gc_probability = 1
-session.gc_divisor     = 100
-session.gc_maxlifetime = 1440
-session.bug_compat_42 = On
-session.bug_compat_warn = On
-session.referer_check =
-session.entropy_length = 0
-;session.entropy_file = /dev/urandom
-session.entropy_file =
-;session.entropy_length = 16
-session.cache_limiter = nocache
-session.cache_expire = 180
-session.use_trans_sid = 0
-session.hash_function = 0
-session.hash_bits_per_character = 4
-url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=,fieldset="
-
-[mbstring]
-;mbstring.language = Japanese
-;mbstring.internal_encoding = EUC-JP
-;mbstring.http_input = auto
-;mbstring.http_output = SJIS
-;mbstring.encoding_translation = Off
-;mbstring.detect_order = auto
-;mbstring.substitute_character = none;
-;mbstring.func_overload = 0
-;mbstring.strict_detection = Off
-;mbstring.http_output_conv_mimetype=
-;mbstring.script_encoding=
-
-[gd]
-;gd.jpeg_ignore_warning = 0
-
-[exif]
-;exif.encode_unicode = ISO-8859-15
-;exif.decode_unicode_motorola = UCS-2BE
-;exif.decode_unicode_intel    = UCS-2LE
-;exif.encode_jis =
-;exif.decode_jis_motorola = JIS
-;exif.decode_jis_intel    = JIS
-
-[soap]
-soap.wsdl_cache_enabled=1
-soap.wsdl_cache_dir="/tmp"
-soap.wsdl_cache_ttl=86400
-soap.wsdl_cache_limit = 5
-
-[sysvshm]
-;sysvshm.init_mem = 10000
-
-[ldap]
-ldap.max_links = -1
-
-[mcrypt]
-;mcrypt.algorithms_dir=
-;mcrypt.modes_dir=
-

--- a/lang/php5/files/php5-fastcgi.config
+++ /dev/null
@@ -1,4 +1,1 @@
-config php5-fastcgi
-	option enabled 1
-	option port '1026'
 

--- a/lang/php5/files/php5-fastcgi.init
+++ /dev/null
@@ -1,31 +1,1 @@
-#!/bin/sh /etc/rc.common
-# Copyright (C) 2010-2011 OpenWrt.org
 
-START=50
-
-SERVICE_DAEMONIZE=1
-SERVICE_WRITE_PID=1
-
-start_instance() {
-	local section="$1"
-	local enabled
-	local port
-
-	config_get_bool enabled "$section" 'enabled' 0
-	config_get port "$section" 'port' 1026
-
-	[ $enabled -gt 0 ] || return 1
-
-	PHP_FCGI_CHILDREN='' \
-	service_start /usr/bin/php-fcgi -b $port
-}
-
-start() {
-	config_load 'php5-fastcgi'
-	config_foreach start_instance 'php5-fastcgi'
-}
-
-stop() {
-	service_stop /usr/bin/php-fcgi
-}
-

--- a/lang/php5/patches/090-restore-sqlite2.patch
+++ /dev/null
@@ -1,50846 +1,1 @@
---- /dev/null
-+++ b/ext/sqlite/config.m4
-@@ -0,0 +1,157 @@
-+dnl $Id$
-+dnl config.m4 for extension sqlite
-+dnl vim:et:ts=2:sw=2
-+
-+PHP_ARG_WITH(sqlite, for sqlite support,
-+[  --without-sqlite=DIR    Do not include sqlite support.  DIR is the sqlite base
-+                          install directory [BUNDLED]], yes)
-+
-+PHP_ARG_ENABLE(sqlite-utf8, whether to enable UTF-8 support in sqlite (default: ISO-8859-1),
-+[  --enable-sqlite-utf8      SQLite: Enable UTF-8 support for SQLite], no, no)
-+
-+
-+
-+dnl
-+dnl PHP_PROG_LEMON
-+dnl
-+dnl Search for lemon binary and check its version
-+dnl
-+AC_DEFUN([PHP_PROG_LEMON],[
-+  # we only support certain lemon versions
-+  lemon_version_list="1.0"
-+
-+  AC_CHECK_PROG(LEMON, lemon, lemon)
-+  if test "$LEMON"; then
-+    AC_CACHE_CHECK([for lemon version], php_cv_lemon_version, [
-+      lemon_version=`$LEMON -x 2>/dev/null | $SED -e 's/^.* //'`
-+      php_cv_lemon_version=invalid
-+      for lemon_check_version in $lemon_version_list; do
-+        if test "$lemon_version" = "$lemon_check_version"; then
-+          php_cv_lemon_version="$lemon_check_version (ok)"
-+        fi
-+      done
-+    ])
-+  else
-+    lemon_version=none
-+  fi
-+  case $php_cv_lemon_version in
-+    ""|invalid[)]
-+      lemon_msg="lemon versions supported for regeneration of libsqlite parsers: $lemon_version_list (found: $lemon_version)."
-+      AC_MSG_WARN([$lemon_msg])
-+      LEMON="exit 0;"
-+      ;;
-+  esac
-+  PHP_SUBST(LEMON)
-+])
-+
-+
-+if test "$PHP_SQLITE" != "no"; then
-+  if test "$PHP_PDO" != "no"; then
-+    PHP_CHECK_PDO_INCLUDES([], [AC_MSG_WARN([Cannot find php_pdo_driver.h.])])
-+    if test -n "$pdo_inc_path"; then
-+      AC_DEFINE([PHP_SQLITE2_HAVE_PDO], [1], [Have PDO])
-+      pdo_inc_path="-I$pdo_inc_path"
-+    fi
-+  fi  
-+
-+  if test "$PHP_SQLITE" != "yes"; then
-+    SEARCH_PATH="/usr/local /usr"
-+    SEARCH_FOR="/include/sqlite.h"
-+    if test -r $PHP_SQLITE/; then # path given as parameter
-+      SQLITE_DIR=$PHP_SQLITE
-+    else # search default path list
-+      AC_MSG_CHECKING([for sqlite files in default path])
-+      for i in $SEARCH_PATH ; do
-+        if test -r $i/$SEARCH_FOR; then
-+          SQLITE_DIR=$i
-+          AC_MSG_RESULT(found in $i)
-+        fi
-+      done
-+    fi
-+  
-+    if test -z "$SQLITE_DIR"; then
-+      AC_MSG_RESULT([not found])
-+      AC_MSG_ERROR([Please reinstall the sqlite distribution from http://www.sqlite.org])
-+    fi
-+
-+    PHP_CHECK_LIBRARY(sqlite, sqlite_open, [
-+      PHP_ADD_LIBRARY_WITH_PATH(sqlite, $SQLITE_DIR/$PHP_LIBDIR, SQLITE_SHARED_LIBADD)
-+      PHP_ADD_INCLUDE($SQLITE_DIR/include)
-+    ],[
-+      AC_MSG_ERROR([wrong sqlite lib version or lib not found])
-+    ],[
-+      -L$SQLITE_DIR/$PHP_LIBDIR -lm
-+    ])
-+    SQLITE_MODULE_TYPE=external
-+    PHP_SQLITE_CFLAGS=$pdo_inc_path
-+    sqlite_extra_sources="libsqlite/src/encode.c"
-+  else
-+    # use bundled library
-+    PHP_PROG_LEMON
-+    SQLITE_MODULE_TYPE=builtin
-+    PHP_SQLITE_CFLAGS="-I@ext_srcdir@/libsqlite/src -I@ext_builddir@/libsqlite/src $pdo_inc_path"
-+    sqlite_extra_sources="libsqlite/src/opcodes.c \
-+        libsqlite/src/parse.c libsqlite/src/encode.c \
-+        libsqlite/src/auth.c libsqlite/src/btree.c libsqlite/src/build.c \
-+        libsqlite/src/delete.c libsqlite/src/expr.c libsqlite/src/func.c \
-+        libsqlite/src/hash.c libsqlite/src/insert.c libsqlite/src/main.c \
-+        libsqlite/src/os.c libsqlite/src/pager.c \
-+        libsqlite/src/printf.c libsqlite/src/random.c \
-+        libsqlite/src/select.c libsqlite/src/table.c libsqlite/src/tokenize.c \
-+        libsqlite/src/update.c libsqlite/src/util.c libsqlite/src/vdbe.c \
-+        libsqlite/src/attach.c libsqlite/src/btree_rb.c libsqlite/src/pragma.c \
-+        libsqlite/src/vacuum.c libsqlite/src/copy.c \
-+        libsqlite/src/vdbeaux.c libsqlite/src/date.c \
-+        libsqlite/src/where.c libsqlite/src/trigger.c"
-+  fi
-+  dnl
-+  dnl Common for both bundled/external
-+  dnl
-+  sqlite_sources="sqlite.c sess_sqlite.c pdo_sqlite2.c $sqlite_extra_sources" 
-+  PHP_NEW_EXTENSION(sqlite, $sqlite_sources, $ext_shared,,$PHP_SQLITE_CFLAGS)
-+  PHP_ADD_EXTENSION_DEP(sqlite, spl, true)
-+  PHP_ADD_EXTENSION_DEP(sqlite, pdo, true)
-+
-+  PHP_ADD_MAKEFILE_FRAGMENT
-+  PHP_SUBST(SQLITE_SHARED_LIBADD)
-+  PHP_INSTALL_HEADERS([$ext_builddir/libsqlite/src/sqlite.h])
-+  
-+  if test "$SQLITE_MODULE_TYPE" = "builtin"; then
-+    PHP_ADD_BUILD_DIR($ext_builddir/libsqlite/src, 1)
-+    AC_CHECK_SIZEOF(char *, 4)
-+    AC_DEFINE(SQLITE_PTR_SZ, SIZEOF_CHAR_P, [Size of a pointer])
-+    dnl use latin 1 for SQLite older than 2.8.9; the utf-8 handling 
-+    dnl in funcs.c uses assert(), which is a bit silly and something 
-+    dnl we want to avoid. This assert() was removed in SQLite 2.8.9.
-+    if test "$PHP_SQLITE_UTF8" = "yes"; then
-+      SQLITE_ENCODING="UTF8"
-+      AC_DEFINE(SQLITE_UTF8, 1, [ ])
-+    else
-+      SQLITE_ENCODING="ISO8859"
-+    fi
-+    PHP_SUBST(SQLITE_ENCODING)
-+
-+    SQLITE_VERSION=`cat $ext_srcdir/libsqlite/VERSION`
-+    PHP_SUBST(SQLITE_VERSION)
-+
-+    sed -e s/--VERS--/$SQLITE_VERSION/ -e s/--ENCODING--/$SQLITE_ENCODING/ $ext_srcdir/libsqlite/src/sqlite.h.in > $ext_builddir/libsqlite/src/sqlite.h
-+
-+    if test "$ext_shared" = "no" || test "$ext_srcdir" != "$abs_srcdir"; then
-+      echo '#include <php_config.h>' > $ext_builddir/libsqlite/src/config.h
-+    else
-+      echo "#include \"$abs_builddir/config.h\"" > $ext_builddir/libsqlite/src/config.h
-+    fi
-+    
-+    cat >> $ext_builddir/libsqlite/src/config.h <<EOF
-+#if ZTS
-+# define THREADSAFE 1
-+#endif
-+#if !ZEND_DEBUG
-+# define NDEBUG
-+#endif
-+EOF
-+  fi
-+  
-+  AC_CHECK_FUNCS(usleep nanosleep)
-+  AC_CHECK_HEADERS(time.h)
-+fi
---- /dev/null
-+++ b/ext/sqlite/config.w32
-@@ -0,0 +1,39 @@
-+// $Id$
-+// vim:ft=javascript
-+
-+ARG_WITH("sqlite", "SQLite support", "no");
-+
-+if (PHP_SQLITE != "no") {
-+	copy_and_subst(configure_module_dirname + "\\libsqlite\\src\\sqlite.h.in",
-+		configure_module_dirname + "\\libsqlite\\src\\sqlite.h", new Array(
-+			"--VERS--", file_get_contents(configure_module_dirname + "\\libsqlite\\VERSION").replace(new RegExp("[\r\n]+", "g"), ""),
-+			"--ENCODING--", "ISO8859"
-+		));
-+	
-+	FSO.CopyFile(configure_module_dirname + "\\libsqlite\\src\\sqlite_config.w32.h",
-+	   	configure_module_dirname + "\\libsqlite\\src\\config.h");
-+
-+	if (FSO.FileExists(configure_module_dirname + "\\..\\pdo\\php_pdo_driver.h")) {
-+		PHP_SQLITE2_PDO_CFLAGS = " /DPHP_SQLITE2_HAVE_PDO=1 /I " + configure_module_dirname + "\\..";
-+		ADD_EXTENSION_DEP('sqlite', 'pdo')
-+	} else {
-+		PHP_SQLITE2_PDO_CFLAGS = "";
-+	}
-+	
-+	EXTENSION("sqlite", "sqlite.c sess_sqlite.c pdo_sqlite2.c", null,
-+		"/D PHP_SQLITE_EXPORTS /I " + configure_module_dirname + "/libsqlite/src" +
-+		PHP_SQLITE2_PDO_CFLAGS);
-+		
-+	
-+	ADD_SOURCES(configure_module_dirname + "/libsqlite/src", "opcodes.c parse.c encode.c \
-+		auth.c btree.c build.c delete.c expr.c func.c hash.c insert.c \
-+		main.c os.c pager.c printf.c random.c select.c table.c tokenize.c \
-+		update.c util.c vdbe.c attach.c btree_rb.c pragma.c vacuum.c \
-+		copy.c where.c trigger.c vdbeaux.c date.c", "sqlite");
-+
-+	AC_DEFINE("HAVE_SQLITE", 1, "SQLite support");
-+	if (!PHP_SQLITE_SHARED) {
-+		ADD_DEF_FILE(configure_module_dirname + "\\php_sqlite.def");
-+	}
-+	ADD_EXTENSION_DEP('sqlite', 'spl')
-+}
---- /dev/null
-+++ b/ext/sqlite/CREDITS
-@@ -0,0 +1,2 @@
-+SQLite
-+Wez Furlong, Tal Peer, Marcus Boerger, Ilia Alshanetsky
---- /dev/null
-+++ b/ext/sqlite/libsqlite/README
-@@ -0,0 +1,37 @@
-+This directory contains source code to 
-+
-+    SQLite: An Embeddable SQL Database Engine
-+
-+To compile the project, first create a directory in which to place
-+the build products.  It is recommended, but not required, that the
-+build directory be separate from the source directory.  Cd into the
-+build directory and then from the build directory run the configure
-+script found at the root of the source tree.  Then run "make".
-+
-+For example:
-+
-+    tar xzf sqlite.tar.gz    ;#  Unpack the source tree into "sqlite"
-+    mkdir bld                ;#  Build will occur in a sibling directory
-+    cd bld                   ;#  Change to the build directory
-+    ../sqlite/configure      ;#  Run the configure script
-+    make                     ;#  Run the makefile.
-+
-+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
-+"Makefile.linux-gcc" in the top directory of the source tree that you
-+can copy and edit to suite your needs.  Comments on the generic makefile
-+show what changes are needed.
-+
-+The linux binaries on the website are created using the generic makefile,
-+not the configure script.  The configure script is unmaintained.  (You
-+can volunteer to take over maintenance of the configure script, if you want!)
-+The windows binaries on the website are created using MinGW32 configured
-+as a cross-compiler running under Linux.  For details, see the ./publish.sh
-+script at the top-level of the source tree.
-+
-+Contacts:
-+
-+   http://www.sqlite.org/
-+   http://www.hwaci.com/sw/sqlite/
-+   http://groups.yahoo.com/group/sqlite/
-+   drh@hwaci.com
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/attach.c
-@@ -0,0 +1,311 @@
-+/*
-+** 2003 April 6
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains code used to implement the ATTACH and DETACH commands.
-+**
-+** $Id$
-+*/
-+#include "sqliteInt.h"
-+
-+/*
-+** This routine is called by the parser to process an ATTACH statement:
-+**
-+**     ATTACH DATABASE filename AS dbname
-+**
-+** The pFilename and pDbname arguments are the tokens that define the
-+** filename and dbname in the ATTACH statement.
-+*/
-+void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey){
-+  Db *aNew;
-+  int rc, i;
-+  char *zFile, *zName;
-+  sqlite *db;
-+  Vdbe *v;
-+
-+  v = sqliteGetVdbe(pParse);
-+  sqliteVdbeAddOp(v, OP_Halt, 0, 0);
-+  if( pParse->explain ) return;
-+  db = pParse->db;
-+  if( db->file_format<4 ){
-+    sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an "
-+       "older format master database", 0);
-+    pParse->rc = SQLITE_ERROR;
-+    return;
-+  }
-+  if( db->nDb>=MAX_ATTACHED+2 ){
-+    sqliteErrorMsg(pParse, "too many attached databases - max %d", 
-+       MAX_ATTACHED);
-+    pParse->rc = SQLITE_ERROR;
-+    return;
-+  }
-+
-+  zFile = 0;
-+  sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0);
-+  if( zFile==0 ) return;
-+  sqliteDequote(zFile);
-+#ifndef SQLITE_OMIT_AUTHORIZATION
-+  if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){
-+    sqliteFree(zFile);
-+    return;
-+  }
-+#endif /* SQLITE_OMIT_AUTHORIZATION */
-+
-+  zName = 0;
-+  sqliteSetNString(&zName, pDbname->z, pDbname->n, 0);
-+  if( zName==0 ) return;
-+  sqliteDequote(zName);
-+  for(i=0; i<db->nDb; i++){
-+    if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){
-+      sqliteErrorMsg(pParse, "database %z is already in use", zName);
-+      pParse->rc = SQLITE_ERROR;
-+      sqliteFree(zFile);
-+      return;
-+    }
-+  }
-+
-+  if( db->aDb==db->aDbStatic ){
-+    aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
-+    if( aNew==0 ) return;
-+    memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
-+  }else{
-+    aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
-+    if( aNew==0 ) return;
-+  }
-+  db->aDb = aNew;
-+  aNew = &db->aDb[db->nDb++];
-+  memset(aNew, 0, sizeof(*aNew));
-+  sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
-+  sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
-+  sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
-+  sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
-+  aNew->zName = zName;
-+  rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
-+  if( rc ){
-+    sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
-+  }
-+#if SQLITE_HAS_CODEC
-+  {
-+    extern int sqliteCodecAttach(sqlite*, int, void*, int);
-+    char *zKey = 0;
-+    int nKey;
-+    if( pKey && pKey->z && pKey->n ){
-+      sqliteSetNString(&zKey, pKey->z, pKey->n, 0);
-+      sqliteDequote(zKey);
-+      nKey = strlen(zKey);
-+    }else{
-+      zKey = 0;
-+      nKey = 0;
-+    }
-+    sqliteCodecAttach(db, db->nDb-1, zKey, nKey);
-+  }
-+#endif
-+  sqliteFree(zFile);
-+  db->flags &= ~SQLITE_Initialized;
-+  if( pParse->nErr ) return;
-+  if( rc==SQLITE_OK ){
-+    rc = sqliteInit(pParse->db, &pParse->zErrMsg);
-+  }
-+  if( rc ){
-+    int i = db->nDb - 1;
-+    assert( i>=2 );
-+    if( db->aDb[i].pBt ){
-+      sqliteBtreeClose(db->aDb[i].pBt);
-+      db->aDb[i].pBt = 0;
-+    }
-+    sqliteResetInternalSchema(db, 0);
-+    pParse->nErr++;
-+    pParse->rc = SQLITE_ERROR;
-+  }
-+}
-+
-+/*
-+** This routine is called by the parser to process a DETACH statement:
-+**
-+**    DETACH DATABASE dbname
-+**
-+** The pDbname argument is the name of the database in the DETACH statement.
-+*/
-+void sqliteDetach(Parse *pParse, Token *pDbname){
-+  int i;
-+  sqlite *db;
-+  Vdbe *v;
-+  Db *pDb;
-+
-+  v = sqliteGetVdbe(pParse);
-+  sqliteVdbeAddOp(v, OP_Halt, 0, 0);
-+  if( pParse->explain ) return;
-+  db = pParse->db;
-+  for(i=0; i<db->nDb; i++){
-+    pDb = &db->aDb[i];
-+    if( pDb->pBt==0 || pDb->zName==0 ) continue;
-+    if( strlen(pDb->zName)!=pDbname->n ) continue;
-+    if( sqliteStrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break;
-+  }
-+  if( i>=db->nDb ){
-+    sqliteErrorMsg(pParse, "no such database: %T", pDbname);
-+    return;
-+  }
-+  if( i<2 ){
-+    sqliteErrorMsg(pParse, "cannot detach database %T", pDbname);
-+    return;
-+  }
-+#ifndef SQLITE_OMIT_AUTHORIZATION
-+  if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){
-+    return;
-+  }
-+#endif /* SQLITE_OMIT_AUTHORIZATION */
-+  sqliteBtreeClose(pDb->pBt);
-+  pDb->pBt = 0;
-+  sqliteFree(pDb->zName);
-+  sqliteResetInternalSchema(db, i);
-+  if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
-+  db->nDb--;
-+  if( i<db->nDb ){
-+    db->aDb[i] = db->aDb[db->nDb];
-+    memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0]));
-+    sqliteResetInternalSchema(db, i);
-+  }
-+}
-+
-+/*
-+** Initialize a DbFixer structure.  This routine must be called prior
-+** to passing the structure to one of the sqliteFixAAAA() routines below.
-+**
-+** The return value indicates whether or not fixation is required.  TRUE
-+** means we do need to fix the database references, FALSE means we do not.
-+*/
-+int sqliteFixInit(
-+  DbFixer *pFix,      /* The fixer to be initialized */
-+  Parse *pParse,      /* Error messages will be written here */
-+  int iDb,            /* This is the database that must must be used */
-+  const char *zType,  /* "view", "trigger", or "index" */
-+  const Token *pName  /* Name of the view, trigger, or index */
-+){
-+  sqlite *db;
-+
-+  if( iDb<0 || iDb==1 ) return 0;
-+  db = pParse->db;
-+  assert( db->nDb>iDb );
-+  pFix->pParse = pParse;
-+  pFix->zDb = db->aDb[iDb].zName;
-+  pFix->zType = zType;
-+  pFix->pName = pName;
-+  return 1;
-+}
-+
-+/*
-+** The following set of routines walk through the parse tree and assign
-+** a specific database to all table references where the database name
-+** was left unspecified in the original SQL statement.  The pFix structure
-+** must have been initialized by a prior call to sqliteFixInit().
-+**
-+** These routines are used to make sure that an index, trigger, or
-+** view in one database does not refer to objects in a different database.
-+** (Exception: indices, triggers, and views in the TEMP database are
-+** allowed to refer to anything.)  If a reference is explicitly made
-+** to an object in a different database, an error message is added to
-+** pParse->zErrMsg and these routines return non-zero.  If everything
-+** checks out, these routines return 0.
-+*/
-+int sqliteFixSrcList(
-+  DbFixer *pFix,       /* Context of the fixation */
-+  SrcList *pList       /* The Source list to check and modify */
-+){
-+  int i;
-+  const char *zDb;
-+
-+  if( pList==0 ) return 0;
-+  zDb = pFix->zDb;
-+  for(i=0; i<pList->nSrc; i++){
-+    if( pList->a[i].zDatabase==0 ){
-+      pList->a[i].zDatabase = sqliteStrDup(zDb);
-+    }else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){
-+      sqliteErrorMsg(pFix->pParse,
-+         "%s %z cannot reference objects in database %s",
-+         pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n),
-+         pList->a[i].zDatabase);
-+      return 1;
-+    }
-+    if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1;
-+    if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1;
-+  }
-+  return 0;
-+}
-+int sqliteFixSelect(
-+  DbFixer *pFix,       /* Context of the fixation */
-+  Select *pSelect      /* The SELECT statement to be fixed to one database */
-+){
-+  while( pSelect ){
-+    if( sqliteFixExprList(pFix, pSelect->pEList) ){
-+      return 1;
-+    }
-+    if( sqliteFixSrcList(pFix, pSelect->pSrc) ){
-+      return 1;
-+    }
-+    if( sqliteFixExpr(pFix, pSelect->pWhere) ){
-+      return 1;
-+    }
-+    if( sqliteFixExpr(pFix, pSelect->pHaving) ){
-+      return 1;
-+    }
-+    pSelect = pSelect->pPrior;
-+  }
-+  return 0;
-+}
-+int sqliteFixExpr(
-+  DbFixer *pFix,     /* Context of the fixation */
-+  Expr *pExpr        /* The expression to be fixed to one database */
-+){
-+  while( pExpr ){
-+    if( sqliteFixSelect(pFix, pExpr->pSelect) ){
-+      return 1;
-+    }
-+    if( sqliteFixExprList(pFix, pExpr->pList) ){
-+      return 1;
-+    }
-+    if( sqliteFixExpr(pFix, pExpr->pRight) ){
-+      return 1;
-+    }
-+    pExpr = pExpr->pLeft;
-+  }
-+  return 0;
-+}
-+int sqliteFixExprList(
-+  DbFixer *pFix,     /* Context of the fixation */
-+  ExprList *pList    /* The expression to be fixed to one database */
-+){
-+  int i;
-+  if( pList==0 ) return 0;
-+  for(i=0; i<pList->nExpr; i++){
-+    if( sqliteFixExpr(pFix, pList->a[i].pExpr) ){
-+      return 1;
-+    }
-+  }
-+  return 0;
-+}
-+int sqliteFixTriggerStep(
-+  DbFixer *pFix,     /* Context of the fixation */
-+  TriggerStep *pStep /* The trigger step be fixed to one database */
-+){
-+  while( pStep ){
-+    if( sqliteFixSelect(pFix, pStep->pSelect) ){
-+      return 1;
-+    }
-+    if( sqliteFixExpr(pFix, pStep->pWhere) ){
-+      return 1;
-+    }
-+    if( sqliteFixExprList(pFix, pStep->pExprList) ){
-+      return 1;
-+    }
-+    pStep = pStep->pNext;
-+  }
-+  return 0;
-+}
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/auth.c
-@@ -0,0 +1,219 @@
-+/*
-+** 2003 January 11
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains code used to implement the sqlite_set_authorizer()
-+** API.  This facility is an optional feature of the library.  Embedded
-+** systems that do not need this facility may omit it by recompiling
-+** the library with -DSQLITE_OMIT_AUTHORIZATION=1
-+**
-+** $Id$
-+*/
-+#include "sqliteInt.h"
-+
-+/*
-+** All of the code in this file may be omitted by defining a single
-+** macro.
-+*/
-+#ifndef SQLITE_OMIT_AUTHORIZATION
-+
-+/*
-+** Set or clear the access authorization function.
-+**
-+** The access authorization function is be called during the compilation
-+** phase to verify that the user has read and/or write access permission on
-+** various fields of the database.  The first argument to the auth function
-+** is a copy of the 3rd argument to this routine.  The second argument
-+** to the auth function is one of these constants:
-+**
-+**       SQLITE_COPY
-+**       SQLITE_CREATE_INDEX
-+**       SQLITE_CREATE_TABLE
-+**       SQLITE_CREATE_TEMP_INDEX
-+**       SQLITE_CREATE_TEMP_TABLE
-+**       SQLITE_CREATE_TEMP_TRIGGER
-+**       SQLITE_CREATE_TEMP_VIEW
-+**       SQLITE_CREATE_TRIGGER
-+**       SQLITE_CREATE_VIEW
-+**       SQLITE_DELETE
-+**       SQLITE_DROP_INDEX
-+**       SQLITE_DROP_TABLE
-+**       SQLITE_DROP_TEMP_INDEX
-+**       SQLITE_DROP_TEMP_TABLE
-+**       SQLITE_DROP_TEMP_TRIGGER
-+**       SQLITE_DROP_TEMP_VIEW
-+**       SQLITE_DROP_TRIGGER
-+**       SQLITE_DROP_VIEW
-+**       SQLITE_INSERT
-+**       SQLITE_PRAGMA
-+**       SQLITE_READ
-+**       SQLITE_SELECT
-+**       SQLITE_TRANSACTION
-+**       SQLITE_UPDATE
-+**
-+** The third and fourth arguments to the auth function are the name of
-+** the table and the column that are being accessed.  The auth function
-+** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE.  If
-+** SQLITE_OK is returned, it means that access is allowed.  SQLITE_DENY
-+** means that the SQL statement will never-run - the sqlite_exec() call
-+** will return with an error.  SQLITE_IGNORE means that the SQL statement
-+** should run but attempts to read the specified column will return NULL
-+** and attempts to write the column will be ignored.
-+**
-+** Setting the auth function to NULL disables this hook.  The default
-+** setting of the auth function is NULL.
-+*/
-+int sqlite_set_authorizer(
-+  sqlite *db,
-+  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
-+  void *pArg
-+){
-+  db->xAuth = xAuth;
-+  db->pAuthArg = pArg;
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Write an error message into pParse->zErrMsg that explains that the
-+** user-supplied authorization function returned an illegal value.
-+*/
-+static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
-+  sqliteErrorMsg(pParse, "illegal return value (%d) from the "
-+    "authorization function - should be SQLITE_OK, SQLITE_IGNORE, "
-+    "or SQLITE_DENY", rc);
-+  pParse->rc = SQLITE_MISUSE;
-+}
-+
-+/*
-+** The pExpr should be a TK_COLUMN expression.  The table referred to
-+** is in pTabList or else it is the NEW or OLD table of a trigger.  
-+** Check to see if it is OK to read this particular column.
-+**
-+** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN 
-+** instruction into a TK_NULL.  If the auth function returns SQLITE_DENY,
-+** then generate an error.
-+*/
-+void sqliteAuthRead(
-+  Parse *pParse,        /* The parser context */
-+  Expr *pExpr,          /* The expression to check authorization on */
-+  SrcList *pTabList     /* All table that pExpr might refer to */
-+){
-+  sqlite *db = pParse->db;
-+  int rc;
-+  Table *pTab;          /* The table being read */
-+  const char *zCol;     /* Name of the column of the table */
-+  int iSrc;             /* Index in pTabList->a[] of table being read */
-+  const char *zDBase;   /* Name of database being accessed */
-+  TriggerStack *pStack; /* The stack of current triggers */
-+
-+  if( db->xAuth==0 ) return;
-+  assert( pExpr->op==TK_COLUMN );
-+  for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
-+    if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
-+  }
-+  if( iSrc>=0 && iSrc<pTabList->nSrc ){
-+    pTab = pTabList->a[iSrc].pTab;
-+  }else if( (pStack = pParse->trigStack)!=0 ){
-+    /* This must be an attempt to read the NEW or OLD pseudo-tables
-+    ** of a trigger.
-+    */
-+    assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
-+    pTab = pStack->pTab;
-+  }else{
-+    return;
-+  }
-+  if( pTab==0 ) return;
-+  if( pExpr->iColumn>=0 ){
-+    assert( pExpr->iColumn<pTab->nCol );
-+    zCol = pTab->aCol[pExpr->iColumn].zName;
-+  }else if( pTab->iPKey>=0 ){
-+    assert( pTab->iPKey<pTab->nCol );
-+    zCol = pTab->aCol[pTab->iPKey].zName;
-+  }else{
-+    zCol = "ROWID";
-+  }
-+  assert( pExpr->iDb<db->nDb );
-+  zDBase = db->aDb[pExpr->iDb].zName;
-+  rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, 
-+                 pParse->zAuthContext);
-+  if( rc==SQLITE_IGNORE ){
-+    pExpr->op = TK_NULL;
-+  }else if( rc==SQLITE_DENY ){
-+    if( db->nDb>2 || pExpr->iDb!=0 ){
-+      sqliteErrorMsg(pParse, "access to %s.%s.%s is prohibited", 
-+         zDBase, pTab->zName, zCol);
-+    }else{
-+      sqliteErrorMsg(pParse, "access to %s.%s is prohibited", pTab->zName,zCol);
-+    }
-+    pParse->rc = SQLITE_AUTH;
-+  }else if( rc!=SQLITE_OK ){
-+    sqliteAuthBadReturnCode(pParse, rc);
-+  }
-+}
-+
-+/*
-+** Do an authorization check using the code and arguments given.  Return
-+** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY.  If SQLITE_DENY
-+** is returned, then the error count and error message in pParse are
-+** modified appropriately.
-+*/
-+int sqliteAuthCheck(
-+  Parse *pParse,
-+  int code,
-+  const char *zArg1,
-+  const char *zArg2,
-+  const char *zArg3
-+){
-+  sqlite *db = pParse->db;
-+  int rc;
-+
-+  if( db->init.busy || db->xAuth==0 ){
-+    return SQLITE_OK;
-+  }
-+  rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
-+  if( rc==SQLITE_DENY ){
-+    sqliteErrorMsg(pParse, "not authorized");
-+    pParse->rc = SQLITE_AUTH;
-+  }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
-+    rc = SQLITE_DENY;
-+    sqliteAuthBadReturnCode(pParse, rc);
-+  }
-+  return rc;
-+}
-+
-+/*
-+** Push an authorization context.  After this routine is called, the
-+** zArg3 argument to authorization callbacks will be zContext until
-+** popped.  Or if pParse==0, this routine is a no-op.
-+*/
-+void sqliteAuthContextPush(
-+  Parse *pParse,
-+  AuthContext *pContext, 
-+  const char *zContext
-+){
-+  pContext->pParse = pParse;
-+  if( pParse ){
-+    pContext->zAuthContext = pParse->zAuthContext;
-+    pParse->zAuthContext = zContext;
-+  }
-+}
-+
-+/*
-+** Pop an authorization context that was previously pushed
-+** by sqliteAuthContextPush
-+*/
-+void sqliteAuthContextPop(AuthContext *pContext){
-+  if( pContext->pParse ){
-+    pContext->pParse->zAuthContext = pContext->zAuthContext;
-+    pContext->pParse = 0;
-+  }
-+}
-+
-+#endif /* SQLITE_OMIT_AUTHORIZATION */
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/btree.c
-@@ -0,0 +1,3584 @@
-+/*
-+** 2001 September 15
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** $Id$
-+**
-+** This file implements a external (disk-based) database using BTrees.
-+** For a detailed discussion of BTrees, refer to
-+**
-+**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
-+**     "Sorting And Searching", pages 473-480. Addison-Wesley
-+**     Publishing Company, Reading, Massachusetts.
-+**
-+** The basic idea is that each page of the file contains N database
-+** entries and N+1 pointers to subpages.
-+**
-+**   ----------------------------------------------------------------
-+**   |  Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N) | Ptr(N+1) |
-+**   ----------------------------------------------------------------
-+**
-+** All of the keys on the page that Ptr(0) points to have values less
-+** than Key(0).  All of the keys on page Ptr(1) and its subpages have
-+** values greater than Key(0) and less than Key(1).  All of the keys
-+** on Ptr(N+1) and its subpages have values greater than Key(N).  And
-+** so forth.
-+**
-+** Finding a particular key requires reading O(log(M)) pages from the 
-+** disk where M is the number of entries in the tree.
-+**
-+** In this implementation, a single file can hold one or more separate 
-+** BTrees.  Each BTree is identified by the index of its root page.  The
-+** key and data for any entry are combined to form the "payload".  Up to
-+** MX_LOCAL_PAYLOAD bytes of payload can be carried directly on the
-+** database page.  If the payload is larger than MX_LOCAL_PAYLOAD bytes
-+** then surplus bytes are stored on overflow pages.  The payload for an
-+** entry and the preceding pointer are combined to form a "Cell".  Each 
-+** page has a small header which contains the Ptr(N+1) pointer.
-+**
-+** The first page of the file contains a magic string used to verify that
-+** the file really is a valid BTree database, a pointer to a list of unused
-+** pages in the file, and some meta information.  The root of the first
-+** BTree begins on page 2 of the file.  (Pages are numbered beginning with
-+** 1, not 0.)  Thus a minimum database contains 2 pages.
-+*/
-+#include "sqliteInt.h"
-+#include "pager.h"
-+#include "btree.h"
-+#include <assert.h>
-+
-+/* Forward declarations */
-+static BtOps sqliteBtreeOps;
-+static BtCursorOps sqliteBtreeCursorOps;
-+
-+/*
-+** Macros used for byteswapping.  B is a pointer to the Btree
-+** structure.  This is needed to access the Btree.needSwab boolean
-+** in order to tell if byte swapping is needed or not.
-+** X is an unsigned integer.  SWAB16 byte swaps a 16-bit integer.
-+** SWAB32 byteswaps a 32-bit integer.
-+*/
-+#define SWAB16(B,X)   ((B)->needSwab? swab16((u16)X) : ((u16)X))
-+#define SWAB32(B,X)   ((B)->needSwab? swab32(X) : (X))
-+#define SWAB_ADD(B,X,A) \
-+   if((B)->needSwab){ X=swab32(swab32(X)+A); }else{ X += (A); }
-+
-+/*
-+** The following global variable - available only if SQLITE_TEST is
-+** defined - is used to determine whether new databases are created in
-+** native byte order or in non-native byte order.  Non-native byte order
-+** databases are created for testing purposes only.  Under normal operation,
-+** only native byte-order databases should be created, but we should be
-+** able to read or write existing databases regardless of the byteorder.
-+*/
-+#ifdef SQLITE_TEST
-+int btree_native_byte_order = 1;
-+#else
-+# define btree_native_byte_order 1
-+#endif
-+
-+/*
-+** Forward declarations of structures used only in this file.
-+*/
-+typedef struct PageOne PageOne;
-+typedef struct MemPage MemPage;
-+typedef struct PageHdr PageHdr;
-+typedef struct Cell Cell;
-+typedef struct CellHdr CellHdr;
-+typedef struct FreeBlk FreeBlk;
-+typedef struct OverflowPage OverflowPage;
-+typedef struct FreelistInfo FreelistInfo;
-+
-+/*
-+** All structures on a database page are aligned to 4-byte boundries.
-+** This routine rounds up a number of bytes to the next multiple of 4.
-+**
-+** This might need to change for computer architectures that require
-+** and 8-byte alignment boundry for structures.
-+*/
-+#define ROUNDUP(X)  ((X+3) & ~3)
-+
-+/*
-+** This is a magic string that appears at the beginning of every
-+** SQLite database in order to identify the file as a real database.
-+*/
-+static const char zMagicHeader[] = 
-+   "** This file contains an SQLite 2.1 database **";
-+#define MAGIC_SIZE (sizeof(zMagicHeader))
-+
-+/*
-+** This is a magic integer also used to test the integrity of the database
-+** file.  This integer is used in addition to the string above so that
-+** if the file is written on a little-endian architecture and read
-+** on a big-endian architectures (or vice versa) we can detect the
-+** problem.
-+**
-+** The number used was obtained at random and has no special
-+** significance other than the fact that it represents a different
-+** integer on little-endian and big-endian machines.
-+*/
-+#define MAGIC 0xdae37528
-+
-+/*
-+** The first page of the database file contains a magic header string
-+** to identify the file as an SQLite database file.  It also contains
-+** a pointer to the first free page of the file.  Page 2 contains the
-+** root of the principle BTree.  The file might contain other BTrees
-+** rooted on pages above 2.
-+**
-+** The first page also contains SQLITE_N_BTREE_META integers that
-+** can be used by higher-level routines.
-+**
-+** Remember that pages are numbered beginning with 1.  (See pager.c
-+** for additional information.)  Page 0 does not exist and a page
-+** number of 0 is used to mean "no such page".
-+*/
-+struct PageOne {
-+  char zMagic[MAGIC_SIZE]; /* String that identifies the file as a database */
-+  int iMagic;              /* Integer to verify correct byte order */
-+  Pgno freeList;           /* First free page in a list of all free pages */
-+  int nFree;               /* Number of pages on the free list */
-+  int aMeta[SQLITE_N_BTREE_META-1];  /* User defined integers */
-+};
-+
-+/*
-+** Each database page has a header that is an instance of this
-+** structure.
-+**
-+** PageHdr.firstFree is 0 if there is no free space on this page.
-+** Otherwise, PageHdr.firstFree is the index in MemPage.u.aDisk[] of a 
-+** FreeBlk structure that describes the first block of free space.  
-+** All free space is defined by a linked list of FreeBlk structures.
-+**
-+** Data is stored in a linked list of Cell structures.  PageHdr.firstCell
-+** is the index into MemPage.u.aDisk[] of the first cell on the page.  The
-+** Cells are kept in sorted order.
-+**
-+** A Cell contains all information about a database entry and a pointer
-+** to a child page that contains other entries less than itself.  In
-+** other words, the i-th Cell contains both Ptr(i) and Key(i).  The
-+** right-most pointer of the page is contained in PageHdr.rightChild.
-+*/
-+struct PageHdr {
-+  Pgno rightChild;  /* Child page that comes after all cells on this page */
-+  u16 firstCell;    /* Index in MemPage.u.aDisk[] of the first cell */
-+  u16 firstFree;    /* Index in MemPage.u.aDisk[] of the first free block */
-+};
-+
-+/*
-+** Entries on a page of the database are called "Cells".  Each Cell
-+** has a header and data.  This structure defines the header.  The
-+** key and data (collectively the "payload") follow this header on
-+** the database page.
-+**
-+** A definition of the complete Cell structure is given below.  The
-+** header for the cell must be defined first in order to do some
-+** of the sizing #defines that follow.
-+*/
-+struct CellHdr {
-+  Pgno leftChild; /* Child page that comes before this cell */
-+  u16 nKey;       /* Number of bytes in the key */
-+  u16 iNext;      /* Index in MemPage.u.aDisk[] of next cell in sorted order */
-+  u8 nKeyHi;      /* Upper 8 bits of key size for keys larger than 64K bytes */
-+  u8 nDataHi;     /* Upper 8 bits of data size when the size is more than 64K */
-+  u16 nData;      /* Number of bytes of data */
-+};
-+
-+/*
-+** The key and data size are split into a lower 16-bit segment and an
-+** upper 8-bit segment in order to pack them together into a smaller
-+** space.  The following macros reassembly a key or data size back
-+** into an integer.
-+*/
-+#define NKEY(b,h)  (SWAB16(b,h.nKey) + h.nKeyHi*65536)
-+#define NDATA(b,h) (SWAB16(b,h.nData) + h.nDataHi*65536)
-+
-+/*
-+** The minimum size of a complete Cell.  The Cell must contain a header
-+** and at least 4 bytes of payload.
-+*/
-+#define MIN_CELL_SIZE  (sizeof(CellHdr)+4)
-+
-+/*
-+** The maximum number of database entries that can be held in a single
-+** page of the database. 
-+*/
-+#define MX_CELL ((SQLITE_USABLE_SIZE-sizeof(PageHdr))/MIN_CELL_SIZE)
-+
-+/*
-+** The amount of usable space on a single page of the BTree.  This is the
-+** page size minus the overhead of the page header.
-+*/
-+#define USABLE_SPACE  (SQLITE_USABLE_SIZE - sizeof(PageHdr))
-+
-+/*
-+** The maximum amount of payload (in bytes) that can be stored locally for
-+** a database entry.  If the entry contains more data than this, the
-+** extra goes onto overflow pages.
-+**
-+** This number is chosen so that at least 4 cells will fit on every page.
-+*/
-+#define MX_LOCAL_PAYLOAD ((USABLE_SPACE/4-(sizeof(CellHdr)+sizeof(Pgno)))&~3)
-+
-+/*
-+** Data on a database page is stored as a linked list of Cell structures.
-+** Both the key and the data are stored in aPayload[].  The key always comes
-+** first.  The aPayload[] field grows as necessary to hold the key and data,
-+** up to a maximum of MX_LOCAL_PAYLOAD bytes.  If the size of the key and
-+** data combined exceeds MX_LOCAL_PAYLOAD bytes, then Cell.ovfl is the
-+** page number of the first overflow page.
-+**
-+** Though this structure is fixed in size, the Cell on the database
-+** page varies in size.  Every cell has a CellHdr and at least 4 bytes
-+** of payload space.  Additional payload bytes (up to the maximum of
-+** MX_LOCAL_PAYLOAD) and the Cell.ovfl value are allocated only as
-+** needed.
-+*/
-+struct Cell {
-+  CellHdr h;                        /* The cell header */
-+  char aPayload[MX_LOCAL_PAYLOAD];  /* Key and data */
-+  Pgno ovfl;                        /* The first overflow page */
-+};
-+
-+/*
-+** Free space on a page is remembered using a linked list of the FreeBlk
-+** structures.  Space on a database page is allocated in increments of
-+** at least 4 bytes and is always aligned to a 4-byte boundry.  The
-+** linked list of FreeBlks is always kept in order by address.
-+*/
-+struct FreeBlk {
-+  u16 iSize;      /* Number of bytes in this block of free space */
-+  u16 iNext;      /* Index in MemPage.u.aDisk[] of the next free block */
-+};
-+
-+/*
-+** The number of bytes of payload that will fit on a single overflow page.
-+*/
-+#define OVERFLOW_SIZE (SQLITE_USABLE_SIZE-sizeof(Pgno))
-+
-+/*
-+** When the key and data for a single entry in the BTree will not fit in
-+** the MX_LOCAL_PAYLOAD bytes of space available on the database page,
-+** then all extra bytes are written to a linked list of overflow pages.
-+** Each overflow page is an instance of the following structure.
-+**
-+** Unused pages in the database are also represented by instances of
-+** the OverflowPage structure.  The PageOne.freeList field is the
-+** page number of the first page in a linked list of unused database
-+** pages.
-+*/
-+struct OverflowPage {
-+  Pgno iNext;
-+  char aPayload[OVERFLOW_SIZE];
-+};
-+
-+/*
-+** The PageOne.freeList field points to a linked list of overflow pages
-+** hold information about free pages.  The aPayload section of each
-+** overflow page contains an instance of the following structure.  The
-+** aFree[] array holds the page number of nFree unused pages in the disk
-+** file.
-+*/
-+struct FreelistInfo {
-+  int nFree;
-+  Pgno aFree[(OVERFLOW_SIZE-sizeof(int))/sizeof(Pgno)];
-+};
-+
-+/*
-+** For every page in the database file, an instance of the following structure
-+** is stored in memory.  The u.aDisk[] array contains the raw bits read from
-+** the disk.  The rest is auxiliary information held in memory only. The
-+** auxiliary info is only valid for regular database pages - it is not
-+** used for overflow pages and pages on the freelist.
-+**
-+** Of particular interest in the auxiliary info is the apCell[] entry.  Each
-+** apCell[] entry is a pointer to a Cell structure in u.aDisk[].  The cells are
-+** put in this array so that they can be accessed in constant time, rather
-+** than in linear time which would be needed if we had to walk the linked 
-+** list on every access.
-+**
-+** Note that apCell[] contains enough space to hold up to two more Cells
-+** than can possibly fit on one page.  In the steady state, every apCell[]
-+** points to memory inside u.aDisk[].  But in the middle of an insert
-+** operation, some apCell[] entries may temporarily point to data space
-+** outside of u.aDisk[].  This is a transient situation that is quickly
-+** resolved.  But while it is happening, it is possible for a database
-+** page to hold as many as two more cells than it might otherwise hold.
-+** The extra two entries in apCell[] are an allowance for this situation.
-+**
-+** The pParent field points back to the parent page.  This allows us to
-+** walk up the BTree from any leaf to the root.  Care must be taken to
-+** unref() the parent page pointer when this page is no longer referenced.
-+** The pageDestructor() routine handles that chore.
-+*/
-+struct MemPage {
-+  union u_page_data {
-+    char aDisk[SQLITE_PAGE_SIZE];  /* Page data stored on disk */
-+    PageHdr hdr;                   /* Overlay page header */
-+  } u;
-+  u8 isInit;                     /* True if auxiliary data is initialized */
-+  u8 idxShift;                   /* True if apCell[] indices have changed */
-+  u8 isOverfull;                 /* Some apCell[] points outside u.aDisk[] */
-+  MemPage *pParent;              /* The parent of this page.  NULL for root */
-+  int idxParent;                 /* Index in pParent->apCell[] of this node */
-+  int nFree;                     /* Number of free bytes in u.aDisk[] */
-+  int nCell;                     /* Number of entries on this page */
-+  Cell *apCell[MX_CELL+2];       /* All data entires in sorted order */
-+};
-+
-+/*
-+** The in-memory image of a disk page has the auxiliary information appended
-+** to the end.  EXTRA_SIZE is the number of bytes of space needed to hold
-+** that extra information.
-+*/
-+#define EXTRA_SIZE (sizeof(MemPage)-sizeof(union u_page_data))
-+
-+/*
-+** Everything we need to know about an open database
-+*/
-+struct Btree {
-+  BtOps *pOps;          /* Function table */
-+  Pager *pPager;        /* The page cache */
-+  BtCursor *pCursor;    /* A list of all open cursors */
-+  PageOne *page1;       /* First page of the database */
-+  u8 inTrans;           /* True if a transaction is in progress */
-+  u8 inCkpt;            /* True if there is a checkpoint on the transaction */
-+  u8 readOnly;          /* True if the underlying file is readonly */
-+  u8 needSwab;          /* Need to byte-swapping */
-+};
-+typedef Btree Bt;
-+
-+/*
-+** A cursor is a pointer to a particular entry in the BTree.
-+** The entry is identified by its MemPage and the index in
-+** MemPage.apCell[] of the entry.
-+*/
-+struct BtCursor {
-+  BtCursorOps *pOps;        /* Function table */
-+  Btree *pBt;               /* The Btree to which this cursor belongs */
-+  BtCursor *pNext, *pPrev;  /* Forms a linked list of all cursors */
-+  BtCursor *pShared;        /* Loop of cursors with the same root page */
-+  Pgno pgnoRoot;            /* The root page of this tree */
-+  MemPage *pPage;           /* Page that contains the entry */
-+  int idx;                  /* Index of the entry in pPage->apCell[] */
-+  u8 wrFlag;                /* True if writable */
-+  u8 eSkip;                 /* Determines if next step operation is a no-op */
-+  u8 iMatch;                /* compare result from last sqliteBtreeMoveto() */
-+};
-+
-+/*
-+** Legal values for BtCursor.eSkip.
-+*/
-+#define SKIP_NONE     0   /* Always step the cursor */
-+#define SKIP_NEXT     1   /* The next sqliteBtreeNext() is a no-op */
-+#define SKIP_PREV     2   /* The next sqliteBtreePrevious() is a no-op */
-+#define SKIP_INVALID  3   /* Calls to Next() and Previous() are invalid */
-+
-+/* Forward declarations */
-+static int fileBtreeCloseCursor(BtCursor *pCur);
-+
-+/*
-+** Routines for byte swapping.
-+*/
-+u16 swab16(u16 x){
-+  return ((x & 0xff)<<8) | ((x>>8)&0xff);
-+}
-+u32 swab32(u32 x){
-+  return ((x & 0xff)<<24) | ((x & 0xff00)<<8) |
-+         ((x>>8) & 0xff00) | ((x>>24)&0xff);
-+}
-+
-+/*
-+** Compute the total number of bytes that a Cell needs on the main
-+** database page.  The number returned includes the Cell header,
-+** local payload storage, and the pointer to overflow pages (if
-+** applicable).  Additional space allocated on overflow pages
-+** is NOT included in the value returned from this routine.
-+*/
-+static int cellSize(Btree *pBt, Cell *pCell){
-+  int n = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h);
-+  if( n>MX_LOCAL_PAYLOAD ){
-+    n = MX_LOCAL_PAYLOAD + sizeof(Pgno);
-+  }else{
-+    n = ROUNDUP(n);
-+  }
-+  n += sizeof(CellHdr);
-+  return n;
-+}
-+
-+/*
-+** Defragment the page given.  All Cells are moved to the
-+** beginning of the page and all free space is collected 
-+** into one big FreeBlk at the end of the page.
-+*/
-+static void defragmentPage(Btree *pBt, MemPage *pPage){
-+  int pc, i, n;
-+  FreeBlk *pFBlk;
-+  char newPage[SQLITE_USABLE_SIZE];
-+
-+  assert( sqlitepager_iswriteable(pPage) );
-+  assert( pPage->isInit );
-+  pc = sizeof(PageHdr);
-+  pPage->u.hdr.firstCell = SWAB16(pBt, pc);
-+  memcpy(newPage, pPage->u.aDisk, pc);
-+  for(i=0; i<pPage->nCell; i++){
-+    Cell *pCell = pPage->apCell[i];
-+
-+    /* This routine should never be called on an overfull page.  The
-+    ** following asserts verify that constraint. */
-+    assert( Addr(pCell) > Addr(pPage) );
-+    assert( Addr(pCell) < Addr(pPage) + SQLITE_USABLE_SIZE );
-+
-+    n = cellSize(pBt, pCell);
-+    pCell->h.iNext = SWAB16(pBt, pc + n);
-+    memcpy(&newPage[pc], pCell, n);
-+    pPage->apCell[i] = (Cell*)&pPage->u.aDisk[pc];
-+    pc += n;
-+  }
-+  assert( pPage->nFree==SQLITE_USABLE_SIZE-pc );
-+  memcpy(pPage->u.aDisk, newPage, pc);
-+  if( pPage->nCell>0 ){
-+    pPage->apCell[pPage->nCell-1]->h.iNext = 0;
-+  }
-+  pFBlk = (FreeBlk*)&pPage->u.aDisk[pc];
-+  pFBlk->iSize = SWAB16(pBt, SQLITE_USABLE_SIZE - pc);
-+  pFBlk->iNext = 0;
-+  pPage->u.hdr.firstFree = SWAB16(pBt, pc);
-+  memset(&pFBlk[1], 0, SQLITE_USABLE_SIZE - pc - sizeof(FreeBlk));
-+}
-+
-+/*
-+** Allocate nByte bytes of space on a page.  nByte must be a 
-+** multiple of 4.
-+**
-+** Return the index into pPage->u.aDisk[] of the first byte of
-+** the new allocation. Or return 0 if there is not enough free
-+** space on the page to satisfy the allocation request.
-+**
-+** If the page contains nBytes of free space but does not contain
-+** nBytes of contiguous free space, then this routine automatically
-+** calls defragementPage() to consolidate all free space before 
-+** allocating the new chunk.
-+*/
-+static int allocateSpace(Btree *pBt, MemPage *pPage, int nByte){
-+  FreeBlk *p;
-+  u16 *pIdx;
-+  int start;
-+  int iSize;
-+#ifndef NDEBUG
-+  int cnt = 0;
-+#endif
-+
-+  assert( sqlitepager_iswriteable(pPage) );
-+  assert( nByte==ROUNDUP(nByte) );
-+  assert( pPage->isInit );
-+  if( pPage->nFree<nByte || pPage->isOverfull ) return 0;
-+  pIdx = &pPage->u.hdr.firstFree;
-+  p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)];
-+  while( (iSize = SWAB16(pBt, p->iSize))<nByte ){
-+    assert( cnt++ < SQLITE_USABLE_SIZE/4 );
-+    if( p->iNext==0 ){
-+      defragmentPage(pBt, pPage);
-+      pIdx = &pPage->u.hdr.firstFree;
-+    }else{
-+      pIdx = &p->iNext;
-+    }
-+    p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)];
-+  }
-+  if( iSize==nByte ){
-+    start = SWAB16(pBt, *pIdx);
-+    *pIdx = p->iNext;
-+  }else{
-+    FreeBlk *pNew;
-+    start = SWAB16(pBt, *pIdx);
-+    pNew = (FreeBlk*)&pPage->u.aDisk[start + nByte];
-+    pNew->iNext = p->iNext;
-+    pNew->iSize = SWAB16(pBt, iSize - nByte);
-+    *pIdx = SWAB16(pBt, start + nByte);
-+  }
-+  pPage->nFree -= nByte;
-+  return start;
-+}
-+
-+/*
-+** Return a section of the MemPage.u.aDisk[] to the freelist.
-+** The first byte of the new free block is pPage->u.aDisk[start]
-+** and the size of the block is "size" bytes.  Size must be
-+** a multiple of 4.
-+**
-+** Most of the effort here is involved in coalesing adjacent
-+** free blocks into a single big free block.
-+*/
-+static void freeSpace(Btree *pBt, MemPage *pPage, int start, int size){
-+  int end = start + size;
-+  u16 *pIdx, idx;
-+  FreeBlk *pFBlk;
-+  FreeBlk *pNew;
-+  FreeBlk *pNext;
-+  int iSize;
-+
-+  assert( sqlitepager_iswriteable(pPage) );
-+  assert( size == ROUNDUP(size) );
-+  assert( start == ROUNDUP(start) );
-+  assert( pPage->isInit );
-+  pIdx = &pPage->u.hdr.firstFree;
-+  idx = SWAB16(pBt, *pIdx);
-+  while( idx!=0 && idx<start ){
-+    pFBlk = (FreeBlk*)&pPage->u.aDisk[idx];
-+    iSize = SWAB16(pBt, pFBlk->iSize);
-+    if( idx + iSize == start ){
-+      pFBlk->iSize = SWAB16(pBt, iSize + size);
-+      if( idx + iSize + size == SWAB16(pBt, pFBlk->iNext) ){
-+        pNext = (FreeBlk*)&pPage->u.aDisk[idx + iSize + size];
-+        if( pBt->needSwab ){
-+          pFBlk->iSize = swab16((u16)swab16(pNext->iSize)+iSize+size);
-+        }else{
-+          pFBlk->iSize += pNext->iSize;
-+        }
-+        pFBlk->iNext = pNext->iNext;
-+      }
-+      pPage->nFree += size;
-+      return;
-+    }
-+    pIdx = &pFBlk->iNext;
-+    idx = SWAB16(pBt, *pIdx);
-+  }
-+  pNew = (FreeBlk*)&pPage->u.aDisk[start];
-+  if( idx != end ){
-+    pNew->iSize = SWAB16(pBt, size);
-+    pNew->iNext = SWAB16(pBt, idx);
-+  }else{
-+    pNext = (FreeBlk*)&pPage->u.aDisk[idx];
-+    pNew->iSize = SWAB16(pBt, size + SWAB16(pBt, pNext->iSize));
-+    pNew->iNext = pNext->iNext;
-+  }
-+  *pIdx = SWAB16(pBt, start);
-+  pPage->nFree += size;
-+}
-+
-+/*
-+** Initialize the auxiliary information for a disk block.
-+**
-+** The pParent parameter must be a pointer to the MemPage which
-+** is the parent of the page being initialized.  The root of the
-+** BTree (usually page 2) has no parent and so for that page, 
-+** pParent==NULL.
-+**
-+** Return SQLITE_OK on success.  If we see that the page does
-+** not contain a well-formed database page, then return 
-+** SQLITE_CORRUPT.  Note that a return of SQLITE_OK does not
-+** guarantee that the page is well-formed.  It only shows that
-+** we failed to detect any corruption.
-+*/
-+static int initPage(Bt *pBt, MemPage *pPage, Pgno pgnoThis, MemPage *pParent){
-+  int idx;           /* An index into pPage->u.aDisk[] */
-+  Cell *pCell;       /* A pointer to a Cell in pPage->u.aDisk[] */
-+  FreeBlk *pFBlk;    /* A pointer to a free block in pPage->u.aDisk[] */
-+  int sz;            /* The size of a Cell in bytes */
-+  int freeSpace;     /* Amount of free space on the page */
-+
-+  if( pPage->pParent ){
-+    assert( pPage->pParent==pParent );
-+    return SQLITE_OK;
-+  }
-+  if( pParent ){
-+    pPage->pParent = pParent;
-+    sqlitepager_ref(pParent);
-+  }
-+  if( pPage->isInit ) return SQLITE_OK;
-+  pPage->isInit = 1;
-+  pPage->nCell = 0;
-+  freeSpace = USABLE_SPACE;
-+  idx = SWAB16(pBt, pPage->u.hdr.firstCell);
-+  while( idx!=0 ){
-+    if( idx>SQLITE_USABLE_SIZE-MIN_CELL_SIZE ) goto page_format_error;
-+    if( idx<sizeof(PageHdr) ) goto page_format_error;
-+    if( idx!=ROUNDUP(idx) ) goto page_format_error;
-+    pCell = (Cell*)&pPage->u.aDisk[idx];
-+    sz = cellSize(pBt, pCell);
-+    if( idx+sz > SQLITE_USABLE_SIZE ) goto page_format_error;
-+    freeSpace -= sz;
-+    pPage->apCell[pPage->nCell++] = pCell;
-+    idx = SWAB16(pBt, pCell->h.iNext);
-+  }
-+  pPage->nFree = 0;
-+  idx = SWAB16(pBt, pPage->u.hdr.firstFree);
-+  while( idx!=0 ){
-+    int iNext;
-+    if( idx>SQLITE_USABLE_SIZE-sizeof(FreeBlk) ) goto page_format_error;
-+    if( idx<sizeof(PageHdr) ) goto page_format_error;
-+    pFBlk = (FreeBlk*)&pPage->u.aDisk[idx];
-+    pPage->nFree += SWAB16(pBt, pFBlk->iSize);
-+    iNext = SWAB16(pBt, pFBlk->iNext);
-+    if( iNext>0 && iNext <= idx ) goto page_format_error;
-+    idx = iNext;
-+  }
-+  if( pPage->nCell==0 && pPage->nFree==0 ){
-+    /* As a special case, an uninitialized root page appears to be
-+    ** an empty database */
-+    return SQLITE_OK;
-+  }
-+  if( pPage->nFree!=freeSpace ) goto page_format_error;
-+  return SQLITE_OK;
-+
-+page_format_error:
-+  return SQLITE_CORRUPT;
-+}
-+
-+/*
-+** Set up a raw page so that it looks like a database page holding
-+** no entries.
-+*/
-+static void zeroPage(Btree *pBt, MemPage *pPage){
-+  PageHdr *pHdr;
-+  FreeBlk *pFBlk;
-+  assert( sqlitepager_iswriteable(pPage) );
-+  memset(pPage, 0, SQLITE_USABLE_SIZE);
-+  pHdr = &pPage->u.hdr;
-+  pHdr->firstCell = 0;
-+  pHdr->firstFree = SWAB16(pBt, sizeof(*pHdr));
-+  pFBlk = (FreeBlk*)&pHdr[1];
-+  pFBlk->iNext = 0;
-+  pPage->nFree = SQLITE_USABLE_SIZE - sizeof(*pHdr);
-+  pFBlk->iSize = SWAB16(pBt, pPage->nFree);
-+  pPage->nCell = 0;
-+  pPage->isOverfull = 0;
-+}
-+
-+/*
-+** This routine is called when the reference count for a page
-+** reaches zero.  We need to unref the pParent pointer when that
-+** happens.
-+*/
-+static void pageDestructor(void *pData){
-+  MemPage *pPage = (MemPage*)pData;
-+  if( pPage->pParent ){
-+    MemPage *pParent = pPage->pParent;
-+    pPage->pParent = 0;
-+    sqlitepager_unref(pParent);
-+  }
-+}
-+
-+/*
-+** Open a new database.
-+**
-+** Actually, this routine just sets up the internal data structures
-+** for accessing the database.  We do not open the database file 
-+** until the first page is loaded.
-+**
-+** zFilename is the name of the database file.  If zFilename is NULL
-+** a new database with a random name is created.  This randomly named
-+** database file will be deleted when sqliteBtreeClose() is called.
-+*/
-+int sqliteBtreeOpen(
-+  const char *zFilename,    /* Name of the file containing the BTree database */
-+  int omitJournal,          /* if TRUE then do not journal this file */
-+  int nCache,               /* How many pages in the page cache */
-+  Btree **ppBtree           /* Pointer to new Btree object written here */
-+){
-+  Btree *pBt;
-+  int rc;
-+
-+  /*
-+  ** The following asserts make sure that structures used by the btree are
-+  ** the right size.  This is to guard against size changes that result
-+  ** when compiling on a different architecture.
-+  */
-+  assert( sizeof(u32)==4 );
-+  assert( sizeof(u16)==2 );
-+  assert( sizeof(Pgno)==4 );
-+  assert( sizeof(PageHdr)==8 );
-+  assert( sizeof(CellHdr)==12 );
-+  assert( sizeof(FreeBlk)==4 );
-+  assert( sizeof(OverflowPage)==SQLITE_USABLE_SIZE );
-+  assert( sizeof(FreelistInfo)==OVERFLOW_SIZE );
-+  assert( sizeof(ptr)==sizeof(char*) );
-+  assert( sizeof(uptr)==sizeof(ptr) );
-+
-+  pBt = sqliteMalloc( sizeof(*pBt) );
-+  if( pBt==0 ){
-+    *ppBtree = 0;
-+    return SQLITE_NOMEM;
-+  }
-+  if( nCache<10 ) nCache = 10;
-+  rc = sqlitepager_open(&pBt->pPager, zFilename, nCache, EXTRA_SIZE,
-+                        !omitJournal);
-+  if( rc!=SQLITE_OK ){
-+    if( pBt->pPager ) sqlitepager_close(pBt->pPager);
-+    sqliteFree(pBt);
-+    *ppBtree = 0;
-+    return rc;
-+  }
-+  sqlitepager_set_destructor(pBt->pPager, pageDestructor);
-+  pBt->pCursor = 0;
-+  pBt->page1 = 0;
-+  pBt->readOnly = sqlitepager_isreadonly(pBt->pPager);
-+  pBt->pOps = &sqliteBtreeOps;
-+  *ppBtree = pBt;
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Close an open database and invalidate all cursors.
-+*/
-+static int fileBtreeClose(Btree *pBt){
-+  while( pBt->pCursor ){
-+    fileBtreeCloseCursor(pBt->pCursor);
-+  }
-+  sqlitepager_close(pBt->pPager);
-+  sqliteFree(pBt);
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Change the limit on the number of pages allowed in the cache.
-+**
-+** The maximum number of cache pages is set to the absolute
-+** value of mxPage.  If mxPage is negative, the pager will
-+** operate asynchronously - it will not stop to do fsync()s
-+** to insure data is written to the disk surface before
-+** continuing.  Transactions still work if synchronous is off,
-+** and the database cannot be corrupted if this program
-+** crashes.  But if the operating system crashes or there is
-+** an abrupt power failure when synchronous is off, the database
-+** could be left in an inconsistent and unrecoverable state.
-+** Synchronous is on by default so database corruption is not
-+** normally a worry.
-+*/
-+static int fileBtreeSetCacheSize(Btree *pBt, int mxPage){
-+  sqlitepager_set_cachesize(pBt->pPager, mxPage);
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Change the way data is synced to disk in order to increase or decrease
-+** how well the database resists damage due to OS crashes and power
-+** failures.  Level 1 is the same as asynchronous (no syncs() occur and
-+** there is a high probability of damage)  Level 2 is the default.  There
-+** is a very low but non-zero probability of damage.  Level 3 reduces the
-+** probability of damage to near zero but with a write performance reduction.
-+*/
-+static int fileBtreeSetSafetyLevel(Btree *pBt, int level){
-+  sqlitepager_set_safety_level(pBt->pPager, level);
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Get a reference to page1 of the database file.  This will
-+** also acquire a readlock on that file.
-+**
-+** SQLITE_OK is returned on success.  If the file is not a
-+** well-formed database file, then SQLITE_CORRUPT is returned.
-+** SQLITE_BUSY is returned if the database is locked.  SQLITE_NOMEM
-+** is returned if we run out of memory.  SQLITE_PROTOCOL is returned
-+** if there is a locking protocol violation.
-+*/
-+static int lockBtree(Btree *pBt){
-+  int rc;
-+  if( pBt->page1 ) return SQLITE_OK;
-+  rc = sqlitepager_get(pBt->pPager, 1, (void**)&pBt->page1);
-+  if( rc!=SQLITE_OK ) return rc;
-+
-+  /* Do some checking to help insure the file we opened really is
-+  ** a valid database file. 
-+  */
-+  if( sqlitepager_pagecount(pBt->pPager)>0 ){
-+    PageOne *pP1 = pBt->page1;
-+    if( strcmp(pP1->zMagic,zMagicHeader)!=0 ||
-+          (pP1->iMagic!=MAGIC && swab32(pP1->iMagic)!=MAGIC) ){
-+      rc = SQLITE_NOTADB;
-+      goto page1_init_failed;
-+    }
-+    pBt->needSwab = pP1->iMagic!=MAGIC;
-+  }
-+  return rc;
-+
-+page1_init_failed:
-+  sqlitepager_unref(pBt->page1);
-+  pBt->page1 = 0;
-+  return rc;
-+}
-+
-+/*
-+** If there are no outstanding cursors and we are not in the middle
-+** of a transaction but there is a read lock on the database, then
-+** this routine unrefs the first page of the database file which 
-+** has the effect of releasing the read lock.
-+**
-+** If there are any outstanding cursors, this routine is a no-op.
-+**
-+** If there is a transaction in progress, this routine is a no-op.
-+*/
-+static void unlockBtreeIfUnused(Btree *pBt){
-+  if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
-+    sqlitepager_unref(pBt->page1);
-+    pBt->page1 = 0;
-+    pBt->inTrans = 0;
-+    pBt->inCkpt = 0;
-+  }
-+}
-+
-+/*
-+** Create a new database by initializing the first two pages of the
-+** file.
-+*/
-+static int newDatabase(Btree *pBt){
-+  MemPage *pRoot;
-+  PageOne *pP1;
-+  int rc;
-+  if( sqlitepager_pagecount(pBt->pPager)>1 ) return SQLITE_OK;
-+  pP1 = pBt->page1;
-+  rc = sqlitepager_write(pBt->page1);
-+  if( rc ) return rc;
-+  rc = sqlitepager_get(pBt->pPager, 2, (void**)&pRoot);
-+  if( rc ) return rc;
-+  rc = sqlitepager_write(pRoot);
-+  if( rc ){
-+    sqlitepager_unref(pRoot);
-+    return rc;
-+  }
-+  strcpy(pP1->zMagic, zMagicHeader);
-+  if( btree_native_byte_order ){
-+    pP1->iMagic = MAGIC;
-+    pBt->needSwab = 0;
-+  }else{
-+    pP1->iMagic = swab32(MAGIC);
-+    pBt->needSwab = 1;
-+  }
-+  zeroPage(pBt, pRoot);
-+  sqlitepager_unref(pRoot);
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Attempt to start a new transaction.
-+**
-+** A transaction must be started before attempting any changes
-+** to the database.  None of the following routines will work
-+** unless a transaction is started first:
-+**
-+**      sqliteBtreeCreateTable()
-+**      sqliteBtreeCreateIndex()
-+**      sqliteBtreeClearTable()
-+**      sqliteBtreeDropTable()
-+**      sqliteBtreeInsert()
-+**      sqliteBtreeDelete()
-+**      sqliteBtreeUpdateMeta()
-+*/
-+static int fileBtreeBeginTrans(Btree *pBt){
-+  int rc;
-+  if( pBt->inTrans ) return SQLITE_ERROR;
-+  if( pBt->readOnly ) return SQLITE_READONLY;
-+  if( pBt->page1==0 ){
-+    rc = lockBtree(pBt);
-+    if( rc!=SQLITE_OK ){
-+      return rc;
-+    }
-+  }
-+  rc = sqlitepager_begin(pBt->page1);
-+  if( rc==SQLITE_OK ){
-+    rc = newDatabase(pBt);
-+  }
-+  if( rc==SQLITE_OK ){
-+    pBt->inTrans = 1;
-+    pBt->inCkpt = 0;
-+  }else{
-+    unlockBtreeIfUnused(pBt);
-+  }
-+  return rc;
-+}
-+
-+/*
-+** Commit the transaction currently in progress.
-+**
-+** This will release the write lock on the database file.  If there
-+** are no active cursors, it also releases the read lock.
-+*/
-+static int fileBtreeCommit(Btree *pBt){
-+  int rc;
-+  rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager);
-+  pBt->inTrans = 0;
-+  pBt->inCkpt = 0;
-+  unlockBtreeIfUnused(pBt);
-+  return rc;
-+}
-+
-+/*
-+** Rollback the transaction in progress.  All cursors will be
-+** invalided by this operation.  Any attempt to use a cursor
-+** that was open at the beginning of this operation will result
-+** in an error.
-+**
-+** This will release the write lock on the database file.  If there
-+** are no active cursors, it also releases the read lock.
-+*/
-+static int fileBtreeRollback(Btree *pBt){
-+  int rc;
-+  BtCursor *pCur;
-+  if( pBt->inTrans==0 ) return SQLITE_OK;
-+  pBt->inTrans = 0;
-+  pBt->inCkpt = 0;
-+  rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager);
-+  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-+    if( pCur->pPage && pCur->pPage->isInit==0 ){
-+      sqlitepager_unref(pCur->pPage);
-+      pCur->pPage = 0;
-+    }
-+  }
-+  unlockBtreeIfUnused(pBt);
-+  return rc;
-+}
-+
-+/*
-+** Set the checkpoint for the current transaction.  The checkpoint serves
-+** as a sub-transaction that can be rolled back independently of the
-+** main transaction.  You must start a transaction before starting a
-+** checkpoint.  The checkpoint is ended automatically if the transaction
-+** commits or rolls back.
-+**
-+** Only one checkpoint may be active at a time.  It is an error to try
-+** to start a new checkpoint if another checkpoint is already active.
-+*/
-+static int fileBtreeBeginCkpt(Btree *pBt){
-+  int rc;
-+  if( !pBt->inTrans || pBt->inCkpt ){
-+    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
-+  }
-+  rc = pBt->readOnly ? SQLITE_OK : sqlitepager_ckpt_begin(pBt->pPager);
-+  pBt->inCkpt = 1;
-+  return rc;
-+}
-+
-+
-+/*
-+** Commit a checkpoint to transaction currently in progress.  If no
-+** checkpoint is active, this is a no-op.
-+*/
-+static int fileBtreeCommitCkpt(Btree *pBt){
-+  int rc;
-+  if( pBt->inCkpt && !pBt->readOnly ){
-+    rc = sqlitepager_ckpt_commit(pBt->pPager);
-+  }else{
-+    rc = SQLITE_OK;
-+  }
-+  pBt->inCkpt = 0;
-+  return rc;
-+}
-+
-+/*
-+** Rollback the checkpoint to the current transaction.  If there
-+** is no active checkpoint or transaction, this routine is a no-op.
-+**
-+** All cursors will be invalided by this operation.  Any attempt
-+** to use a cursor that was open at the beginning of this operation
-+** will result in an error.
-+*/
-+static int fileBtreeRollbackCkpt(Btree *pBt){
-+  int rc;
-+  BtCursor *pCur;
-+  if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK;
-+  rc = sqlitepager_ckpt_rollback(pBt->pPager);
-+  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-+    if( pCur->pPage && pCur->pPage->isInit==0 ){
-+      sqlitepager_unref(pCur->pPage);
-+      pCur->pPage = 0;
-+    }
-+  }
-+  pBt->inCkpt = 0;
-+  return rc;
-+}
-+
-+/*
-+** Create a new cursor for the BTree whose root is on the page
-+** iTable.  The act of acquiring a cursor gets a read lock on 
-+** the database file.
-+**
-+** If wrFlag==0, then the cursor can only be used for reading.
-+** If wrFlag==1, then the cursor can be used for reading or for
-+** writing if other conditions for writing are also met.  These
-+** are the conditions that must be met in order for writing to
-+** be allowed:
-+**
-+** 1:  The cursor must have been opened with wrFlag==1
-+**
-+** 2:  No other cursors may be open with wrFlag==0 on the same table
-+**
-+** 3:  The database must be writable (not on read-only media)
-+**
-+** 4:  There must be an active transaction.
-+**
-+** Condition 2 warrants further discussion.  If any cursor is opened
-+** on a table with wrFlag==0, that prevents all other cursors from
-+** writing to that table.  This is a kind of "read-lock".  When a cursor
-+** is opened with wrFlag==0 it is guaranteed that the table will not
-+** change as long as the cursor is open.  This allows the cursor to
-+** do a sequential scan of the table without having to worry about
-+** entries being inserted or deleted during the scan.  Cursors should
-+** be opened with wrFlag==0 only if this read-lock property is needed.
-+** That is to say, cursors should be opened with wrFlag==0 only if they
-+** intend to use the sqliteBtreeNext() system call.  All other cursors
-+** should be opened with wrFlag==1 even if they never really intend
-+** to write.
-+** 
-+** No checking is done to make sure that page iTable really is the
-+** root page of a b-tree.  If it is not, then the cursor acquired
-+** will not work correctly.
-+*/
-+static 
-+int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
-+  int rc;
-+  BtCursor *pCur, *pRing;
-+
-+  if( pBt->readOnly && wrFlag ){
-+    *ppCur = 0;
-+    return SQLITE_READONLY;
-+  }
-+  if( pBt->page1==0 ){
-+    rc = lockBtree(pBt);
-+    if( rc!=SQLITE_OK ){
-+      *ppCur = 0;
-+      return rc;
-+    }
-+  }
-+  pCur = sqliteMalloc( sizeof(*pCur) );
-+  if( pCur==0 ){
-+    rc = SQLITE_NOMEM;
-+    goto create_cursor_exception;
-+  }
-+  pCur->pgnoRoot = (Pgno)iTable;
-+  rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pCur->pPage);
-+  if( rc!=SQLITE_OK ){
-+    goto create_cursor_exception;
-+  }
-+  rc = initPage(pBt, pCur->pPage, pCur->pgnoRoot, 0);
-+  if( rc!=SQLITE_OK ){
-+    goto create_cursor_exception;
-+  }
-+  pCur->pOps = &sqliteBtreeCursorOps;
-+  pCur->pBt = pBt;
-+  pCur->wrFlag = wrFlag;
-+  pCur->idx = 0;
-+  pCur->eSkip = SKIP_INVALID;
-+  pCur->pNext = pBt->pCursor;
-+  if( pCur->pNext ){
-+    pCur->pNext->pPrev = pCur;
-+  }
-+  pCur->pPrev = 0;
-+  pRing = pBt->pCursor;
-+  while( pRing && pRing->pgnoRoot!=pCur->pgnoRoot ){ pRing = pRing->pNext; }
-+  if( pRing ){
-+    pCur->pShared = pRing->pShared;
-+    pRing->pShared = pCur;
-+  }else{
-+    pCur->pShared = pCur;
-+  }
-+  pBt->pCursor = pCur;
-+  *ppCur = pCur;
-+  return SQLITE_OK;
-+
-+create_cursor_exception:
-+  *ppCur = 0;
-+  if( pCur ){
-+    if( pCur->pPage ) sqlitepager_unref(pCur->pPage);
-+    sqliteFree(pCur);
-+  }
-+  unlockBtreeIfUnused(pBt);
-+  return rc;
-+}
-+
-+/*
-+** Close a cursor.  The read lock on the database file is released
-+** when the last cursor is closed.
-+*/
-+static int fileBtreeCloseCursor(BtCursor *pCur){
-+  Btree *pBt = pCur->pBt;
-+  if( pCur->pPrev ){
-+    pCur->pPrev->pNext = pCur->pNext;
-+  }else{
-+    pBt->pCursor = pCur->pNext;
-+  }
-+  if( pCur->pNext ){
-+    pCur->pNext->pPrev = pCur->pPrev;
-+  }
-+  if( pCur->pPage ){
-+    sqlitepager_unref(pCur->pPage);
-+  }
-+  if( pCur->pShared!=pCur ){
-+    BtCursor *pRing = pCur->pShared;
-+    while( pRing->pShared!=pCur ){ pRing = pRing->pShared; }
-+    pRing->pShared = pCur->pShared;
-+  }
-+  unlockBtreeIfUnused(pBt);
-+  sqliteFree(pCur);
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Make a temporary cursor by filling in the fields of pTempCur.
-+** The temporary cursor is not on the cursor list for the Btree.
-+*/
-+static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){
-+  memcpy(pTempCur, pCur, sizeof(*pCur));
-+  pTempCur->pNext = 0;
-+  pTempCur->pPrev = 0;
-+  if( pTempCur->pPage ){
-+    sqlitepager_ref(pTempCur->pPage);
-+  }
-+}
-+
-+/*
-+** Delete a temporary cursor such as was made by the CreateTemporaryCursor()
-+** function above.
-+*/
-+static void releaseTempCursor(BtCursor *pCur){
-+  if( pCur->pPage ){
-+    sqlitepager_unref(pCur->pPage);
-+  }
-+}
-+
-+/*
-+** Set *pSize to the number of bytes of key in the entry the
-+** cursor currently points to.  Always return SQLITE_OK.
-+** Failure is not possible.  If the cursor is not currently
-+** pointing to an entry (which can happen, for example, if
-+** the database is empty) then *pSize is set to 0.
-+*/
-+static int fileBtreeKeySize(BtCursor *pCur, int *pSize){
-+  Cell *pCell;
-+  MemPage *pPage;
-+
-+  pPage = pCur->pPage;
-+  assert( pPage!=0 );
-+  if( pCur->idx >= pPage->nCell ){
-+    *pSize = 0;
-+  }else{
-+    pCell = pPage->apCell[pCur->idx];
-+    *pSize = NKEY(pCur->pBt, pCell->h);
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Read payload information from the entry that the pCur cursor is
-+** pointing to.  Begin reading the payload at "offset" and read
-+** a total of "amt" bytes.  Put the result in zBuf.
-+**
-+** This routine does not make a distinction between key and data.
-+** It just reads bytes from the payload area.
-+*/
-+static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
-+  char *aPayload;
-+  Pgno nextPage;
-+  int rc;
-+  Btree *pBt = pCur->pBt;
-+  assert( pCur!=0 && pCur->pPage!=0 );
-+  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
-+  aPayload = pCur->pPage->apCell[pCur->idx]->aPayload;
-+  if( offset<MX_LOCAL_PAYLOAD ){
-+    int a = amt;
-+    if( a+offset>MX_LOCAL_PAYLOAD ){
-+      a = MX_LOCAL_PAYLOAD - offset;
-+    }
-+    memcpy(zBuf, &aPayload[offset], a);
-+    if( a==amt ){
-+      return SQLITE_OK;
-+    }
-+    offset = 0;
-+    zBuf += a;
-+    amt -= a;
-+  }else{
-+    offset -= MX_LOCAL_PAYLOAD;
-+  }
-+  if( amt>0 ){
-+    nextPage = SWAB32(pBt, pCur->pPage->apCell[pCur->idx]->ovfl);
-+  }
-+  while( amt>0 && nextPage ){
-+    OverflowPage *pOvfl;
-+    rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
-+    if( rc!=0 ){
-+      return rc;
-+    }
-+    nextPage = SWAB32(pBt, pOvfl->iNext);
-+    if( offset<OVERFLOW_SIZE ){
-+      int a = amt;
-+      if( a + offset > OVERFLOW_SIZE ){
-+        a = OVERFLOW_SIZE - offset;
-+      }
-+      memcpy(zBuf, &pOvfl->aPayload[offset], a);
-+      offset = 0;
-+      amt -= a;
-+      zBuf += a;
-+    }else{
-+      offset -= OVERFLOW_SIZE;
-+    }
-+    sqlitepager_unref(pOvfl);
-+  }
-+  if( amt>0 ){
-+    return SQLITE_CORRUPT;
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Read part of the key associated with cursor pCur.  A maximum
-+** of "amt" bytes will be transfered into zBuf[].  The transfer
-+** begins at "offset".  The number of bytes actually read is
-+** returned. 
-+**
-+** Change:  It used to be that the amount returned will be smaller
-+** than the amount requested if there are not enough bytes in the key
-+** to satisfy the request.  But now, it must be the case that there
-+** is enough data available to satisfy the request.  If not, an exception
-+** is raised.  The change was made in an effort to boost performance
-+** by eliminating unneeded tests.
-+*/
-+static int fileBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){
-+  MemPage *pPage;
-+
-+  assert( amt>=0 );
-+  assert( offset>=0 );
-+  assert( pCur->pPage!=0 );
-+  pPage = pCur->pPage;
-+  if( pCur->idx >= pPage->nCell ){
-+    return 0;
-+  }
-+  assert( amt+offset <= NKEY(pCur->pBt, pPage->apCell[pCur->idx]->h) );
-+  getPayload(pCur, offset, amt, zBuf);
-+  return amt;
-+}
-+
-+/*
-+** Set *pSize to the number of bytes of data in the entry the
-+** cursor currently points to.  Always return SQLITE_OK.
-+** Failure is not possible.  If the cursor is not currently
-+** pointing to an entry (which can happen, for example, if
-+** the database is empty) then *pSize is set to 0.
-+*/
-+static int fileBtreeDataSize(BtCursor *pCur, int *pSize){
-+  Cell *pCell;
-+  MemPage *pPage;
-+
-+  pPage = pCur->pPage;
-+  assert( pPage!=0 );
-+  if( pCur->idx >= pPage->nCell ){
-+    *pSize = 0;
-+  }else{
-+    pCell = pPage->apCell[pCur->idx];
-+    *pSize = NDATA(pCur->pBt, pCell->h);
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Read part of the data associated with cursor pCur.  A maximum
-+** of "amt" bytes will be transfered into zBuf[].  The transfer
-+** begins at "offset".  The number of bytes actually read is
-+** returned.  The amount returned will be smaller than the
-+** amount requested if there are not enough bytes in the data
-+** to satisfy the request.
-+*/
-+static int fileBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
-+  Cell *pCell;
-+  MemPage *pPage;
-+
-+  assert( amt>=0 );
-+  assert( offset>=0 );
-+  assert( pCur->pPage!=0 );
-+  pPage = pCur->pPage;
-+  if( pCur->idx >= pPage->nCell ){
-+    return 0;
-+  }
-+  pCell = pPage->apCell[pCur->idx];
-+  assert( amt+offset <= NDATA(pCur->pBt, pCell->h) );
-+  getPayload(pCur, offset + NKEY(pCur->pBt, pCell->h), amt, zBuf);
-+  return amt;
-+}
-+
-+/*
-+** Compare an external key against the key on the entry that pCur points to.
-+**
-+** The external key is pKey and is nKey bytes long.  The last nIgnore bytes
-+** of the key associated with pCur are ignored, as if they do not exist.
-+** (The normal case is for nIgnore to be zero in which case the entire
-+** internal key is used in the comparison.)
-+**
-+** The comparison result is written to *pRes as follows:
-+**
-+**    *pRes<0    This means pCur<pKey
-+**
-+**    *pRes==0   This means pCur==pKey for all nKey bytes
-+**
-+**    *pRes>0    This means pCur>pKey
-+**
-+** When one key is an exact prefix of the other, the shorter key is
-+** considered less than the longer one.  In order to be equal the
-+** keys must be exactly the same length. (The length of the pCur key
-+** is the actual key length minus nIgnore bytes.)
-+*/
-+static int fileBtreeKeyCompare(
-+  BtCursor *pCur,       /* Pointer to entry to compare against */
-+  const void *pKey,     /* Key to compare against entry that pCur points to */
-+  int nKey,             /* Number of bytes in pKey */
-+  int nIgnore,          /* Ignore this many bytes at the end of pCur */
-+  int *pResult          /* Write the result here */
-+){
-+  Pgno nextPage;
-+  int n, c, rc, nLocal;
-+  Cell *pCell;
-+  Btree *pBt = pCur->pBt;
-+  const char *zKey  = (const char*)pKey;
-+
-+  assert( pCur->pPage );
-+  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
-+  pCell = pCur->pPage->apCell[pCur->idx];
-+  nLocal = NKEY(pBt, pCell->h) - nIgnore;
-+  if( nLocal<0 ) nLocal = 0;
-+  n = nKey<nLocal ? nKey : nLocal;
-+  if( n>MX_LOCAL_PAYLOAD ){
-+    n = MX_LOCAL_PAYLOAD;
-+  }
-+  c = memcmp(pCell->aPayload, zKey, n);
-+  if( c!=0 ){
-+    *pResult = c;
-+    return SQLITE_OK;
-+  }
-+  zKey += n;
-+  nKey -= n;
-+  nLocal -= n;
-+  nextPage = SWAB32(pBt, pCell->ovfl);
-+  while( nKey>0 && nLocal>0 ){
-+    OverflowPage *pOvfl;
-+    if( nextPage==0 ){
-+      return SQLITE_CORRUPT;
-+    }
-+    rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
-+    if( rc ){
-+      return rc;
-+    }
-+    nextPage = SWAB32(pBt, pOvfl->iNext);
-+    n = nKey<nLocal ? nKey : nLocal;
-+    if( n>OVERFLOW_SIZE ){
-+      n = OVERFLOW_SIZE;
-+    }
-+    c = memcmp(pOvfl->aPayload, zKey, n);
-+    sqlitepager_unref(pOvfl);
-+    if( c!=0 ){
-+      *pResult = c;
-+      return SQLITE_OK;
-+    }
-+    nKey -= n;
-+    nLocal -= n;
-+    zKey += n;
-+  }
-+  if( c==0 ){
-+    c = nLocal - nKey;
-+  }
-+  *pResult = c;
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Move the cursor down to a new child page.  The newPgno argument is the
-+** page number of the child page in the byte order of the disk image.
-+*/
-+static int moveToChild(BtCursor *pCur, int newPgno){
-+  int rc;
-+  MemPage *pNewPage;
-+  Btree *pBt = pCur->pBt;
-+
-+  newPgno = SWAB32(pBt, newPgno);
-+  rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage);
-+  if( rc ) return rc;
-+  rc = initPage(pBt, pNewPage, newPgno, pCur->pPage);
-+  if( rc ) return rc;
-+  assert( pCur->idx>=pCur->pPage->nCell
-+          || pCur->pPage->apCell[pCur->idx]->h.leftChild==SWAB32(pBt,newPgno) );
-+  assert( pCur->idx<pCur->pPage->nCell
-+          || pCur->pPage->u.hdr.rightChild==SWAB32(pBt,newPgno) );
-+  pNewPage->idxParent = pCur->idx;
-+  pCur->pPage->idxShift = 0;
-+  sqlitepager_unref(pCur->pPage);
-+  pCur->pPage = pNewPage;
-+  pCur->idx = 0;
-+  if( pNewPage->nCell<1 ){
-+    return SQLITE_CORRUPT;
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Move the cursor up to the parent page.
-+**
-+** pCur->idx is set to the cell index that contains the pointer
-+** to the page we are coming from.  If we are coming from the
-+** right-most child page then pCur->idx is set to one more than
-+** the largest cell index.
-+*/
-+static void moveToParent(BtCursor *pCur){
-+  Pgno oldPgno;
-+  MemPage *pParent;
-+  MemPage *pPage;
-+  int idxParent;
-+  pPage = pCur->pPage;
-+  assert( pPage!=0 );
-+  pParent = pPage->pParent;
-+  assert( pParent!=0 );
-+  idxParent = pPage->idxParent;
-+  sqlitepager_ref(pParent);
-+  sqlitepager_unref(pPage);
-+  pCur->pPage = pParent;
-+  assert( pParent->idxShift==0 );
-+  if( pParent->idxShift==0 ){
-+    pCur->idx = idxParent;
-+#ifndef NDEBUG  
-+    /* Verify that pCur->idx is the correct index to point back to the child
-+    ** page we just came from 
-+    */
-+    oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
-+    if( pCur->idx<pParent->nCell ){
-+      assert( pParent->apCell[idxParent]->h.leftChild==oldPgno );
-+    }else{
-+      assert( pParent->u.hdr.rightChild==oldPgno );
-+    }
-+#endif
-+  }else{
-+    /* The MemPage.idxShift flag indicates that cell indices might have 
-+    ** changed since idxParent was set and hence idxParent might be out
-+    ** of date.  So recompute the parent cell index by scanning all cells
-+    ** and locating the one that points to the child we just came from.
-+    */
-+    int i;
-+    pCur->idx = pParent->nCell;
-+    oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
-+    for(i=0; i<pParent->nCell; i++){
-+      if( pParent->apCell[i]->h.leftChild==oldPgno ){
-+        pCur->idx = i;
-+        break;
-+      }
-+    }
-+  }
-+}
-+
-+/*
-+** Move the cursor to the root page
-+*/
-+static int moveToRoot(BtCursor *pCur){
-+  MemPage *pNew;
-+  int rc;
-+  Btree *pBt = pCur->pBt;
-+
-+  rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pNew);
-+  if( rc ) return rc;
-+  rc = initPage(pBt, pNew, pCur->pgnoRoot, 0);
-+  if( rc ) return rc;
-+  sqlitepager_unref(pCur->pPage);
-+  pCur->pPage = pNew;
-+  pCur->idx = 0;
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Move the cursor down to the left-most leaf entry beneath the
-+** entry to which it is currently pointing.
-+*/
-+static int moveToLeftmost(BtCursor *pCur){
-+  Pgno pgno;
-+  int rc;
-+
-+  while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
-+    rc = moveToChild(pCur, pgno);
-+    if( rc ) return rc;
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Move the cursor down to the right-most leaf entry beneath the
-+** page to which it is currently pointing.  Notice the difference
-+** between moveToLeftmost() and moveToRightmost().  moveToLeftmost()
-+** finds the left-most entry beneath the *entry* whereas moveToRightmost()
-+** finds the right-most entry beneath the *page*.
-+*/
-+static int moveToRightmost(BtCursor *pCur){
-+  Pgno pgno;
-+  int rc;
-+
-+  while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
-+    pCur->idx = pCur->pPage->nCell;
-+    rc = moveToChild(pCur, pgno);
-+    if( rc ) return rc;
-+  }
-+  pCur->idx = pCur->pPage->nCell - 1;
-+  return SQLITE_OK;
-+}
-+
-+/* Move the cursor to the first entry in the table.  Return SQLITE_OK
-+** on success.  Set *pRes to 0 if the cursor actually points to something
-+** or set *pRes to 1 if the table is empty.
-+*/
-+static int fileBtreeFirst(BtCursor *pCur, int *pRes){
-+  int rc;
-+  if( pCur->pPage==0 ) return SQLITE_ABORT;
-+  rc = moveToRoot(pCur);
-+  if( rc ) return rc;
-+  if( pCur->pPage->nCell==0 ){
-+    *pRes = 1;
-+    return SQLITE_OK;
-+  }
-+  *pRes = 0;
-+  rc = moveToLeftmost(pCur);
-+  pCur->eSkip = SKIP_NONE;
-+  return rc;
-+}
-+
-+/* Move the cursor to the last entry in the table.  Return SQLITE_OK
-+** on success.  Set *pRes to 0 if the cursor actually points to something
-+** or set *pRes to 1 if the table is empty.
-+*/
-+static int fileBtreeLast(BtCursor *pCur, int *pRes){
-+  int rc;
-+  if( pCur->pPage==0 ) return SQLITE_ABORT;
-+  rc = moveToRoot(pCur);
-+  if( rc ) return rc;
-+  assert( pCur->pPage->isInit );
-+  if( pCur->pPage->nCell==0 ){
-+    *pRes = 1;
-+    return SQLITE_OK;
-+  }
-+  *pRes = 0;
-+  rc = moveToRightmost(pCur);
-+  pCur->eSkip = SKIP_NONE;
-+  return rc;
-+}
-+
-+/* Move the cursor so that it points to an entry near pKey.
-+** Return a success code.
-+**
-+** If an exact match is not found, then the cursor is always
-+** left pointing at a leaf page which would hold the entry if it
-+** were present.  The cursor might point to an entry that comes
-+** before or after the key.
-+**
-+** The result of comparing the key with the entry to which the
-+** cursor is left pointing is stored in pCur->iMatch.  The same
-+** value is also written to *pRes if pRes!=NULL.  The meaning of
-+** this value is as follows:
-+**
-+**     *pRes<0      The cursor is left pointing at an entry that
-+**                  is smaller than pKey or if the table is empty
-+**                  and the cursor is therefore left point to nothing.
-+**
-+**     *pRes==0     The cursor is left pointing at an entry that
-+**                  exactly matches pKey.
-+**
-+**     *pRes>0      The cursor is left pointing at an entry that
-+**                  is larger than pKey.
-+*/
-+static
-+int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
-+  int rc;
-+  if( pCur->pPage==0 ) return SQLITE_ABORT;
-+  pCur->eSkip = SKIP_NONE;
-+  rc = moveToRoot(pCur);
-+  if( rc ) return rc;
-+  for(;;){
-+    int lwr, upr;
-+    Pgno chldPg;
-+    MemPage *pPage = pCur->pPage;
-+    int c = -1;  /* pRes return if table is empty must be -1 */
-+    lwr = 0;
-+    upr = pPage->nCell-1;
-+    while( lwr<=upr ){
-+      pCur->idx = (lwr+upr)/2;
-+      rc = fileBtreeKeyCompare(pCur, pKey, nKey, 0, &c);
-+      if( rc ) return rc;
-+      if( c==0 ){
-+        pCur->iMatch = c;
-+        if( pRes ) *pRes = 0;
-+        return SQLITE_OK;
-+      }
-+      if( c<0 ){
-+        lwr = pCur->idx+1;
-+      }else{
-+        upr = pCur->idx-1;
-+      }
-+    }
-+    assert( lwr==upr+1 );
-+    assert( pPage->isInit );
-+    if( lwr>=pPage->nCell ){
-+      chldPg = pPage->u.hdr.rightChild;
-+    }else{
-+      chldPg = pPage->apCell[lwr]->h.leftChild;
-+    }
-+    if( chldPg==0 ){
-+      pCur->iMatch = c;
-+      if( pRes ) *pRes = c;
-+      return SQLITE_OK;
-+    }
-+    pCur->idx = lwr;
-+    rc = moveToChild(pCur, chldPg);
-+    if( rc ) return rc;
-+  }
-+  /* NOT REACHED */
-+}
-+
-+/*
-+** Advance the cursor to the next entry in the database.  If
-+** successful then set *pRes=0.  If the cursor
-+** was already pointing to the last entry in the database before
-+** this routine was called, then set *pRes=1.
-+*/
-+static int fileBtreeNext(BtCursor *pCur, int *pRes){
-+  int rc;
-+  MemPage *pPage = pCur->pPage;
-+  assert( pRes!=0 );
-+  if( pPage==0 ){
-+    *pRes = 1;
-+    return SQLITE_ABORT;
-+  }
-+  assert( pPage->isInit );
-+  assert( pCur->eSkip!=SKIP_INVALID );
-+  if( pPage->nCell==0 ){
-+    *pRes = 1;
-+    return SQLITE_OK;
-+  }
-+  assert( pCur->idx<pPage->nCell );
-+  if( pCur->eSkip==SKIP_NEXT ){
-+    pCur->eSkip = SKIP_NONE;
-+    *pRes = 0;
-+    return SQLITE_OK;
-+  }
-+  pCur->eSkip = SKIP_NONE;
-+  pCur->idx++;
-+  if( pCur->idx>=pPage->nCell ){
-+    if( pPage->u.hdr.rightChild ){
-+      rc = moveToChild(pCur, pPage->u.hdr.rightChild);
-+      if( rc ) return rc;
-+      rc = moveToLeftmost(pCur);
-+      *pRes = 0;
-+      return rc;
-+    }
-+    do{
-+      if( pPage->pParent==0 ){
-+        *pRes = 1;
-+        return SQLITE_OK;
-+      }
-+      moveToParent(pCur);
-+      pPage = pCur->pPage;
-+    }while( pCur->idx>=pPage->nCell );
-+    *pRes = 0;
-+    return SQLITE_OK;
-+  }
-+  *pRes = 0;
-+  if( pPage->u.hdr.rightChild==0 ){
-+    return SQLITE_OK;
-+  }
-+  rc = moveToLeftmost(pCur);
-+  return rc;
-+}
-+
-+/*
-+** Step the cursor to the back to the previous entry in the database.  If
-+** successful then set *pRes=0.  If the cursor
-+** was already pointing to the first entry in the database before
-+** this routine was called, then set *pRes=1.
-+*/
-+static int fileBtreePrevious(BtCursor *pCur, int *pRes){
-+  int rc;
-+  Pgno pgno;
-+  MemPage *pPage;
-+  pPage = pCur->pPage;
-+  if( pPage==0 ){
-+    *pRes = 1;
-+    return SQLITE_ABORT;
-+  }
-+  assert( pPage->isInit );
-+  assert( pCur->eSkip!=SKIP_INVALID );
-+  if( pPage->nCell==0 ){
-+    *pRes = 1;
-+    return SQLITE_OK;
-+  }
-+  if( pCur->eSkip==SKIP_PREV ){
-+    pCur->eSkip = SKIP_NONE;
-+    *pRes = 0;
-+    return SQLITE_OK;
-+  }
-+  pCur->eSkip = SKIP_NONE;
-+  assert( pCur->idx>=0 );
-+  if( (pgno = pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
-+    rc = moveToChild(pCur, pgno);
-+    if( rc ) return rc;
-+    rc = moveToRightmost(pCur);
-+  }else{
-+    while( pCur->idx==0 ){
-+      if( pPage->pParent==0 ){
-+        if( pRes ) *pRes = 1;
-+        return SQLITE_OK;
-+      }
-+      moveToParent(pCur);
-+      pPage = pCur->pPage;
-+    }
-+    pCur->idx--;
-+    rc = SQLITE_OK;
-+  }
-+  *pRes = 0;
-+  return rc;
-+}
-+
-+/*
-+** Allocate a new page from the database file.
-+**
-+** The new page is marked as dirty.  (In other words, sqlitepager_write()
-+** has already been called on the new page.)  The new page has also
-+** been referenced and the calling routine is responsible for calling
-+** sqlitepager_unref() on the new page when it is done.
-+**
-+** SQLITE_OK is returned on success.  Any other return value indicates
-+** an error.  *ppPage and *pPgno are undefined in the event of an error.
-+** Do not invoke sqlitepager_unref() on *ppPage if an error is returned.
-+**
-+** If the "nearby" parameter is not 0, then a (feeble) effort is made to 
-+** locate a page close to the page number "nearby".  This can be used in an
-+** attempt to keep related pages close to each other in the database file,
-+** which in turn can make database access faster.
-+*/
-+static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
-+  PageOne *pPage1 = pBt->page1;
-+  int rc;
-+  if( pPage1->freeList ){
-+    OverflowPage *pOvfl;
-+    FreelistInfo *pInfo;
-+
-+    rc = sqlitepager_write(pPage1);
-+    if( rc ) return rc;
-+    SWAB_ADD(pBt, pPage1->nFree, -1);
-+    rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
-+                        (void**)&pOvfl);
-+    if( rc ) return rc;
-+    rc = sqlitepager_write(pOvfl);
-+    if( rc ){
-+      sqlitepager_unref(pOvfl);
-+      return rc;
-+    }
-+    pInfo = (FreelistInfo*)pOvfl->aPayload;
-+    if( pInfo->nFree==0 ){
-+      *pPgno = SWAB32(pBt, pPage1->freeList);
-+      pPage1->freeList = pOvfl->iNext;
-+      *ppPage = (MemPage*)pOvfl;
-+    }else{
-+      int closest, n;
-+      n = SWAB32(pBt, pInfo->nFree);
-+      if( n>1 && nearby>0 ){
-+        int i, dist;
-+        closest = 0;
-+        dist = SWAB32(pBt, pInfo->aFree[0]) - nearby;
-+        if( dist<0 ) dist = -dist;
-+        for(i=1; i<n; i++){
-+          int d2 = SWAB32(pBt, pInfo->aFree[i]) - nearby;
-+          if( d2<0 ) d2 = -d2;
-+          if( d2<dist ) closest = i;
-+        }
-+      }else{
-+        closest = 0;
-+      }
-+      SWAB_ADD(pBt, pInfo->nFree, -1);
-+      *pPgno = SWAB32(pBt, pInfo->aFree[closest]);
-+      pInfo->aFree[closest] = pInfo->aFree[n-1];
-+      rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
-+      sqlitepager_unref(pOvfl);
-+      if( rc==SQLITE_OK ){
-+        sqlitepager_dont_rollback(*ppPage);
-+        rc = sqlitepager_write(*ppPage);
-+      }
-+    }
-+  }else{
-+    *pPgno = sqlitepager_pagecount(pBt->pPager) + 1;
-+    rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
-+    if( rc ) return rc;
-+    rc = sqlitepager_write(*ppPage);
-+  }
-+  return rc;
-+}
-+
-+/*
-+** Add a page of the database file to the freelist.  Either pgno or
-+** pPage but not both may be 0. 
-+**
-+** sqlitepager_unref() is NOT called for pPage.
-+*/
-+static int freePage(Btree *pBt, void *pPage, Pgno pgno){
-+  PageOne *pPage1 = pBt->page1;
-+  OverflowPage *pOvfl = (OverflowPage*)pPage;
-+  int rc;
-+  int needUnref = 0;
-+  MemPage *pMemPage;
-+
-+  if( pgno==0 ){
-+    assert( pOvfl!=0 );
-+    pgno = sqlitepager_pagenumber(pOvfl);
-+  }
-+  assert( pgno>2 );
-+  assert( sqlitepager_pagenumber(pOvfl)==pgno );
-+  pMemPage = (MemPage*)pPage;
-+  pMemPage->isInit = 0;
-+  if( pMemPage->pParent ){
-+    sqlitepager_unref(pMemPage->pParent);
-+    pMemPage->pParent = 0;
-+  }
-+  rc = sqlitepager_write(pPage1);
-+  if( rc ){
-+    return rc;
-+  }
-+  SWAB_ADD(pBt, pPage1->nFree, 1);
-+  if( pPage1->nFree!=0 && pPage1->freeList!=0 ){
-+    OverflowPage *pFreeIdx;
-+    rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
-+                        (void**)&pFreeIdx);
-+    if( rc==SQLITE_OK ){
-+      FreelistInfo *pInfo = (FreelistInfo*)pFreeIdx->aPayload;
-+      int n = SWAB32(pBt, pInfo->nFree);
-+      if( n<(sizeof(pInfo->aFree)/sizeof(pInfo->aFree[0])) ){
-+        rc = sqlitepager_write(pFreeIdx);
-+        if( rc==SQLITE_OK ){
-+          pInfo->aFree[n] = SWAB32(pBt, pgno);
-+          SWAB_ADD(pBt, pInfo->nFree, 1);
-+          sqlitepager_unref(pFreeIdx);
-+          sqlitepager_dont_write(pBt->pPager, pgno);
-+          return rc;
-+        }
-+      }
-+      sqlitepager_unref(pFreeIdx);
-+    }
-+  }
-+  if( pOvfl==0 ){
-+    assert( pgno>0 );
-+    rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pOvfl);
-+    if( rc ) return rc;
-+    needUnref = 1;
-+  }
-+  rc = sqlitepager_write(pOvfl);
-+  if( rc ){
-+    if( needUnref ) sqlitepager_unref(pOvfl);
-+    return rc;
-+  }
-+  pOvfl->iNext = pPage1->freeList;
-+  pPage1->freeList = SWAB32(pBt, pgno);
-+  memset(pOvfl->aPayload, 0, OVERFLOW_SIZE);
-+  if( needUnref ) rc = sqlitepager_unref(pOvfl);
-+  return rc;
-+}
-+
-+/*
-+** Erase all the data out of a cell.  This involves returning overflow
-+** pages back the freelist.
-+*/
-+static int clearCell(Btree *pBt, Cell *pCell){
-+  Pager *pPager = pBt->pPager;
-+  OverflowPage *pOvfl;
-+  Pgno ovfl, nextOvfl;
-+  int rc;
-+
-+  if( NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h) <= MX_LOCAL_PAYLOAD ){
-+    return SQLITE_OK;
-+  }
-+  ovfl = SWAB32(pBt, pCell->ovfl);
-+  pCell->ovfl = 0;
-+  while( ovfl ){
-+    rc = sqlitepager_get(pPager, ovfl, (void**)&pOvfl);
-+    if( rc ) return rc;
-+    nextOvfl = SWAB32(pBt, pOvfl->iNext);
-+    rc = freePage(pBt, pOvfl, ovfl);
-+    if( rc ) return rc;
-+    sqlitepager_unref(pOvfl);
-+    ovfl = nextOvfl;
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Create a new cell from key and data.  Overflow pages are allocated as
-+** necessary and linked to this cell.  
-+*/
-+static int fillInCell(
-+  Btree *pBt,              /* The whole Btree.  Needed to allocate pages */
-+  Cell *pCell,             /* Populate this Cell structure */
-+  const void *pKey, int nKey,    /* The key */
-+  const void *pData,int nData    /* The data */
-+){
-+  OverflowPage *pOvfl, *pPrior;
-+  Pgno *pNext;
-+  int spaceLeft;
-+  int n, rc;
-+  int nPayload;
-+  const char *pPayload;
-+  char *pSpace;
-+  Pgno nearby = 0;
-+
-+  pCell->h.leftChild = 0;
-+  pCell->h.nKey = SWAB16(pBt, nKey & 0xffff);
-+  pCell->h.nKeyHi = nKey >> 16;
-+  pCell->h.nData = SWAB16(pBt, nData & 0xffff);
-+  pCell->h.nDataHi = nData >> 16;
-+  pCell->h.iNext = 0;
-+
-+  pNext = &pCell->ovfl;
-+  pSpace = pCell->aPayload;
-+  spaceLeft = MX_LOCAL_PAYLOAD;
-+  pPayload = pKey;
-+  pKey = 0;
-+  nPayload = nKey;
-+  pPrior = 0;
-+  while( nPayload>0 ){
-+    if( spaceLeft==0 ){
-+      rc = allocatePage(pBt, (MemPage**)&pOvfl, pNext, nearby);
-+      if( rc ){
-+        *pNext = 0;
-+      }else{
-+        nearby = *pNext;
-+      }
-+      if( pPrior ) sqlitepager_unref(pPrior);
-+      if( rc ){
-+        clearCell(pBt, pCell);
-+        return rc;
-+      }
-+      if( pBt->needSwab ) *pNext = swab32(*pNext);
-+      pPrior = pOvfl;
-+      spaceLeft = OVERFLOW_SIZE;
-+      pSpace = pOvfl->aPayload;
-+      pNext = &pOvfl->iNext;
-+    }
-+    n = nPayload;
-+    if( n>spaceLeft ) n = spaceLeft;
-+    memcpy(pSpace, pPayload, n);
-+    nPayload -= n;
-+    if( nPayload==0 && pData ){
-+      pPayload = pData;
-+      nPayload = nData;
-+      pData = 0;
-+    }else{
-+      pPayload += n;
-+    }
-+    spaceLeft -= n;
-+    pSpace += n;
-+  }
-+  *pNext = 0;
-+  if( pPrior ){
-+    sqlitepager_unref(pPrior);
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Change the MemPage.pParent pointer on the page whose number is
-+** given in the second argument so that MemPage.pParent holds the
-+** pointer in the third argument.
-+*/
-+static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent,int idx){
-+  MemPage *pThis;
-+
-+  if( pgno==0 ) return;
-+  assert( pPager!=0 );
-+  pThis = sqlitepager_lookup(pPager, pgno);
-+  if( pThis && pThis->isInit ){
-+    if( pThis->pParent!=pNewParent ){
-+      if( pThis->pParent ) sqlitepager_unref(pThis->pParent);
-+      pThis->pParent = pNewParent;
-+      if( pNewParent ) sqlitepager_ref(pNewParent);
-+    }
-+    pThis->idxParent = idx;
-+    sqlitepager_unref(pThis);
-+  }
-+}
-+
-+/*
-+** Reparent all children of the given page to be the given page.
-+** In other words, for every child of pPage, invoke reparentPage()
-+** to make sure that each child knows that pPage is its parent.
-+**
-+** This routine gets called after you memcpy() one page into
-+** another.
-+*/
-+static void reparentChildPages(Btree *pBt, MemPage *pPage){
-+  int i;
-+  Pager *pPager = pBt->pPager;
-+  for(i=0; i<pPage->nCell; i++){
-+    reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage, i);
-+  }
-+  reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage, i);
-+  pPage->idxShift = 0;
-+}
-+
-+/*
-+** Remove the i-th cell from pPage.  This routine effects pPage only.
-+** The cell content is not freed or deallocated.  It is assumed that
-+** the cell content has been copied someplace else.  This routine just
-+** removes the reference to the cell from pPage.
-+**
-+** "sz" must be the number of bytes in the cell.
-+**
-+** Do not bother maintaining the integrity of the linked list of Cells.
-+** Only the pPage->apCell[] array is important.  The relinkCellList() 
-+** routine will be called soon after this routine in order to rebuild 
-+** the linked list.
-+*/
-+static void dropCell(Btree *pBt, MemPage *pPage, int idx, int sz){
-+  int j;
-+  assert( idx>=0 && idx<pPage->nCell );
-+  assert( sz==cellSize(pBt, pPage->apCell[idx]) );
-+  assert( sqlitepager_iswriteable(pPage) );
-+  freeSpace(pBt, pPage, Addr(pPage->apCell[idx]) - Addr(pPage), sz);
-+  for(j=idx; j<pPage->nCell-1; j++){
-+    pPage->apCell[j] = pPage->apCell[j+1];
-+  }
-+  pPage->nCell--;
-+  pPage->idxShift = 1;
-+}
-+
-+/*
-+** Insert a new cell on pPage at cell index "i".  pCell points to the
-+** content of the cell.
-+**
-+** If the cell content will fit on the page, then put it there.  If it
-+** will not fit, then just make pPage->apCell[i] point to the content
-+** and set pPage->isOverfull.  
-+**
-+** Do not bother maintaining the integrity of the linked list of Cells.
-+** Only the pPage->apCell[] array is important.  The relinkCellList() 
-+** routine will be called soon after this routine in order to rebuild 
-+** the linked list.
-+*/
-+static void insertCell(Btree *pBt, MemPage *pPage, int i, Cell *pCell, int sz){
-+  int idx, j;
-+  assert( i>=0 && i<=pPage->nCell );
-+  assert( sz==cellSize(pBt, pCell) );
-+  assert( sqlitepager_iswriteable(pPage) );
-+  idx = allocateSpace(pBt, pPage, sz);
-+  for(j=pPage->nCell; j>i; j--){
-+    pPage->apCell[j] = pPage->apCell[j-1];
-+  }
-+  pPage->nCell++;
-+  if( idx<=0 ){
-+    pPage->isOverfull = 1;
-+    pPage->apCell[i] = pCell;
-+  }else{
-+    memcpy(&pPage->u.aDisk[idx], pCell, sz);
-+    pPage->apCell[i] = (Cell*)&pPage->u.aDisk[idx];
-+  }
-+  pPage->idxShift = 1;
-+}
-+
-+/*
-+** Rebuild the linked list of cells on a page so that the cells
-+** occur in the order specified by the pPage->apCell[] array.  
-+** Invoke this routine once to repair damage after one or more
-+** invocations of either insertCell() or dropCell().
-+*/
-+static void relinkCellList(Btree *pBt, MemPage *pPage){
-+  int i;
-+  u16 *pIdx;
-+  assert( sqlitepager_iswriteable(pPage) );
-+  pIdx = &pPage->u.hdr.firstCell;
-+  for(i=0; i<pPage->nCell; i++){
-+    int idx = Addr(pPage->apCell[i]) - Addr(pPage);
-+    assert( idx>0 && idx<SQLITE_USABLE_SIZE );
-+    *pIdx = SWAB16(pBt, idx);
-+    pIdx = &pPage->apCell[i]->h.iNext;
-+  }
-+  *pIdx = 0;
-+}
-+
-+/*
-+** Make a copy of the contents of pFrom into pTo.  The pFrom->apCell[]
-+** pointers that point into pFrom->u.aDisk[] must be adjusted to point
-+** into pTo->u.aDisk[] instead.  But some pFrom->apCell[] entries might
-+** not point to pFrom->u.aDisk[].  Those are unchanged.
-+*/
-+static void copyPage(MemPage *pTo, MemPage *pFrom){
-+  uptr from, to;
-+  int i;
-+  memcpy(pTo->u.aDisk, pFrom->u.aDisk, SQLITE_USABLE_SIZE);
-+  pTo->pParent = 0;
-+  pTo->isInit = 1;
-+  pTo->nCell = pFrom->nCell;
-+  pTo->nFree = pFrom->nFree;
-+  pTo->isOverfull = pFrom->isOverfull;
-+  to = Addr(pTo);
-+  from = Addr(pFrom);
-+  for(i=0; i<pTo->nCell; i++){
-+    uptr x = Addr(pFrom->apCell[i]);
-+    if( x>from && x<from+SQLITE_USABLE_SIZE ){
-+      *((uptr*)&pTo->apCell[i]) = x + to - from;
-+    }else{
-+      pTo->apCell[i] = pFrom->apCell[i];
-+    }
-+  }
-+}
-+
-+/*
-+** The following parameters determine how many adjacent pages get involved
-+** in a balancing operation.  NN is the number of neighbors on either side
-+** of the page that participate in the balancing operation.  NB is the
-+** total number of pages that participate, including the target page and
-+** NN neighbors on either side.
-+**
-+** The minimum value of NN is 1 (of course).  Increasing NN above 1
-+** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
-+** in exchange for a larger degradation in INSERT and UPDATE performance.
-+** The value of NN appears to give the best results overall.
-+*/
-+#define NN 1             /* Number of neighbors on either side of pPage */
-+#define NB (NN*2+1)      /* Total pages involved in the balance */
-+
-+/*
-+** This routine redistributes Cells on pPage and up to two siblings
-+** of pPage so that all pages have about the same amount of free space.
-+** Usually one sibling on either side of pPage is used in the balancing,
-+** though both siblings might come from one side if pPage is the first
-+** or last child of its parent.  If pPage has fewer than two siblings
-+** (something which can only happen if pPage is the root page or a 
-+** child of root) then all available siblings participate in the balancing.
-+**
-+** The number of siblings of pPage might be increased or decreased by
-+** one in an effort to keep pages between 66% and 100% full. The root page
-+** is special and is allowed to be less than 66% full. If pPage is 
-+** the root page, then the depth of the tree might be increased
-+** or decreased by one, as necessary, to keep the root page from being
-+** overfull or empty.
-+**
-+** This routine calls relinkCellList() on its input page regardless of
-+** whether or not it does any real balancing.  Client routines will typically
-+** invoke insertCell() or dropCell() before calling this routine, so we
-+** need to call relinkCellList() to clean up the mess that those other
-+** routines left behind.
-+**
-+** pCur is left pointing to the same cell as when this routine was called
-+** even if that cell gets moved to a different page.  pCur may be NULL.
-+** Set the pCur parameter to NULL if you do not care about keeping track
-+** of a cell as that will save this routine the work of keeping track of it.
-+**
-+** Note that when this routine is called, some of the Cells on pPage
-+** might not actually be stored in pPage->u.aDisk[].  This can happen
-+** if the page is overfull.  Part of the job of this routine is to
-+** make sure all Cells for pPage once again fit in pPage->u.aDisk[].
-+**
-+** In the course of balancing the siblings of pPage, the parent of pPage
-+** might become overfull or underfull.  If that happens, then this routine
-+** is called recursively on the parent.
-+**
-+** If this routine fails for any reason, it might leave the database
-+** in a corrupted state.  So if this routine fails, the database should
-+** be rolled back.
-+*/
-+static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
-+  MemPage *pParent;            /* The parent of pPage */
-+  int nCell;                   /* Number of cells in apCell[] */
-+  int nOld;                    /* Number of pages in apOld[] */
-+  int nNew;                    /* Number of pages in apNew[] */
-+  int nDiv;                    /* Number of cells in apDiv[] */
-+  int i, j, k;                 /* Loop counters */
-+  int idx;                     /* Index of pPage in pParent->apCell[] */
-+  int nxDiv;                   /* Next divider slot in pParent->apCell[] */
-+  int rc;                      /* The return code */
-+  int iCur;                    /* apCell[iCur] is the cell of the cursor */
-+  MemPage *pOldCurPage;        /* The cursor originally points to this page */
-+  int subtotal;                /* Subtotal of bytes in cells on one page */
-+  MemPage *extraUnref = 0;     /* A page that needs to be unref-ed */
-+  MemPage *apOld[NB];          /* pPage and up to two siblings */
-+  Pgno pgnoOld[NB];            /* Page numbers for each page in apOld[] */
-+  MemPage *apNew[NB+1];        /* pPage and up to NB siblings after balancing */
-+  Pgno pgnoNew[NB+1];          /* Page numbers for each page in apNew[] */
-+  int idxDiv[NB];              /* Indices of divider cells in pParent */
-+  Cell *apDiv[NB];             /* Divider cells in pParent */
-+  Cell aTemp[NB];              /* Temporary holding area for apDiv[] */
-+  int cntNew[NB+1];            /* Index in apCell[] of cell after i-th page */
-+  int szNew[NB+1];             /* Combined size of cells place on i-th page */
-+  MemPage aOld[NB];            /* Temporary copies of pPage and its siblings */
-+  Cell *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */
-+  int szCell[(MX_CELL+2)*NB];  /* Local size of all cells */
-+
-+  /* 
-+  ** Return without doing any work if pPage is neither overfull nor
-+  ** underfull.
-+  */
-+  assert( sqlitepager_iswriteable(pPage) );
-+  if( !pPage->isOverfull && pPage->nFree<SQLITE_USABLE_SIZE/2 
-+        && pPage->nCell>=2){
-+    relinkCellList(pBt, pPage);
-+    return SQLITE_OK;
-+  }
-+
-+  /*
-+  ** Find the parent of the page to be balanceed.
-+  ** If there is no parent, it means this page is the root page and
-+  ** special rules apply.
-+  */
-+  pParent = pPage->pParent;
-+  if( pParent==0 ){
-+    Pgno pgnoChild;
-+    MemPage *pChild;
-+    assert( pPage->isInit );
-+    if( pPage->nCell==0 ){
-+      if( pPage->u.hdr.rightChild ){
-+        /*
-+        ** The root page is empty.  Copy the one child page
-+        ** into the root page and return.  This reduces the depth
-+        ** of the BTree by one.
-+        */
-+        pgnoChild = SWAB32(pBt, pPage->u.hdr.rightChild);
-+        rc = sqlitepager_get(pBt->pPager, pgnoChild, (void**)&pChild);
-+        if( rc ) return rc;
-+        memcpy(pPage, pChild, SQLITE_USABLE_SIZE);
-+        pPage->isInit = 0;
-+        rc = initPage(pBt, pPage, sqlitepager_pagenumber(pPage), 0);
-+        assert( rc==SQLITE_OK );
-+        reparentChildPages(pBt, pPage);
-+        if( pCur && pCur->pPage==pChild ){
-+          sqlitepager_unref(pChild);
-+          pCur->pPage = pPage;
-+          sqlitepager_ref(pPage);
-+        }
-+        freePage(pBt, pChild, pgnoChild);
-+        sqlitepager_unref(pChild);
-+      }else{
-+        relinkCellList(pBt, pPage);
-+      }
-+      return SQLITE_OK;
-+    }
-+    if( !pPage->isOverfull ){
-+      /* It is OK for the root page to be less than half full.
-+      */
-+      relinkCellList(pBt, pPage);
-+      return SQLITE_OK;
-+    }
-+    /*
-+    ** If we get to here, it means the root page is overfull.
-+    ** When this happens, Create a new child page and copy the
-+    ** contents of the root into the child.  Then make the root
-+    ** page an empty page with rightChild pointing to the new
-+    ** child.  Then fall thru to the code below which will cause
-+    ** the overfull child page to be split.
-+    */
-+    rc = sqlitepager_write(pPage);
-+    if( rc ) return rc;
-+    rc = allocatePage(pBt, &pChild, &pgnoChild, sqlitepager_pagenumber(pPage));
-+    if( rc ) return rc;
-+    assert( sqlitepager_iswriteable(pChild) );
-+    copyPage(pChild, pPage);
-+    pChild->pParent = pPage;
-+    pChild->idxParent = 0;
-+    sqlitepager_ref(pPage);
-+    pChild->isOverfull = 1;
-+    if( pCur && pCur->pPage==pPage ){
-+      sqlitepager_unref(pPage);
-+      pCur->pPage = pChild;
-+    }else{
-+      extraUnref = pChild;
-+    }
-+    zeroPage(pBt, pPage);
-+    pPage->u.hdr.rightChild = SWAB32(pBt, pgnoChild);
-+    pParent = pPage;
-+    pPage = pChild;
-+  }
-+  rc = sqlitepager_write(pParent);
-+  if( rc ) return rc;
-+  assert( pParent->isInit );
-+  
-+  /*
-+  ** Find the Cell in the parent page whose h.leftChild points back
-+  ** to pPage.  The "idx" variable is the index of that cell.  If pPage
-+  ** is the rightmost child of pParent then set idx to pParent->nCell 
-+  */
-+  if( pParent->idxShift ){
-+    Pgno pgno, swabPgno;
-+    pgno = sqlitepager_pagenumber(pPage);
-+    swabPgno = SWAB32(pBt, pgno);
-+    for(idx=0; idx<pParent->nCell; idx++){
-+      if( pParent->apCell[idx]->h.leftChild==swabPgno ){
-+        break;
-+      }
-+    }
-+    assert( idx<pParent->nCell || pParent->u.hdr.rightChild==swabPgno );
-+  }else{
-+    idx = pPage->idxParent;
-+  }
-+
-+  /*
-+  ** Initialize variables so that it will be safe to jump
-+  ** directly to balance_cleanup at any moment.
-+  */
-+  nOld = nNew = 0;
-+  sqlitepager_ref(pParent);
-+
-+  /*
-+  ** Find sibling pages to pPage and the Cells in pParent that divide
-+  ** the siblings.  An attempt is made to find NN siblings on either
-+  ** side of pPage.  More siblings are taken from one side, however, if
-+  ** pPage there are fewer than NN siblings on the other side.  If pParent
-+  ** has NB or fewer children then all children of pParent are taken.
-+  */
-+  nxDiv = idx - NN;
-+  if( nxDiv + NB > pParent->nCell ){
-+    nxDiv = pParent->nCell - NB + 1;
-+  }
-+  if( nxDiv<0 ){
-+    nxDiv = 0;
-+  }
-+  nDiv = 0;
-+  for(i=0, k=nxDiv; i<NB; i++, k++){
-+    if( k<pParent->nCell ){
-+      idxDiv[i] = k;
-+      apDiv[i] = pParent->apCell[k];
-+      nDiv++;
-+      pgnoOld[i] = SWAB32(pBt, apDiv[i]->h.leftChild);
-+    }else if( k==pParent->nCell ){
-+      pgnoOld[i] = SWAB32(pBt, pParent->u.hdr.rightChild);
-+    }else{
-+      break;
-+    }
-+    rc = sqlitepager_get(pBt->pPager, pgnoOld[i], (void**)&apOld[i]);
-+    if( rc ) goto balance_cleanup;
-+    rc = initPage(pBt, apOld[i], pgnoOld[i], pParent);
-+    if( rc ) goto balance_cleanup;
-+    apOld[i]->idxParent = k;
-+    nOld++;
-+  }
-+
-+  /*
-+  ** Set iCur to be the index in apCell[] of the cell that the cursor
-+  ** is pointing to.  We will need this later on in order to keep the
-+  ** cursor pointing at the same cell.  If pCur points to a page that
-+  ** has no involvement with this rebalancing, then set iCur to a large
-+  ** number so that the iCur==j tests always fail in the main cell
-+  ** distribution loop below.
-+  */
-+  if( pCur ){
-+    iCur = 0;
-+    for(i=0; i<nOld; i++){
-+      if( pCur->pPage==apOld[i] ){
-+        iCur += pCur->idx;
-+        break;
-+      }
-+      iCur += apOld[i]->nCell;
-+      if( i<nOld-1 && pCur->pPage==pParent && pCur->idx==idxDiv[i] ){
-+        break;
-+      }
-+      iCur++;
-+    }
-+    pOldCurPage = pCur->pPage;
-+  }
-+
-+  /*
-+  ** Make copies of the content of pPage and its siblings into aOld[].
-+  ** The rest of this function will use data from the copies rather
-+  ** that the original pages since the original pages will be in the
-+  ** process of being overwritten.
-+  */
-+  for(i=0; i<nOld; i++){
-+    copyPage(&aOld[i], apOld[i]);
-+  }
-+
-+  /*
-+  ** Load pointers to all cells on sibling pages and the divider cells
-+  ** into the local apCell[] array.  Make copies of the divider cells
-+  ** into aTemp[] and remove the the divider Cells from pParent.
-+  */
-+  nCell = 0;
-+  for(i=0; i<nOld; i++){
-+    MemPage *pOld = &aOld[i];
-+    for(j=0; j<pOld->nCell; j++){
-+      apCell[nCell] = pOld->apCell[j];
-+      szCell[nCell] = cellSize(pBt, apCell[nCell]);
-+      nCell++;
-+    }
-+    if( i<nOld-1 ){
-+      szCell[nCell] = cellSize(pBt, apDiv[i]);
-+      memcpy(&aTemp[i], apDiv[i], szCell[nCell]);
-+      apCell[nCell] = &aTemp[i];
-+      dropCell(pBt, pParent, nxDiv, szCell[nCell]);
-+      assert( SWAB32(pBt, apCell[nCell]->h.leftChild)==pgnoOld[i] );
-+      apCell[nCell]->h.leftChild = pOld->u.hdr.rightChild;
-+      nCell++;
-+    }
-+  }
-+
-+  /*
-+  ** Figure out the number of pages needed to hold all nCell cells.
-+  ** Store this number in "k".  Also compute szNew[] which is the total
-+  ** size of all cells on the i-th page and cntNew[] which is the index
-+  ** in apCell[] of the cell that divides path i from path i+1.  
-+  ** cntNew[k] should equal nCell.
-+  **
-+  ** This little patch of code is critical for keeping the tree
-+  ** balanced. 
-+  */
-+  for(subtotal=k=i=0; i<nCell; i++){
-+    subtotal += szCell[i];
-+    if( subtotal > USABLE_SPACE ){
-+      szNew[k] = subtotal - szCell[i];
-+      cntNew[k] = i;
-+      subtotal = 0;
-+      k++;
-+    }
-+  }
-+  szNew[k] = subtotal;
-+  cntNew[k] = nCell;
-+  k++;
-+  for(i=k-1; i>0; i--){
-+    while( szNew[i]<USABLE_SPACE/2 ){
-+      cntNew[i-1]--;
-+      assert( cntNew[i-1]>0 );
-+      szNew[i] += szCell[cntNew[i-1]];
-+      szNew[i-1] -= szCell[cntNew[i-1]-1];
-+    }
-+  }
-+  assert( cntNew[0]>0 );
-+
-+  /*
-+  ** Allocate k new pages.  Reuse old pages where possible.
-+  */
-+  for(i=0; i<k; i++){
-+    if( i<nOld ){
-+      apNew[i] = apOld[i];
-+      pgnoNew[i] = pgnoOld[i];
-+      apOld[i] = 0;
-+      sqlitepager_write(apNew[i]);
-+    }else{
-+      rc = allocatePage(pBt, &apNew[i], &pgnoNew[i], pgnoNew[i-1]);
-+      if( rc ) goto balance_cleanup;
-+    }
-+    nNew++;
-+    zeroPage(pBt, apNew[i]);
-+    apNew[i]->isInit = 1;
-+  }
-+
-+  /* Free any old pages that were not reused as new pages.
-+  */
-+  while( i<nOld ){
-+    rc = freePage(pBt, apOld[i], pgnoOld[i]);
-+    if( rc ) goto balance_cleanup;
-+    sqlitepager_unref(apOld[i]);
-+    apOld[i] = 0;
-+    i++;
-+  }
-+
-+  /*
-+  ** Put the new pages in accending order.  This helps to
-+  ** keep entries in the disk file in order so that a scan
-+  ** of the table is a linear scan through the file.  That
-+  ** in turn helps the operating system to deliver pages
-+  ** from the disk more rapidly.
-+  **
-+  ** An O(n^2) insertion sort algorithm is used, but since
-+  ** n is never more than NB (a small constant), that should
-+  ** not be a problem.
-+  **
-+  ** When NB==3, this one optimization makes the database
-+  ** about 25% faster for large insertions and deletions.
-+  */
-+  for(i=0; i<k-1; i++){
-+    int minV = pgnoNew[i];
-+    int minI = i;
-+    for(j=i+1; j<k; j++){
-+      if( pgnoNew[j]<(unsigned)minV ){
-+        minI = j;
-+        minV = pgnoNew[j];
-+      }
-+    }
-+    if( minI>i ){
-+      int t;
-+      MemPage *pT;
-+      t = pgnoNew[i];
-+      pT = apNew[i];
-+      pgnoNew[i] = pgnoNew[minI];
-+      apNew[i] = apNew[minI];
-+      pgnoNew[minI] = t;
-+      apNew[minI] = pT;
-+    }
-+  }
-+
-+  /*
-+  ** Evenly distribute the data in apCell[] across the new pages.
-+  ** Insert divider cells into pParent as necessary.
-+  */
-+  j = 0;
-+  for(i=0; i<nNew; i++){
-+    MemPage *pNew = apNew[i];
-+    while( j<cntNew[i] ){
-+      assert( pNew->nFree>=szCell[j] );
-+      if( pCur && iCur==j ){ pCur->pPage = pNew; pCur->idx = pNew->nCell; }
-+      insertCell(pBt, pNew, pNew->nCell, apCell[j], szCell[j]);
-+      j++;
-+    }
-+    assert( pNew->nCell>0 );
-+    assert( !pNew->isOverfull );
-+    relinkCellList(pBt, pNew);
-+    if( i<nNew-1 && j<nCell ){
-+      pNew->u.hdr.rightChild = apCell[j]->h.leftChild;
-+      apCell[j]->h.leftChild = SWAB32(pBt, pgnoNew[i]);
-+      if( pCur && iCur==j ){ pCur->pPage = pParent; pCur->idx = nxDiv; }
-+      insertCell(pBt, pParent, nxDiv, apCell[j], szCell[j]);
-+      j++;
-+      nxDiv++;
-+    }
-+  }
-+  assert( j==nCell );
-+  apNew[nNew-1]->u.hdr.rightChild = aOld[nOld-1].u.hdr.rightChild;
-+  if( nxDiv==pParent->nCell ){
-+    pParent->u.hdr.rightChild = SWAB32(pBt, pgnoNew[nNew-1]);
-+  }else{
-+    pParent->apCell[nxDiv]->h.leftChild = SWAB32(pBt, pgnoNew[nNew-1]);
-+  }
-+  if( pCur ){
-+    if( j<=iCur && pCur->pPage==pParent && pCur->idx>idxDiv[nOld-1] ){
-+      assert( pCur->pPage==pOldCurPage );
-+      pCur->idx += nNew - nOld;
-+    }else{
-+      assert( pOldCurPage!=0 );
-+      sqlitepager_ref(pCur->pPage);
-+      sqlitepager_unref(pOldCurPage);
-+    }
-+  }
-+
-+  /*
-+  ** Reparent children of all cells.
-+  */
-+  for(i=0; i<nNew; i++){
-+    reparentChildPages(pBt, apNew[i]);
-+  }
-+  reparentChildPages(pBt, pParent);
-+
-+  /*
-+  ** balance the parent page.
-+  */
-+  rc = balance(pBt, pParent, pCur);
-+
-+  /*
-+  ** Cleanup before returning.
-+  */
-+balance_cleanup:
-+  if( extraUnref ){
-+    sqlitepager_unref(extraUnref);
-+  }
-+  for(i=0; i<nOld; i++){
-+    if( apOld[i]!=0 && apOld[i]!=&aOld[i] ) sqlitepager_unref(apOld[i]);
-+  }
-+  for(i=0; i<nNew; i++){
-+    sqlitepager_unref(apNew[i]);
-+  }
-+  if( pCur && pCur->pPage==0 ){
-+    pCur->pPage = pParent;
-+    pCur->idx = 0;
-+  }else{
-+    sqlitepager_unref(pParent);
-+  }
-+  return rc;
-+}
-+
-+/*
-+** This routine checks all cursors that point to the same table
-+** as pCur points to.  If any of those cursors were opened with
-+** wrFlag==0 then this routine returns SQLITE_LOCKED.  If all
-+** cursors point to the same table were opened with wrFlag==1
-+** then this routine returns SQLITE_OK.
-+**
-+** In addition to checking for read-locks (where a read-lock 
-+** means a cursor opened with wrFlag==0) this routine also moves
-+** all cursors other than pCur so that they are pointing to the 
-+** first Cell on root page.  This is necessary because an insert 
-+** or delete might change the number of cells on a page or delete
-+** a page entirely and we do not want to leave any cursors 
-+** pointing to non-existant pages or cells.
-+*/
-+static int checkReadLocks(BtCursor *pCur){
-+  BtCursor *p;
-+  assert( pCur->wrFlag );
-+  for(p=pCur->pShared; p!=pCur; p=p->pShared){
-+    assert( p );
-+    assert( p->pgnoRoot==pCur->pgnoRoot );
-+    if( p->wrFlag==0 ) return SQLITE_LOCKED;
-+    if( sqlitepager_pagenumber(p->pPage)!=p->pgnoRoot ){
-+      moveToRoot(p);
-+    }
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Insert a new record into the BTree.  The key is given by (pKey,nKey)
-+** and the data is given by (pData,nData).  The cursor is used only to
-+** define what database the record should be inserted into.  The cursor
-+** is left pointing at the new record.
-+*/
-+static int fileBtreeInsert(
-+  BtCursor *pCur,                /* Insert data into the table of this cursor */
-+  const void *pKey, int nKey,    /* The key of the new record */
-+  const void *pData, int nData   /* The data of the new record */
-+){
-+  Cell newCell;
-+  int rc;
-+  int loc;
-+  int szNew;
-+  MemPage *pPage;
-+  Btree *pBt = pCur->pBt;
-+
-+  if( pCur->pPage==0 ){
-+    return SQLITE_ABORT;  /* A rollback destroyed this cursor */
-+  }
-+  if( !pBt->inTrans || nKey+nData==0 ){
-+    /* Must start a transaction before doing an insert */
-+    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
-+  }
-+  assert( !pBt->readOnly );
-+  if( !pCur->wrFlag ){
-+    return SQLITE_PERM;   /* Cursor not open for writing */
-+  }
-+  if( checkReadLocks(pCur) ){
-+    return SQLITE_LOCKED; /* The table pCur points to has a read lock */
-+  }
-+  rc = fileBtreeMoveto(pCur, pKey, nKey, &loc);
-+  if( rc ) return rc;
-+  pPage = pCur->pPage;
-+  assert( pPage->isInit );
-+  rc = sqlitepager_write(pPage);
-+  if( rc ) return rc;
-+  rc = fillInCell(pBt, &newCell, pKey, nKey, pData, nData);
-+  if( rc ) return rc;
-+  szNew = cellSize(pBt, &newCell);
-+  if( loc==0 ){
-+    newCell.h.leftChild = pPage->apCell[pCur->idx]->h.leftChild;
-+    rc = clearCell(pBt, pPage->apCell[pCur->idx]);
-+    if( rc ) return rc;
-+    dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pPage->apCell[pCur->idx]));
-+  }else if( loc<0 && pPage->nCell>0 ){
-+    assert( pPage->u.hdr.rightChild==0 );  /* Must be a leaf page */
-+    pCur->idx++;
-+  }else{
-+    assert( pPage->u.hdr.rightChild==0 );  /* Must be a leaf page */
-+  }
-+  insertCell(pBt, pPage, pCur->idx, &newCell, szNew);
-+  rc = balance(pCur->pBt, pPage, pCur);
-+  /* sqliteBtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */
-+  /* fflush(stdout); */
-+  pCur->eSkip = SKIP_INVALID;
-+  return rc;
-+}
-+
-+/*
-+** Delete the entry that the cursor is pointing to.
-+**
-+** The cursor is left pointing at either the next or the previous
-+** entry.  If the cursor is left pointing to the next entry, then 
-+** the pCur->eSkip flag is set to SKIP_NEXT which forces the next call to 
-+** sqliteBtreeNext() to be a no-op.  That way, you can always call
-+** sqliteBtreeNext() after a delete and the cursor will be left
-+** pointing to the first entry after the deleted entry.  Similarly,
-+** pCur->eSkip is set to SKIP_PREV is the cursor is left pointing to
-+** the entry prior to the deleted entry so that a subsequent call to
-+** sqliteBtreePrevious() will always leave the cursor pointing at the
-+** entry immediately before the one that was deleted.
-+*/
-+static int fileBtreeDelete(BtCursor *pCur){
-+  MemPage *pPage = pCur->pPage;
-+  Cell *pCell;
-+  int rc;
-+  Pgno pgnoChild;
-+  Btree *pBt = pCur->pBt;
-+
-+  assert( pPage->isInit );
-+  if( pCur->pPage==0 ){
-+    return SQLITE_ABORT;  /* A rollback destroyed this cursor */
-+  }
-+  if( !pBt->inTrans ){
-+    /* Must start a transaction before doing a delete */
-+    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
-+  }
-+  assert( !pBt->readOnly );
-+  if( pCur->idx >= pPage->nCell ){
-+    return SQLITE_ERROR;  /* The cursor is not pointing to anything */
-+  }
-+  if( !pCur->wrFlag ){
-+    return SQLITE_PERM;   /* Did not open this cursor for writing */
-+  }
-+  if( checkReadLocks(pCur) ){
-+    return SQLITE_LOCKED; /* The table pCur points to has a read lock */
-+  }
-+  rc = sqlitepager_write(pPage);
-+  if( rc ) return rc;
-+  pCell = pPage->apCell[pCur->idx];
-+  pgnoChild = SWAB32(pBt, pCell->h.leftChild);
-+  clearCell(pBt, pCell);
-+  if( pgnoChild ){
-+    /*
-+    ** The entry we are about to delete is not a leaf so if we do not
-+    ** do something we will leave a hole on an internal page.
-+    ** We have to fill the hole by moving in a cell from a leaf.  The
-+    ** next Cell after the one to be deleted is guaranteed to exist and
-+    ** to be a leaf so we can use it.
-+    */
-+    BtCursor leafCur;
-+    Cell *pNext;
-+    int szNext;
-+    int notUsed;
-+    getTempCursor(pCur, &leafCur);
-+    rc = fileBtreeNext(&leafCur, &notUsed);
-+    if( rc!=SQLITE_OK ){
-+      if( rc!=SQLITE_NOMEM ) rc = SQLITE_CORRUPT;
-+      return rc;
-+    }
-+    rc = sqlitepager_write(leafCur.pPage);
-+    if( rc ) return rc;
-+    dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell));
-+    pNext = leafCur.pPage->apCell[leafCur.idx];
-+    szNext = cellSize(pBt, pNext);
-+    pNext->h.leftChild = SWAB32(pBt, pgnoChild);
-+    insertCell(pBt, pPage, pCur->idx, pNext, szNext);
-+    rc = balance(pBt, pPage, pCur);
-+    if( rc ) return rc;
-+    pCur->eSkip = SKIP_NEXT;
-+    dropCell(pBt, leafCur.pPage, leafCur.idx, szNext);
-+    rc = balance(pBt, leafCur.pPage, pCur);
-+    releaseTempCursor(&leafCur);
-+  }else{
-+    dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell));
-+    if( pCur->idx>=pPage->nCell ){
-+      pCur->idx = pPage->nCell-1;
-+      if( pCur->idx<0 ){ 
-+        pCur->idx = 0;
-+        pCur->eSkip = SKIP_NEXT;
-+      }else{
-+        pCur->eSkip = SKIP_PREV;
-+      }
-+    }else{
-+      pCur->eSkip = SKIP_NEXT;
-+    }
-+    rc = balance(pBt, pPage, pCur);
-+  }
-+  return rc;
-+}
-+
-+/*
-+** Create a new BTree table.  Write into *piTable the page
-+** number for the root page of the new table.
-+**
-+** In the current implementation, BTree tables and BTree indices are the 
-+** the same.  In the future, we may change this so that BTree tables
-+** are restricted to having a 4-byte integer key and arbitrary data and
-+** BTree indices are restricted to having an arbitrary key and no data.
-+** But for now, this routine also serves to create indices.
-+*/
-+static int fileBtreeCreateTable(Btree *pBt, int *piTable){
-+  MemPage *pRoot;
-+  Pgno pgnoRoot;
-+  int rc;
-+  if( !pBt->inTrans ){
-+    /* Must start a transaction first */
-+    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
-+  }
-+  if( pBt->readOnly ){
-+    return SQLITE_READONLY;
-+  }
-+  rc = allocatePage(pBt, &pRoot, &pgnoRoot, 0);
-+  if( rc ) return rc;
-+  assert( sqlitepager_iswriteable(pRoot) );
-+  zeroPage(pBt, pRoot);
-+  sqlitepager_unref(pRoot);
-+  *piTable = (int)pgnoRoot;
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Erase the given database page and all its children.  Return
-+** the page to the freelist.
-+*/
-+static int clearDatabasePage(Btree *pBt, Pgno pgno, int freePageFlag){
-+  MemPage *pPage;
-+  int rc;
-+  Cell *pCell;
-+  int idx;
-+
-+  rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pPage);
-+  if( rc ) return rc;
-+  rc = sqlitepager_write(pPage);
-+  if( rc ) return rc;
-+  rc = initPage(pBt, pPage, pgno, 0);
-+  if( rc ) return rc;
-+  idx = SWAB16(pBt, pPage->u.hdr.firstCell);
-+  while( idx>0 ){
-+    pCell = (Cell*)&pPage->u.aDisk[idx];
-+    idx = SWAB16(pBt, pCell->h.iNext);
-+    if( pCell->h.leftChild ){
-+      rc = clearDatabasePage(pBt, SWAB32(pBt, pCell->h.leftChild), 1);
-+      if( rc ) return rc;
-+    }
-+    rc = clearCell(pBt, pCell);
-+    if( rc ) return rc;
-+  }
-+  if( pPage->u.hdr.rightChild ){
-+    rc = clearDatabasePage(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
-+    if( rc ) return rc;
-+  }
-+  if( freePageFlag ){
-+    rc = freePage(pBt, pPage, pgno);
-+  }else{
-+    zeroPage(pBt, pPage);
-+  }
-+  sqlitepager_unref(pPage);
-+  return rc;
-+}
-+
-+/*
-+** Delete all information from a single table in the database.
-+*/
-+static int fileBtreeClearTable(Btree *pBt, int iTable){
-+  int rc;
-+  BtCursor *pCur;
-+  if( !pBt->inTrans ){
-+    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
-+  }
-+  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-+    if( pCur->pgnoRoot==(Pgno)iTable ){
-+      if( pCur->wrFlag==0 ) return SQLITE_LOCKED;
-+      moveToRoot(pCur);
-+    }
-+  }
-+  rc = clearDatabasePage(pBt, (Pgno)iTable, 0);
-+  if( rc ){
-+    fileBtreeRollback(pBt);
-+  }
-+  return rc;
-+}
-+
-+/*
-+** Erase all information in a table and add the root of the table to
-+** the freelist.  Except, the root of the principle table (the one on
-+** page 2) is never added to the freelist.
-+*/
-+static int fileBtreeDropTable(Btree *pBt, int iTable){
-+  int rc;
-+  MemPage *pPage;
-+  BtCursor *pCur;
-+  if( !pBt->inTrans ){
-+    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
-+  }
-+  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-+    if( pCur->pgnoRoot==(Pgno)iTable ){
-+      return SQLITE_LOCKED;  /* Cannot drop a table that has a cursor */
-+    }
-+  }
-+  rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, (void**)&pPage);
-+  if( rc ) return rc;
-+  rc = fileBtreeClearTable(pBt, iTable);
-+  if( rc ) return rc;
-+  if( iTable>2 ){
-+    rc = freePage(pBt, pPage, iTable);
-+  }else{
-+    zeroPage(pBt, pPage);
-+  }
-+  sqlitepager_unref(pPage);
-+  return rc;  
-+}
-+
-+#if 0 /* UNTESTED */
-+/*
-+** Copy all cell data from one database file into another.
-+** pages back the freelist.
-+*/
-+static int copyCell(Btree *pBtFrom, BTree *pBtTo, Cell *pCell){
-+  Pager *pFromPager = pBtFrom->pPager;
-+  OverflowPage *pOvfl;
-+  Pgno ovfl, nextOvfl;
-+  Pgno *pPrev;
-+  int rc = SQLITE_OK;
-+  MemPage *pNew, *pPrevPg;
-+  Pgno new;
-+
-+  if( NKEY(pBtTo, pCell->h) + NDATA(pBtTo, pCell->h) <= MX_LOCAL_PAYLOAD ){
-+    return SQLITE_OK;
-+  }
-+  pPrev = &pCell->ovfl;
-+  pPrevPg = 0;
-+  ovfl = SWAB32(pBtTo, pCell->ovfl);
-+  while( ovfl && rc==SQLITE_OK ){
-+    rc = sqlitepager_get(pFromPager, ovfl, (void**)&pOvfl);
-+    if( rc ) return rc;
-+    nextOvfl = SWAB32(pBtFrom, pOvfl->iNext);
-+    rc = allocatePage(pBtTo, &pNew, &new, 0);
-+    if( rc==SQLITE_OK ){
-+      rc = sqlitepager_write(pNew);
-+      if( rc==SQLITE_OK ){
-+        memcpy(pNew, pOvfl, SQLITE_USABLE_SIZE);
-+        *pPrev = SWAB32(pBtTo, new);
-+        if( pPrevPg ){
-+          sqlitepager_unref(pPrevPg);
-+        }
-+        pPrev = &pOvfl->iNext;
-+        pPrevPg = pNew;
-+      }
-+    }
-+    sqlitepager_unref(pOvfl);
-+    ovfl = nextOvfl;
-+  }
-+  if( pPrevPg ){
-+    sqlitepager_unref(pPrevPg);
-+  }
-+  return rc;
-+}
-+#endif
-+
-+
-+#if 0 /* UNTESTED */
-+/*
-+** Copy a page of data from one database over to another.
-+*/
-+static int copyDatabasePage(
-+  Btree *pBtFrom,
-+  Pgno pgnoFrom,
-+  Btree *pBtTo,
-+  Pgno *pTo
-+){
-+  MemPage *pPageFrom, *pPage;
-+  Pgno to;
-+  int rc;
-+  Cell *pCell;
-+  int idx;
-+
-+  rc = sqlitepager_get(pBtFrom->pPager, pgno, (void**)&pPageFrom);
-+  if( rc ) return rc;
-+  rc = allocatePage(pBt, &pPage, pTo, 0);
-+  if( rc==SQLITE_OK ){
-+    rc = sqlitepager_write(pPage);
-+  }
-+  if( rc==SQLITE_OK ){
-+    memcpy(pPage, pPageFrom, SQLITE_USABLE_SIZE);
-+    idx = SWAB16(pBt, pPage->u.hdr.firstCell);
-+    while( idx>0 ){
-+      pCell = (Cell*)&pPage->u.aDisk[idx];
-+      idx = SWAB16(pBt, pCell->h.iNext);
-+      if( pCell->h.leftChild ){
-+        Pgno newChld;
-+        rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pCell->h.leftChild),
-+                              pBtTo, &newChld);
-+        if( rc ) return rc;
-+        pCell->h.leftChild = SWAB32(pBtFrom, newChld);
-+      }
-+      rc = copyCell(pBtFrom, pBtTo, pCell);
-+      if( rc ) return rc;
-+    }
-+    if( pPage->u.hdr.rightChild ){
-+      Pgno newChld;
-+      rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pPage->u.hdr.rightChild), 
-+                            pBtTo, &newChld);
-+      if( rc ) return rc;
-+      pPage->u.hdr.rightChild = SWAB32(pBtTo, newChild);
-+    }
-+  }
-+  sqlitepager_unref(pPage);
-+  return rc;
-+}
-+#endif
-+
-+/*
-+** Read the meta-information out of a database file.
-+*/
-+static int fileBtreeGetMeta(Btree *pBt, int *aMeta){
-+  PageOne *pP1;
-+  int rc;
-+  int i;
-+
-+  rc = sqlitepager_get(pBt->pPager, 1, (void**)&pP1);
-+  if( rc ) return rc;
-+  aMeta[0] = SWAB32(pBt, pP1->nFree);
-+  for(i=0; i<sizeof(pP1->aMeta)/sizeof(pP1->aMeta[0]); i++){
-+    aMeta[i+1] = SWAB32(pBt, pP1->aMeta[i]);
-+  }
-+  sqlitepager_unref(pP1);
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Write meta-information back into the database.
-+*/
-+static int fileBtreeUpdateMeta(Btree *pBt, int *aMeta){
-+  PageOne *pP1;
-+  int rc, i;
-+  if( !pBt->inTrans ){
-+    return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
-+  }
-+  pP1 = pBt->page1;
-+  rc = sqlitepager_write(pP1);
-+  if( rc ) return rc;   
-+  for(i=0; i<sizeof(pP1->aMeta)/sizeof(pP1->aMeta[0]); i++){
-+    pP1->aMeta[i] = SWAB32(pBt, aMeta[i+1]);
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/******************************************************************************
-+** The complete implementation of the BTree subsystem is above this line.
-+** All the code the follows is for testing and troubleshooting the BTree
-+** subsystem.  None of the code that follows is used during normal operation.
-+******************************************************************************/
-+
-+/*
-+** Print a disassembly of the given page on standard output.  This routine
-+** is used for debugging and testing only.
-+*/
-+#ifdef SQLITE_TEST
-+static int fileBtreePageDump(Btree *pBt, int pgno, int recursive){
-+  int rc;
-+  MemPage *pPage;
-+  int i, j;
-+  int nFree;
-+  u16 idx;
-+  char range[20];
-+  unsigned char payload[20];
-+  rc = sqlitepager_get(pBt->pPager, (Pgno)pgno, (void**)&pPage);
-+  if( rc ){
-+    return rc;
-+  }
-+  if( recursive ) printf("PAGE %d:\n", pgno);
-+  i = 0;
-+  idx = SWAB16(pBt, pPage->u.hdr.firstCell);
-+  while( idx>0 && idx<=SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){
-+    Cell *pCell = (Cell*)&pPage->u.aDisk[idx];
-+    int sz = cellSize(pBt, pCell);
-+    sprintf(range,"%d..%d", idx, idx+sz-1);
-+    sz = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h);
-+    if( sz>sizeof(payload)-1 ) sz = sizeof(payload)-1;
-+    memcpy(payload, pCell->aPayload, sz);
-+    for(j=0; j<sz; j++){
-+      if( payload[j]<0x20 || payload[j]>0x7f ) payload[j] = '.';
-+    }
-+    payload[sz] = 0;
-+    printf(
-+      "cell %2d: i=%-10s chld=%-4d nk=%-4d nd=%-4d payload=%s\n",
-+      i, range, (int)pCell->h.leftChild, 
-+      NKEY(pBt, pCell->h), NDATA(pBt, pCell->h),
-+      payload
-+    );
-+    if( pPage->isInit && pPage->apCell[i]!=pCell ){
-+      printf("**** apCell[%d] does not match on prior entry ****\n", i);
-+    }
-+    i++;
-+    idx = SWAB16(pBt, pCell->h.iNext);
-+  }
-+  if( idx!=0 ){
-+    printf("ERROR: next cell index out of range: %d\n", idx);
-+  }
-+  printf("right_child: %d\n", SWAB32(pBt, pPage->u.hdr.rightChild));
-+  nFree = 0;
-+  i = 0;
-+  idx = SWAB16(pBt, pPage->u.hdr.firstFree);
-+  while( idx>0 && idx<SQLITE_USABLE_SIZE ){
-+    FreeBlk *p = (FreeBlk*)&pPage->u.aDisk[idx];
-+    sprintf(range,"%d..%d", idx, idx+p->iSize-1);
-+    nFree += SWAB16(pBt, p->iSize);
-+    printf("freeblock %2d: i=%-10s size=%-4d total=%d\n",
-+       i, range, SWAB16(pBt, p->iSize), nFree);
-+    idx = SWAB16(pBt, p->iNext);
-+    i++;
-+  }
-+  if( idx!=0 ){
-+    printf("ERROR: next freeblock index out of range: %d\n", idx);
-+  }
-+  if( recursive && pPage->u.hdr.rightChild!=0 ){
-+    idx = SWAB16(pBt, pPage->u.hdr.firstCell);
-+    while( idx>0 && idx<SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){
-+      Cell *pCell = (Cell*)&pPage->u.aDisk[idx];
-+      fileBtreePageDump(pBt, SWAB32(pBt, pCell->h.leftChild), 1);
-+      idx = SWAB16(pBt, pCell->h.iNext);
-+    }
-+    fileBtreePageDump(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
-+  }
-+  sqlitepager_unref(pPage);
-+  return SQLITE_OK;
-+}
-+#endif
-+
-+#ifdef SQLITE_TEST
-+/*
-+** Fill aResult[] with information about the entry and page that the
-+** cursor is pointing to.
-+** 
-+**   aResult[0] =  The page number
-+**   aResult[1] =  The entry number
-+**   aResult[2] =  Total number of entries on this page
-+**   aResult[3] =  Size of this entry
-+**   aResult[4] =  Number of free bytes on this page
-+**   aResult[5] =  Number of free blocks on the page
-+**   aResult[6] =  Page number of the left child of this entry
-+**   aResult[7] =  Page number of the right child for the whole page
-+**
-+** This routine is used for testing and debugging only.
-+*/
-+static int fileBtreeCursorDump(BtCursor *pCur, int *aResult){
-+  int cnt, idx;
-+  MemPage *pPage = pCur->pPage;
-+  Btree *pBt = pCur->pBt;
-+  aResult[0] = sqlitepager_pagenumber(pPage);
-+  aResult[1] = pCur->idx;
-+  aResult[2] = pPage->nCell;
-+  if( pCur->idx>=0 && pCur->idx<pPage->nCell ){
-+    aResult[3] = cellSize(pBt, pPage->apCell[pCur->idx]);
-+    aResult[6] = SWAB32(pBt, pPage->apCell[pCur->idx]->h.leftChild);
-+  }else{
-+    aResult[3] = 0;
-+    aResult[6] = 0;
-+  }
-+  aResult[4] = pPage->nFree;
-+  cnt = 0;
-+  idx = SWAB16(pBt, pPage->u.hdr.firstFree);
-+  while( idx>0 && idx<SQLITE_USABLE_SIZE ){
-+    cnt++;
-+    idx = SWAB16(pBt, ((FreeBlk*)&pPage->u.aDisk[idx])->iNext);
-+  }
-+  aResult[5] = cnt;
-+  aResult[7] = SWAB32(pBt, pPage->u.hdr.rightChild);
-+  return SQLITE_OK;
-+}
-+#endif
-+
-+/*
-+** Return the pager associated with a BTree.  This routine is used for
-+** testing and debugging only.
-+*/
-+static Pager *fileBtreePager(Btree *pBt){
-+  return pBt->pPager;
-+}
-+
-+/*
-+** This structure is passed around through all the sanity checking routines
-+** in order to keep track of some global state information.
-+*/
-+typedef struct IntegrityCk IntegrityCk;
-+struct IntegrityCk {
-+  Btree *pBt;    /* The tree being checked out */
-+  Pager *pPager; /* The associated pager.  Also accessible by pBt->pPager */
-+  int nPage;     /* Number of pages in the database */
-+  int *anRef;    /* Number of times each page is referenced */
-+  char *zErrMsg; /* An error message.  NULL of no errors seen. */
-+};
-+
-+/*
-+** Append a message to the error message string.
-+*/
-+static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){
-+  if( pCheck->zErrMsg ){
-+    char *zOld = pCheck->zErrMsg;
-+    pCheck->zErrMsg = 0;
-+    sqliteSetString(&pCheck->zErrMsg, zOld, "\n", zMsg1, zMsg2, (char*)0);
-+    sqliteFree(zOld);
-+  }else{
-+    sqliteSetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0);
-+  }
-+}
-+
-+/*
-+** Add 1 to the reference count for page iPage.  If this is the second
-+** reference to the page, add an error message to pCheck->zErrMsg.
-+** Return 1 if there are 2 ore more references to the page and 0 if
-+** if this is the first reference to the page.
-+**
-+** Also check that the page number is in bounds.
-+*/
-+static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){
-+  if( iPage==0 ) return 1;
-+  if( iPage>pCheck->nPage || iPage<0 ){
-+    char zBuf[100];
-+    sprintf(zBuf, "invalid page number %d", iPage);
-+    checkAppendMsg(pCheck, zContext, zBuf);
-+    return 1;
-+  }
-+  if( pCheck->anRef[iPage]==1 ){
-+    char zBuf[100];
-+    sprintf(zBuf, "2nd reference to page %d", iPage);
-+    checkAppendMsg(pCheck, zContext, zBuf);
-+    return 1;
-+  }
-+  return  (pCheck->anRef[iPage]++)>1;
-+}
-+
-+/*
-+** Check the integrity of the freelist or of an overflow page list.
-+** Verify that the number of pages on the list is N.
-+*/
-+static void checkList(
-+  IntegrityCk *pCheck,  /* Integrity checking context */
-+  int isFreeList,       /* True for a freelist.  False for overflow page list */
-+  int iPage,            /* Page number for first page in the list */
-+  int N,                /* Expected number of pages in the list */
-+  char *zContext        /* Context for error messages */
-+){
-+  int i;
-+  char zMsg[100];
-+  while( N-- > 0 ){
-+    OverflowPage *pOvfl;
-+    if( iPage<1 ){
-+      sprintf(zMsg, "%d pages missing from overflow list", N+1);
-+      checkAppendMsg(pCheck, zContext, zMsg);
-+      break;
-+    }
-+    if( checkRef(pCheck, iPage, zContext) ) break;
-+    if( sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pOvfl) ){
-+      sprintf(zMsg, "failed to get page %d", iPage);
-+      checkAppendMsg(pCheck, zContext, zMsg);
-+      break;
-+    }
-+    if( isFreeList ){
-+      FreelistInfo *pInfo = (FreelistInfo*)pOvfl->aPayload;
-+      int n = SWAB32(pCheck->pBt, pInfo->nFree);
-+      for(i=0; i<n; i++){
-+        checkRef(pCheck, SWAB32(pCheck->pBt, pInfo->aFree[i]), zContext);
-+      }
-+      N -= n;
-+    }
-+    iPage = SWAB32(pCheck->pBt, pOvfl->iNext);
-+    sqlitepager_unref(pOvfl);
-+  }
-+}
-+
-+/*
-+** Return negative if zKey1<zKey2.
-+** Return zero if zKey1==zKey2.
-+** Return positive if zKey1>zKey2.
-+*/
-+static int keyCompare(
-+  const char *zKey1, int nKey1,
-+  const char *zKey2, int nKey2
-+){
-+  int min = nKey1>nKey2 ? nKey2 : nKey1;
-+  int c = memcmp(zKey1, zKey2, min);
-+  if( c==0 ){
-+    c = nKey1 - nKey2;
-+  }
-+  return c;
-+}
-+
-+/*
-+** Do various sanity checks on a single page of a tree.  Return
-+** the tree depth.  Root pages return 0.  Parents of root pages
-+** return 1, and so forth.
-+** 
-+** These checks are done:
-+**
-+**      1.  Make sure that cells and freeblocks do not overlap
-+**          but combine to completely cover the page.
-+**      2.  Make sure cell keys are in order.
-+**      3.  Make sure no key is less than or equal to zLowerBound.
-+**      4.  Make sure no key is greater than or equal to zUpperBound.
-+**      5.  Check the integrity of overflow pages.
-+**      6.  Recursively call checkTreePage on all children.
-+**      7.  Verify that the depth of all children is the same.
-+**      8.  Make sure this page is at least 33% full or else it is
-+**          the root of the tree.
-+*/
-+static int checkTreePage(
-+  IntegrityCk *pCheck,  /* Context for the sanity check */
-+  int iPage,            /* Page number of the page to check */
-+  MemPage *pParent,     /* Parent page */
-+  char *zParentContext, /* Parent context */
-+  char *zLowerBound,    /* All keys should be greater than this, if not NULL */
-+  int nLower,           /* Number of characters in zLowerBound */
-+  char *zUpperBound,    /* All keys should be less than this, if not NULL */
-+  int nUpper            /* Number of characters in zUpperBound */
-+){
-+  MemPage *pPage;
-+  int i, rc, depth, d2, pgno;
-+  char *zKey1, *zKey2;
-+  int nKey1, nKey2;
-+  BtCursor cur;
-+  Btree *pBt;
-+  char zMsg[100];
-+  char zContext[100];
-+  char hit[SQLITE_USABLE_SIZE];
-+
-+  /* Check that the page exists
-+  */
-+  cur.pBt = pBt = pCheck->pBt;
-+  if( iPage==0 ) return 0;
-+  if( checkRef(pCheck, iPage, zParentContext) ) return 0;
-+  sprintf(zContext, "On tree page %d: ", iPage);
-+  if( (rc = sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pPage))!=0 ){
-+    sprintf(zMsg, "unable to get the page. error code=%d", rc);
-+    checkAppendMsg(pCheck, zContext, zMsg);
-+    return 0;
-+  }
-+  if( (rc = initPage(pBt, pPage, (Pgno)iPage, pParent))!=0 ){
-+    sprintf(zMsg, "initPage() returns error code %d", rc);
-+    checkAppendMsg(pCheck, zContext, zMsg);
-+    sqlitepager_unref(pPage);
-+    return 0;
-+  }
-+
-+  /* Check out all the cells.
-+  */
-+  depth = 0;
-+  if( zLowerBound ){
-+    zKey1 = sqliteMalloc( nLower+1 );
-+    memcpy(zKey1, zLowerBound, nLower);
-+    zKey1[nLower] = 0;
-+  }else{
-+    zKey1 = 0;
-+  }
-+  nKey1 = nLower;
-+  cur.pPage = pPage;
-+  for(i=0; i<pPage->nCell; i++){
-+    Cell *pCell = pPage->apCell[i];
-+    int sz;
-+
-+    /* Check payload overflow pages
-+    */
-+    nKey2 = NKEY(pBt, pCell->h);
-+    sz = nKey2 + NDATA(pBt, pCell->h);
-+    sprintf(zContext, "On page %d cell %d: ", iPage, i);
-+    if( sz>MX_LOCAL_PAYLOAD ){
-+      int nPage = (sz - MX_LOCAL_PAYLOAD + OVERFLOW_SIZE - 1)/OVERFLOW_SIZE;
-+      checkList(pCheck, 0, SWAB32(pBt, pCell->ovfl), nPage, zContext);
-+    }
-+
-+    /* Check that keys are in the right order
-+    */
-+    cur.idx = i;
-+    zKey2 = sqliteMallocRaw( nKey2+1 );
-+    getPayload(&cur, 0, nKey2, zKey2);
-+    if( zKey1 && keyCompare(zKey1, nKey1, zKey2, nKey2)>=0 ){
-+      checkAppendMsg(pCheck, zContext, "Key is out of order");
-+    }
-+
-+    /* Check sanity of left child page.
-+    */
-+    pgno = SWAB32(pBt, pCell->h.leftChild);
-+    d2 = checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zKey2,nKey2);
-+    if( i>0 && d2!=depth ){
-+      checkAppendMsg(pCheck, zContext, "Child page depth differs");
-+    }
-+    depth = d2;
-+    sqliteFree(zKey1);
-+    zKey1 = zKey2;
-+    nKey1 = nKey2;
-+  }
-+  pgno = SWAB32(pBt, pPage->u.hdr.rightChild);
-+  sprintf(zContext, "On page %d at right child: ", iPage);
-+  checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zUpperBound,nUpper);
-+  sqliteFree(zKey1);
-+ 
-+  /* Check for complete coverage of the page
-+  */
-+  memset(hit, 0, sizeof(hit));
-+  memset(hit, 1, sizeof(PageHdr));
-+  for(i=SWAB16(pBt, pPage->u.hdr.firstCell); i>0 && i<SQLITE_USABLE_SIZE; ){
-+    Cell *pCell = (Cell*)&pPage->u.aDisk[i];
-+    int j;
-+    for(j=i+cellSize(pBt, pCell)-1; j>=i; j--) hit[j]++;
-+    i = SWAB16(pBt, pCell->h.iNext);
-+  }
-+  for(i=SWAB16(pBt,pPage->u.hdr.firstFree); i>0 && i<SQLITE_USABLE_SIZE; ){
-+    FreeBlk *pFBlk = (FreeBlk*)&pPage->u.aDisk[i];
-+    int j;
-+    for(j=i+SWAB16(pBt,pFBlk->iSize)-1; j>=i; j--) hit[j]++;
-+    i = SWAB16(pBt,pFBlk->iNext);
-+  }
-+  for(i=0; i<SQLITE_USABLE_SIZE; i++){
-+    if( hit[i]==0 ){
-+      sprintf(zMsg, "Unused space at byte %d of page %d", i, iPage);
-+      checkAppendMsg(pCheck, zMsg, 0);
-+      break;
-+    }else if( hit[i]>1 ){
-+      sprintf(zMsg, "Multiple uses for byte %d of page %d", i, iPage);
-+      checkAppendMsg(pCheck, zMsg, 0);
-+      break;
-+    }
-+  }
-+
-+  /* Check that free space is kept to a minimum
-+  */
-+#if 0
-+  if( pParent && pParent->nCell>2 && pPage->nFree>3*SQLITE_USABLE_SIZE/4 ){
-+    sprintf(zMsg, "free space (%d) greater than max (%d)", pPage->nFree,
-+       SQLITE_USABLE_SIZE/3);
-+    checkAppendMsg(pCheck, zContext, zMsg);
-+  }
-+#endif
-+
-+  sqlitepager_unref(pPage);
-+  return depth;
-+}
-+
-+/*
-+** This routine does a complete check of the given BTree file.  aRoot[] is
-+** an array of pages numbers were each page number is the root page of
-+** a table.  nRoot is the number of entries in aRoot.
-+**
-+** If everything checks out, this routine returns NULL.  If something is
-+** amiss, an error message is written into memory obtained from malloc()
-+** and a pointer to that error message is returned.  The calling function
-+** is responsible for freeing the error message when it is done.
-+*/
-+char *fileBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
-+  int i;
-+  int nRef;
-+  IntegrityCk sCheck;
-+
-+  nRef = *sqlitepager_stats(pBt->pPager);
-+  if( lockBtree(pBt)!=SQLITE_OK ){
-+    return sqliteStrDup("Unable to acquire a read lock on the database");
-+  }
-+  sCheck.pBt = pBt;
-+  sCheck.pPager = pBt->pPager;
-+  sCheck.nPage = sqlitepager_pagecount(sCheck.pPager);
-+  if( sCheck.nPage==0 ){
-+    unlockBtreeIfUnused(pBt);
-+    return 0;
-+  }
-+  sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) );
-+  sCheck.anRef[1] = 1;
-+  for(i=2; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; }
-+  sCheck.zErrMsg = 0;
-+
-+  /* Check the integrity of the freelist
-+  */
-+  checkList(&sCheck, 1, SWAB32(pBt, pBt->page1->freeList),
-+            SWAB32(pBt, pBt->page1->nFree), "Main freelist: ");
-+
-+  /* Check all the tables.
-+  */
-+  for(i=0; i<nRoot; i++){
-+    if( aRoot[i]==0 ) continue;
-+    checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ", 0,0,0,0);
-+  }
-+
-+  /* Make sure every page in the file is referenced
-+  */
-+  for(i=1; i<=sCheck.nPage; i++){
-+    if( sCheck.anRef[i]==0 ){
-+      char zBuf[100];
-+      sprintf(zBuf, "Page %d is never used", i);
-+      checkAppendMsg(&sCheck, zBuf, 0);
-+    }
-+  }
-+
-+  /* Make sure this analysis did not leave any unref() pages
-+  */
-+  unlockBtreeIfUnused(pBt);
-+  if( nRef != *sqlitepager_stats(pBt->pPager) ){
-+    char zBuf[100];
-+    sprintf(zBuf, 
-+      "Outstanding page count goes from %d to %d during this analysis",
-+      nRef, *sqlitepager_stats(pBt->pPager)
-+    );
-+    checkAppendMsg(&sCheck, zBuf, 0);
-+  }
-+
-+  /* Clean  up and report errors.
-+  */
-+  sqliteFree(sCheck.anRef);
-+  return sCheck.zErrMsg;
-+}
-+
-+/*
-+** Return the full pathname of the underlying database file.
-+*/
-+static const char *fileBtreeGetFilename(Btree *pBt){
-+  assert( pBt->pPager!=0 );
-+  return sqlitepager_filename(pBt->pPager);
-+}
-+
-+/*
-+** Copy the complete content of pBtFrom into pBtTo.  A transaction
-+** must be active for both files.
-+**
-+** The size of file pBtFrom may be reduced by this operation.
-+** If anything goes wrong, the transaction on pBtFrom is rolled back.
-+*/
-+static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
-+  int rc = SQLITE_OK;
-+  Pgno i, nPage, nToPage;
-+
-+  if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR;
-+  if( pBtTo->needSwab!=pBtFrom->needSwab ) return SQLITE_ERROR;
-+  if( pBtTo->pCursor ) return SQLITE_BUSY;
-+  memcpy(pBtTo->page1, pBtFrom->page1, SQLITE_USABLE_SIZE);
-+  rc = sqlitepager_overwrite(pBtTo->pPager, 1, pBtFrom->page1);
-+  nToPage = sqlitepager_pagecount(pBtTo->pPager);
-+  nPage = sqlitepager_pagecount(pBtFrom->pPager);
-+  for(i=2; rc==SQLITE_OK && i<=nPage; i++){
-+    void *pPage;
-+    rc = sqlitepager_get(pBtFrom->pPager, i, &pPage);
-+    if( rc ) break;
-+    rc = sqlitepager_overwrite(pBtTo->pPager, i, pPage);
-+    if( rc ) break;
-+    sqlitepager_unref(pPage);
-+  }
-+  for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
-+    void *pPage;
-+    rc = sqlitepager_get(pBtTo->pPager, i, &pPage);
-+    if( rc ) break;
-+    rc = sqlitepager_write(pPage);
-+    sqlitepager_unref(pPage);
-+    sqlitepager_dont_write(pBtTo->pPager, i);
-+  }
-+  if( !rc && nPage<nToPage ){
-+    rc = sqlitepager_truncate(pBtTo->pPager, nPage);
-+  }
-+  if( rc ){
-+    fileBtreeRollback(pBtTo);
-+  }
-+  return rc;  
-+}
-+
-+/*
-+** The following tables contain pointers to all of the interface
-+** routines for this implementation of the B*Tree backend.  To
-+** substitute a different implemention of the backend, one has merely
-+** to provide pointers to alternative functions in similar tables.
-+*/
-+static BtOps sqliteBtreeOps = {
-+    fileBtreeClose,
-+    fileBtreeSetCacheSize,
-+    fileBtreeSetSafetyLevel,
-+    fileBtreeBeginTrans,
-+    fileBtreeCommit,
-+    fileBtreeRollback,
-+    fileBtreeBeginCkpt,
-+    fileBtreeCommitCkpt,
-+    fileBtreeRollbackCkpt,
-+    fileBtreeCreateTable,
-+    fileBtreeCreateTable,  /* Really sqliteBtreeCreateIndex() */
-+    fileBtreeDropTable,
-+    fileBtreeClearTable,
-+    fileBtreeCursor,
-+    fileBtreeGetMeta,
-+    fileBtreeUpdateMeta,
-+    fileBtreeIntegrityCheck,
-+    fileBtreeGetFilename,
-+    fileBtreeCopyFile,
-+    fileBtreePager,
-+#ifdef SQLITE_TEST
-+    fileBtreePageDump,
-+#endif
-+};
-+static BtCursorOps sqliteBtreeCursorOps = {
-+    fileBtreeMoveto,
-+    fileBtreeDelete,
-+    fileBtreeInsert,
-+    fileBtreeFirst,
-+    fileBtreeLast,
-+    fileBtreeNext,
-+    fileBtreePrevious,
-+    fileBtreeKeySize,
-+    fileBtreeKey,
-+    fileBtreeKeyCompare,
-+    fileBtreeDataSize,
-+    fileBtreeData,
-+    fileBtreeCloseCursor,
-+#ifdef SQLITE_TEST
-+    fileBtreeCursorDump,
-+#endif
-+};
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/btree.h
-@@ -0,0 +1,156 @@
-+/*
-+** 2001 September 15
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This header file defines the interface that the sqlite B-Tree file
-+** subsystem.  See comments in the source code for a detailed description
-+** of what each interface routine does.
-+**
-+** @(#) $Id$
-+*/
-+#ifndef _BTREE_H_
-+#define _BTREE_H_
-+
-+/*
-+** Forward declarations of structure
-+*/
-+typedef struct Btree Btree;
-+typedef struct BtCursor BtCursor;
-+typedef struct BtOps BtOps;
-+typedef struct BtCursorOps BtCursorOps;
-+
-+
-+/*
-+** An instance of the following structure contains pointers to all
-+** methods against an open BTree.  Alternative BTree implementations
-+** (examples: file based versus in-memory) can be created by substituting
-+** different methods.  Users of the BTree cannot tell the difference.
-+**
-+** In C++ we could do this by defining a virtual base class and then
-+** creating subclasses for each different implementation.  But this is
-+** C not C++ so we have to be a little more explicit.
-+*/
-+struct BtOps {
-+    int (*Close)(Btree*);
-+    int (*SetCacheSize)(Btree*, int);
-+    int (*SetSafetyLevel)(Btree*, int);
-+    int (*BeginTrans)(Btree*);
-+    int (*Commit)(Btree*);
-+    int (*Rollback)(Btree*);
-+    int (*BeginCkpt)(Btree*);
-+    int (*CommitCkpt)(Btree*);
-+    int (*RollbackCkpt)(Btree*);
-+    int (*CreateTable)(Btree*, int*);
-+    int (*CreateIndex)(Btree*, int*);
-+    int (*DropTable)(Btree*, int);
-+    int (*ClearTable)(Btree*, int);
-+    int (*Cursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur);
-+    int (*GetMeta)(Btree*, int*);
-+    int (*UpdateMeta)(Btree*, int*);
-+    char *(*IntegrityCheck)(Btree*, int*, int);
-+    const char *(*GetFilename)(Btree*);
-+    int (*Copyfile)(Btree*,Btree*);
-+    struct Pager *(*Pager)(Btree*);
-+#ifdef SQLITE_TEST
-+    int (*PageDump)(Btree*, int, int);
-+#endif
-+};
-+
-+/*
-+** An instance of this structure defines all of the methods that can
-+** be executed against a cursor.
-+*/
-+struct BtCursorOps {
-+    int (*Moveto)(BtCursor*, const void *pKey, int nKey, int *pRes);
-+    int (*Delete)(BtCursor*);
-+    int (*Insert)(BtCursor*, const void *pKey, int nKey,
-+                             const void *pData, int nData);
-+    int (*First)(BtCursor*, int *pRes);
-+    int (*Last)(BtCursor*, int *pRes);
-+    int (*Next)(BtCursor*, int *pRes);
-+    int (*Previous)(BtCursor*, int *pRes);
-+    int (*KeySize)(BtCursor*, int *pSize);
-+    int (*Key)(BtCursor*, int offset, int amt, char *zBuf);
-+    int (*KeyCompare)(BtCursor*, const void *pKey, int nKey,
-+                                 int nIgnore, int *pRes);
-+    int (*DataSize)(BtCursor*, int *pSize);
-+    int (*Data)(BtCursor*, int offset, int amt, char *zBuf);
-+    int (*CloseCursor)(BtCursor*);
-+#ifdef SQLITE_TEST
-+    int (*CursorDump)(BtCursor*, int*);
-+#endif
-+};
-+
-+/*
-+** The number of 4-byte "meta" values contained on the first page of each
-+** database file.
-+*/
-+#define SQLITE_N_BTREE_META 10
-+
-+int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
-+int sqliteRbtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
-+
-+#define btOps(pBt) (*((BtOps **)(pBt)))
-+#define btCOps(pCur) (*((BtCursorOps **)(pCur)))
-+
-+#define sqliteBtreeClose(pBt)              (btOps(pBt)->Close(pBt))
-+#define sqliteBtreeSetCacheSize(pBt, sz)   (btOps(pBt)->SetCacheSize(pBt, sz))
-+#define sqliteBtreeSetSafetyLevel(pBt, sl) (btOps(pBt)->SetSafetyLevel(pBt, sl))
-+#define sqliteBtreeBeginTrans(pBt)         (btOps(pBt)->BeginTrans(pBt))
-+#define sqliteBtreeCommit(pBt)             (btOps(pBt)->Commit(pBt))
-+#define sqliteBtreeRollback(pBt)           (btOps(pBt)->Rollback(pBt))
-+#define sqliteBtreeBeginCkpt(pBt)          (btOps(pBt)->BeginCkpt(pBt))
-+#define sqliteBtreeCommitCkpt(pBt)         (btOps(pBt)->CommitCkpt(pBt))
-+#define sqliteBtreeRollbackCkpt(pBt)       (btOps(pBt)->RollbackCkpt(pBt))
-+#define sqliteBtreeCreateTable(pBt,piTable)\
-+                (btOps(pBt)->CreateTable(pBt,piTable))
-+#define sqliteBtreeCreateIndex(pBt, piIndex)\
-+                (btOps(pBt)->CreateIndex(pBt, piIndex))
-+#define sqliteBtreeDropTable(pBt, iTable) (btOps(pBt)->DropTable(pBt, iTable))
-+#define sqliteBtreeClearTable(pBt, iTable)\
-+                (btOps(pBt)->ClearTable(pBt, iTable))
-+#define sqliteBtreeCursor(pBt, iTable, wrFlag, ppCur)\
-+                (btOps(pBt)->Cursor(pBt, iTable, wrFlag, ppCur))
-+#define sqliteBtreeMoveto(pCur, pKey, nKey, pRes)\
-+                (btCOps(pCur)->Moveto(pCur, pKey, nKey, pRes))
-+#define sqliteBtreeDelete(pCur)           (btCOps(pCur)->Delete(pCur))
-+#define sqliteBtreeInsert(pCur, pKey, nKey, pData, nData) \
-+                (btCOps(pCur)->Insert(pCur, pKey, nKey, pData, nData))
-+#define sqliteBtreeFirst(pCur, pRes)      (btCOps(pCur)->First(pCur, pRes))
-+#define sqliteBtreeLast(pCur, pRes)       (btCOps(pCur)->Last(pCur, pRes))
-+#define sqliteBtreeNext(pCur, pRes)       (btCOps(pCur)->Next(pCur, pRes))
-+#define sqliteBtreePrevious(pCur, pRes)   (btCOps(pCur)->Previous(pCur, pRes))
-+#define sqliteBtreeKeySize(pCur, pSize)   (btCOps(pCur)->KeySize(pCur, pSize) )
-+#define sqliteBtreeKey(pCur, offset, amt, zBuf)\
-+                (btCOps(pCur)->Key(pCur, offset, amt, zBuf))
-+#define sqliteBtreeKeyCompare(pCur, pKey, nKey, nIgnore, pRes)\
-+                (btCOps(pCur)->KeyCompare(pCur, pKey, nKey, nIgnore, pRes))
-+#define sqliteBtreeDataSize(pCur, pSize)  (btCOps(pCur)->DataSize(pCur, pSize))
-+#define sqliteBtreeData(pCur, offset, amt, zBuf)\
-+                (btCOps(pCur)->Data(pCur, offset, amt, zBuf))
-+#define sqliteBtreeCloseCursor(pCur)      (btCOps(pCur)->CloseCursor(pCur))
-+#define sqliteBtreeGetMeta(pBt, aMeta)    (btOps(pBt)->GetMeta(pBt, aMeta))
-+#define sqliteBtreeUpdateMeta(pBt, aMeta) (btOps(pBt)->UpdateMeta(pBt, aMeta))
-+#define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\
-+                (btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot))
-+#define sqliteBtreeGetFilename(pBt)       (btOps(pBt)->GetFilename(pBt))
-+#define sqliteBtreeCopyFile(pBt1, pBt2)   (btOps(pBt1)->Copyfile(pBt1, pBt2))
-+#define sqliteBtreePager(pBt)             (btOps(pBt)->Pager(pBt))
-+
-+#ifdef SQLITE_TEST
-+#define sqliteBtreePageDump(pBt, pgno, recursive)\
-+                (btOps(pBt)->PageDump(pBt, pgno, recursive))
-+#define sqliteBtreeCursorDump(pCur, aResult)\
-+                (btCOps(pCur)->CursorDump(pCur, aResult))
-+int btree_native_byte_order;
-+#endif /* SQLITE_TEST */
-+
-+
-+#endif /* _BTREE_H_ */
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/btree_rb.c
-@@ -0,0 +1,1488 @@
-+/*
-+** 2003 Feb 4
-+**
-+** 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.
-+**
-+*************************************************************************
-+** $Id$
-+**
-+** This file implements an in-core database using Red-Black balanced
-+** binary trees.
-+** 
-+** It was contributed to SQLite by anonymous on 2003-Feb-04 23:24:49 UTC.
-+*/
-+#include "btree.h"
-+#include "sqliteInt.h"
-+#include <assert.h>
-+
-+/*
-+** Omit this whole file if the SQLITE_OMIT_INMEMORYDB macro is
-+** defined.  This allows a lot of code to be omitted for installations
-+** that do not need it.
-+*/
-+#ifndef SQLITE_OMIT_INMEMORYDB
-+
-+
-+typedef struct BtRbTree BtRbTree;
-+typedef struct BtRbNode BtRbNode;
-+typedef struct BtRollbackOp BtRollbackOp;
-+typedef struct Rbtree Rbtree;
-+typedef struct RbtCursor RbtCursor;
-+
-+/* Forward declarations */
-+static BtOps sqliteRbtreeOps;
-+static BtCursorOps sqliteRbtreeCursorOps;
-+
-+/*
-+ * During each transaction (or checkpoint), a linked-list of
-+ * "rollback-operations" is accumulated. If the transaction is rolled back,
-+ * then the list of operations must be executed (to restore the database to
-+ * it's state before the transaction started). If the transaction is to be
-+ * committed, just delete the list.
-+ *
-+ * Each operation is represented as follows, depending on the value of eOp:
-+ *
-+ * ROLLBACK_INSERT  ->  Need to insert (pKey, pData) into table iTab.
-+ * ROLLBACK_DELETE  ->  Need to delete the record (pKey) into table iTab.
-+ * ROLLBACK_CREATE  ->  Need to create table iTab.
-+ * ROLLBACK_DROP    ->  Need to drop table iTab.
-+ */
-+struct BtRollbackOp {
-+  u8 eOp;
-+  int iTab;
-+  int nKey; 
-+  void *pKey;
-+  int nData;
-+  void *pData;
-+  BtRollbackOp *pNext;
-+};
-+
-+/*
-+** Legal values for BtRollbackOp.eOp:
-+*/
-+#define ROLLBACK_INSERT 1 /* Insert a record */
-+#define ROLLBACK_DELETE 2 /* Delete a record */
-+#define ROLLBACK_CREATE 3 /* Create a table */
-+#define ROLLBACK_DROP   4 /* Drop a table */
-+
-+struct Rbtree {
-+  BtOps *pOps;    /* Function table */
-+  int aMetaData[SQLITE_N_BTREE_META];
-+
-+  int next_idx;   /* next available table index */
-+  Hash tblHash;   /* All created tables, by index */
-+  u8 isAnonymous; /* True if this Rbtree is to be deleted when closed */
-+  u8 eTransState; /* State of this Rbtree wrt transactions */
-+
-+  BtRollbackOp *pTransRollback; 
-+  BtRollbackOp *pCheckRollback;
-+  BtRollbackOp *pCheckRollbackTail;
-+};
-+
-+/*
-+** Legal values for Rbtree.eTransState.
-+*/
-+#define TRANS_NONE           0  /* No transaction is in progress */
-+#define TRANS_INTRANSACTION  1  /* A transaction is in progress */
-+#define TRANS_INCHECKPOINT   2  /* A checkpoint is in progress  */
-+#define TRANS_ROLLBACK       3  /* We are currently rolling back a checkpoint or
-+                                 * transaction. */
-+
-+struct RbtCursor {
-+  BtCursorOps *pOps;        /* Function table */
-+  Rbtree    *pRbtree;
-+  BtRbTree *pTree;
-+  int       iTree;          /* Index of pTree in pRbtree */
-+  BtRbNode *pNode;
-+  RbtCursor *pShared;       /* List of all cursors on the same Rbtree */
-+  u8 eSkip;                 /* Determines if next step operation is a no-op */
-+  u8 wrFlag;                /* True if this cursor is open for writing */
-+};
-+
-+/*
-+** Legal values for RbtCursor.eSkip.
-+*/
-+#define SKIP_NONE     0   /* Always step the cursor */
-+#define SKIP_NEXT     1   /* The next sqliteRbtreeNext() is a no-op */
-+#define SKIP_PREV     2   /* The next sqliteRbtreePrevious() is a no-op */
-+#define SKIP_INVALID  3   /* Calls to Next() and Previous() are invalid */
-+
-+struct BtRbTree {
-+  RbtCursor *pCursors;     /* All cursors pointing to this tree */
-+  BtRbNode *pHead;         /* Head of the tree, or NULL */
-+};
-+
-+struct BtRbNode {
-+  int nKey;
-+  void *pKey;
-+  int nData;
-+  void *pData;
-+  u8 isBlack;        /* true for a black node, 0 for a red node */
-+  BtRbNode *pParent; /* Nodes parent node, NULL for the tree head */
-+  BtRbNode *pLeft;   /* Nodes left child, or NULL */
-+  BtRbNode *pRight;  /* Nodes right child, or NULL */
-+
-+  int nBlackHeight;  /* Only used during the red-black integrity check */
-+};
-+
-+/* Forward declarations */
-+static int memRbtreeMoveto(
-+  RbtCursor* pCur,
-+  const void *pKey,
-+  int nKey,
-+  int *pRes
-+);
-+static int memRbtreeClearTable(Rbtree* tree, int n);
-+static int memRbtreeNext(RbtCursor* pCur, int *pRes);
-+static int memRbtreeLast(RbtCursor* pCur, int *pRes);
-+static int memRbtreePrevious(RbtCursor* pCur, int *pRes);
-+
-+
-+/*
-+** This routine checks all cursors that point to the same table
-+** as pCur points to.  If any of those cursors were opened with
-+** wrFlag==0 then this routine returns SQLITE_LOCKED.  If all
-+** cursors point to the same table were opened with wrFlag==1
-+** then this routine returns SQLITE_OK.
-+**
-+** In addition to checking for read-locks (where a read-lock 
-+** means a cursor opened with wrFlag==0) this routine also NULLs
-+** out the pNode field of all other cursors.
-+** This is necessary because an insert 
-+** or delete might change erase the node out from under
-+** another cursor.
-+*/
-+static int checkReadLocks(RbtCursor *pCur){
-+  RbtCursor *p;
-+  assert( pCur->wrFlag );
-+  for(p=pCur->pTree->pCursors; p; p=p->pShared){
-+    if( p!=pCur ){
-+      if( p->wrFlag==0 ) return SQLITE_LOCKED;
-+      p->pNode = 0;
-+    }
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/*
-+ * The key-compare function for the red-black trees. Returns as follows:
-+ *
-+ * (key1 < key2)             -1
-+ * (key1 == key2)             0 
-+ * (key1 > key2)              1
-+ *
-+ * Keys are compared using memcmp(). If one key is an exact prefix of the
-+ * other, then the shorter key is less than the longer key.
-+ */
-+static int key_compare(void const*pKey1, int nKey1, void const*pKey2, int nKey2)
-+{
-+  int mcmp = memcmp(pKey1, pKey2, (nKey1 <= nKey2)?nKey1:nKey2);
-+  if( mcmp == 0){
-+    if( nKey1 == nKey2 ) return 0;
-+    return ((nKey1 < nKey2)?-1:1);
-+  }
-+  return ((mcmp>0)?1:-1);
-+}
-+
-+/*
-+ * Perform the LEFT-rotate transformation on node X of tree pTree. This
-+ * transform is part of the red-black balancing code.
-+ *
-+ *        |                   |
-+ *        X                   Y
-+ *       / \                 / \
-+ *      a   Y               X   c
-+ *         / \             / \
-+ *        b   c           a   b
-+ *
-+ *      BEFORE              AFTER
-+ */
-+static void leftRotate(BtRbTree *pTree, BtRbNode *pX)
-+{
-+  BtRbNode *pY;
-+  BtRbNode *pb;
-+  pY = pX->pRight;
-+  pb = pY->pLeft;
-+
-+  pY->pParent = pX->pParent;
-+  if( pX->pParent ){
-+    if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY;
-+    else pX->pParent->pRight = pY;
-+  }
-+  pY->pLeft = pX;
-+  pX->pParent = pY;
-+  pX->pRight = pb;
-+  if( pb ) pb->pParent = pX;
-+  if( pTree->pHead == pX ) pTree->pHead = pY;
-+}
-+
-+/*
-+ * Perform the RIGHT-rotate transformation on node X of tree pTree. This
-+ * transform is part of the red-black balancing code.
-+ *
-+ *        |                   |
-+ *        X                   Y
-+ *       / \                 / \
-+ *      Y   c               a   X
-+ *     / \                     / \
-+ *    a   b                   b   c
-+ *
-+ *      BEFORE              AFTER
-+ */
-+static void rightRotate(BtRbTree *pTree, BtRbNode *pX)
-+{
-+  BtRbNode *pY;
-+  BtRbNode *pb;
-+  pY = pX->pLeft;
-+  pb = pY->pRight;
-+
-+  pY->pParent = pX->pParent;
-+  if( pX->pParent ){
-+    if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY;
-+    else pX->pParent->pRight = pY;
-+  }
-+  pY->pRight = pX;
-+  pX->pParent = pY;
-+  pX->pLeft = pb;
-+  if( pb ) pb->pParent = pX;
-+  if( pTree->pHead == pX ) pTree->pHead = pY;
-+}
-+
-+/*
-+ * A string-manipulation helper function for check_redblack_tree(). If (orig ==
-+ * NULL) a copy of val is returned. If (orig != NULL) then a copy of the *
-+ * concatenation of orig and val is returned. The original orig is deleted
-+ * (using sqliteFree()).
-+ */
-+static char *append_val(char * orig, char const * val){
-+  char *z;
-+  if( !orig ){
-+    z = sqliteStrDup( val );
-+  } else{
-+    z = 0;
-+    sqliteSetString(&z, orig, val, (char*)0);
-+    sqliteFree( orig );
-+  }
-+  return z;
-+}
-+
-+/*
-+ * Append a string representation of the entire node to orig and return it.
-+ * This is used to produce debugging information if check_redblack_tree() finds
-+ * a problem with a red-black binary tree.
-+ */
-+static char *append_node(char * orig, BtRbNode *pNode, int indent)
-+{
-+  char buf[128];
-+  int i;
-+
-+  for( i=0; i<indent; i++ ){
-+      orig = append_val(orig, " ");
-+  }
-+
-+  sprintf(buf, "%p", pNode);
-+  orig = append_val(orig, buf);
-+
-+  if( pNode ){
-+    indent += 3;
-+    if( pNode->isBlack ){
-+      orig = append_val(orig, " B \n");
-+    }else{
-+      orig = append_val(orig, " R \n");
-+    }
-+    orig = append_node( orig, pNode->pLeft, indent );
-+    orig = append_node( orig, pNode->pRight, indent );
-+  }else{
-+    orig = append_val(orig, "\n");
-+  }
-+  return orig;
-+}
-+
-+/*
-+ * Print a representation of a node to stdout. This function is only included
-+ * so you can call it from within a debugger if things get really bad.  It
-+ * is not called from anyplace in the code.
-+ */
-+static void print_node(BtRbNode *pNode)
-+{
-+    char * str = append_node(0, pNode, 0);
-+    printf("%s", str);
-+
-+    /* Suppress a warning message about print_node() being unused */
-+    (void)print_node;
-+}
-+
-+/* 
-+ * Check the following properties of the red-black tree:
-+ * (1) - If a node is red, both of it's children are black
-+ * (2) - Each path from a given node to a leaf (NULL) node passes thru the
-+ *       same number of black nodes 
-+ *
-+ * If there is a problem, append a description (using append_val() ) to *msg.
-+ */
-+static void check_redblack_tree(BtRbTree * tree, char ** msg)
-+{
-+  BtRbNode *pNode;
-+
-+  /* 0 -> came from parent 
-+   * 1 -> came from left
-+   * 2 -> came from right */
-+  int prev_step = 0;
-+
-+  pNode = tree->pHead;
-+  while( pNode ){
-+    switch( prev_step ){
-+      case 0:
-+        if( pNode->pLeft ){
-+          pNode = pNode->pLeft;
-+        }else{ 
-+          prev_step = 1;
-+        }
-+        break;
-+      case 1:
-+        if( pNode->pRight ){
-+          pNode = pNode->pRight;
-+          prev_step = 0;
-+        }else{
-+          prev_step = 2;
-+        }
-+        break;
-+      case 2:
-+        /* Check red-black property (1) */
-+        if( !pNode->isBlack &&
-+            ( (pNode->pLeft && !pNode->pLeft->isBlack) ||
-+              (pNode->pRight && !pNode->pRight->isBlack) )
-+          ){
-+          char buf[128];
-+          sprintf(buf, "Red node with red child at %p\n", pNode);
-+          *msg = append_val(*msg, buf);
-+          *msg = append_node(*msg, tree->pHead, 0);
-+          *msg = append_val(*msg, "\n");
-+        }
-+
-+        /* Check red-black property (2) */
-+        { 
-+          int leftHeight = 0;
-+          int rightHeight = 0;
-+          if( pNode->pLeft ){
-+            leftHeight += pNode->pLeft->nBlackHeight;
-+            leftHeight += (pNode->pLeft->isBlack?1:0);
-+          }
-+          if( pNode->pRight ){
-+            rightHeight += pNode->pRight->nBlackHeight;
-+            rightHeight += (pNode->pRight->isBlack?1:0);
-+          }
-+          if( leftHeight != rightHeight ){
-+            char buf[128];
-+            sprintf(buf, "Different black-heights at %p\n", pNode);
-+            *msg = append_val(*msg, buf);
-+            *msg = append_node(*msg, tree->pHead, 0);
-+            *msg = append_val(*msg, "\n");
-+          }
-+          pNode->nBlackHeight = leftHeight;
-+        }
-+
-+        if( pNode->pParent ){
-+          if( pNode == pNode->pParent->pLeft ) prev_step = 1;
-+          else prev_step = 2;
-+        }
-+        pNode = pNode->pParent;
-+        break;
-+      default: assert(0);
-+    }
-+  }
-+} 
-+
-+/*
-+ * Node pX has just been inserted into pTree (by code in sqliteRbtreeInsert()).
-+ * It is possible that pX is a red node with a red parent, which is a violation
-+ * of the red-black tree properties. This function performs rotations and 
-+ * color changes to rebalance the tree
-+ */
-+static void do_insert_balancing(BtRbTree *pTree, BtRbNode *pX)
-+{
-+  /* In the first iteration of this loop, pX points to the red node just
-+   * inserted in the tree. If the parent of pX exists (pX is not the root
-+   * node) and is red, then the properties of the red-black tree are
-+   * violated.
-+   *
-+   * At the start of any subsequent iterations, pX points to a red node
-+   * with a red parent. In all other respects the tree is a legal red-black
-+   * binary tree. */
-+  while( pX != pTree->pHead && !pX->pParent->isBlack ){
-+    BtRbNode *pUncle;
-+    BtRbNode *pGrandparent;
-+
-+    /* Grandparent of pX must exist and must be black. */
-+    pGrandparent = pX->pParent->pParent;
-+    assert( pGrandparent );
-+    assert( pGrandparent->isBlack );
-+
-+    /* Uncle of pX may or may not exist. */
-+    if( pX->pParent == pGrandparent->pLeft ) 
-+      pUncle = pGrandparent->pRight;
-+    else 
-+      pUncle = pGrandparent->pLeft;
-+
-+    /* If the uncle of pX exists and is red, we do the following:
-+     *       |                 |
-+     *      G(b)              G(r)
-+     *      /  \              /  \        
-+     *   U(r)   P(r)       U(b)  P(b)
-+     *            \                \
-+     *           X(r)              X(r)
-+     *
-+     *     BEFORE             AFTER
-+     * pX is then set to G. If the parent of G is red, then the while loop
-+     * will run again.  */
-+    if( pUncle && !pUncle->isBlack ){
-+      pGrandparent->isBlack = 0;
-+      pUncle->isBlack = 1;
-+      pX->pParent->isBlack = 1;
-+      pX = pGrandparent;
-+    }else{
-+
-+      if( pX->pParent == pGrandparent->pLeft ){
-+        if( pX == pX->pParent->pRight ){
-+          /* If pX is a right-child, do the following transform, essentially
-+           * to change pX into a left-child: 
-+           *       |                  | 
-+           *      G(b)               G(b)
-+           *      /  \               /  \        
-+           *   P(r)   U(b)        X(r)  U(b)
-+           *      \                /
-+           *     X(r)            P(r) <-- new X
-+           *
-+           *     BEFORE             AFTER
-+           */
-+          pX = pX->pParent;
-+          leftRotate(pTree, pX);
-+        }
-+
-+        /* Do the following transform, which balances the tree :) 
-+         *       |                  | 
-+         *      G(b)               P(b)
-+         *      /  \               /  \        
-+         *   P(r)   U(b)        X(r)  G(r)
-+         *    /                         \
-+         *  X(r)                        U(b)
-+         *
-+         *     BEFORE             AFTER
-+         */
-+        assert( pGrandparent == pX->pParent->pParent );
-+        pGrandparent->isBlack = 0;
-+        pX->pParent->isBlack = 1;
-+        rightRotate( pTree, pGrandparent );
-+
-+      }else{
-+        /* This code is symetric to the illustrated case above. */
-+        if( pX == pX->pParent->pLeft ){
-+          pX = pX->pParent;
-+          rightRotate(pTree, pX);
-+        }
-+        assert( pGrandparent == pX->pParent->pParent );
-+        pGrandparent->isBlack = 0;
-+        pX->pParent->isBlack = 1;
-+        leftRotate( pTree, pGrandparent );
-+      }
-+    }
-+  }
-+  pTree->pHead->isBlack = 1;
-+}
-+
-+/*
-+ * A child of pParent, which in turn had child pX, has just been removed from 
-+ * pTree (the figure below depicts the operation, Z is being removed). pParent
-+ * or pX, or both may be NULL.  
-+ *                |           |
-+ *                P           P
-+ *               / \         / \
-+ *              Z           X
-+ *             / \
-+ *            X  nil
-+ *
-+ * This function is only called if Z was black. In this case the red-black tree
-+ * properties have been violated, and pX has an "extra black". This function 
-+ * performs rotations and color-changes to re-balance the tree.
-+ */
-+static 
-+void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent)
-+{
-+  BtRbNode *pSib; 
-+
-+  /* TODO: Comment this code! */
-+  while( pX != pTree->pHead && (!pX || pX->isBlack) ){
-+    if( pX == pParent->pLeft ){
-+      pSib = pParent->pRight;
-+      if( pSib && !(pSib->isBlack) ){
-+        pSib->isBlack = 1;
-+        pParent->isBlack = 0;
-+        leftRotate(pTree, pParent);
-+        pSib = pParent->pRight;
-+      }
-+      if( !pSib ){
-+        pX = pParent;
-+      }else if( 
-+          (!pSib->pLeft  || pSib->pLeft->isBlack) &&
-+          (!pSib->pRight || pSib->pRight->isBlack) ) {
-+        pSib->isBlack = 0;
-+        pX = pParent;
-+      }else{
-+        if( (!pSib->pRight || pSib->pRight->isBlack) ){
-+          if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
-+          pSib->isBlack = 0;
-+          rightRotate( pTree, pSib );
-+          pSib = pParent->pRight;
-+        }
-+        pSib->isBlack = pParent->isBlack;
-+        pParent->isBlack = 1;
-+        if( pSib->pRight ) pSib->pRight->isBlack = 1;
-+        leftRotate(pTree, pParent);
-+        pX = pTree->pHead;
-+      }
-+    }else{
-+      pSib = pParent->pLeft;
-+      if( pSib && !(pSib->isBlack) ){
-+        pSib->isBlack = 1;
-+        pParent->isBlack = 0;
-+        rightRotate(pTree, pParent);
-+        pSib = pParent->pLeft;
-+      }
-+      if( !pSib ){
-+        pX = pParent;
-+      }else if( 
-+          (!pSib->pLeft  || pSib->pLeft->isBlack) &&
-+          (!pSib->pRight || pSib->pRight->isBlack) ){
-+        pSib->isBlack = 0;
-+        pX = pParent;
-+      }else{
-+        if( (!pSib->pLeft || pSib->pLeft->isBlack) ){
-+          if( pSib->pRight ) pSib->pRight->isBlack = 1;
-+          pSib->isBlack = 0;
-+          leftRotate( pTree, pSib );
-+          pSib = pParent->pLeft;
-+        }
-+        pSib->isBlack = pParent->isBlack;
-+        pParent->isBlack = 1;
-+        if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
-+        rightRotate(pTree, pParent);
-+        pX = pTree->pHead;
-+      }
-+    }
-+    pParent = pX->pParent;
-+  }
-+  if( pX ) pX->isBlack = 1;
-+}
-+
-+/*
-+ * Create table n in tree pRbtree. Table n must not exist.
-+ */
-+static void btreeCreateTable(Rbtree* pRbtree, int n)
-+{
-+  BtRbTree *pNewTbl = sqliteMalloc(sizeof(BtRbTree));
-+  sqliteHashInsert(&pRbtree->tblHash, 0, n, pNewTbl);
-+}
-+
-+/*
-+ * Log a single "rollback-op" for the given Rbtree. See comments for struct
-+ * BtRollbackOp.
-+ */
-+static void btreeLogRollbackOp(Rbtree* pRbtree, BtRollbackOp *pRollbackOp)
-+{
-+  assert( pRbtree->eTransState == TRANS_INCHECKPOINT ||
-+      pRbtree->eTransState == TRANS_INTRANSACTION );
-+  if( pRbtree->eTransState == TRANS_INTRANSACTION ){
-+    pRollbackOp->pNext = pRbtree->pTransRollback;
-+    pRbtree->pTransRollback = pRollbackOp;
-+  }
-+  if( pRbtree->eTransState == TRANS_INCHECKPOINT ){
-+    if( !pRbtree->pCheckRollback ){
-+      pRbtree->pCheckRollbackTail = pRollbackOp;
-+    }
-+    pRollbackOp->pNext = pRbtree->pCheckRollback;
-+    pRbtree->pCheckRollback = pRollbackOp;
-+  }
-+}
-+
-+int sqliteRbtreeOpen(
-+  const char *zFilename,
-+  int mode,
-+  int nPg,
-+  Btree **ppBtree
-+){
-+  Rbtree **ppRbtree = (Rbtree**)ppBtree;
-+  *ppRbtree = (Rbtree *)sqliteMalloc(sizeof(Rbtree));
-+  if( sqlite_malloc_failed ) goto open_no_mem;
-+  sqliteHashInit(&(*ppRbtree)->tblHash, SQLITE_HASH_INT, 0);
-+
-+  /* Create a binary tree for the SQLITE_MASTER table at location 2 */
-+  btreeCreateTable(*ppRbtree, 2);
-+  if( sqlite_malloc_failed ) goto open_no_mem;
-+  (*ppRbtree)->next_idx = 3;
-+  (*ppRbtree)->pOps = &sqliteRbtreeOps;
-+  /* Set file type to 4; this is so that "attach ':memory:' as ...."  does not
-+  ** think that the database in uninitialised and refuse to attach
-+  */
-+  (*ppRbtree)->aMetaData[2] = 4;
-+  
-+  return SQLITE_OK;
-+
-+open_no_mem:
-+  *ppBtree = 0;
-+  return SQLITE_NOMEM;
-+}
-+
-+/*
-+ * Create a new table in the supplied Rbtree. Set *n to the new table number.
-+ * Return SQLITE_OK if the operation is a success.
-+ */
-+static int memRbtreeCreateTable(Rbtree* tree, int* n)
-+{
-+  assert( tree->eTransState != TRANS_NONE );
-+
-+  *n = tree->next_idx++;
-+  btreeCreateTable(tree, *n);
-+  if( sqlite_malloc_failed ) return SQLITE_NOMEM;
-+
-+  /* Set up the rollback structure (if we are not doing this as part of a
-+   * rollback) */
-+  if( tree->eTransState != TRANS_ROLLBACK ){
-+    BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
-+    if( pRollbackOp==0 ) return SQLITE_NOMEM;
-+    pRollbackOp->eOp = ROLLBACK_DROP;
-+    pRollbackOp->iTab = *n;
-+    btreeLogRollbackOp(tree, pRollbackOp);
-+  }
-+
-+  return SQLITE_OK;
-+}
-+
-+/*
-+ * Delete table n from the supplied Rbtree. 
-+ */
-+static int memRbtreeDropTable(Rbtree* tree, int n)
-+{
-+  BtRbTree *pTree;
-+  assert( tree->eTransState != TRANS_NONE );
-+
-+  memRbtreeClearTable(tree, n);
-+  pTree = sqliteHashInsert(&tree->tblHash, 0, n, 0);
-+  assert(pTree);
-+  assert( pTree->pCursors==0 );
-+  sqliteFree(pTree);
-+
-+  if( tree->eTransState != TRANS_ROLLBACK ){
-+    BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
-+    if( pRollbackOp==0 ) return SQLITE_NOMEM;
-+    pRollbackOp->eOp = ROLLBACK_CREATE;
-+    pRollbackOp->iTab = n;
-+    btreeLogRollbackOp(tree, pRollbackOp);
-+  }
-+
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeKeyCompare(RbtCursor* pCur, const void *pKey, int nKey,
-+                                 int nIgnore, int *pRes)
-+{
-+  assert(pCur);
-+
-+  if( !pCur->pNode ) {
-+    *pRes = -1;
-+  } else {
-+    if( (pCur->pNode->nKey - nIgnore) < 0 ){
-+      *pRes = -1;
-+    }else{
-+      *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey-nIgnore, 
-+          pKey, nKey);
-+    }
-+  }
-+  return SQLITE_OK;
-+}
-+
-+/*
-+ * Get a new cursor for table iTable of the supplied Rbtree. The wrFlag
-+ * parameter indicates that the cursor is open for writing.
-+ *
-+ * Note that RbtCursor.eSkip and RbtCursor.pNode both initialize to 0.
-+ */
-+static int memRbtreeCursor(
-+  Rbtree* tree,
-+  int iTable,
-+  int wrFlag,
-+  RbtCursor **ppCur
-+){
-+  RbtCursor *pCur;
-+  assert(tree);
-+  pCur = *ppCur = sqliteMalloc(sizeof(RbtCursor));
-+  if( sqlite_malloc_failed ) return SQLITE_NOMEM;
-+  pCur->pTree  = sqliteHashFind(&tree->tblHash, 0, iTable);
-+  assert( pCur->pTree );
-+  pCur->pRbtree = tree;
-+  pCur->iTree  = iTable;
-+  pCur->pOps = &sqliteRbtreeCursorOps;
-+  pCur->wrFlag = wrFlag;
-+  pCur->pShared = pCur->pTree->pCursors;
-+  pCur->pTree->pCursors = pCur;
-+
-+  assert( (*ppCur)->pTree );
-+  return SQLITE_OK;
-+}
-+
-+/*
-+ * Insert a new record into the Rbtree.  The key is given by (pKey,nKey)
-+ * and the data is given by (pData,nData).  The cursor is used only to
-+ * define what database the record should be inserted into.  The cursor
-+ * is left pointing at the new record.
-+ *
-+ * If the key exists already in the tree, just replace the data. 
-+ */
-+static int memRbtreeInsert(
-+  RbtCursor* pCur,
-+  const void *pKey,
-+  int nKey,
-+  const void *pDataInput,
-+  int nData
-+){
-+  void * pData;
-+  int match;
-+
-+  /* It is illegal to call sqliteRbtreeInsert() if we are
-+  ** not in a transaction */
-+  assert( pCur->pRbtree->eTransState != TRANS_NONE );
-+
-+  /* Make sure some other cursor isn't trying to read this same table */
-+  if( checkReadLocks(pCur) ){
-+    return SQLITE_LOCKED; /* The table pCur points to has a read lock */
-+  }
-+
-+  /* Take a copy of the input data now, in case we need it for the 
-+   * replace case */
-+  pData = sqliteMallocRaw(nData);
-+  if( sqlite_malloc_failed ) return SQLITE_NOMEM;
-+  memcpy(pData, pDataInput, nData);
-+
-+  /* Move the cursor to a node near the key to be inserted. If the key already
-+   * exists in the table, then (match == 0). In this case we can just replace
-+   * the data associated with the entry, we don't need to manipulate the tree.
-+   * 
-+   * If there is no exact match, then the cursor points at what would be either
-+   * the predecessor (match == -1) or successor (match == 1) of the
-+   * searched-for key, were it to be inserted. The new node becomes a child of
-+   * this node.
-+   * 
-+   * The new node is initially red.
-+   */
-+  memRbtreeMoveto( pCur, pKey, nKey, &match);
-+  if( match ){
-+    BtRbNode *pNode = sqliteMalloc(sizeof(BtRbNode));
-+    if( pNode==0 ) return SQLITE_NOMEM;
-+    pNode->nKey = nKey;
-+    pNode->pKey = sqliteMallocRaw(nKey);
-+    if( sqlite_malloc_failed ) return SQLITE_NOMEM;
-+    memcpy(pNode->pKey, pKey, nKey);
-+    pNode->nData = nData;
-+    pNode->pData = pData; 
-+    if( pCur->pNode ){
-+      switch( match ){
-+        case -1:
-+          assert( !pCur->pNode->pRight );
-+          pNode->pParent = pCur->pNode;
-+          pCur->pNode->pRight = pNode;
-+          break;
-+        case 1:
-+          assert( !pCur->pNode->pLeft );
-+          pNode->pParent = pCur->pNode;
-+          pCur->pNode->pLeft = pNode;
-+          break;
-+        default:
-+          assert(0);
-+      }
-+    }else{
-+      pCur->pTree->pHead = pNode;
-+    }
-+
-+    /* Point the cursor at the node just inserted, as per SQLite requirements */
-+    pCur->pNode = pNode;
-+
-+    /* A new node has just been inserted, so run the balancing code */
-+    do_insert_balancing(pCur->pTree, pNode);
-+
-+    /* Set up a rollback-op in case we have to roll this operation back */
-+    if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
-+      BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
-+      if( pOp==0 ) return SQLITE_NOMEM;
-+      pOp->eOp = ROLLBACK_DELETE;
-+      pOp->iTab = pCur->iTree;
-+      pOp->nKey = pNode->nKey;
-+      pOp->pKey = sqliteMallocRaw( pOp->nKey );
-+      if( sqlite_malloc_failed ) return SQLITE_NOMEM;
-+      memcpy( pOp->pKey, pNode->pKey, pOp->nKey );
-+      btreeLogRollbackOp(pCur->pRbtree, pOp);
-+    }
-+
-+  }else{ 
-+    /* No need to insert a new node in the tree, as the key already exists.
-+     * Just clobber the current nodes data. */
-+
-+    /* Set up a rollback-op in case we have to roll this operation back */
-+    if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
-+      BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
-+      if( pOp==0 ) return SQLITE_NOMEM;
-+      pOp->iTab = pCur->iTree;
-+      pOp->nKey = pCur->pNode->nKey;
-+      pOp->pKey = sqliteMallocRaw( pOp->nKey );
-+      if( sqlite_malloc_failed ) return SQLITE_NOMEM;
-+      memcpy( pOp->pKey, pCur->pNode->pKey, pOp->nKey );
-+      pOp->nData = pCur->pNode->nData;
-+      pOp->pData = pCur->pNode->pData;
-+      pOp->eOp = ROLLBACK_INSERT;
-+      btreeLogRollbackOp(pCur->pRbtree, pOp);
-+    }else{
-+      sqliteFree( pCur->pNode->pData );
-+    }
-+
-+    /* Actually clobber the nodes data */
-+    pCur->pNode->pData = pData;
-+    pCur->pNode->nData = nData;
-+  }
-+
-+  return SQLITE_OK;
-+}
-+
-+/* Move the cursor so that it points to an entry near pKey.
-+** Return a success code.
-+**
-+**     *pRes<0      The cursor is left pointing at an entry that
-+**                  is smaller than pKey or if the table is empty
-+**                  and the cursor is therefore left point to nothing.
-+**
-+**     *pRes==0     The cursor is left pointing at an entry that
-+**                  exactly matches pKey.
-+**
-+**     *pRes>0      The cursor is left pointing at an entry that
-+**                  is larger than pKey.
-+*/
-+static int memRbtreeMoveto(
-+  RbtCursor* pCur,
-+  const void *pKey,
-+  int nKey,
-+  int *pRes
-+){
-+  BtRbNode *pTmp = 0;
-+
-+  pCur->pNode = pCur->pTree->pHead;
-+  *pRes = -1;
-+  while( pCur->pNode && *pRes ) {
-+    *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey, pKey, nKey);
-+    pTmp = pCur->pNode;
-+    switch( *pRes ){
-+      case 1:    /* cursor > key */
-+        pCur->pNode = pCur->pNode->pLeft;
-+        break;
-+      case -1:   /* cursor < key */
-+        pCur->pNode = pCur->pNode->pRight;
-+        break;
-+    }
-+  } 
-+
-+  /* If (pCur->pNode == NULL), then we have failed to find a match. Set
-+   * pCur->pNode to pTmp, which is either NULL (if the tree is empty) or the
-+   * last node traversed in the search. In either case the relation ship
-+   * between pTmp and the searched for key is already stored in *pRes. pTmp is
-+   * either the successor or predecessor of the key we tried to move to. */
-+  if( !pCur->pNode ) pCur->pNode = pTmp;
-+  pCur->eSkip = SKIP_NONE;
-+
-+  return SQLITE_OK;
-+}
-+
-+
-+/*
-+** Delete the entry that the cursor is pointing to.
-+**
-+** The cursor is left pointing at either the next or the previous
-+** entry.  If the cursor is left pointing to the next entry, then 
-+** the pCur->eSkip flag is set to SKIP_NEXT which forces the next call to 
-+** sqliteRbtreeNext() to be a no-op.  That way, you can always call
-+** sqliteRbtreeNext() after a delete and the cursor will be left
-+** pointing to the first entry after the deleted entry.  Similarly,
-+** pCur->eSkip is set to SKIP_PREV is the cursor is left pointing to
-+** the entry prior to the deleted entry so that a subsequent call to
-+** sqliteRbtreePrevious() will always leave the cursor pointing at the
-+** entry immediately before the one that was deleted.
-+*/
-+static int memRbtreeDelete(RbtCursor* pCur)
-+{
-+  BtRbNode *pZ;      /* The one being deleted */
-+  BtRbNode *pChild;  /* The child of the spliced out node */
-+
-+  /* It is illegal to call sqliteRbtreeDelete() if we are
-+  ** not in a transaction */
-+  assert( pCur->pRbtree->eTransState != TRANS_NONE );
-+
-+  /* Make sure some other cursor isn't trying to read this same table */
-+  if( checkReadLocks(pCur) ){
-+    return SQLITE_LOCKED; /* The table pCur points to has a read lock */
-+  }
-+
-+  pZ = pCur->pNode;
-+  if( !pZ ){
-+    return SQLITE_OK;
-+  }
-+
-+  /* If we are not currently doing a rollback, set up a rollback op for this 
-+   * deletion */
-+  if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
-+    BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
-+    if( pOp==0 ) return SQLITE_NOMEM;
-+    pOp->iTab = pCur->iTree;
-+    pOp->nKey = pZ->nKey;
-+    pOp->pKey = pZ->pKey;
-+    pOp->nData = pZ->nData;
-+    pOp->pData = pZ->pData;
-+    pOp->eOp = ROLLBACK_INSERT;
-+    btreeLogRollbackOp(pCur->pRbtree, pOp);
-+  }
-+
-+  /* First do a standard binary-tree delete (node pZ is to be deleted). How
-+   * to do this depends on how many children pZ has:
-+   *
-+   * If pZ has no children or one child, then splice out pZ.  If pZ has two
-+   * children, splice out the successor of pZ and replace the key and data of
-+   * pZ with the key and data of the spliced out successor.  */
-+  if( pZ->pLeft && pZ->pRight ){
-+    BtRbNode *pTmp;
-+    int dummy;
-+    pCur->eSkip = SKIP_NONE;
-+    memRbtreeNext(pCur, &dummy);
-+    assert( dummy == 0 );
-+    if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){
-+      sqliteFree(pZ->pKey);
-+      sqliteFree(pZ->pData);
-+    }
-+    pZ->pData = pCur->pNode->pData;
-+    pZ->nData = pCur->pNode->nData;
-+    pZ->pKey = pCur->pNode->pKey;
-+    pZ->nKey = pCur->pNode->nKey;
-+    pTmp = pZ;
-+    pZ = pCur->pNode;
-+    pCur->pNode = pTmp;
-+    pCur->eSkip = SKIP_NEXT;
-+  }else{
-+    int res;
-+    pCur->eSkip = SKIP_NONE;
-+    memRbtreeNext(pCur, &res);
-+    pCur->eSkip = SKIP_NEXT;
-+    if( res ){
-+      memRbtreeLast(pCur, &res);
-+      memRbtreePrevious(pCur, &res);
-+      pCur->eSkip = SKIP_PREV;
-+    }
-+    if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){
-+        sqliteFree(pZ->pKey);
-+        sqliteFree(pZ->pData);
-+    }
-+  }
-+
-+  /* pZ now points at the node to be spliced out. This block does the 
-+   * splicing. */
-+  {
-+    BtRbNode **ppParentSlot = 0;
-+    assert( !pZ->pLeft || !pZ->pRight ); /* pZ has at most one child */
-+    pChild = ((pZ->pLeft)?pZ->pLeft:pZ->pRight);
-+    if( pZ->pParent ){
-+      assert( pZ == pZ->pParent->pLeft || pZ == pZ->pParent->pRight );
-+      ppParentSlot = ((pZ == pZ->pParent->pLeft)
-+          ?&pZ->pParent->pLeft:&pZ->pParent->pRight);
-+      *ppParentSlot = pChild;
-+    }else{
-+      pCur->pTree->pHead = pChild;
-+    }
-+    if( pChild ) pChild->pParent = pZ->pParent;
-+  }
-+
-+  /* pZ now points at the spliced out node. pChild is the only child of pZ, or
-+   * NULL if pZ has no children. If pZ is black, and not the tree root, then we
-+   * will have violated the "same number of black nodes in every path to a
-+   * leaf" property of the red-black tree. The code in do_delete_balancing()
-+   * repairs this. */
-+  if( pZ->isBlack ){ 
-+    do_delete_balancing(pCur->pTree, pChild, pZ->pParent);
-+  }
-+
-+  sqliteFree(pZ);
-+  return SQLITE_OK;
-+}
-+
-+/*
-+ * Empty table n of the Rbtree.
-+ */
-+static int memRbtreeClearTable(Rbtree* tree, int n)
-+{
-+  BtRbTree *pTree;
-+  BtRbNode *pNode;
-+
-+  pTree = sqliteHashFind(&tree->tblHash, 0, n);
-+  assert(pTree);
-+
-+  pNode = pTree->pHead;
-+  while( pNode ){
-+    if( pNode->pLeft ){
-+      pNode = pNode->pLeft;
-+    }
-+    else if( pNode->pRight ){
-+      pNode = pNode->pRight;
-+    }
-+    else {
-+      BtRbNode *pTmp = pNode->pParent;
-+      if( tree->eTransState == TRANS_ROLLBACK ){
-+        sqliteFree( pNode->pKey );
-+        sqliteFree( pNode->pData );
-+      }else{
-+        BtRollbackOp *pRollbackOp = sqliteMallocRaw(sizeof(BtRollbackOp));
-+        if( pRollbackOp==0 ) return SQLITE_NOMEM;
-+        pRollbackOp->eOp = ROLLBACK_INSERT;
-+        pRollbackOp->iTab = n;
-+        pRollbackOp->nKey = pNode->nKey;
-+        pRollbackOp->pKey = pNode->pKey;
-+        pRollbackOp->nData = pNode->nData;
-+        pRollbackOp->pData = pNode->pData;
-+        btreeLogRollbackOp(tree, pRollbackOp);
-+      }
-+      sqliteFree( pNode );
-+      if( pTmp ){
-+        if( pTmp->pLeft == pNode ) pTmp->pLeft = 0;
-+        else if( pTmp->pRight == pNode ) pTmp->pRight = 0;
-+      }
-+      pNode = pTmp;
-+    }
-+  }
-+
-+  pTree->pHead = 0;
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeFirst(RbtCursor* pCur, int *pRes)
-+{
-+  if( pCur->pTree->pHead ){
-+    pCur->pNode = pCur->pTree->pHead;
-+    while( pCur->pNode->pLeft ){
-+      pCur->pNode = pCur->pNode->pLeft;
-+    }
-+  }
-+  if( pCur->pNode ){
-+    *pRes = 0;
-+  }else{
-+    *pRes = 1;
-+  }
-+  pCur->eSkip = SKIP_NONE;
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeLast(RbtCursor* pCur, int *pRes)
-+{
-+  if( pCur->pTree->pHead ){
-+    pCur->pNode = pCur->pTree->pHead;
-+    while( pCur->pNode->pRight ){
-+      pCur->pNode = pCur->pNode->pRight;
-+    }
-+  }
-+  if( pCur->pNode ){
-+    *pRes = 0;
-+  }else{
-+    *pRes = 1;
-+  }
-+  pCur->eSkip = SKIP_NONE;
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Advance the cursor to the next entry in the database.  If
-+** successful then set *pRes=0.  If the cursor
-+** was already pointing to the last entry in the database before
-+** this routine was called, then set *pRes=1.
-+*/
-+static int memRbtreeNext(RbtCursor* pCur, int *pRes)
-+{
-+  if( pCur->pNode && pCur->eSkip != SKIP_NEXT ){
-+    if( pCur->pNode->pRight ){
-+      pCur->pNode = pCur->pNode->pRight;
-+      while( pCur->pNode->pLeft )
-+        pCur->pNode = pCur->pNode->pLeft;
-+    }else{
-+      BtRbNode * pX = pCur->pNode;
-+      pCur->pNode = pX->pParent;
-+      while( pCur->pNode && (pCur->pNode->pRight == pX) ){
-+        pX = pCur->pNode;
-+        pCur->pNode = pX->pParent;
-+      }
-+    }
-+  }
-+  pCur->eSkip = SKIP_NONE;
-+
-+  if( !pCur->pNode ){
-+    *pRes = 1;
-+  }else{
-+    *pRes = 0;
-+  }
-+
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreePrevious(RbtCursor* pCur, int *pRes)
-+{
-+  if( pCur->pNode && pCur->eSkip != SKIP_PREV ){
-+    if( pCur->pNode->pLeft ){
-+      pCur->pNode = pCur->pNode->pLeft;
-+      while( pCur->pNode->pRight )
-+        pCur->pNode = pCur->pNode->pRight;
-+    }else{
-+      BtRbNode * pX = pCur->pNode;
-+      pCur->pNode = pX->pParent;
-+      while( pCur->pNode && (pCur->pNode->pLeft == pX) ){
-+        pX = pCur->pNode;
-+        pCur->pNode = pX->pParent;
-+      }
-+    }
-+  }
-+  pCur->eSkip = SKIP_NONE;
-+
-+  if( !pCur->pNode ){
-+    *pRes = 1;
-+  }else{
-+    *pRes = 0;
-+  }
-+
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeKeySize(RbtCursor* pCur, int *pSize)
-+{
-+  if( pCur->pNode ){
-+    *pSize = pCur->pNode->nKey;
-+  }else{
-+    *pSize = 0;
-+  }
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeKey(RbtCursor* pCur, int offset, int amt, char *zBuf)
-+{
-+  if( !pCur->pNode ) return 0;
-+  if( !pCur->pNode->pKey || ((amt + offset) <= pCur->pNode->nKey) ){
-+    memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, amt);
-+  }else{
-+    memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, pCur->pNode->nKey-offset);
-+    amt = pCur->pNode->nKey-offset;
-+  }
-+  return amt;
-+}
-+
-+static int memRbtreeDataSize(RbtCursor* pCur, int *pSize)
-+{
-+  if( pCur->pNode ){
-+    *pSize = pCur->pNode->nData;
-+  }else{
-+    *pSize = 0;
-+  }
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeData(RbtCursor *pCur, int offset, int amt, char *zBuf)
-+{
-+  if( !pCur->pNode ) return 0;
-+  if( (amt + offset) <= pCur->pNode->nData ){
-+    memcpy(zBuf, ((char*)pCur->pNode->pData)+offset, amt);
-+  }else{
-+    memcpy(zBuf, ((char*)pCur->pNode->pData)+offset ,pCur->pNode->nData-offset);
-+    amt = pCur->pNode->nData-offset;
-+  }
-+  return amt;
-+}
-+
-+static int memRbtreeCloseCursor(RbtCursor* pCur)
-+{
-+  if( pCur->pTree->pCursors==pCur ){
-+    pCur->pTree->pCursors = pCur->pShared;
-+  }else{
-+    RbtCursor *p = pCur->pTree->pCursors;
-+    while( p && p->pShared!=pCur ){ p = p->pShared; }
-+    assert( p!=0 );
-+    if( p ){
-+      p->pShared = pCur->pShared;
-+    }
-+  }
-+  sqliteFree(pCur);
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeGetMeta(Rbtree* tree, int* aMeta)
-+{
-+  memcpy( aMeta, tree->aMetaData, sizeof(int) * SQLITE_N_BTREE_META );
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeUpdateMeta(Rbtree* tree, int* aMeta)
-+{
-+  memcpy( tree->aMetaData, aMeta, sizeof(int) * SQLITE_N_BTREE_META );
-+  return SQLITE_OK;
-+}
-+
-+/*
-+ * Check that each table in the Rbtree meets the requirements for a red-black
-+ * binary tree. If an error is found, return an explanation of the problem in 
-+ * memory obtained from sqliteMalloc(). Parameters aRoot and nRoot are ignored. 
-+ */
-+static char *memRbtreeIntegrityCheck(Rbtree* tree, int* aRoot, int nRoot)
-+{
-+  char * msg = 0;
-+  HashElem *p;
-+
-+  for(p=sqliteHashFirst(&tree->tblHash); p; p=sqliteHashNext(p)){
-+    BtRbTree *pTree = sqliteHashData(p);
-+    check_redblack_tree(pTree, &msg);
-+  }
-+
-+  return msg;
-+}
-+
-+static int memRbtreeSetCacheSize(Rbtree* tree, int sz)
-+{
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeSetSafetyLevel(Rbtree *pBt, int level){
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeBeginTrans(Rbtree* tree)
-+{
-+  if( tree->eTransState != TRANS_NONE ) 
-+    return SQLITE_ERROR;
-+
-+  assert( tree->pTransRollback == 0 );
-+  tree->eTransState = TRANS_INTRANSACTION;
-+  return SQLITE_OK;
-+}
-+
-+/*
-+** Delete a linked list of BtRollbackOp structures.
-+*/
-+static void deleteRollbackList(BtRollbackOp *pOp){
-+  while( pOp ){
-+    BtRollbackOp *pTmp = pOp->pNext;
-+    sqliteFree(pOp->pData);
-+    sqliteFree(pOp->pKey);
-+    sqliteFree(pOp);
-+    pOp = pTmp;
-+  }
-+}
-+
-+static int memRbtreeCommit(Rbtree* tree){
-+  /* Just delete pTransRollback and pCheckRollback */
-+  deleteRollbackList(tree->pCheckRollback);
-+  deleteRollbackList(tree->pTransRollback);
-+  tree->pTransRollback = 0;
-+  tree->pCheckRollback = 0;
-+  tree->pCheckRollbackTail = 0;
-+  tree->eTransState = TRANS_NONE;
-+  return SQLITE_OK;
-+}
-+
-+/*
-+ * Close the supplied Rbtree. Delete everything associated with it.
-+ */
-+static int memRbtreeClose(Rbtree* tree)
-+{
-+  HashElem *p;
-+  memRbtreeCommit(tree);
-+  while( (p=sqliteHashFirst(&tree->tblHash))!=0 ){
-+    tree->eTransState = TRANS_ROLLBACK;
-+    memRbtreeDropTable(tree, sqliteHashKeysize(p));
-+  }
-+  sqliteHashClear(&tree->tblHash);
-+  sqliteFree(tree);
-+  return SQLITE_OK;
-+}
-+
-+/*
-+ * Execute and delete the supplied rollback-list on pRbtree.
-+ */
-+static void execute_rollback_list(Rbtree *pRbtree, BtRollbackOp *pList)
-+{
-+  BtRollbackOp *pTmp;
-+  RbtCursor cur;
-+  int res;
-+
-+  cur.pRbtree = pRbtree;
-+  cur.wrFlag = 1;
-+  while( pList ){
-+    switch( pList->eOp ){
-+      case ROLLBACK_INSERT:
-+        cur.pTree  = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab );
-+        assert(cur.pTree);
-+        cur.iTree  = pList->iTab;
-+        cur.eSkip  = SKIP_NONE;
-+        memRbtreeInsert( &cur, pList->pKey,
-+            pList->nKey, pList->pData, pList->nData );
-+        break;
-+      case ROLLBACK_DELETE:
-+        cur.pTree  = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab );
-+        assert(cur.pTree);
-+        cur.iTree  = pList->iTab;
-+        cur.eSkip  = SKIP_NONE;
-+        memRbtreeMoveto(&cur, pList->pKey, pList->nKey, &res);
-+        assert(res == 0);
-+        memRbtreeDelete( &cur );
-+        break;
-+      case ROLLBACK_CREATE:
-+        btreeCreateTable(pRbtree, pList->iTab);
-+        break;
-+      case ROLLBACK_DROP:
-+        memRbtreeDropTable(pRbtree, pList->iTab);
-+        break;
-+      default:
-+        assert(0);
-+    }
-+    sqliteFree(pList->pKey);
-+    sqliteFree(pList->pData);
-+    pTmp = pList->pNext;
-+    sqliteFree(pList);
-+    pList = pTmp;
-+  }
-+}
-+
-+static int memRbtreeRollback(Rbtree* tree)
-+{
-+  tree->eTransState = TRANS_ROLLBACK;
-+  execute_rollback_list(tree, tree->pCheckRollback);
-+  execute_rollback_list(tree, tree->pTransRollback);
-+  tree->pTransRollback = 0;
-+  tree->pCheckRollback = 0;
-+  tree->pCheckRollbackTail = 0;
-+  tree->eTransState = TRANS_NONE;
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeBeginCkpt(Rbtree* tree)
-+{
-+  if( tree->eTransState != TRANS_INTRANSACTION ) 
-+    return SQLITE_ERROR;
-+
-+  assert( tree->pCheckRollback == 0 );
-+  assert( tree->pCheckRollbackTail == 0 );
-+  tree->eTransState = TRANS_INCHECKPOINT;
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeCommitCkpt(Rbtree* tree)
-+{
-+  if( tree->eTransState == TRANS_INCHECKPOINT ){ 
-+    if( tree->pCheckRollback ){
-+      tree->pCheckRollbackTail->pNext = tree->pTransRollback;
-+      tree->pTransRollback = tree->pCheckRollback;
-+      tree->pCheckRollback = 0;
-+      tree->pCheckRollbackTail = 0;
-+    }
-+    tree->eTransState = TRANS_INTRANSACTION;
-+  }
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeRollbackCkpt(Rbtree* tree)
-+{
-+  if( tree->eTransState != TRANS_INCHECKPOINT ) return SQLITE_OK;
-+  tree->eTransState = TRANS_ROLLBACK;
-+  execute_rollback_list(tree, tree->pCheckRollback);
-+  tree->pCheckRollback = 0;
-+  tree->pCheckRollbackTail = 0;
-+  tree->eTransState = TRANS_INTRANSACTION;
-+  return SQLITE_OK;
-+}
-+
-+#ifdef SQLITE_TEST
-+static int memRbtreePageDump(Rbtree* tree, int pgno, int rec)
-+{
-+  assert(!"Cannot call sqliteRbtreePageDump");
-+  return SQLITE_OK;
-+}
-+
-+static int memRbtreeCursorDump(RbtCursor* pCur, int* aRes)
-+{
-+  assert(!"Cannot call sqliteRbtreeCursorDump");
-+  return SQLITE_OK;
-+}
-+#endif
-+
-+static struct Pager *memRbtreePager(Rbtree* tree)
-+{
-+  return 0;
-+}
-+
-+/*
-+** Return the full pathname of the underlying database file.
-+*/
-+static const char *memRbtreeGetFilename(Rbtree *pBt){
-+  return 0;  /* A NULL return indicates there is no underlying file */
-+}
-+
-+/*
-+** The copy file function is not implemented for the in-memory database
-+*/
-+static int memRbtreeCopyFile(Rbtree *pBt, Rbtree *pBt2){
-+  return SQLITE_INTERNAL;  /* Not implemented */
-+}
-+
-+static BtOps sqliteRbtreeOps = {
-+    (int(*)(Btree*)) memRbtreeClose,
-+    (int(*)(Btree*,int)) memRbtreeSetCacheSize,
-+    (int(*)(Btree*,int)) memRbtreeSetSafetyLevel,
-+    (int(*)(Btree*)) memRbtreeBeginTrans,
-+    (int(*)(Btree*)) memRbtreeCommit,
-+    (int(*)(Btree*)) memRbtreeRollback,
-+    (int(*)(Btree*)) memRbtreeBeginCkpt,
-+    (int(*)(Btree*)) memRbtreeCommitCkpt,
-+    (int(*)(Btree*)) memRbtreeRollbackCkpt,
-+    (int(*)(Btree*,int*)) memRbtreeCreateTable,
-+    (int(*)(Btree*,int*)) memRbtreeCreateTable,
-+    (int(*)(Btree*,int)) memRbtreeDropTable,
-+    (int(*)(Btree*,int)) memRbtreeClearTable,
-+    (int(*)(Btree*,int,int,BtCursor**)) memRbtreeCursor,
-+    (int(*)(Btree*,int*)) memRbtreeGetMeta,
-+    (int(*)(Btree*,int*)) memRbtreeUpdateMeta,
-+    (char*(*)(Btree*,int*,int)) memRbtreeIntegrityCheck,
-+    (const char*(*)(Btree*)) memRbtreeGetFilename,
-+    (int(*)(Btree*,Btree*)) memRbtreeCopyFile,
-+    (struct Pager*(*)(Btree*)) memRbtreePager,
-+#ifdef SQLITE_TEST
-+    (int(*)(Btree*,int,int)) memRbtreePageDump,
-+#endif
-+};
-+
-+static BtCursorOps sqliteRbtreeCursorOps = {
-+    (int(*)(BtCursor*,const void*,int,int*)) memRbtreeMoveto,
-+    (int(*)(BtCursor*)) memRbtreeDelete,
-+    (int(*)(BtCursor*,const void*,int,const void*,int)) memRbtreeInsert,
-+    (int(*)(BtCursor*,int*)) memRbtreeFirst,
-+    (int(*)(BtCursor*,int*)) memRbtreeLast,
-+    (int(*)(BtCursor*,int*)) memRbtreeNext,
-+    (int(*)(BtCursor*,int*)) memRbtreePrevious,
-+    (int(*)(BtCursor*,int*)) memRbtreeKeySize,
-+    (int(*)(BtCursor*,int,int,char*)) memRbtreeKey,
-+    (int(*)(BtCursor*,const void*,int,int,int*)) memRbtreeKeyCompare,
-+    (int(*)(BtCursor*,int*)) memRbtreeDataSize,
-+    (int(*)(BtCursor*,int,int,char*)) memRbtreeData,
-+    (int(*)(BtCursor*)) memRbtreeCloseCursor,
-+#ifdef SQLITE_TEST
-+    (int(*)(BtCursor*,int*)) memRbtreeCursorDump,
-+#endif
-+
-+};
-+
-+#endif /* SQLITE_OMIT_INMEMORYDB */
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/build.c
-@@ -0,0 +1,2156 @@
-+/*
-+** 2001 September 15
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains C code routines that are called by the SQLite parser
-+** when syntax rules are reduced.  The routines in this file handle the
-+** following kinds of SQL syntax:
-+**
-+**     CREATE TABLE
-+**     DROP TABLE
-+**     CREATE INDEX
-+**     DROP INDEX
-+**     creating ID lists
-+**     BEGIN TRANSACTION
-+**     COMMIT
-+**     ROLLBACK
-+**     PRAGMA
-+**
-+** $Id$
-+*/
-+#include "sqliteInt.h"
-+#include <ctype.h>
-+
-+/*
-+** This routine is called when a new SQL statement is beginning to
-+** be parsed.  Check to see if the schema for the database needs
-+** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables.
-+** If it does, then read it.
-+*/
-+void sqliteBeginParse(Parse *pParse, int explainFlag){
-+  sqlite *db = pParse->db;
-+  int i;
-+  pParse->explain = explainFlag;
-+  if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){
-+    int rc = sqliteInit(db, &pParse->zErrMsg);
-+    if( rc!=SQLITE_OK ){
-+      pParse->rc = rc;
-+      pParse->nErr++;
-+    }
-+  }
-+  for(i=0; i<db->nDb; i++){
-+    DbClearProperty(db, i, DB_Locked);
-+    if( !db->aDb[i].inTrans ){
-+      DbClearProperty(db, i, DB_Cookie);
-+    }
-+  }
-+  pParse->nVar = 0;
-+}
-+
-+/*
-+** This routine is called after a single SQL statement has been
-+** parsed and we want to execute the VDBE code to implement 
-+** that statement.  Prior action routines should have already
-+** constructed VDBE code to do the work of the SQL statement.
-+** This routine just has to execute the VDBE code.
-+**
-+** Note that if an error occurred, it might be the case that
-+** no VDBE code was generated.
-+*/
-+void sqliteExec(Parse *pParse){
-+  sqlite *db = pParse->db;
-+  Vdbe *v = pParse->pVdbe;
-+
-+  if( v==0 && (v = sqliteGetVdbe(pParse))!=0 ){
-+    sqliteVdbeAddOp(v, OP_Halt, 0, 0);
-+  }
-+  if( sqlite_malloc_failed ) return;
-+  if( v && pParse->nErr==0 ){
-+    FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
-+    sqliteVdbeTrace(v, trace);
-+    sqliteVdbeMakeReady(v, pParse->nVar, pParse->explain);
-+    pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE;
-+    pParse->colNamesSet = 0;
-+  }else if( pParse->rc==SQLITE_OK ){
-+    pParse->rc = SQLITE_ERROR;
-+  }
-+  pParse->nTab = 0;
-+  pParse->nMem = 0;
-+  pParse->nSet = 0;
-+  pParse->nAgg = 0;
-+  pParse->nVar = 0;
-+}
-+
-+/*
-+** Locate the in-memory structure that describes 
-+** a particular database table given the name
-+** of that table and (optionally) the name of the database
-+** containing the table.  Return NULL if not found.
-+**
-+** If zDatabase is 0, all databases are searched for the
-+** table and the first matching table is returned.  (No checking
-+** for duplicate table names is done.)  The search order is
-+** TEMP first, then MAIN, then any auxiliary databases added
-+** using the ATTACH command.
-+**
-+** See also sqliteLocateTable().
-+*/
-+Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){
-+  Table *p = 0;
-+  int i;
-+  for(i=0; i<db->nDb; i++){
-+    int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
-+    if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[j].zName) ) continue;
-+    p = sqliteHashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1);
-+    if( p ) break;
-+  }
-+  return p;
-+}
-+
-+/*
-+** Locate the in-memory structure that describes 
-+** a particular database table given the name
-+** of that table and (optionally) the name of the database
-+** containing the table.  Return NULL if not found.
-+** Also leave an error message in pParse->zErrMsg.
-+**
-+** The difference between this routine and sqliteFindTable()
-+** is that this routine leaves an error message in pParse->zErrMsg
-+** where sqliteFindTable() does not.
-+*/
-+Table *sqliteLocateTable(Parse *pParse, const char *zName, const char *zDbase){
-+  Table *p;
-+
-+  p = sqliteFindTable(pParse->db, zName, zDbase);
-+  if( p==0 ){
-+    if( zDbase ){
-+      sqliteErrorMsg(pParse, "no such table: %s.%s", zDbase, zName);
-+    }else if( sqliteFindTable(pParse->db, zName, 0)!=0 ){
-+      sqliteErrorMsg(pParse, "table \"%s\" is not in database \"%s\"",
-+         zName, zDbase);
-+    }else{
-+      sqliteErrorMsg(pParse, "no such table: %s", zName);
-+    }
-+  }
-+  return p;
-+}
-+
-+/*
-+** Locate the in-memory structure that describes 
-+** a particular index given the name of that index
-+** and the name of the database that contains the index.
-+** Return NULL if not found.
-+**
-+** If zDatabase is 0, all databases are searched for the
-+** table and the first matching index is returned.  (No checking
-+** for duplicate index names is done.)  The search order is
-+** TEMP first, then MAIN, then any auxiliary databases added
-+** using the ATTACH command.
-+*/
-+Index *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){
-+  Index *p = 0;
-+  int i;
-+  for(i=0; i<db->nDb; i++){
-+    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
-+    if( zDb && sqliteStrICmp(zDb, db->aDb[j].zName) ) continue;
-+    p = sqliteHashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1);
-+    if( p ) break;
-+  }
-+  return p;
-+}
-+
-+/*
-+** Remove the given index from the index hash table, and free
-+** its memory structures.
-+**
-+** The index is removed from the database hash tables but
-+** it is not unlinked from the Table that it indexes.
-+** Unlinking from the Table must be done by the calling function.
-+*/
-+static void sqliteDeleteIndex(sqlite *db, Index *p){
-+  Index *pOld;
-+
-+  assert( db!=0 && p->zName!=0 );
-+  pOld = sqliteHashInsert(&db->aDb[p->iDb].idxHash, p->zName,
-+                          strlen(p->zName)+1, 0);
-+  if( pOld!=0 && pOld!=p ){
-+    sqliteHashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
-+                     strlen(pOld->zName)+1, pOld);
-+  }
-+  sqliteFree(p);
-+}
-+
-+/*
-+** Unlink the given index from its table, then remove
-+** the index from the index hash table and free its memory
-+** structures.
-+*/
-+void sqliteUnlinkAndDeleteIndex(sqlite *db, Index *pIndex){
-+  if( pIndex->pTable->pIndex==pIndex ){
-+    pIndex->pTable->pIndex = pIndex->pNext;
-+  }else{
-+    Index *p;
-+    for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
-+    if( p && p->pNext==pIndex ){
-+      p->pNext = pIndex->pNext;
-+    }
-+  }
-+  sqliteDeleteIndex(db, pIndex);
-+}
-+
-+/*
-+** Erase all schema information from the in-memory hash tables of
-+** database connection.  This routine is called to reclaim memory
-+** before the connection closes.  It is also called during a rollback
-+** if there were schema changes during the transaction.
-+**
-+** If iDb<=0 then reset the internal schema tables for all database
-+** files.  If iDb>=2 then reset the internal schema for only the
-+** single file indicated.
-+*/
-+void sqliteResetInternalSchema(sqlite *db, int iDb){
-+  HashElem *pElem;
-+  Hash temp1;
-+  Hash temp2;
-+  int i, j;
-+
-+  assert( iDb>=0 && iDb<db->nDb );
-+  db->flags &= ~SQLITE_Initialized;
-+  for(i=iDb; i<db->nDb; i++){
-+    Db *pDb = &db->aDb[i];
-+    temp1 = pDb->tblHash;
-+    temp2 = pDb->trigHash;
-+    sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0);
-+    sqliteHashClear(&pDb->aFKey);
-+    sqliteHashClear(&pDb->idxHash);
-+    for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
-+      Trigger *pTrigger = sqliteHashData(pElem);
-+      sqliteDeleteTrigger(pTrigger);
-+    }
-+    sqliteHashClear(&temp2);
-+    sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0);
-+    for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
-+      Table *pTab = sqliteHashData(pElem);
-+      sqliteDeleteTable(db, pTab);
-+    }
-+    sqliteHashClear(&temp1);
-+    DbClearProperty(db, i, DB_SchemaLoaded);
-+    if( iDb>0 ) return;
-+  }
-+  assert( iDb==0 );
-+  db->flags &= ~SQLITE_InternChanges;
-+
-+  /* If one or more of the auxiliary database files has been closed,
-+  ** then remove then from the auxiliary database list.  We take the
-+  ** opportunity to do this here since we have just deleted all of the
-+  ** schema hash tables and therefore do not have to make any changes
-+  ** to any of those tables.
-+  */
-+  for(i=0; i<db->nDb; i++){
-+    struct Db *pDb = &db->aDb[i];
-+    if( pDb->pBt==0 ){
-+      if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
-+      pDb->pAux = 0;
-+    }
-+  }
-+  for(i=j=2; i<db->nDb; i++){
-+    struct Db *pDb = &db->aDb[i];
-+    if( pDb->pBt==0 ){
-+      sqliteFree(pDb->zName);
-+      pDb->zName = 0;
-+      continue;
-+    }
-+    if( j<i ){
-+      db->aDb[j] = db->aDb[i];
-+    }
-+    j++;
-+  }
-+  memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j]));
-+  db->nDb = j;
-+  if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
-+    memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
-+    sqliteFree(db->aDb);
-+    db->aDb = db->aDbStatic;
-+  }
-+}
-+
-+/*
-+** This routine is called whenever a rollback occurs.  If there were
-+** schema changes during the transaction, then we have to reset the
-+** internal hash tables and reload them from disk.
-+*/
-+void sqliteRollbackInternalChanges(sqlite *db){
-+  if( db->flags & SQLITE_InternChanges ){
-+    sqliteResetInternalSchema(db, 0);
-+  }
-+}
-+
-+/*
-+** This routine is called when a commit occurs.
-+*/
-+void sqliteCommitInternalChanges(sqlite *db){
-+  db->aDb[0].schema_cookie = db->next_cookie;
-+  db->flags &= ~SQLITE_InternChanges;
-+}
-+
-+/*
-+** Remove the memory data structures associated with the given
-+** Table.  No changes are made to disk by this routine.
-+**
-+** This routine just deletes the data structure.  It does not unlink
-+** the table data structure from the hash table.  Nor does it remove
-+** foreign keys from the sqlite.aFKey hash table.  But it does destroy
-+** memory structures of the indices and foreign keys associated with 
-+** the table.
-+**
-+** Indices associated with the table are unlinked from the "db"
-+** data structure if db!=NULL.  If db==NULL, indices attached to
-+** the table are deleted, but it is assumed they have already been
-+** unlinked.
-+*/
-+void sqliteDeleteTable(sqlite *db, Table *pTable){
-+  int i;
-+  Index *pIndex, *pNext;
-+  FKey *pFKey, *pNextFKey;
-+
-+  if( pTable==0 ) return;
-+
-+  /* Delete all indices associated with this table
-+  */
-+  for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
-+    pNext = pIndex->pNext;
-+    assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) );
-+    sqliteDeleteIndex(db, pIndex);
-+  }
-+
-+  /* Delete all foreign keys associated with this table.  The keys
-+  ** should have already been unlinked from the db->aFKey hash table 
-+  */
-+  for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
-+    pNextFKey = pFKey->pNextFrom;
-+    assert( pTable->iDb<db->nDb );
-+    assert( sqliteHashFind(&db->aDb[pTable->iDb].aFKey,
-+                           pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
-+    sqliteFree(pFKey);
-+  }
-+
-+  /* Delete the Table structure itself.
-+  */
-+  for(i=0; i<pTable->nCol; i++){
-+    sqliteFree(pTable->aCol[i].zName);
-+    sqliteFree(pTable->aCol[i].zDflt);
-+    sqliteFree(pTable->aCol[i].zType);
-+  }
-+  sqliteFree(pTable->zName);
-+  sqliteFree(pTable->aCol);
-+  sqliteSelectDelete(pTable->pSelect);
-+  sqliteFree(pTable);
-+}
-+
-+/*
-+** Unlink the given table from the hash tables and the delete the
-+** table structure with all its indices and foreign keys.
-+*/
-+static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
-+  Table *pOld;
-+  FKey *pF1, *pF2;
-+  int i = p->iDb;
-+  assert( db!=0 );
-+  pOld = sqliteHashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1, 0);
-+  assert( pOld==0 || pOld==p );
-+  for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
-+    int nTo = strlen(pF1->zTo) + 1;
-+    pF2 = sqliteHashFind(&db->aDb[i].aFKey, pF1->zTo, nTo);
-+    if( pF2==pF1 ){
-+      sqliteHashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo);
-+    }else{
-+      while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
-+      if( pF2 ){
-+        pF2->pNextTo = pF1->pNextTo;
-+      }
-+    }
-+  }
-+  sqliteDeleteTable(db, p);
-+}
-+
-+/*
-+** Construct the name of a user table or index from a token.
-+**
-+** Space to hold the name is obtained from sqliteMalloc() and must
-+** be freed by the calling function.
-+*/
-+char *sqliteTableNameFromToken(Token *pName){
-+  char *zName = sqliteStrNDup(pName->z, pName->n);
-+  sqliteDequote(zName);
-+  return zName;
-+}
-+
-+/*
-+** Generate code to open the appropriate master table.  The table
-+** opened will be SQLITE_MASTER for persistent tables and 
-+** SQLITE_TEMP_MASTER for temporary tables.  The table is opened
-+** on cursor 0.
-+*/
-+void sqliteOpenMasterTable(Vdbe *v, int isTemp){
-+  sqliteVdbeAddOp(v, OP_Integer, isTemp, 0);
-+  sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
-+}
-+
-+/*
-+** Begin constructing a new table representation in memory.  This is
-+** the first of several action routines that get called in response
-+** to a CREATE TABLE statement.  In particular, this routine is called
-+** after seeing tokens "CREATE" and "TABLE" and the table name.  The
-+** pStart token is the CREATE and pName is the table name.  The isTemp
-+** flag is true if the table should be stored in the auxiliary database
-+** file instead of in the main database file.  This is normally the case
-+** when the "TEMP" or "TEMPORARY" keyword occurs in between
-+** CREATE and TABLE.
-+**
-+** The new table record is initialized and put in pParse->pNewTable.
-+** As more of the CREATE TABLE statement is parsed, additional action
-+** routines will be called to add more information to this record.
-+** At the end of the CREATE TABLE statement, the sqliteEndTable() routine
-+** is called to complete the construction of the new table record.
-+*/
-+void sqliteStartTable(
-+  Parse *pParse,   /* Parser context */
-+  Token *pStart,   /* The "CREATE" token */
-+  Token *pName,    /* Name of table or view to create */
-+  int isTemp,      /* True if this is a TEMP table */
-+  int isView       /* True if this is a VIEW */
-+){
-+  Table *pTable;
-+  Index *pIdx;
-+  char *zName;
-+  sqlite *db = pParse->db;
-+  Vdbe *v;
-+  int iDb;
-+
-+  pParse->sFirstToken = *pStart;
-+  zName = sqliteTableNameFromToken(pName);
-+  if( zName==0 ) return;
-+  if( db->init.iDb==1 ) isTemp = 1;
-+#ifndef SQLITE_OMIT_AUTHORIZATION
-+  assert( (isTemp & 1)==isTemp );
-+  {
-+    int code;
-+    char *zDb = isTemp ? "temp" : "main";
-+    if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
-+      sqliteFree(zName);
-+      return;
-+    }
-+    if( isView ){
-+      if( isTemp ){
-+        code = SQLITE_CREATE_TEMP_VIEW;
-+      }else{
-+        code = SQLITE_CREATE_VIEW;
-+      }
-+    }else{
-+      if( isTemp ){
-+        code = SQLITE_CREATE_TEMP_TABLE;
-+      }else{
-+        code = SQLITE_CREATE_TABLE;
-+      }
-+    }
-+    if( sqliteAuthCheck(pParse, code, zName, 0, zDb) ){
-+      sqliteFree(zName);
-+      return;
-+    }
-+  }
-+#endif
-+ 
-+
-+  /* Before trying to create a temporary table, make sure the Btree for
-+  ** holding temporary tables is open.
-+  */
-+  if( isTemp && db->aDb[1].pBt==0 && !pParse->explain ){
-+    int rc = sqliteBtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt);
-+    if( rc!=SQLITE_OK ){
-+      sqliteErrorMsg(pParse, "unable to open a temporary database "
-+        "file for storing temporary tables");
-+      pParse->nErr++;
-+      return;
-+    }
-+    if( db->flags & SQLITE_InTrans ){
-+      rc = sqliteBtreeBeginTrans(db->aDb[1].pBt);
-+      if( rc!=SQLITE_OK ){
-+        sqliteErrorMsg(pParse, "unable to get a write lock on "
-+          "the temporary database file");
-+        return;
-+      }
-+    }
-+  }
-+
-+  /* Make sure the new table name does not collide with an existing
-+  ** index or table name.  Issue an error message if it does.
-+  **
-+  ** If we are re-reading the sqlite_master table because of a schema
-+  ** change and a new permanent table is found whose name collides with
-+  ** an existing temporary table, that is not an error.
-+  */
-+  pTable = sqliteFindTable(db, zName, 0);
-+  iDb = isTemp ? 1 : db->init.iDb;
-+  if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){
-+    sqliteErrorMsg(pParse, "table %T already exists", pName);
-+    sqliteFree(zName);
-+    return;
-+  }
-+  if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
-+          (pIdx->iDb==0 || !db->init.busy) ){
-+    sqliteErrorMsg(pParse, "there is already an index named %s", zName);
-+    sqliteFree(zName);
-+    return;
-+  }
-+  pTable = sqliteMalloc( sizeof(Table) );
-+  if( pTable==0 ){
-+    sqliteFree(zName);
-+    return;
-+  }
-+  pTable->zName = zName;
-+  pTable->nCol = 0;
-+  pTable->aCol = 0;
-+  pTable->iPKey = -1;
-+  pTable->pIndex = 0;
-+  pTable->iDb = iDb;
-+  if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
-+  pParse->pNewTable = pTable;
-+
-+  /* Begin generating the code that will insert the table record into
-+  ** the SQLITE_MASTER table.  Note in particular that we must go ahead
-+  ** and allocate the record number for the table entry now.  Before any
-+  ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
-+  ** indices to be created and the table record must come before the 
-+  ** indices.  Hence, the record number for the table must be allocated
-+  ** now.
-+  */
-+  if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){
-+    sqliteBeginWriteOperation(pParse, 0, isTemp);
-+    if( !isTemp ){
-+      sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
-+      sqliteVdbeAddOp(v, OP_SetCookie, 0, 1);
-+    }
-+    sqliteOpenMasterTable(v, isTemp);
-+    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
-+    sqliteVdbeAddOp(v, OP_Dup, 0, 0);
-+    sqliteVdbeAddOp(v, OP_String, 0, 0);
-+    sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
-+  }
-+}
-+
-+/*
-+** Add a new column to the table currently being constructed.
-+**
-+** The parser calls this routine once for each column declaration
-+** in a CREATE TABLE statement.  sqliteStartTable() gets called
-+** first to get things going.  Then this routine is called for each
-+** column.
-+*/
-+void sqliteAddColumn(Parse *pParse, Token *pName){
-+  Table *p;
-+  int i;
-+  char *z = 0;
-+  Column *pCol;
-+  if( (p = pParse->pNewTable)==0 ) return;
-+  sqliteSetNString(&z, pName->z, pName->n, 0);
-+  if( z==0 ) return;
-+  sqliteDequote(z);
-+  for(i=0; i<p->nCol; i++){
-+    if( sqliteStrICmp(z, p->aCol[i].zName)==0 ){
-+      sqliteErrorMsg(pParse, "duplicate column name: %s", z);
-+      sqliteFree(z);
-+      return;
-+    }
-+  }
-+  if( (p->nCol & 0x7)==0 ){
-+    Column *aNew;
-+    aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));
-+    if( aNew==0 ) return;
-+    p->aCol = aNew;
-+  }
-+  pCol = &p->aCol[p->nCol];
-+  memset(pCol, 0, sizeof(p->aCol[0]));
-+  pCol->zName = z;
-+  pCol->sortOrder = SQLITE_SO_NUM;
-+  p->nCol++;
-+}
-+
-+/*
-+** This routine is called by the parser while in the middle of
-+** parsing a CREATE TABLE statement.  A "NOT NULL" constraint has
-+** been seen on a column.  This routine sets the notNull flag on
-+** the column currently under construction.
-+*/
-+void sqliteAddNotNull(Parse *pParse, int onError){
-+  Table *p;
-+  int i;
-+  if( (p = pParse->pNewTable)==0 ) return;
-+  i = p->nCol-1;
-+  if( i>=0 ) p->aCol[i].notNull = onError;
-+}
-+
-+/*
-+** This routine is called by the parser while in the middle of
-+** parsing a CREATE TABLE statement.  The pFirst token is the first
-+** token in the sequence of tokens that describe the type of the
-+** column currently under construction.   pLast is the last token
-+** in the sequence.  Use this information to construct a string
-+** that contains the typename of the column and store that string
-+** in zType.
-+*/ 
-+void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
-+  Table *p;
-+  int i, j;
-+  int n;
-+  char *z, **pz;
-+  Column *pCol;
-+  if( (p = pParse->pNewTable)==0 ) return;
-+  i = p->nCol-1;
-+  if( i<0 ) return;
-+  pCol = &p->aCol[i];
-+  pz = &pCol->zType;
-+  n = pLast->n + Addr(pLast->z) - Addr(pFirst->z);
-+  sqliteSetNString(pz, pFirst->z, n, 0);
-+  z = *pz;
-+  if( z==0 ) return;
-+  for(i=j=0; z[i]; i++){
-+    int c = z[i];
-+    if( isspace(c) ) continue;
-+    z[j++] = c;
-+  }
-+  z[j] = 0;
-+  if( pParse->db->file_format>=4 ){
-+    pCol->sortOrder = sqliteCollateType(z, n);
-+  }else{
-+    pCol->sortOrder = SQLITE_SO_NUM;
-+  }
-+}
-+
-+/*
-+** The given token is the default value for the last column added to
-+** the table currently under construction.  If "minusFlag" is true, it
-+** means the value token was preceded by a minus sign.
-+**
-+** This routine is called by the parser while in the middle of
-+** parsing a CREATE TABLE statement.
-+*/
-+void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
-+  Table *p;
-+  int i;
-+  char **pz;
-+  if( (p = pParse->pNewTable)==0 ) return;
-+  i = p->nCol-1;
-+  if( i<0 ) return;
-+  pz = &p->aCol[i].zDflt;
-+  if( minusFlag ){
-+    sqliteSetNString(pz, "-", 1, pVal->z, pVal->n, 0);
-+  }else{
-+    sqliteSetNString(pz, pVal->z, pVal->n, 0);
-+  }
-+  sqliteDequote(*pz);
-+}
-+
-+/*
-+** Designate the PRIMARY KEY for the table.  pList is a list of names 
-+** of columns that form the primary key.  If pList is NULL, then the
-+** most recently added column of the table is the primary key.
-+**
-+** A table can have at most one primary key.  If the table already has
-+** a primary key (and this is the second primary key) then create an
-+** error.
-+**
-+** If the PRIMARY KEY is on a single column whose datatype is INTEGER,
-+** then we will try to use that column as the row id.  (Exception:
-+** For backwards compatibility with older databases, do not do this
-+** if the file format version number is less than 1.)  Set the Table.iPKey
-+** field of the table under construction to be the index of the
-+** INTEGER PRIMARY KEY column.  Table.iPKey is set to -1 if there is
-+** no INTEGER PRIMARY KEY.
-+**
-+** If the key is not an INTEGER PRIMARY KEY, then create a unique
-+** index for the key.  No index is created for INTEGER PRIMARY KEYs.
-+*/
-+void sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError){
-+  Table *pTab = pParse->pNewTable;
-+  char *zType = 0;
-+  int iCol = -1, i;
-+  if( pTab==0 ) goto primary_key_exit;
-+  if( pTab->hasPrimKey ){
-+    sqliteErrorMsg(pParse, 
-+      "table \"%s\" has more than one primary key", pTab->zName);
-+    goto primary_key_exit;
-+  }
-+  pTab->hasPrimKey = 1;
-+  if( pList==0 ){
-+    iCol = pTab->nCol - 1;
-+    pTab->aCol[iCol].isPrimKey = 1;
-+  }else{
-+    for(i=0; i<pList->nId; i++){
-+      for(iCol=0; iCol<pTab->nCol; iCol++){
-+        if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ) break;
-+      }
-+      if( iCol<pTab->nCol ) pTab->aCol[iCol].isPrimKey = 1;
-+    }
-+    if( pList->nId>1 ) iCol = -1;
-+  }
-+  if( iCol>=0 && iCol<pTab->nCol ){
-+    zType = pTab->aCol[iCol].zType;
-+  }
-+  if( pParse->db->file_format>=1 && 
-+           zType && sqliteStrICmp(zType, "INTEGER")==0 ){
-+    pTab->iPKey = iCol;
-+    pTab->keyConf = onError;
-+  }else{
-+    sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0);
-+    pList = 0;
-+  }
-+
-+primary_key_exit:
-+  sqliteIdListDelete(pList);
-+  return;
-+}
-+
-+/*
-+** Return the appropriate collating type given a type name.
-+**
-+** The collation type is text (SQLITE_SO_TEXT) if the type
-+** name contains the character stream "text" or "blob" or
-+** "clob".  Any other type name is collated as numeric
-+** (SQLITE_SO_NUM).
-+*/
-+int sqliteCollateType(const char *zType, int nType){
-+  int i;
-+  for(i=0; i<nType-3; i++){
-+    int c = *(zType++) | 0x60;
-+    if( (c=='b' || c=='c') && sqliteStrNICmp(zType, "lob", 3)==0 ){
-+      return SQLITE_SO_TEXT;
-+    }
-+    if( c=='c' && sqliteStrNICmp(zType, "har", 3)==0 ){
-+      return SQLITE_SO_TEXT;
-+    }
-+    if( c=='t' && sqliteStrNICmp(zType, "ext", 3)==0 ){
-+      return SQLITE_SO_TEXT;
-+    }
-+  }
-+  return SQLITE_SO_NUM;
-+}
-+
-+/*
-+** This routine is called by the parser while in the middle of
-+** parsing a CREATE TABLE statement.  A "COLLATE" clause has
-+** been seen on a column.  This routine sets the Column.sortOrder on
-+** the column currently under construction.
-+*/
-+void sqliteAddCollateType(Parse *pParse, int collType){
-+  Table *p;
-+  int i;
-+  if( (p = pParse->pNewTable)==0 ) return;
-+  i = p->nCol-1;
-+  if( i>=0 ) p->aCol[i].sortOrder = collType;
-+}
-+
-+/*
-+** Come up with a new random value for the schema cookie.  Make sure
-+** the new value is different from the old.
-+**
-+** The schema cookie is used to determine when the schema for the
-+** database changes.  After each schema change, the cookie value
-+** changes.  When a process first reads the schema it records the
-+** cookie.  Thereafter, whenever it goes to access the database,
-+** it checks the cookie to make sure the schema has not changed
-+** since it was last read.
-+**
-+** This plan is not completely bullet-proof.  It is possible for
-+** the schema to change multiple times and for the cookie to be
-+** set back to prior value.  But schema changes are infrequent
-+** and the probability of hitting the same cookie value is only
-+** 1 chance in 2^32.  So we're safe enough.
-+*/
-+void sqliteChangeCookie(sqlite *db, Vdbe *v){
-+  if( db->next_cookie==db->aDb[0].schema_cookie ){
-+    unsigned char r;
-+    sqliteRandomness(1, &r);
-+    db->next_cookie = db->aDb[0].schema_cookie + r + 1;
-+    db->flags |= SQLITE_InternChanges;
-+    sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0);
-+    sqliteVdbeAddOp(v, OP_SetCookie, 0, 0);
-+  }
-+}
-+
-+/*
-+** Measure the number of characters needed to output the given
-+** identifier.  The number returned includes any quotes used
-+** but does not include the null terminator.
-+*/
-+static int identLength(const char *z){
-+  int n;
-+  int needQuote = 0;
-+  for(n=0; *z; n++, z++){
-+    if( *z=='\'' ){ n++; needQuote=1; }
-+  }
-+  return n + needQuote*2;
-+}
-+
-+/*
-+** Write an identifier onto the end of the given string.  Add
-+** quote characters as needed.
-+*/
-+static void identPut(char *z, int *pIdx, char *zIdent){
-+  int i, j, needQuote;
-+  i = *pIdx;
-+  for(j=0; zIdent[j]; j++){
-+    if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
-+  }
-+  needQuote =  zIdent[j]!=0 || isdigit(zIdent[0])
-+                  || sqliteKeywordCode(zIdent, j)!=TK_ID;
-+  if( needQuote ) z[i++] = '\'';
-+  for(j=0; zIdent[j]; j++){
-+    z[i++] = zIdent[j];
-+    if( zIdent[j]=='\'' ) z[i++] = '\'';
-+  }
-+  if( needQuote ) z[i++] = '\'';
-+  z[i] = 0;
-+  *pIdx = i;
-+}
-+
-+/*
-+** Generate a CREATE TABLE statement appropriate for the given
-+** table.  Memory to hold the text of the statement is obtained
-+** from sqliteMalloc() and must be freed by the calling function.
-+*/
-+static char *createTableStmt(Table *p){
-+  int i, k, n;
-+  char *zStmt;
-+  char *zSep, *zSep2, *zEnd;
-+  n = 0;
-+  for(i=0; i<p->nCol; i++){
-+    n += identLength(p->aCol[i].zName);
-+  }
-+  n += identLength(p->zName);
-+  if( n<40 ){
-+    zSep = "";
-+    zSep2 = ",";
-+    zEnd = ")";
-+  }else{
-+    zSep = "\n  ";
-+    zSep2 = ",\n  ";
-+    zEnd = "\n)";
-+  }
-+  n += 35 + 6*p->nCol;
-+  zStmt = sqliteMallocRaw( n );
-+  if( zStmt==0 ) return 0;
-+  strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE ");
-+  k = strlen(zStmt);
-+  identPut(zStmt, &k, p->zName);
-+  zStmt[k++] = '(';
-+  for(i=0; i<p->nCol; i++){
-+    strcpy(&zStmt[k], zSep);
-+    k += strlen(&zStmt[k]);
-+    zSep = zSep2;
-+    identPut(zStmt, &k, p->aCol[i].zName);
-+  }
-+  strcpy(&zStmt[k], zEnd);
-+  return zStmt;
-+}
-+
-+/*
-+** This routine is called to report the final ")" that terminates
-+** a CREATE TABLE statement.
-+**
-+** The table structure that other action routines have been building
-+** is added to the internal hash tables, assuming no errors have
-+** occurred.
-+**
-+** An entry for the table is made in the master table on disk, unless
-+** this is a temporary table or db->init.busy==1.  When db->init.busy==1
-+** it means we are reading the sqlite_master table because we just
-+** connected to the database or because the sqlite_master table has
-+** recently changes, so the entry for this table already exists in
-+** the sqlite_master table.  We do not want to create it again.
-+**
-+** If the pSelect argument is not NULL, it means that this routine
-+** was called to create a table generated from a 
-+** "CREATE TABLE ... AS SELECT ..." statement.  The column names of
-+** the new table will match the result set of the SELECT.
-+*/
-+void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
-+  Table *p;
-+  sqlite *db = pParse->db;
-+
-+  if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite_malloc_failed ) return;
-+  p = pParse->pNewTable;
-+  if( p==0 ) return;
-+
-+  /* If the table is generated from a SELECT, then construct the
-+  ** list of columns and the text of the table.
-+  */
-+  if( pSelect ){
-+    Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect);
-+    if( pSelTab==0 ) return;
-+    assert( p->aCol==0 );
-+    p->nCol = pSelTab->nCol;
-+    p->aCol = pSelTab->aCol;
-+    pSelTab->nCol = 0;
-+    pSelTab->aCol = 0;
-+    sqliteDeleteTable(0, pSelTab);
-+  }
-+
-+  /* If the db->init.busy is 1 it means we are reading the SQL off the
-+  ** "sqlite_master" or "sqlite_temp_master" table on the disk.
-+  ** So do not write to the disk again.  Extract the root page number
-+  ** for the table from the db->init.newTnum field.  (The page number
-+  ** should have been put there by the sqliteOpenCb routine.)
-+  */
-+  if( db->init.busy ){
-+    p->tnum = db->init.newTnum;
-+  }
-+
-+  /* If not initializing, then create a record for the new table
-+  ** in the SQLITE_MASTER table of the database.  The record number
-+  ** for the new table entry should already be on the stack.
-+  **
-+  ** If this is a TEMPORARY table, write the entry into the auxiliary
-+  ** file instead of into the main database file.
-+  */
-+  if( !db->init.busy ){
-+    int n;
-+    Vdbe *v;
-+
-+    v = sqliteGetVdbe(pParse);
-+    if( v==0 ) return;
-+    if( p->pSelect==0 ){
-+      /* A regular table */
-+      sqliteVdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER);
-+    }else{
-+      /* A view */
-+      sqliteVdbeAddOp(v, OP_Integer, 0, 0);
-+    }
-+    p->tnum = 0;
-+    sqliteVdbeAddOp(v, OP_Pull, 1, 0);
-+    sqliteVdbeOp3(v, OP_String, 0, 0, p->pSelect==0?"table":"view", P3_STATIC);
-+    sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0);
-+    sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0);
-+    sqliteVdbeAddOp(v, OP_Dup, 4, 0);
-+    sqliteVdbeAddOp(v, OP_String, 0, 0);
-+    if( pSelect ){
-+      char *z = createTableStmt(p);
-+      n = z ? strlen(z) : 0;
-+      sqliteVdbeChangeP3(v, -1, z, n);
-+      sqliteFree(z);
-+    }else{
-+      assert( pEnd!=0 );
-+      n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1;
-+      sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n);
-+    }
-+    sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
-+    sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
-+    if( !p->iDb ){
-+      sqliteChangeCookie(db, v);
-+    }
-+    sqliteVdbeAddOp(v, OP_Close, 0, 0);
-+    if( pSelect ){
-+      sqliteVdbeAddOp(v, OP_Integer, p->iDb, 0);
-+      sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0);
-+      pParse->nTab = 2;
-+      sqliteSelect(pParse, pSelect, SRT_Table, 1, 0, 0, 0);
-+    }
-+    sqliteEndWriteOperation(pParse);
-+  }
-+
-+  /* Add the table to the in-memory representation of the database.
-+  */
-+  if( pParse->explain==0 && pParse->nErr==0 ){
-+    Table *pOld;
-+    FKey *pFKey;
-+    pOld = sqliteHashInsert(&db->aDb[p->iDb].tblHash, 
-+                            p->zName, strlen(p->zName)+1, p);
-+    if( pOld ){
-+      assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
-+      return;
-+    }
-+    for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
-+      int nTo = strlen(pFKey->zTo) + 1;
-+      pFKey->pNextTo = sqliteHashFind(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo);
-+      sqliteHashInsert(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo, pFKey);
-+    }
-+    pParse->pNewTable = 0;
-+    db->nTable++;
-+    db->flags |= SQLITE_InternChanges;
-+  }
-+}
-+
-+/*
-+** The parser calls this routine in order to create a new VIEW
-+*/
-+void sqliteCreateView(
-+  Parse *pParse,     /* The parsing context */
-+  Token *pBegin,     /* The CREATE token that begins the statement */
-+  Token *pName,      /* The token that holds the name of the view */
-+  Select *pSelect,   /* A SELECT statement that will become the new view */
-+  int isTemp         /* TRUE for a TEMPORARY view */
-+){
-+  Table *p;
-+  int n;
-+  const char *z;
-+  Token sEnd;
-+  DbFixer sFix;
-+
-+  sqliteStartTable(pParse, pBegin, pName, isTemp, 1);
-+  p = pParse->pNewTable;
-+  if( p==0 || pParse->nErr ){
-+    sqliteSelectDelete(pSelect);
-+    return;
-+  }
-+  if( sqliteFixInit(&sFix, pParse, p->iDb, "view", pName)
-+    && sqliteFixSelect(&sFix, pSelect)
-+  ){
-+    sqliteSelectDelete(pSelect);
-+    return;
-+  }
-+
-+  /* Make a copy of the entire SELECT statement that defines the view.
-+  ** This will force all the Expr.token.z values to be dynamically
-+  ** allocated rather than point to the input string - which means that
-+  ** they will persist after the current sqlite_exec() call returns.
-+  */
-+  p->pSelect = sqliteSelectDup(pSelect);
-+  sqliteSelectDelete(pSelect);
-+  if( !pParse->db->init.busy ){
-+    sqliteViewGetColumnNames(pParse, p);
-+  }
-+
-+  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
-+  ** the end.
-+  */
-+  sEnd = pParse->sLastToken;
-+  if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){
-+    sEnd.z += sEnd.n;
-+  }
-+  sEnd.n = 0;
-+  n = sEnd.z - pBegin->z;
-+  z = pBegin->z;
-+  while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; }
-+  sEnd.z = &z[n-1];
-+  sEnd.n = 1;
-+
-+  /* Use sqliteEndTable() to add the view to the SQLITE_MASTER table */
-+  sqliteEndTable(pParse, &sEnd, 0);
-+  return;
-+}
-+
-+/*
-+** The Table structure pTable is really a VIEW.  Fill in the names of
-+** the columns of the view in the pTable structure.  Return the number
-+** of errors.  If an error is seen leave an error message in pParse->zErrMsg.
-+*/
-+int sqliteViewGetColumnNames(Parse *pParse, Table *pTable){
-+  ExprList *pEList;
-+  Select *pSel;
-+  Table *pSelTab;
-+  int nErr = 0;
-+
-+  assert( pTable );
-+
-+  /* A positive nCol means the columns names for this view are
-+  ** already known.
-+  */
-+  if( pTable->nCol>0 ) return 0;
-+
-+  /* A negative nCol is a special marker meaning that we are currently
-+  ** trying to compute the column names.  If we enter this routine with
-+  ** a negative nCol, it means two or more views form a loop, like this:
-+  **
-+  **     CREATE VIEW one AS SELECT * FROM two;
-+  **     CREATE VIEW two AS SELECT * FROM one;
-+  **
-+  ** 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( pTable->nCol<0 ){
-+    sqliteErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
-+    return 1;
-+  }
-+
-+  /* If we get this far, it means we need to compute the table names.
-+  */
-+  assert( pTable->pSelect ); /* If nCol==0, then pTable must be a VIEW */
-+  pSel = pTable->pSelect;
-+
-+  /* Note that the call to sqliteResultSetOfSelect() will expand any
-+  ** "*" elements in this list.  But we will need to restore the list
-+  ** back to its original configuration afterwards, so we save a copy of
-+  ** the original in pEList.
-+  */
-+  pEList = pSel->pEList;
-+  pSel->pEList = sqliteExprListDup(pEList);
-+  if( pSel->pEList==0 ){
-+    pSel->pEList = pEList;
-+    return 1;  /* Malloc failed */
-+  }
-+  pTable->nCol = -1;
-+  pSelTab = sqliteResultSetOfSelect(pParse, 0, pSel);
-+  if( pSelTab ){
-+    assert( pTable->aCol==0 );
-+    pTable->nCol = pSelTab->nCol;
-+    pTable->aCol = pSelTab->aCol;
-+    pSelTab->nCol = 0;
-+    pSelTab->aCol = 0;
-+    sqliteDeleteTable(0, pSelTab);
-+    DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews);
-+  }else{
-+    pTable->nCol = 0;
-+    nErr++;
-+  }
-+  sqliteSelectUnbind(pSel);
-+  sqliteExprListDelete(pSel->pEList);
-+  pSel->pEList = pEList;
-+  return nErr;  
-+}
-+
-+/*
-+** Clear the column names from the VIEW pTable.
-+**
-+** This routine is called whenever any other table or view is modified.
-+** The view passed into this routine might depend directly or indirectly
-+** on the modified or deleted table so we need to clear the old column
-+** names so that they will be recomputed.
-+*/
-+static void sqliteViewResetColumnNames(Table *pTable){
-+  int i;
-+  Column *pCol;
-+  assert( pTable!=0 && pTable->pSelect!=0 );
-+  for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
-+    sqliteFree(pCol->zName);
-+    sqliteFree(pCol->zDflt);
-+    sqliteFree(pCol->zType);
-+  }
-+  sqliteFree(pTable->aCol);
-+  pTable->aCol = 0;
-+  pTable->nCol = 0;
-+}
-+
-+/*
-+** Clear the column names from every VIEW in database idx.
-+*/
-+static void sqliteViewResetAll(sqlite *db, int idx){
-+  HashElem *i;
-+  if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
-+  for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
-+    Table *pTab = sqliteHashData(i);
-+    if( pTab->pSelect ){
-+      sqliteViewResetColumnNames(pTab);
-+    }
-+  }
-+  DbClearProperty(db, idx, DB_UnresetViews);
-+}
-+
-+/*
-+** Given a token, look up a table with that name.  If not found, leave
-+** an error for the parser to find and return NULL.
-+*/
-+Table *sqliteTableFromToken(Parse *pParse, Token *pTok){
-+  char *zName;
-+  Table *pTab;
-+  zName = sqliteTableNameFromToken(pTok);
-+  if( zName==0 ) return 0;
-+  pTab = sqliteFindTable(pParse->db, zName, 0);
-+  sqliteFree(zName);
-+  if( pTab==0 ){
-+    sqliteErrorMsg(pParse, "no such table: %T", pTok);
-+  }
-+  return pTab;
-+}
-+
-+/*
-+** This routine is called to do the work of a DROP TABLE statement.
-+** pName is the name of the table to be dropped.
-+*/
-+void sqliteDropTable(Parse *pParse, Token *pName, int isView){
-+  Table *pTable;
-+  Vdbe *v;
-+  int base;
-+  sqlite *db = pParse->db;
-+  int iDb;
-+
-+  if( pParse->nErr || sqlite_malloc_failed ) return;
-+  pTable = sqliteTableFromToken(pParse, pName);
-+  if( pTable==0 ) return;
-+  iDb = pTable->iDb;
-+  assert( iDb>=0 && iDb<db->nDb );
-+#ifndef SQLITE_OMIT_AUTHORIZATION
-+  {
-+    int code;
-+    const char *zTab = SCHEMA_TABLE(pTable->iDb);
-+    const char *zDb = db->aDb[pTable->iDb].zName;
-+    if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
-+      return;
-+    }
-+    if( isView ){
-+      if( iDb==1 ){
-+        code = SQLITE_DROP_TEMP_VIEW;
-+      }else{
-+        code = SQLITE_DROP_VIEW;
-+      }
-+    }else{
-+      if( iDb==1 ){
-+        code = SQLITE_DROP_TEMP_TABLE;
-+      }else{
-+        code = SQLITE_DROP_TABLE;
-+      }
-+    }
-+    if( sqliteAuthCheck(pParse, code, pTable->zName, 0, zDb) ){
-+      return;
-+    }
-+    if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTable->zName, 0, zDb) ){
-+      return;
-+    }
-+  }
-+#endif
-+  if( pTable->readOnly ){
-+    sqliteErrorMsg(pParse, "table %s may not be dropped", pTable->zName);
-+    pParse->nErr++;
-+    return;
-+  }
-+  if( isView && pTable->pSelect==0 ){
-+    sqliteErrorMsg(pParse, "use DROP TABLE to delete table %s", pTable->zName);
-+    return;
-+  }
-+  if( !isView && pTable->pSelect ){
-+    sqliteErrorMsg(pParse, "use DROP VIEW to delete view %s", pTable->zName);
-+    return;
-+  }
-+
-+  /* Generate code to remove the table from the master table
-+  ** on disk.
-+  */
-+  v = sqliteGetVdbe(pParse);
-+  if( v ){
-+    static VdbeOpList dropTable[] = {
-+      { OP_Rewind,     0, ADDR(8),  0},
-+      { OP_String,     0, 0,        0}, /* 1 */
-+      { OP_MemStore,   1, 1,        0},
-+      { OP_MemLoad,    1, 0,        0}, /* 3 */
-+      { OP_Column,     0, 2,        0},
-+      { OP_Ne,         0, ADDR(7),  0},
-+      { OP_Delete,     0, 0,        0},
-+      { OP_Next,       0, ADDR(3),  0}, /* 7 */
-+    };
-+    Index *pIdx;
-+    Trigger *pTrigger;
-+    sqliteBeginWriteOperation(pParse, 0, pTable->iDb);
-+
-+    /* Drop all triggers associated with the table being dropped */
-+    pTrigger = pTable->pTrigger;
-+    while( pTrigger ){
-+      assert( pTrigger->iDb==pTable->iDb || pTrigger->iDb==1 );
-+      sqliteDropTriggerPtr(pParse, pTrigger, 1);
-+      if( pParse->explain ){
-+        pTrigger = pTrigger->pNext;
-+      }else{
-+        pTrigger = pTable->pTrigger;
-+      }
-+    }
-+
-+    /* Drop all SQLITE_MASTER entries that refer to the table */
-+    sqliteOpenMasterTable(v, pTable->iDb);
-+    base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
-+    sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);
-+
-+    /* Drop all SQLITE_TEMP_MASTER entries that refer to the table */
-+    if( pTable->iDb!=1 ){
-+      sqliteOpenMasterTable(v, 1);
-+      base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
-+      sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);
-+    }
-+
-+    if( pTable->iDb==0 ){
-+      sqliteChangeCookie(db, v);
-+    }
-+    sqliteVdbeAddOp(v, OP_Close, 0, 0);
-+    if( !isView ){
-+      sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->iDb);
-+      for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
-+        sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
-+      }
-+    }
-+    sqliteEndWriteOperation(pParse);
-+  }
-+
-+  /* Delete the in-memory description of the table.
-+  **
-+  ** Exception: if the SQL statement began with the EXPLAIN keyword,
-+  ** then no changes should be made.
-+  */
-+  if( !pParse->explain ){
-+    sqliteUnlinkAndDeleteTable(db, pTable);
-+    db->flags |= SQLITE_InternChanges;
-+  }
-+  sqliteViewResetAll(db, iDb);
-+}
-+
-+/*
-+** This routine constructs a P3 string suitable for an OP_MakeIdxKey
-+** opcode and adds that P3 string to the most recently inserted instruction
-+** in the virtual machine.  The P3 string consists of a single character
-+** for each column in the index pIdx of table pTab.  If the column uses
-+** a numeric sort order, then the P3 string character corresponding to
-+** that column is 'n'.  If the column uses a text sort order, then the
-+** P3 string is 't'.  See the OP_MakeIdxKey opcode documentation for
-+** additional information.  See also the sqliteAddKeyType() routine.
-+*/
-+void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){
-+  char *zType;
-+  Table *pTab;
-+  int i, n;
-+  assert( pIdx!=0 && pIdx->pTable!=0 );
-+  pTab = pIdx->pTable;
-+  n = pIdx->nColumn;
-+  zType = sqliteMallocRaw( n+1 );
-+  if( zType==0 ) return;
-+  for(i=0; i<n; i++){
-+    int iCol = pIdx->aiColumn[i];
-+    assert( iCol>=0 && iCol<pTab->nCol );
-+    if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
-+      zType[i] = 't';
-+    }else{
-+      zType[i] = 'n';
-+    }
-+  }
-+  zType[n] = 0;
-+  sqliteVdbeChangeP3(v, -1, zType, n);
-+  sqliteFree(zType);
-+}
-+
-+/*
-+** This routine is called to create a new foreign key on the table
-+** currently under construction.  pFromCol determines which columns
-+** in the current table point to the foreign key.  If pFromCol==0 then
-+** connect the key to the last column inserted.  pTo is the name of
-+** the table referred to.  pToCol is a list of tables in the other
-+** pTo table that the foreign key points to.  flags contains all
-+** information about the conflict resolution algorithms specified
-+** in the ON DELETE, ON UPDATE and ON INSERT clauses.
-+**
-+** An FKey structure is created and added to the table currently
-+** under construction in the pParse->pNewTable field.  The new FKey
-+** is not linked into db->aFKey at this point - that does not happen
-+** until sqliteEndTable().
-+**
-+** The foreign key is set for IMMEDIATE processing.  A subsequent call
-+** to sqliteDeferForeignKey() might change this to DEFERRED.
-+*/
-+void sqliteCreateForeignKey(
-+  Parse *pParse,       /* Parsing context */
-+  IdList *pFromCol,    /* Columns in this table that point to other table */
-+  Token *pTo,          /* Name of the other table */
-+  IdList *pToCol,      /* Columns in the other table */
-+  int flags            /* Conflict resolution algorithms. */
-+){
-+  Table *p = pParse->pNewTable;
-+  int nByte;
-+  int i;
-+  int nCol;
-+  char *z;
-+  FKey *pFKey = 0;
-+
-+  assert( pTo!=0 );
-+  if( p==0 || pParse->nErr ) goto fk_end;
-+  if( pFromCol==0 ){
-+    int iCol = p->nCol-1;
-+    if( iCol<0 ) goto fk_end;
-+    if( pToCol && pToCol->nId!=1 ){
-+      sqliteErrorMsg(pParse, "foreign key on %s"
-+         " should reference only one column of table %T",
-+         p->aCol[iCol].zName, pTo);
-+      goto fk_end;
-+    }
-+    nCol = 1;
-+  }else if( pToCol && pToCol->nId!=pFromCol->nId ){
-+    sqliteErrorMsg(pParse,
-+        "number of columns in foreign key does not match the number of "
-+        "columns in the referenced table");
-+    goto fk_end;
-+  }else{
-+    nCol = pFromCol->nId;
-+  }
-+  nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1;
-+  if( pToCol ){
-+    for(i=0; i<pToCol->nId; i++){
-+      nByte += strlen(pToCol->a[i].zName) + 1;
-+    }
-+  }
-+  pFKey = sqliteMalloc( nByte );
-+  if( pFKey==0 ) goto fk_end;
-+  pFKey->pFrom = p;
-+  pFKey->pNextFrom = p->pFKey;
-+  z = (char*)&pFKey[1];
-+  pFKey->aCol = (struct sColMap*)z;
-+  z += sizeof(struct sColMap)*nCol;
-+  pFKey->zTo = z;
-+  memcpy(z, pTo->z, pTo->n);
-+  z[pTo->n] = 0;
-+  z += pTo->n+1;
-+  pFKey->pNextTo = 0;
-+  pFKey->nCol = nCol;
-+  if( pFromCol==0 ){
-+    pFKey->aCol[0].iFrom = p->nCol-1;
-+  }else{
-+    for(i=0; i<nCol; i++){
-+      int j;
-+      for(j=0; j<p->nCol; j++){
-+        if( sqliteStrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
-+          pFKey->aCol[i].iFrom = j;
-+          break;
-+        }
-+      }
-+      if( j>=p->nCol ){
-+        sqliteErrorMsg(pParse, 
-+          "unknown column \"%s\" in foreign key definition", 
-+          pFromCol->a[i].zName);
-+        goto fk_end;
-+      }
-+    }
-+  }
-+  if( pToCol ){
-+    for(i=0; i<nCol; i++){
-+      int n = strlen(pToCol->a[i].zName);
-+      pFKey->aCol[i].zCol = z;
-+      memcpy(z, pToCol->a[i].zName, n);
-+      z[n] = 0;
-+      z += n+1;
-+    }
-+  }
-+  pFKey->isDeferred = 0;
-+  pFKey->deleteConf = flags & 0xff;
-+  pFKey->updateConf = (flags >> 8 ) & 0xff;
-+  pFKey->insertConf = (flags >> 16 ) & 0xff;
-+
-+  /* Link the foreign key to the table as the last step.
-+  */
-+  p->pFKey = pFKey;
-+  pFKey = 0;
-+
-+fk_end:
-+  sqliteFree(pFKey);
-+  sqliteIdListDelete(pFromCol);
-+  sqliteIdListDelete(pToCol);
-+}
-+
-+/*
-+** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
-+** clause is seen as part of a foreign key definition.  The isDeferred
-+** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
-+** The behavior of the most recently created foreign key is adjusted
-+** accordingly.
-+*/
-+void sqliteDeferForeignKey(Parse *pParse, int isDeferred){
-+  Table *pTab;
-+  FKey *pFKey;
-+  if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
-+  pFKey->isDeferred = isDeferred;
-+}
-+
-+/*
-+** Create a new index for an SQL table.  pIndex is the name of the index 
-+** and pTable is the name of the table that is to be indexed.  Both will 
-+** be NULL for a primary key or an index that is created to satisfy a
-+** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
-+** as the table to be indexed.  pParse->pNewTable is a table that is
-+** currently being constructed by a CREATE TABLE statement.
-+**
-+** pList is a list of columns to be indexed.  pList will be NULL if this
-+** is a primary key or unique-constraint on the most recent column added
-+** to the table currently under construction.  
-+*/
-+void sqliteCreateIndex(
-+  Parse *pParse,   /* All information about this parse */
-+  Token *pName,    /* Name of the index.  May be NULL */
-+  SrcList *pTable, /* Name of the table to index.  Use pParse->pNewTable if 0 */
-+  IdList *pList,   /* A list of columns to be indexed */
-+  int onError,     /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
-+  Token *pStart,   /* The CREATE token that begins a CREATE TABLE statement */
-+  Token *pEnd      /* The ")" that closes the CREATE INDEX statement */
-+){
-+  Table *pTab;     /* Table to be indexed */
-+  Index *pIndex;   /* The index to be created */
-+  char *zName = 0;
-+  int i, j;
-+  Token nullId;    /* Fake token for an empty ID list */
-+  DbFixer sFix;    /* For assigning database names to pTable */
-+  int isTemp;      /* True for a temporary index */
-+  sqlite *db = pParse->db;
-+
-+  if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
-+  if( db->init.busy 
-+     && sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName)
-+     && sqliteFixSrcList(&sFix, pTable)
-+  ){
-+    goto exit_create_index;
-+  }
-+
-+  /*
-+  ** Find the table that is to be indexed.  Return early if not found.
-+  */
-+  if( pTable!=0 ){
-+    assert( pName!=0 );
-+    assert( pTable->nSrc==1 );
-+    pTab =  sqliteSrcListLookup(pParse, pTable);
-+  }else{
-+    assert( pName==0 );
-+    pTab =  pParse->pNewTable;
-+  }
-+  if( pTab==0 || pParse->nErr ) goto exit_create_index;
-+  if( pTab->readOnly ){
-+    sqliteErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
-+    goto exit_create_index;
-+  }
-+  if( pTab->iDb>=2 && db->init.busy==0 ){
-+    sqliteErrorMsg(pParse, "table %s may not have indices added", pTab->zName);
-+    goto exit_create_index;
-+  }
-+  if( pTab->pSelect ){
-+    sqliteErrorMsg(pParse, "views may not be indexed");
-+    goto exit_create_index;
-+  }
-+  isTemp = pTab->iDb==1;
-+
-+  /*
-+  ** Find the name of the index.  Make sure there is not already another
-+  ** index or table with the same name.  
-+  **
-+  ** Exception:  If we are reading the names of permanent indices from the
-+  ** sqlite_master table (because some other process changed the schema) and
-+  ** one of the index names collides with the name of a temporary table or
-+  ** index, then we will continue to process this index.
-+  **
-+  ** If pName==0 it means that we are
-+  ** dealing with a primary key or UNIQUE constraint.  We have to invent our
-+  ** own name.
-+  */
-+  if( pName && !db->init.busy ){
-+    Index *pISameName;    /* Another index with the same name */
-+    Table *pTSameName;    /* A table with same name as the index */
-+    zName = sqliteTableNameFromToken(pName);
-+    if( zName==0 ) goto exit_create_index;
-+    if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
-+      sqliteErrorMsg(pParse, "index %s already exists", zName);
-+      goto exit_create_index;
-+    }
-+    if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){
-+      sqliteErrorMsg(pParse, "there is already a table named %s", zName);
-+      goto exit_create_index;
-+    }
-+  }else if( pName==0 ){
-+    char zBuf[30];
-+    int n;
-+    Index *pLoop;
-+    for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
-+    sprintf(zBuf,"%d)",n);
-+    zName = 0;
-+    sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
-+    if( zName==0 ) goto exit_create_index;
-+  }else{
-+    zName = sqliteTableNameFromToken(pName);
-+  }
-+
-+  /* Check for authorization to create an index.
-+  */
-+#ifndef SQLITE_OMIT_AUTHORIZATION
-+  {
-+    const char *zDb = db->aDb[pTab->iDb].zName;
-+
-+    assert( pTab->iDb==db->init.iDb || isTemp );
-+    if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
-+      goto exit_create_index;
-+    }
-+    i = SQLITE_CREATE_INDEX;
-+    if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
-+    if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){
-+      goto exit_create_index;
-+    }
-+  }
-+#endif
-+
-+  /* If pList==0, it means this routine was called to make a primary
-+  ** key out of the last column added to the table under construction.
-+  ** So create a fake list to simulate this.
-+  */
-+  if( pList==0 ){
-+    nullId.z = pTab->aCol[pTab->nCol-1].zName;
-+    nullId.n = strlen(nullId.z);
-+    pList = sqliteIdListAppend(0, &nullId);
-+    if( pList==0 ) goto exit_create_index;
-+  }
-+
-+  /* 
-+  ** Allocate the index structure. 
-+  */
-+  pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 +
-+                        sizeof(int)*pList->nId );
-+  if( pIndex==0 ) goto exit_create_index;
-+  pIndex->aiColumn = (int*)&pIndex[1];
-+  pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];
-+  strcpy(pIndex->zName, zName);
-+  pIndex->pTable = pTab;
-+  pIndex->nColumn = pList->nId;
-+  pIndex->onError = onError;
-+  pIndex->autoIndex = pName==0;
-+  pIndex->iDb = isTemp ? 1 : db->init.iDb;
-+
-+  /* Scan the names of the columns of the table to be indexed and
-+  ** load the column indices into the Index structure.  Report an error
-+  ** if any column is not found.
-+  */
-+  for(i=0; i<pList->nId; i++){
-+    for(j=0; j<pTab->nCol; j++){
-+      if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break;
-+    }
-+    if( j>=pTab->nCol ){
-+      sqliteErrorMsg(pParse, "table %s has no column named %s",
-+        pTab->zName, pList->a[i].zName);
-+      sqliteFree(pIndex);
-+      goto exit_create_index;
-+    }
-+    pIndex->aiColumn[i] = j;
-+  }
-+
-+  /* Link the new Index structure to its table and to the other
-+  ** in-memory database structures. 
-+  */
-+  if( !pParse->explain ){
-+    Index *p;
-+    p = sqliteHashInsert(&db->aDb[pIndex->iDb].idxHash, 
-+                         pIndex->zName, strlen(pIndex->zName)+1, pIndex);
-+    if( p ){
-+      assert( p==pIndex );  /* Malloc must have failed */
-+      sqliteFree(pIndex);
-+      goto exit_create_index;
-+    }
-+    db->flags |= SQLITE_InternChanges;
-+  }
-+
-+  /* When adding an index to the list of indices for a table, make
-+  ** sure all indices labeled OE_Replace come after all those labeled
-+  ** OE_Ignore.  This is necessary for the correct operation of UPDATE
-+  ** and INSERT.
-+  */
-+  if( onError!=OE_Replace || pTab->pIndex==0
-+       || pTab->pIndex->onError==OE_Replace){
-+    pIndex->pNext = pTab->pIndex;
-+    pTab->pIndex = pIndex;
-+  }else{
-+    Index *pOther = pTab->pIndex;
-+    while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
-+      pOther = pOther->pNext;
-+    }
-+    pIndex->pNext = pOther->pNext;
-+    pOther->pNext = pIndex;
-+  }
-+
-+  /* If the db->init.busy is 1 it means we are reading the SQL off the
-+  ** "sqlite_master" table on the disk.  So do not write to the disk
-+  ** again.  Extract the table number from the db->init.newTnum field.
-+  */
-+  if( db->init.busy && pTable!=0 ){
-+    pIndex->tnum = db->init.newTnum;
-+  }
-+
-+  /* If the db->init.busy is 0 then create the index on disk.  This
-+  ** involves writing the index into the master table and filling in the
-+  ** index with the current table contents.
-+  **
-+  ** The db->init.busy is 0 when the user first enters a CREATE INDEX 
-+  ** command.  db->init.busy is 1 when a database is opened and 
-+  ** CREATE INDEX statements are read out of the master table.  In
-+  ** the latter case the index already exists on disk, which is why
-+  ** we don't want to recreate it.
-+  **
-+  ** If pTable==0 it means this index is generated as a primary key
-+  ** or UNIQUE constraint of a CREATE TABLE statement.  Since the table
-+  ** has just been created, it contains no data and the index initialization
-+  ** step can be skipped.
-+  */
-+  else if( db->init.busy==0 ){
-+    int n;
-+    Vdbe *v;
-+    int lbl1, lbl2;
-+    int i;
-+    int addr;
-+
-+    v = sqliteGetVdbe(pParse);
-+    if( v==0 ) goto exit_create_index;
-+    if( pTable!=0 ){
-+      sqliteBeginWriteOperation(pParse, 0, isTemp);
-+      sqliteOpenMasterTable(v, isTemp);
-+    }
-+    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
-+    sqliteVdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC);
-+    sqliteVdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0);
-+    sqliteVdbeOp3(v, OP_String, 0, 0, pTab->zName, 0);
-+    sqliteVdbeOp3(v, OP_CreateIndex, 0, isTemp,(char*)&pIndex->tnum,P3_POINTER);
-+    pIndex->tnum = 0;
-+    if( pTable ){
-+      sqliteVdbeCode(v,
-+          OP_Dup,       0,      0,
-+          OP_Integer,   isTemp, 0,
-+          OP_OpenWrite, 1,      0,
-+      0);
-+    }
-+    addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
-+    if( pStart && pEnd ){
-+      n = Addr(pEnd->z) - Addr(pStart->z) + 1;
-+      sqliteVdbeChangeP3(v, addr, pStart->z, n);
-+    }
-+    sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
-+    sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
-+    if( pTable ){
-+      sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-+      sqliteVdbeOp3(v, OP_OpenRead, 2, pTab->tnum, pTab->zName, 0);
-+      lbl2 = sqliteVdbeMakeLabel(v);
-+      sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
-+      lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
-+      for(i=0; i<pIndex->nColumn; i++){
-+        int iCol = pIndex->aiColumn[i];
-+        if( pTab->iPKey==iCol ){
-+          sqliteVdbeAddOp(v, OP_Dup, i, 0);
-+        }else{
-+          sqliteVdbeAddOp(v, OP_Column, 2, iCol);
-+        }
-+      }
-+      sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
-+      if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIndex);
-+      sqliteVdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
-+                      "indexed columns are not unique", P3_STATIC);
-+      sqliteVdbeAddOp(v, OP_Next, 2, lbl1);
-+      sqliteVdbeResolveLabel(v, lbl2);
-+      sqliteVdbeAddOp(v, OP_Close, 2, 0);
-+      sqliteVdbeAddOp(v, OP_Close, 1, 0);
-+    }
-+    if( pTable!=0 ){
-+      if( !isTemp ){
-+        sqliteChangeCookie(db, v);
-+      }
-+      sqliteVdbeAddOp(v, OP_Close, 0, 0);
-+      sqliteEndWriteOperation(pParse);
-+    }
-+  }
-+
-+  /* Clean up before exiting */
-+exit_create_index:
-+  sqliteIdListDelete(pList);
-+  sqliteSrcListDelete(pTable);
-+  sqliteFree(zName);
-+  return;
-+}
-+
-+/*
-+** This routine will drop an existing named index.  This routine
-+** implements the DROP INDEX statement.
-+*/
-+void sqliteDropIndex(Parse *pParse, SrcList *pName){
-+  Index *pIndex;
-+  Vdbe *v;
-+  sqlite *db = pParse->db;
-+
-+  if( pParse->nErr || sqlite_malloc_failed ) return;
-+  assert( pName->nSrc==1 );
-+  pIndex = sqliteFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
-+  if( pIndex==0 ){
-+    sqliteErrorMsg(pParse, "no such index: %S", pName, 0);
-+    goto exit_drop_index;
-+  }
-+  if( pIndex->autoIndex ){
-+    sqliteErrorMsg(pParse, "index associated with UNIQUE "
-+      "or PRIMARY KEY constraint cannot be dropped", 0);
-+    goto exit_drop_index;
-+  }
-+  if( pIndex->iDb>1 ){
-+    sqliteErrorMsg(pParse, "cannot alter schema of attached "
-+       "databases", 0);
-+    goto exit_drop_index;
-+  }
-+#ifndef SQLITE_OMIT_AUTHORIZATION
-+  {
-+    int code = SQLITE_DROP_INDEX;
-+    Table *pTab = pIndex->pTable;
-+    const char *zDb = db->aDb[pIndex->iDb].zName;
-+    const char *zTab = SCHEMA_TABLE(pIndex->iDb);
-+    if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
-+      goto exit_drop_index;
-+    }
-+    if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX;
-+    if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
-+      goto exit_drop_index;
-+    }
-+  }
-+#endif
-+
-+  /* Generate code to remove the index and from the master table */
-+  v = sqliteGetVdbe(pParse);
-+  if( v ){
-+    static VdbeOpList dropIndex[] = {
-+      { OP_Rewind,     0, ADDR(9), 0}, 
-+      { OP_String,     0, 0,       0}, /* 1 */
-+      { OP_MemStore,   1, 1,       0},
-+      { OP_MemLoad,    1, 0,       0}, /* 3 */
-+      { OP_Column,     0, 1,       0},
-+      { OP_Eq,         0, ADDR(8), 0},
-+      { OP_Next,       0, ADDR(3), 0},
-+      { OP_Goto,       0, ADDR(9), 0},
-+      { OP_Delete,     0, 0,       0}, /* 8 */
-+    };
-+    int base;
-+
-+    sqliteBeginWriteOperation(pParse, 0, pIndex->iDb);
-+    sqliteOpenMasterTable(v, pIndex->iDb);
-+    base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
-+    sqliteVdbeChangeP3(v, base+1, pIndex->zName, 0);
-+    if( pIndex->iDb==0 ){
-+      sqliteChangeCookie(db, v);
-+    }
-+    sqliteVdbeAddOp(v, OP_Close, 0, 0);
-+    sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
-+    sqliteEndWriteOperation(pParse);
-+  }
-+
-+  /* Delete the in-memory description of this index.
-+  */
-+  if( !pParse->explain ){
-+    sqliteUnlinkAndDeleteIndex(db, pIndex);
-+    db->flags |= SQLITE_InternChanges;
-+  }
-+
-+exit_drop_index:
-+  sqliteSrcListDelete(pName);
-+}
-+
-+/*
-+** Append a new element to the given IdList.  Create a new IdList if
-+** need be.
-+**
-+** A new IdList is returned, or NULL if malloc() fails.
-+*/
-+IdList *sqliteIdListAppend(IdList *pList, Token *pToken){
-+  if( pList==0 ){
-+    pList = sqliteMalloc( sizeof(IdList) );
-+    if( pList==0 ) return 0;
-+    pList->nAlloc = 0;
-+  }
-+  if( pList->nId>=pList->nAlloc ){
-+    struct IdList_item *a;
-+    pList->nAlloc = pList->nAlloc*2 + 5;
-+    a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) );
-+    if( a==0 ){
-+      sqliteIdListDelete(pList);
-+      return 0;
-+    }
-+    pList->a = a;
-+  }
-+  memset(&pList->a[pList->nId], 0, sizeof(pList->a[0]));
-+  if( pToken ){
-+    char **pz = &pList->a[pList->nId].zName;
-+    sqliteSetNString(pz, pToken->z, pToken->n, 0);
-+    if( *pz==0 ){
-+      sqliteIdListDelete(pList);
-+      return 0;
-+    }else{
-+      sqliteDequote(*pz);
-+    }
-+  }
-+  pList->nId++;
-+  return pList;
-+}
-+
-+/*
-+** 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.
-+**
-+** A new SrcList is returned, or NULL if malloc() fails.
-+**
-+** If pDatabase is not null, it means that the table has an optional
-+** database name prefix.  Like this:  "database.table".  The pDatabase
-+** points to the table name and the pTable points to the database name.
-+** The SrcList.a[].zName field is filled with the table name which might
-+** come from pTable (if pDatabase is NULL) or from pDatabase.  
-+** SrcList.a[].zDatabase is filled with the database name from pTable,
-+** or with NULL if no database is specified.
-+**
-+** In other words, if call like this:
-+**
-+**         sqliteSrcListAppend(A,B,0);
-+**
-+** Then B is a table name and the database name is unspecified.  If called
-+** like this:
-+**
-+**         sqliteSrcListAppend(A,B,C);
-+**
-+** Then C is the table name and B is the database name.
-+*/
-+SrcList *sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
-+  if( pList==0 ){
-+    pList = sqliteMalloc( sizeof(SrcList) );
-+    if( pList==0 ) return 0;
-+    pList->nAlloc = 1;
-+  }
-+  if( pList->nSrc>=pList->nAlloc ){
-+    SrcList *pNew;
-+    pList->nAlloc *= 2;
-+    pNew = sqliteRealloc(pList,
-+               sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) );
-+    if( pNew==0 ){
-+      sqliteSrcListDelete(pList);
-+      return 0;
-+    }
-+    pList = pNew;
-+  }
-+  memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0]));
-+  if( pDatabase && pDatabase->z==0 ){
-+    pDatabase = 0;
-+  }
-+  if( pDatabase && pTable ){
-+    Token *pTemp = pDatabase;
-+    pDatabase = pTable;
-+    pTable = pTemp;
-+  }
-+  if( pTable ){
-+    char **pz = &pList->a[pList->nSrc].zName;
-+    sqliteSetNString(pz, pTable->z, pTable->n, 0);
-+    if( *pz==0 ){
-+      sqliteSrcListDelete(pList);
-+      return 0;
-+    }else{
-+      sqliteDequote(*pz);
-+    }
-+  }
-+  if( pDatabase ){
-+    char **pz = &pList->a[pList->nSrc].zDatabase;
-+    sqliteSetNString(pz, pDatabase->z, pDatabase->n, 0);
-+    if( *pz==0 ){
-+      sqliteSrcListDelete(pList);
-+      return 0;
-+    }else{
-+      sqliteDequote(*pz);
-+    }
-+  }
-+  pList->a[pList->nSrc].iCursor = -1;
-+  pList->nSrc++;
-+  return pList;
-+}
-+
-+/*
-+** Assign cursors to all tables in a SrcList
-+*/
-+void sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList){
-+  int i;
-+  for(i=0; i<pList->nSrc; i++){
-+    if( pList->a[i].iCursor<0 ){
-+      pList->a[i].iCursor = pParse->nTab++;
-+    }
-+  }
-+}
-+
-+/*
-+** Add an alias to the last identifier on the given identifier list.
-+*/
-+void sqliteSrcListAddAlias(SrcList *pList, Token *pToken){
-+  if( pList && pList->nSrc>0 ){
-+    int i = pList->nSrc - 1;
-+    sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0);
-+    sqliteDequote(pList->a[i].zAlias);
-+  }
-+}
-+
-+/*
-+** Delete an IdList.
-+*/
-+void sqliteIdListDelete(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 sqliteIdListIndex(IdList *pList, const char *zName){
-+  int i;
-+  if( pList==0 ) return -1;
-+  for(i=0; i<pList->nId; i++){
-+    if( sqliteStrICmp(pList->a[i].zName, zName)==0 ) return i;
-+  }
-+  return -1;
-+}
-+
-+/*
-+** Delete an entire SrcList including all its substructure.
-+*/
-+void sqliteSrcListDelete(SrcList *pList){
-+  int i;
-+  if( pList==0 ) return;
-+  for(i=0; i<pList->nSrc; i++){
-+    sqliteFree(pList->a[i].zDatabase);
-+    sqliteFree(pList->a[i].zName);
-+    sqliteFree(pList->a[i].zAlias);
-+    if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){
-+      sqliteDeleteTable(0, pList->a[i].pTab);
-+    }
-+    sqliteSelectDelete(pList->a[i].pSelect);
-+    sqliteExprDelete(pList->a[i].pOn);
-+    sqliteIdListDelete(pList->a[i].pUsing);
-+  }
-+  sqliteFree(pList);
-+}
-+
-+/*
-+** Begin a transaction
-+*/
-+void sqliteBeginTransaction(Parse *pParse, int onError){
-+  sqlite *db;
-+
-+  if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
-+  if( pParse->nErr || sqlite_malloc_failed ) return;
-+  if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return;
-+  if( db->flags & SQLITE_InTrans ){
-+    sqliteErrorMsg(pParse, "cannot start a transaction within a transaction");
-+    return;
-+  }
-+  sqliteBeginWriteOperation(pParse, 0, 0);
-+  if( !pParse->explain ){
-+    db->flags |= SQLITE_InTrans;
-+    db->onError = onError;
-+  }
-+}
-+
-+/*
-+** Commit a transaction
-+*/
-+void sqliteCommitTransaction(Parse *pParse){
-+  sqlite *db;
-+
-+  if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
-+  if( pParse->nErr || sqlite_malloc_failed ) return;
-+  if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return;
-+  if( (db->flags & SQLITE_InTrans)==0 ){
-+    sqliteErrorMsg(pParse, "cannot commit - no transaction is active");
-+    return;
-+  }
-+  if( !pParse->explain ){
-+    db->flags &= ~SQLITE_InTrans;
-+  }
-+  sqliteEndWriteOperation(pParse);
-+  if( !pParse->explain ){
-+    db->onError = OE_Default;
-+  }
-+}
-+
-+/*
-+** Rollback a transaction
-+*/
-+void sqliteRollbackTransaction(Parse *pParse){
-+  sqlite *db;
-+  Vdbe *v;
-+
-+  if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
-+  if( pParse->nErr || sqlite_malloc_failed ) return;
-+  if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return;
-+  if( (db->flags & SQLITE_InTrans)==0 ){
-+    sqliteErrorMsg(pParse, "cannot rollback - no transaction is active");
-+    return; 
-+  }
-+  v = sqliteGetVdbe(pParse);
-+  if( v ){
-+    sqliteVdbeAddOp(v, OP_Rollback, 0, 0);
-+  }
-+  if( !pParse->explain ){
-+    db->flags &= ~SQLITE_InTrans;
-+    db->onError = OE_Default;
-+  }
-+}
-+
-+/*
-+** Generate VDBE code that will verify the schema cookie for all
-+** named database files.
-+*/
-+void sqliteCodeVerifySchema(Parse *pParse, int iDb){
-+  sqlite *db = pParse->db;
-+  Vdbe *v = sqliteGetVdbe(pParse);
-+  assert( iDb>=0 && iDb<db->nDb );
-+  assert( db->aDb[iDb].pBt!=0 );
-+  if( iDb!=1 && !DbHasProperty(db, iDb, DB_Cookie) ){
-+    sqliteVdbeAddOp(v, OP_VerifyCookie, iDb, db->aDb[iDb].schema_cookie);
-+    DbSetProperty(db, iDb, DB_Cookie);
-+  }
-+}
-+
-+/*
-+** Generate VDBE code that prepares for doing an operation that
-+** might change the database.
-+**
-+** This routine starts a new transaction if we are not already within
-+** a transaction.  If we are already within a transaction, then a checkpoint
-+** is set if the setCheckpoint parameter is true.  A checkpoint should
-+** be set for operations that might fail (due to a constraint) part of
-+** the way through and which will need to undo some writes without having to
-+** rollback the whole transaction.  For operations where all constraints
-+** can be checked before any changes are made to the database, it is never
-+** necessary to undo a write and the checkpoint should not be set.
-+**
-+** Only database iDb and the temp database are made writable by this call.
-+** If iDb==0, then the main and temp databases are made writable.   If
-+** iDb==1 then only the temp database is made writable.  If iDb>1 then the
-+** specified auxiliary database and the temp database are made writable.
-+*/
-+void sqliteBeginWriteOperation(Parse *pParse, int setCheckpoint, int iDb){
-+  Vdbe *v;
-+  sqlite *db = pParse->db;
-+  if( DbHasProperty(db, iDb, DB_Locked) ) return;
-+  v = sqliteGetVdbe(pParse);
-+  if( v==0 ) return;
-+  if( !db->aDb[iDb].inTrans ){
-+    sqliteVdbeAddOp(v, OP_Transaction, iDb, 0);
-+    DbSetProperty(db, iDb, DB_Locked);
-+    sqliteCodeVerifySchema(pParse, iDb);
-+    if( iDb!=1 ){
-+      sqliteBeginWriteOperation(pParse, setCheckpoint, 1);
-+    }
-+  }else if( setCheckpoint ){
-+    sqliteVdbeAddOp(v, OP_Checkpoint, iDb, 0);
-+    DbSetProperty(db, iDb, DB_Locked);
-+  }
-+}
-+
-+/*
-+** Generate code that concludes an operation that may have changed
-+** the database.  If a statement transaction was started, then emit
-+** an OP_Commit that will cause the changes to be committed to disk.
-+**
-+** Note that checkpoints are automatically committed at the end of
-+** a statement.  Note also that there can be multiple calls to 
-+** sqliteBeginWriteOperation() but there should only be a single
-+** call to sqliteEndWriteOperation() at the conclusion of the statement.
-+*/
-+void sqliteEndWriteOperation(Parse *pParse){
-+  Vdbe *v;
-+  sqlite *db = pParse->db;
-+  if( pParse->trigStack ) return; /* if this is in a trigger */
-+  v = sqliteGetVdbe(pParse);
-+  if( v==0 ) return;
-+  if( db->flags & SQLITE_InTrans ){
-+    /* A BEGIN has executed.  Do not commit until we see an explicit
-+    ** COMMIT statement. */
-+  }else{
-+    sqliteVdbeAddOp(v, OP_Commit, 0, 0);
-+  }
-+}
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/config_static.w32.h
-@@ -0,0 +1 @@
-+#define SQLITE_PTR_SZ 4
-\ No newline at end of file
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/copy.c
-@@ -0,0 +1,110 @@
-+/*
-+** 2003 April 6
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains code used to implement the COPY command.
-+**
-+** $Id$
-+*/
-+#include "sqliteInt.h"
-+
-+/*
-+** The COPY command is for compatibility with PostgreSQL and specificially
-+** for the ability to read the output of pg_dump.  The format is as
-+** follows:
-+**
-+**    COPY table FROM file [USING DELIMITERS string]
-+**
-+** "table" is an existing table name.  We will read lines of code from
-+** file to fill this table with data.  File might be "stdin".  The optional
-+** delimiter string identifies the field separators.  The default is a tab.
-+*/
-+void sqliteCopy(
-+  Parse *pParse,       /* The parser context */
-+  SrcList *pTableName, /* The name of the table into which we will insert */
-+  Token *pFilename,    /* The file from which to obtain information */
-+  Token *pDelimiter,   /* Use this as the field delimiter */
-+  int onError          /* What to do if a constraint fails */
-+){
-+  Table *pTab;
-+  int i;
-+  Vdbe *v;
-+  int addr, end;
-+  char *zFile = 0;
-+  const char *zDb;
-+  sqlite *db = pParse->db;
-+
-+
-+  if( sqlite_malloc_failed  ) goto copy_cleanup;
-+  assert( pTableName->nSrc==1 );
-+  pTab = sqliteSrcListLookup(pParse, pTableName);
-+  if( pTab==0 || sqliteIsReadOnly(pParse, pTab, 0) ) goto copy_cleanup;
-+  zFile = sqliteStrNDup(pFilename->z, pFilename->n);
-+  sqliteDequote(zFile);
-+  assert( pTab->iDb<db->nDb );
-+  zDb = db->aDb[pTab->iDb].zName;
-+  if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb)
-+      || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile, zDb) ){
-+    goto copy_cleanup;
-+  }
-+  v = sqliteGetVdbe(pParse);
-+  if( v ){
-+    sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
-+    addr = sqliteVdbeOp3(v, OP_FileOpen, 0, 0, pFilename->z, pFilename->n);
-+    sqliteVdbeDequoteP3(v, addr);
-+    sqliteOpenTableAndIndices(pParse, pTab, 0);
-+    if( db->flags & SQLITE_CountRows ){
-+      sqliteVdbeAddOp(v, OP_Integer, 0, 0);  /* Initialize the row count */
-+    }
-+    end = sqliteVdbeMakeLabel(v);
-+    addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end);
-+    if( pDelimiter ){
-+      sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
-+      sqliteVdbeDequoteP3(v, addr);
-+    }else{
-+      sqliteVdbeChangeP3(v, addr, "\t", 1);
-+    }
-+    if( pTab->iPKey>=0 ){
-+      sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0);
-+      sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
-+    }else{
-+      sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
-+    }
-+    for(i=0; i<pTab->nCol; i++){
-+      if( i==pTab->iPKey ){
-+        /* The integer primary key column is filled with NULL since its
-+        ** value is always pulled from the record number */
-+        sqliteVdbeAddOp(v, OP_String, 0, 0);
-+      }else{
-+        sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
-+      }
-+    }
-+    sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, pTab->iPKey>=0, 
-+                                   0, onError, addr);
-+    sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0, -1);
-+    if( (db->flags & SQLITE_CountRows)!=0 ){
-+      sqliteVdbeAddOp(v, OP_AddImm, 1, 0);  /* Increment row count */
-+    }
-+    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
-+    sqliteVdbeResolveLabel(v, end);
-+    sqliteVdbeAddOp(v, OP_Noop, 0, 0);
-+    sqliteEndWriteOperation(pParse);
-+    if( db->flags & SQLITE_CountRows ){
-+      sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
-+      sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
-+      sqliteVdbeAddOp(v, OP_Callback, 1, 0);
-+    }
-+  }
-+  
-+copy_cleanup:
-+  sqliteSrcListDelete(pTableName);
-+  sqliteFree(zFile);
-+  return;
-+}
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/date.c
-@@ -0,0 +1,881 @@
-+/*
-+** 2003 October 31
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains the C functions that implement date and time
-+** functions for SQLite.  
-+**
-+** There is only one exported symbol in this file - the function
-+** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
-+** All other code has file scope.
-+**
-+** $Id$
-+**
-+** NOTES:
-+**
-+** SQLite processes all times and dates as Julian Day numbers.  The
-+** dates and times are stored as the number of days since noon
-+** in Greenwich on November 24, 4714 B.C. according to the Gregorian
-+** calendar system.
-+**
-+** 1970-01-01 00:00:00 is JD 2440587.5
-+** 2000-01-01 00:00:00 is JD 2451544.5
-+**
-+** This implemention requires years to be expressed as a 4-digit number
-+** which means that only dates between 0000-01-01 and 9999-12-31 can
-+** be represented, even though julian day numbers allow a much wider
-+** range of dates.
-+**
-+** The Gregorian calendar system is used for all dates and times,
-+** even those that predate the Gregorian calendar.  Historians usually
-+** use the Julian calendar for dates prior to 1582-10-15 and for some
-+** dates afterwards, depending on locale.  Beware of this difference.
-+**
-+** The conversion algorithms are implemented based on descriptions
-+** in the following text:
-+**
-+**      Jean Meeus
-+**      Astronomical Algorithms, 2nd Edition, 1998
-+**      ISBM 0-943396-61-1
-+**      Willmann-Bell, Inc
-+**      Richmond, Virginia (USA)
-+*/
-+#include "os.h"
-+#include "sqliteInt.h"
-+#include <ctype.h>
-+#include <stdlib.h>
-+#include <assert.h>
-+#include <time.h>
-+#ifndef PHP_WIN32
-+#include "main/php_reentrancy.h"
-+#endif
-+
-+#ifndef SQLITE_OMIT_DATETIME_FUNCS
-+
-+/*
-+** A structure for holding a single date and time.
-+*/
-+typedef struct DateTime DateTime;
-+struct DateTime {
-+  double rJD;      /* The julian day number */
-+  int Y, M, D;     /* Year, month, and day */
-+  int h, m;        /* Hour and minutes */
-+  int tz;          /* Timezone offset in minutes */
-+  double s;        /* Seconds */
-+  char validYMD;   /* True if Y,M,D are valid */
-+  char validHMS;   /* True if h,m,s are valid */
-+  char validJD;    /* True if rJD is valid */
-+  char validTZ;    /* True if tz is valid */
-+};
-+
-+
-+/*
-+** Convert zDate into one or more integers.  Additional arguments
-+** come in groups of 5 as follows:
-+**
-+**       N       number of digits in the integer
-+**       min     minimum allowed value of the integer
-+**       max     maximum allowed value of the integer
-+**       nextC   first character after the integer
-+**       pVal    where to write the integers value.
-+**
-+** Conversions continue until one with nextC==0 is encountered.
-+** The function returns the number of successful conversions.
-+*/
-+static int getDigits(const char *zDate, ...){
-+  va_list ap;
-+  int val;
-+  int N;
-+  int min;
-+  int max;
-+  int nextC;
-+  int *pVal;
-+  int cnt = 0;
-+  va_start(ap, zDate);
-+  do{
-+    N = va_arg(ap, int);
-+    min = va_arg(ap, int);
-+    max = va_arg(ap, int);
-+    nextC = va_arg(ap, int);
-+    pVal = va_arg(ap, int*);
-+    val = 0;
-+    while( N-- ){
-+      if( !isdigit(*zDate) ){
-+        return cnt;
-+      }
-+      val = val*10 + *zDate - '0';
-+      zDate++;
-+    }
-+    if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
-+      return cnt;
-+    }
-+    *pVal = val;
-+    zDate++;
-+    cnt++;
-+  }while( nextC );
-+  return cnt;
-+}
-+
-+/*
-+** 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 = sqliteAtoF(z, &zEnd);
-+  return zEnd - z;
-+}
-+
-+/*
-+** Parse a timezone extension on the end of a date-time.
-+** The extension is of the form:
-+**
-+**        (+/-)HH:MM
-+**
-+** If the parse is successful, write the number of minutes
-+** of change in *pnMin and return 0.  If a parser error occurs,
-+** return 0.
-+**
-+** A missing specifier is not considered an error.
-+*/
-+static int parseTimezone(const char *zDate, DateTime *p){
-+  int sgn = 0;
-+  int nHr, nMn;
-+  while( isspace(*zDate) ){ zDate++; }
-+  p->tz = 0;
-+  if( *zDate=='-' ){
-+    sgn = -1;
-+  }else if( *zDate=='+' ){
-+    sgn = +1;
-+  }else{
-+    return *zDate!=0;
-+  }
-+  zDate++;
-+  if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
-+    return 1;
-+  }
-+  zDate += 5;
-+  p->tz = sgn*(nMn + nHr*60);
-+  while( isspace(*zDate) ){ zDate++; }
-+  return *zDate!=0;
-+}
-+
-+/*
-+** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
-+** The HH, MM, and SS must each be exactly 2 digits.  The
-+** fractional seconds FFFF can be one or more digits.
-+**
-+** Return 1 if there is a parsing error and 0 on success.
-+*/
-+static int parseHhMmSs(const char *zDate, DateTime *p){
-+  int h, m, s;
-+  double ms = 0.0;
-+  if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
-+    return 1;
-+  }
-+  zDate += 5;
-+  if( *zDate==':' ){
-+    zDate++;
-+    if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
-+      return 1;
-+    }
-+    zDate += 2;
-+    if( *zDate=='.' && isdigit(zDate[1]) ){
-+      double rScale = 1.0;
-+      zDate++;
-+      while( isdigit(*zDate) ){
-+        ms = ms*10.0 + *zDate - '0';
-+        rScale *= 10.0;
-+        zDate++;
-+      }
-+      ms /= rScale;
-+    }
-+  }else{
-+    s = 0;
-+  }
-+  p->validJD = 0;
-+  p->validHMS = 1;
-+  p->h = h;
-+  p->m = m;
-+  p->s = s + ms;
-+  if( parseTimezone(zDate, p) ) return 1;
-+  p->validTZ = p->tz!=0;
-+  return 0;
-+}
-+
-+/*
-+** Convert from YYYY-MM-DD HH:MM:SS to julian day.  We always assume
-+** that the YYYY-MM-DD is according to the Gregorian calendar.
-+**
-+** Reference:  Meeus page 61
-+*/
-+static void computeJD(DateTime *p){
-+  int Y, M, D, A, B, X1, X2;
-+
-+  if( p->validJD ) return;
-+  if( p->validYMD ){
-+    Y = p->Y;
-+    M = p->M;
-+    D = p->D;
-+  }else{
-+    Y = 2000;  /* If no YMD specified, assume 2000-Jan-01 */
-+    M = 1;
-+    D = 1;
-+  }
-+  if( M<=2 ){
-+    Y--;
-+    M += 12;
-+  }
-+  A = Y/100;
-+  B = 2 - A + (A/4);
-+  X1 = 365.25*(Y+4716);
-+  X2 = 30.6001*(M+1);
-+  p->rJD = X1 + X2 + D + B - 1524.5;
-+  p->validJD = 1;
-+  p->validYMD = 0;
-+  if( p->validHMS ){
-+    p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0;
-+    if( p->validTZ ){
-+      p->rJD += p->tz*60/86400.0;
-+      p->validHMS = 0;
-+      p->validTZ = 0;
-+    }
-+  }
-+}
-+
-+/*
-+** Parse dates of the form
-+**
-+**     YYYY-MM-DD HH:MM:SS.FFF
-+**     YYYY-MM-DD HH:MM:SS
-+**     YYYY-MM-DD HH:MM
-+**     YYYY-MM-DD
-+**
-+** Write the result into the DateTime structure and return 0
-+** on success and 1 if the input string is not a well-formed
-+** date.
-+*/
-+static int parseYyyyMmDd(const char *zDate, DateTime *p){
-+  int Y, M, D, neg;
-+
-+  if( zDate[0]=='-' ){
-+    zDate++;
-+    neg = 1;
-+  }else{
-+    neg = 0;
-+  }
-+  if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
-+    return 1;
-+  }
-+  zDate += 10;
-+  while( isspace(*zDate) ){ zDate++; }
-+  if( parseHhMmSs(zDate, p)==0 ){
-+    /* We got the time */
-+  }else if( *zDate==0 ){
-+    p->validHMS = 0;
-+  }else{
-+    return 1;
-+  }
-+  p->validJD = 0;
-+  p->validYMD = 1;
-+  p->Y = neg ? -Y : Y;
-+  p->M = M;
-+  p->D = D;
-+  if( p->validTZ ){
-+    computeJD(p);
-+  }
-+  return 0;
-+}
-+
-+/*
-+** Attempt to parse the given string into a Julian Day Number.  Return
-+** the number of errors.
-+**
-+** The following are acceptable forms for the input string:
-+**
-+**      YYYY-MM-DD HH:MM:SS.FFF  +/-HH:MM
-+**      DDDD.DD 
-+**      now
-+**
-+** In the first form, the +/-HH:MM is always optional.  The fractional
-+** seconds extension (the ".FFF") is optional.  The seconds portion
-+** (":SS.FFF") is option.  The year and date can be omitted as long
-+** as there is a time string.  The time string can be omitted as long
-+** as there is a year and date.
-+*/
-+static int parseDateOrTime(const char *zDate, DateTime *p){
-+  memset(p, 0, sizeof(*p));
-+  if( parseYyyyMmDd(zDate,p)==0 ){
-+    return 0;
-+  }else if( parseHhMmSs(zDate, p)==0 ){
-+    return 0;
-+  }else if( sqliteStrICmp(zDate,"now")==0){
-+    double r;
-+    if( sqliteOsCurrentTime(&r)==0 ){
-+      p->rJD = r;
-+      p->validJD = 1;
-+      return 0;
-+    }
-+    return 1;
-+  }else if( sqliteIsNumber(zDate) ){
-+    p->rJD = sqliteAtoF(zDate, 0);
-+    p->validJD = 1;
-+    return 0;
-+  }
-+  return 1;
-+}
-+
-+/*
-+** Compute the Year, Month, and Day from the julian day number.
-+*/
-+static void computeYMD(DateTime *p){
-+  int Z, A, B, C, D, E, X1;
-+  if( p->validYMD ) return;
-+  if( !p->validJD ){
-+    p->Y = 2000;
-+    p->M = 1;
-+    p->D = 1;
-+  }else{
-+    Z = p->rJD + 0.5;
-+    A = (Z - 1867216.25)/36524.25;
-+    A = Z + 1 + A - (A/4);
-+    B = A + 1524;
-+    C = (B - 122.1)/365.25;
-+    D = 365.25*C;
-+    E = (B-D)/30.6001;
-+    X1 = 30.6001*E;
-+    p->D = B - D - X1;
-+    p->M = E<14 ? E-1 : E-13;
-+    p->Y = p->M>2 ? C - 4716 : C - 4715;
-+  }
-+  p->validYMD = 1;
-+}
-+
-+/*
-+** Compute the Hour, Minute, and Seconds from the julian day number.
-+*/
-+static void computeHMS(DateTime *p){
-+  int Z, s;
-+  if( p->validHMS ) return;
-+  Z = p->rJD + 0.5;
-+  s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5;
-+  p->s = 0.001*s;
-+  s = p->s;
-+  p->s -= s;
-+  p->h = s/3600;
-+  s -= p->h*3600;
-+  p->m = s/60;
-+  p->s += s - p->m*60;
-+  p->validHMS = 1;
-+}
-+
-+/*
-+** Compute both YMD and HMS
-+*/
-+static void computeYMD_HMS(DateTime *p){
-+  computeYMD(p);
-+  computeHMS(p);
-+}
-+
-+/*
-+** Clear the YMD and HMS and the TZ
-+*/
-+static void clearYMD_HMS_TZ(DateTime *p){
-+  p->validYMD = 0;
-+  p->validHMS = 0;
-+  p->validTZ = 0;
-+}
-+
-+/*
-+** Compute the difference (in days) between localtime and UTC (a.k.a. GMT)
-+** for the time value p where p is in UTC.
-+*/
-+static double localtimeOffset(DateTime *p){
-+  DateTime x, y;
-+  time_t t;
-+  struct tm *pTm, tmbuf;
-+  x = *p;
-+  computeYMD_HMS(&x);
-+  if( x.Y<1971 || x.Y>=2038 ){
-+    x.Y = 2000;
-+    x.M = 1;
-+    x.D = 1;
-+    x.h = 0;
-+    x.m = 0;
-+    x.s = 0.0;
-+  } else {
-+    int s = x.s + 0.5;
-+    x.s = s;
-+  }
-+  x.tz = 0;
-+  x.validJD = 0;
-+  computeJD(&x);
-+  t = (x.rJD-2440587.5)*86400.0 + 0.5;
-+  sqliteOsEnterMutex();
-+  pTm = php_localtime_r(&t, &tmbuf);
-+  if (!pTm) {
-+	  return 0;
-+  }
-+  y.Y = pTm->tm_year + 1900;
-+  y.M = pTm->tm_mon + 1;
-+  y.D = pTm->tm_mday;
-+  y.h = pTm->tm_hour;
-+  y.m = pTm->tm_min;
-+  y.s = pTm->tm_sec;
-+  sqliteOsLeaveMutex();
-+  y.validYMD = 1;
-+  y.validHMS = 1;
-+  y.validJD = 0;
-+  y.validTZ = 0;
-+  computeJD(&y);
-+  return y.rJD - x.rJD;
-+}
-+
-+/*
-+** Process a modifier to a date-time stamp.  The modifiers are
-+** as follows:
-+**
-+**     NNN days
-+**     NNN hours
-+**     NNN minutes
-+**     NNN.NNNN seconds
-+**     NNN months
-+**     NNN years
-+**     start of month
-+**     start of year
-+**     start of week
-+**     start of day
-+**     weekday N
-+**     unixepoch
-+**     localtime
-+**     utc
-+**
-+** Return 0 on success and 1 if there is any kind of error.
-+*/
-+static int parseModifier(const char *zMod, DateTime *p){
-+  int rc = 1;
-+  int n;
-+  double r;
-+  char *z, zBuf[30];
-+  z = zBuf;
-+  for(n=0; n<sizeof(zBuf)-1 && zMod[n]; n++){
-+    z[n] = tolower(zMod[n]);
-+  }
-+  z[n] = 0;
-+  switch( z[0] ){
-+    case 'l': {
-+      /*    localtime
-+      **
-+      ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
-+      ** show local time.
-+      */
-+      if( strcmp(z, "localtime")==0 ){
-+        computeJD(p);
-+        p->rJD += localtimeOffset(p);
-+        clearYMD_HMS_TZ(p);
-+        rc = 0;
-+      }
-+      break;
-+    }
-+    case 'u': {
-+      /*
-+      **    unixepoch
-+      **
-+      ** Treat the current value of p->rJD as the number of
-+      ** seconds since 1970.  Convert to a real julian day number.
-+      */
-+      if( strcmp(z, "unixepoch")==0 && p->validJD ){
-+        p->rJD = p->rJD/86400.0 + 2440587.5;
-+        clearYMD_HMS_TZ(p);
-+        rc = 0;
-+      }else if( strcmp(z, "utc")==0 ){
-+        double c1;
-+        computeJD(p);
-+        c1 = localtimeOffset(p);
-+        p->rJD -= c1;
-+        clearYMD_HMS_TZ(p);
-+        p->rJD += c1 - localtimeOffset(p);
-+        rc = 0;
-+      }
-+      break;
-+    }
-+    case 'w': {
-+      /*
-+      **    weekday N
-+      **
-+      ** Move the date to the same time on the next occurrance of
-+      ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
-+      ** date is already on the appropriate weekday, this is a no-op.
-+      */
-+      if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
-+                 && (n=r)==r && n>=0 && r<7 ){
-+        int Z;
-+        computeYMD_HMS(p);
-+        p->validTZ = 0;
-+        p->validJD = 0;
-+        computeJD(p);
-+        Z = p->rJD + 1.5;
-+        Z %= 7;
-+        if( Z>n ) Z -= 7;
-+        p->rJD += n - Z;
-+        clearYMD_HMS_TZ(p);
-+        rc = 0;
-+      }
-+      break;
-+    }
-+    case 's': {
-+      /*
-+      **    start of TTTTT
-+      **
-+      ** Move the date backwards to the beginning of the current day,
-+      ** or month or year.
-+      */
-+      if( strncmp(z, "start of ", 9)!=0 ) break;
-+      z += 9;
-+      computeYMD(p);
-+      p->validHMS = 1;
-+      p->h = p->m = 0;
-+      p->s = 0.0;
-+      p->validTZ = 0;
-+      p->validJD = 0;
-+      if( strcmp(z,"month")==0 ){
-+        p->D = 1;
-+        rc = 0;
-+      }else if( strcmp(z,"year")==0 ){
-+        computeYMD(p);
-+        p->M = 1;
-+        p->D = 1;
-+        rc = 0;
-+      }else if( strcmp(z,"day")==0 ){
-+        rc = 0;
-+      }
-+      break;
-+    }
-+    case '+':
-+    case '-':
-+    case '0':
-+    case '1':
-+    case '2':
-+    case '3':
-+    case '4':
-+    case '5':
-+    case '6':
-+    case '7':
-+    case '8':
-+    case '9': {
-+      n = getValue(z, &r);
-+      if( n<=0 ) break;
-+      if( z[n]==':' ){
-+        /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
-+        ** specified number of hours, minutes, seconds, and fractional seconds
-+        ** to the time.  The ".FFF" may be omitted.  The ":SS.FFF" may be
-+        ** omitted.
-+        */
-+        const char *z2 = z;
-+        DateTime tx;
-+        int day;
-+        if( !isdigit(*z2) ) z2++;
-+        memset(&tx, 0, sizeof(tx));
-+        if( parseHhMmSs(z2, &tx) ) break;
-+        computeJD(&tx);
-+        tx.rJD -= 0.5;
-+        day = (int)tx.rJD;
-+        tx.rJD -= day;
-+        if( z[0]=='-' ) tx.rJD = -tx.rJD;
-+        computeJD(p);
-+        clearYMD_HMS_TZ(p);
-+       p->rJD += tx.rJD;
-+        rc = 0;
-+        break;
-+      }
-+      z += n;
-+      while( isspace(z[0]) ) z++;
-+      n = strlen(z);
-+      if( n>10 || n<3 ) break;
-+      if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
-+      computeJD(p);
-+      rc = 0;
-+      if( n==3 && strcmp(z,"day")==0 ){
-+        p->rJD += r;
-+      }else if( n==4 && strcmp(z,"hour")==0 ){
-+        p->rJD += r/24.0;
-+      }else if( n==6 && strcmp(z,"minute")==0 ){
-+        p->rJD += r/(24.0*60.0);
-+      }else if( n==6 && strcmp(z,"second")==0 ){
-+        p->rJD += r/(24.0*60.0*60.0);
-+      }else if( n==5 && strcmp(z,"month")==0 ){
-+        int x, y;
-+        computeYMD_HMS(p);
-+        p->M += r;
-+        x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
-+        p->Y += x;
-+        p->M -= x*12;
-+        p->validJD = 0;
-+        computeJD(p);
-+        y = r;
-+        if( y!=r ){
-+          p->rJD += (r - y)*30.0;
-+        }
-+      }else if( n==4 && strcmp(z,"year")==0 ){
-+        computeYMD_HMS(p);
-+        p->Y += r;
-+        p->validJD = 0;
-+        computeJD(p);
-+      }else{
-+        rc = 1;
-+      }
-+      clearYMD_HMS_TZ(p);
-+      break;
-+    }
-+    default: {
-+      break;
-+    }
-+  }
-+  return rc;
-+}
-+
-+/*
-+** Process time function arguments.  argv[0] is a date-time stamp.
-+** argv[1] and following are modifiers.  Parse them all and write
-+** the resulting time into the DateTime structure p.  Return 0
-+** on success and 1 if there are any errors.
-+*/
-+static int isDate(int argc, const char **argv, DateTime *p){
-+  int i;
-+  if( argc==0 ) return 1;
-+  if( argv[0]==0 || parseDateOrTime(argv[0], p) ) return 1;
-+  for(i=1; i<argc; i++){
-+    if( argv[i]==0 || parseModifier(argv[i], p) ) return 1;
-+  }
-+  return 0;
-+}
-+
-+
-+/*
-+** The following routines implement the various date and time functions
-+** of SQLite.
-+*/
-+
-+/*
-+**    julianday( TIMESTRING, MOD, MOD, ...)
-+**
-+** Return the julian day number of the date specified in the arguments
-+*/
-+static void juliandayFunc(sqlite_func *context, int argc, const char **argv){
-+  DateTime x;
-+  if( isDate(argc, argv, &x)==0 ){
-+    computeJD(&x);
-+    sqlite_set_result_double(context, x.rJD);
-+  }
-+}
-+
-+/*
-+**    datetime( TIMESTRING, MOD, MOD, ...)
-+**
-+** Return YYYY-MM-DD HH:MM:SS
-+*/
-+static void datetimeFunc(sqlite_func *context, int argc, const char **argv){
-+  DateTime x;
-+  if( isDate(argc, argv, &x)==0 ){
-+    char zBuf[100];
-+    computeYMD_HMS(&x);
-+    sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m,
-+           (int)(x.s));
-+    sqlite_set_result_string(context, zBuf, -1);
-+  }
-+}
-+
-+/*
-+**    time( TIMESTRING, MOD, MOD, ...)
-+**
-+** Return HH:MM:SS
-+*/
-+static void timeFunc(sqlite_func *context, int argc, const char **argv){
-+  DateTime x;
-+  if( isDate(argc, argv, &x)==0 ){
-+    char zBuf[100];
-+    computeHMS(&x);
-+    sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
-+    sqlite_set_result_string(context, zBuf, -1);
-+  }
-+}
-+
-+/*
-+**    date( TIMESTRING, MOD, MOD, ...)
-+**
-+** Return YYYY-MM-DD
-+*/
-+static void dateFunc(sqlite_func *context, int argc, const char **argv){
-+  DateTime x;
-+  if( isDate(argc, argv, &x)==0 ){
-+    char zBuf[100];
-+    computeYMD(&x);
-+    sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
-+    sqlite_set_result_string(context, zBuf, -1);
-+  }
-+}
-+
-+/*
-+**    strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
-+**
-+** Return a string described by FORMAT.  Conversions as follows:
-+**
-+**   %d  day of month
-+**   %f  ** fractional seconds  SS.SSS
-+**   %H  hour 00-24
-+**   %j  day of year 000-366
-+**   %J  ** Julian day number
-+**   %m  month 01-12
-+**   %M  minute 00-59
-+**   %s  seconds since 1970-01-01
-+**   %S  seconds 00-59
-+**   %w  day of week 0-6  sunday==0
-+**   %W  week of year 00-53
-+**   %Y  year 0000-9999
-+**   %%  %
-+*/
-+static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
-+  DateTime x;
-+  int n, i, j;
-+  char *z;
-+  const char *zFmt = argv[0];
-+  char zBuf[100];
-+  if( argv[0]==0 || isDate(argc-1, argv+1, &x) ) return;
-+  for(i=0, n=1; zFmt[i]; i++, n++){
-+    if( zFmt[i]=='%' ){
-+      switch( zFmt[i+1] ){
-+        case 'd':
-+        case 'H':
-+        case 'm':
-+        case 'M':
-+        case 'S':
-+        case 'W':
-+          n++;
-+          /* fall thru */
-+        case 'w':
-+        case '%':
-+          break;
-+        case 'f':
-+          n += 8;
-+          break;
-+        case 'j':
-+          n += 3;
-+          break;
-+        case 'Y':
-+          n += 8;
-+          break;
-+        case 's':
-+        case 'J':
-+          n += 50;
-+          break;
-+        default:
-+          return;  /* ERROR.  return a NULL */
-+      }
-+      i++;
-+    }
-+  }
-+  if( n<sizeof(zBuf) ){
-+    z = zBuf;
-+  }else{
-+    z = sqliteMalloc( n );
-+    if( z==0 ) return;
-+  }
-+  computeJD(&x);
-+  computeYMD_HMS(&x);
-+  for(i=j=0; zFmt[i]; i++){
-+    if( zFmt[i]!='%' ){
-+      z[j++] = zFmt[i];
-+    }else{
-+      i++;
-+      switch( zFmt[i] ){
-+        case 'd':  sprintf(&z[j],"%02d",x.D); j+=2; break;
-+        case 'f': {
-+          int s = x.s;
-+          int ms = (x.s - s)*1000.0;
-+          sprintf(&z[j],"%02d.%03d",s,ms);
-+          j += strlen(&z[j]);
-+          break;
-+        }
-+        case 'H':  sprintf(&z[j],"%02d",x.h); j+=2; break;
-+        case 'W': /* Fall thru */
-+        case 'j': {
-+          int n;             /* Number of days since 1st day of year */
-+          DateTime y = x;
-+          y.validJD = 0;
-+          y.M = 1;
-+          y.D = 1;
-+          computeJD(&y);
-+          n = x.rJD - y.rJD;
-+          if( zFmt[i]=='W' ){
-+            int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */
-+            wd = ((int)(x.rJD+0.5)) % 7;
-+            sprintf(&z[j],"%02d",(n+7-wd)/7);
-+            j += 2;
-+          }else{
-+            sprintf(&z[j],"%03d",n+1);
-+            j += 3;
-+          }
-+          break;
-+        }
-+        case 'J':  sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break;
-+        case 'm':  sprintf(&z[j],"%02d",x.M); j+=2; break;
-+        case 'M':  sprintf(&z[j],"%02d",x.m); j+=2; break;
-+        case 's': {
-+          sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5));
-+          j += strlen(&z[j]);
-+          break;
-+        }
-+        case 'S':  sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break;
-+        case 'w':  z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
-+        case 'Y':  sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
-+        case '%':  z[j++] = '%'; break;
-+      }
-+    }
-+  }
-+  z[j] = 0;
-+  sqlite_set_result_string(context, z, -1);
-+  if( z!=zBuf ){
-+    sqliteFree(z);
-+  }
-+}
-+
-+
-+#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
-+
-+/*
-+** This function registered all of the above C functions as SQL
-+** functions.  This should be the only routine in this file with
-+** external linkage.
-+*/
-+void sqliteRegisterDateTimeFunctions(sqlite *db){
-+#ifndef SQLITE_OMIT_DATETIME_FUNCS
-+  static struct {
-+     char *zName;
-+     int nArg;
-+     int dataType;
-+     void (*xFunc)(sqlite_func*,int,const char**);
-+  } aFuncs[] = {
-+    { "julianday", -1, SQLITE_NUMERIC, juliandayFunc   },
-+    { "date",      -1, SQLITE_TEXT,    dateFunc        },
-+    { "time",      -1, SQLITE_TEXT,    timeFunc        },
-+    { "datetime",  -1, SQLITE_TEXT,    datetimeFunc    },
-+    { "strftime",  -1, SQLITE_TEXT,    strftimeFunc    },
-+  };
-+  int i;
-+
-+  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
-+    sqlite_create_function(db, aFuncs[i].zName,
-+           aFuncs[i].nArg, aFuncs[i].xFunc, 0);
-+    if( aFuncs[i].xFunc ){
-+      sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
-+    }
-+  }
-+#endif
-+}
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/delete.c
-@@ -0,0 +1,393 @@
-+/*
-+** 2001 September 15
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains C code routines that are called by the parser
-+** to handle DELETE FROM statements.
-+**
-+** $Id$
-+*/
-+#include "sqliteInt.h"
-+
-+/*
-+** Look up every table that is named in pSrc.  If any table is not found,
-+** add an error message to pParse->zErrMsg and return NULL.  If all tables
-+** are found, return a pointer to the last table.
-+*/
-+Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
-+  Table *pTab = 0;
-+  int i;
-+  for(i=0; i<pSrc->nSrc; i++){
-+    const char *zTab = pSrc->a[i].zName;
-+    const char *zDb = pSrc->a[i].zDatabase;
-+    pTab = sqliteLocateTable(pParse, zTab, zDb);
-+    pSrc->a[i].pTab = pTab;
-+  }
-+  return pTab;
-+}
-+
-+/*
-+** Check to make sure the given table is writable.  If it is not
-+** writable, generate an error message and return 1.  If it is
-+** writable return 0;
-+*/
-+int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){
-+  if( pTab->readOnly ){
-+    sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName);
-+    return 1;
-+  }
-+  if( !viewOk && pTab->pSelect ){
-+    sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName);
-+    return 1;
-+  }
-+  return 0;
-+}
-+
-+/*
-+** Process a DELETE FROM statement.
-+*/
-+void sqliteDeleteFrom(
-+  Parse *pParse,         /* The parser context */
-+  SrcList *pTabList,     /* The table from which we should delete things */
-+  Expr *pWhere           /* The WHERE clause.  May be null */
-+){
-+  Vdbe *v;               /* The virtual database engine */
-+  Table *pTab;           /* The table from which records will be deleted */
-+  const char *zDb;       /* Name of database holding pTab */
-+  int end, addr;         /* A couple addresses of generated code */
-+  int i;                 /* Loop counter */
-+  WhereInfo *pWInfo;     /* Information about the WHERE clause */
-+  Index *pIdx;           /* For looping over indices of the table */
-+  int iCur;              /* VDBE Cursor number for pTab */
-+  sqlite *db;            /* Main database structure */
-+  int isView;            /* True if attempting to delete from a view */
-+  AuthContext sContext;  /* Authorization context */
-+
-+  int row_triggers_exist = 0;  /* True if any triggers exist */
-+  int before_triggers;         /* True if there are BEFORE triggers */
-+  int after_triggers;          /* True if there are AFTER triggers */
-+  int oldIdx = -1;             /* Cursor for the OLD table of AFTER triggers */
-+
-+  sContext.pParse = 0;
-+  if( pParse->nErr || sqlite_malloc_failed ){
-+    pTabList = 0;
-+    goto delete_from_cleanup;
-+  }
-+  db = pParse->db;
-+  assert( pTabList->nSrc==1 );
-+
-+  /* Locate the table which we want to delete.  This table has to be
-+  ** put in an SrcList structure because some of the subroutines we
-+  ** will be calling are designed to work with multiple tables and expect
-+  ** an SrcList* parameter instead of just a Table* parameter.
-+  */
-+  pTab = sqliteSrcListLookup(pParse, pTabList);
-+  if( pTab==0 )  goto delete_from_cleanup;
-+  before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, 
-+                         TK_DELETE, TK_BEFORE, TK_ROW, 0);
-+  after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, 
-+                         TK_DELETE, TK_AFTER, TK_ROW, 0);
-+  row_triggers_exist = before_triggers || after_triggers;
-+  isView = pTab->pSelect!=0;
-+  if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
-+    goto delete_from_cleanup;
-+  }
-+  assert( pTab->iDb<db->nDb );
-+  zDb = db->aDb[pTab->iDb].zName;
-+  if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
-+    goto delete_from_cleanup;
-+  }
-+
-+  /* If pTab is really a view, make sure it has been initialized.
-+  */
-+  if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
-+    goto delete_from_cleanup;
-+  }
-+
-+  /* Allocate a cursor used to store the old.* data for a trigger.
-+  */
-+  if( row_triggers_exist ){ 
-+    oldIdx = pParse->nTab++;
-+  }
-+
-+  /* Resolve the column names in all the expressions.
-+  */
-+  assert( pTabList->nSrc==1 );
-+  iCur = pTabList->a[0].iCursor = pParse->nTab++;
-+  if( pWhere ){
-+    if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
-+      goto delete_from_cleanup;
-+    }
-+    if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
-+      goto delete_from_cleanup;
-+    }
-+  }
-+
-+  /* Start the view context
-+  */
-+  if( isView ){
-+    sqliteAuthContextPush(pParse, &sContext, pTab->zName);
-+  }
-+
-+  /* Begin generating code.
-+  */
-+  v = sqliteGetVdbe(pParse);
-+  if( v==0 ){
-+    goto delete_from_cleanup;
-+  }
-+  sqliteBeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
-+
-+  /* If we are trying to delete from a view, construct that view into
-+  ** a temporary table.
-+  */
-+  if( isView ){
-+    Select *pView = sqliteSelectDup(pTab->pSelect);
-+    sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
-+    sqliteSelectDelete(pView);
-+  }
-+
-+  /* Initialize the counter of the number of rows deleted, if
-+  ** we are counting rows.
-+  */
-+  if( db->flags & SQLITE_CountRows ){
-+    sqliteVdbeAddOp(v, OP_Integer, 0, 0);
-+  }
-+
-+  /* Special case: A DELETE without a WHERE clause deletes everything.
-+  ** It is easier just to erase the whole table.  Note, however, that
-+  ** this means that the row change count will be incorrect.
-+  */
-+  if( pWhere==0 && !row_triggers_exist ){
-+    if( db->flags & SQLITE_CountRows ){
-+      /* If counting rows deleted, just count the total number of
-+      ** entries in the table. */
-+      int endOfLoop = sqliteVdbeMakeLabel(v);
-+      int addr;
-+      if( !isView ){
-+        sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-+        sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
-+      }
-+      sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2);
-+      addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
-+      sqliteVdbeAddOp(v, OP_Next, iCur, addr);
-+      sqliteVdbeResolveLabel(v, endOfLoop);
-+      sqliteVdbeAddOp(v, OP_Close, iCur, 0);
-+    }
-+    if( !isView ){
-+      sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
-+      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
-+        sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb);
-+      }
-+    }
-+  }
-+
-+  /* The usual case: There is a WHERE clause so we have to scan through
-+  ** the table and pick which records to delete.
-+  */
-+  else{
-+    /* Begin the database scan
-+    */
-+    pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
-+    if( pWInfo==0 ) goto delete_from_cleanup;
-+
-+    /* Remember the key of every item to be deleted.
-+    */
-+    sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
-+    if( db->flags & SQLITE_CountRows ){
-+      sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
-+    }
-+
-+    /* End the database scan loop.
-+    */
-+    sqliteWhereEnd(pWInfo);
-+
-+    /* Open the pseudo-table used to store OLD if there are triggers.
-+    */
-+    if( row_triggers_exist ){
-+      sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
-+    }
-+
-+    /* Delete every item whose key was written to the list during the
-+    ** database scan.  We have to delete items after the scan is complete
-+    ** because deleting an item can change the scan order.
-+    */
-+    sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
-+    end = sqliteVdbeMakeLabel(v);
-+
-+    /* This is the beginning of the delete loop when there are
-+    ** row triggers.
-+    */
-+    if( row_triggers_exist ){
-+      addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
-+      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
-+      if( !isView ){
-+        sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-+        sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
-+      }
-+      sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
-+
-+      sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
-+      sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
-+      sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
-+      if( !isView ){
-+        sqliteVdbeAddOp(v, OP_Close, iCur, 0);
-+      }
-+
-+      sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, 
-+          oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
-+	  addr);
-+    }
-+
-+    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
-+      ** before the trigger fires.  If there are no row triggers, the
-+      ** cursors are opened only once on the outside the loop.
-+      */
-+      pParse->nTab = iCur + 1;
-+      sqliteOpenTableAndIndices(pParse, pTab, iCur);
-+
-+      /* This is the beginning of the delete loop when there are no
-+      ** row triggers */
-+      if( !row_triggers_exist ){ 
-+        addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
-+      }
-+
-+      /* Delete the row */
-+      sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0);
-+    }
-+
-+    /* If there are row triggers, close all cursors then invoke
-+    ** the AFTER triggers
-+    */
-+    if( row_triggers_exist ){
-+      if( !isView ){
-+        for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
-+          sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
-+        }
-+        sqliteVdbeAddOp(v, OP_Close, iCur, 0);
-+      }
-+      sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, 
-+          oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
-+	  addr);
-+    }
-+
-+    /* End of the delete loop */
-+    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
-+    sqliteVdbeResolveLabel(v, end);
-+    sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
-+
-+    /* Close the cursors after the loop if there are no row triggers */
-+    if( !row_triggers_exist ){
-+      for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
-+        sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
-+      }
-+      sqliteVdbeAddOp(v, OP_Close, iCur, 0);
-+      pParse->nTab = iCur;
-+    }
-+  }
-+  sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
-+  sqliteEndWriteOperation(pParse);
-+
-+  /*
-+  ** Return the number of rows that were deleted.
-+  */
-+  if( db->flags & SQLITE_CountRows ){
-+    sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
-+    sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
-+    sqliteVdbeAddOp(v, OP_Callback, 1, 0);
-+  }
-+
-+delete_from_cleanup:
-+  sqliteAuthContextPop(&sContext);
-+  sqliteSrcListDelete(pTabList);
-+  sqliteExprDelete(pWhere);
-+  return;
-+}
-+
-+/*
-+** This routine generates VDBE code that causes a single row of a
-+** single table to be deleted.
-+**
-+** The VDBE must be in a particular state when this routine is called.
-+** These are the requirements:
-+**
-+**   1.  A read/write cursor pointing to pTab, the table containing the row
-+**       to be deleted, must be opened as cursor number "base".
-+**
-+**   2.  Read/write cursors for all indices of pTab must be open as
-+**       cursor number base+i for the i-th index.
-+**
-+**   3.  The record number of the row to be deleted must be on the top
-+**       of the stack.
-+**
-+** This routine pops the top of the stack to remove the record number
-+** and then generates code to remove both the table record and all index
-+** entries that point to that record.
-+*/
-+void sqliteGenerateRowDelete(
-+  sqlite *db,        /* The database containing the index */
-+  Vdbe *v,           /* Generate code into this VDBE */
-+  Table *pTab,       /* Table containing the row to be deleted */
-+  int iCur,          /* Cursor number for the table */
-+  int count          /* Increment the row change counter */
-+){
-+  int addr;
-+  addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
-+  sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
-+  sqliteVdbeAddOp(v, OP_Delete, iCur,
-+    (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
-+  sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
-+}
-+
-+/*
-+** This routine generates VDBE code that causes the deletion of all
-+** index entries associated with a single row of a single table.
-+**
-+** The VDBE must be in a particular state when this routine is called.
-+** These are the requirements:
-+**
-+**   1.  A read/write cursor pointing to pTab, the table containing the row
-+**       to be deleted, must be opened as cursor number "iCur".
-+**
-+**   2.  Read/write cursors for all indices of pTab must be open as
-+**       cursor number iCur+i for the i-th index.
-+**
-+**   3.  The "iCur" cursor must be pointing to the row that is to be
-+**       deleted.
-+*/
-+void sqliteGenerateRowIndexDelete(
-+  sqlite *db,        /* The database containing the index */
-+  Vdbe *v,           /* Generate code into this VDBE */
-+  Table *pTab,       /* Table containing the row to be deleted */
-+  int iCur,          /* Cursor number for the table */
-+  char *aIdxUsed     /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
-+){
-+  int i;
-+  Index *pIdx;
-+
-+  for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
-+    int j;
-+    if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
-+    sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
-+    for(j=0; j<pIdx->nColumn; j++){
-+      int idx = pIdx->aiColumn[j];
-+      if( idx==pTab->iPKey ){
-+        sqliteVdbeAddOp(v, OP_Dup, j, 0);
-+      }else{
-+        sqliteVdbeAddOp(v, OP_Column, iCur, idx);
-+      }
-+    }
-+    sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
-+    if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
-+    sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
-+  }
-+}
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/encode.c
-@@ -0,0 +1,257 @@
-+/*
-+** 2002 April 25
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains helper routines used to translate binary data into
-+** a null-terminated string (suitable for use in SQLite) and back again.
-+** These are convenience routines for use by people who want to store binary
-+** data in an SQLite database.  The code in this file is not used by any other
-+** part of the SQLite library.
-+**
-+** $Id$
-+*/
-+#include <string.h>
-+#include <assert.h>
-+
-+/*
-+** How This Encoder Works
-+**
-+** The output is allowed to contain any character except 0x27 (') and
-+** 0x00.  This is accomplished by using an escape character to encode
-+** 0x27 and 0x00 as a two-byte sequence.  The escape character is always
-+** 0x01.  An 0x00 is encoded as the two byte sequence 0x01 0x01.  The
-+** 0x27 character is encoded as the two byte sequence 0x01 0x28.  Finally,
-+** the escape character itself is encoded as the two-character sequence
-+** 0x01 0x02.
-+**
-+** To summarize, the encoder works by using an escape sequences as follows:
-+**
-+**       0x00  ->  0x01 0x01
-+**       0x01  ->  0x01 0x02
-+**       0x27  ->  0x01 0x28
-+**
-+** If that were all the encoder did, it would work, but in certain cases
-+** it could double the size of the encoded string.  For example, to
-+** encode a string of 100 0x27 characters would require 100 instances of
-+** the 0x01 0x03 escape sequence resulting in a 200-character output.
-+** We would prefer to keep the size of the encoded string smaller than
-+** this.
-+**
-+** To minimize the encoding size, we first add a fixed offset value to each 
-+** byte in the sequence.  The addition is modulo 256.  (That is to say, if
-+** the sum of the original character value and the offset exceeds 256, then
-+** the higher order bits are truncated.)  The offset is chosen to minimize
-+** the number of characters in the string that need to be escaped.  For
-+** example, in the case above where the string was composed of 100 0x27
-+** characters, the offset might be 0x01.  Each of the 0x27 characters would
-+** then be converted into an 0x28 character which would not need to be
-+** escaped at all and so the 100 character input string would be converted
-+** into just 100 characters of output.  Actually 101 characters of output - 
-+** we have to record the offset used as the first byte in the sequence so
-+** that the string can be decoded.  Since the offset value is stored as
-+** part of the output string and the output string is not allowed to contain
-+** characters 0x00 or 0x27, the offset cannot be 0x00 or 0x27.
-+**
-+** Here, then, are the encoding steps:
-+**
-+**     (1)   Choose an offset value and make it the first character of
-+**           output.
-+**
-+**     (2)   Copy each input character into the output buffer, one by
-+**           one, adding the offset value as you copy.
-+**
-+**     (3)   If the value of an input character plus offset is 0x00, replace
-+**           that one character by the two-character sequence 0x01 0x01.
-+**           If the sum is 0x01, replace it with 0x01 0x02.  If the sum
-+**           is 0x27, replace it with 0x01 0x03.
-+**
-+**     (4)   Put a 0x00 terminator at the end of the output.
-+**
-+** Decoding is obvious:
-+**
-+**     (5)   Copy encoded characters except the first into the decode 
-+**           buffer.  Set the first encoded character aside for use as
-+**           the offset in step 7 below.
-+**
-+**     (6)   Convert each 0x01 0x01 sequence into a single character 0x00.
-+**           Convert 0x01 0x02 into 0x01.  Convert 0x01 0x28 into 0x27.
-+**
-+**     (7)   Subtract the offset value that was the first character of
-+**           the encoded buffer from all characters in the output buffer.
-+**
-+** The only tricky part is step (1) - how to compute an offset value to
-+** minimize the size of the output buffer.  This is accomplished by testing
-+** all offset values and picking the one that results in the fewest number
-+** of escapes.  To do that, we first scan the entire input and count the
-+** number of occurances of each character value in the input.  Suppose
-+** the number of 0x00 characters is N(0), the number of occurances of 0x01
-+** is N(1), and so forth up to the number of occurances of 0xff is N(255).
-+** An offset of 0 is not allowed so we don't have to test it.  The number
-+** of escapes required for an offset of 1 is N(1)+N(2)+N(40).  The number
-+** of escapes required for an offset of 2 is N(2)+N(3)+N(41).  And so forth.
-+** In this way we find the offset that gives the minimum number of escapes,
-+** and thus minimizes the length of the output string.
-+*/
-+
-+/*
-+** Encode a binary buffer "in" of size n bytes so that it contains
-+** no instances of characters '\'' or '\000'.  The output is 
-+** null-terminated and can be used as a string value in an INSERT
-+** or UPDATE statement.  Use sqlite_decode_binary() to convert the
-+** string back into its original binary.
-+**
-+** The result is written into a preallocated output buffer "out".
-+** "out" must be able to hold at least 2 +(257*n)/254 bytes.
-+** In other words, the output will be expanded by as much as 3
-+** bytes for every 254 bytes of input plus 2 bytes of fixed overhead.
-+** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.)
-+**
-+** The return value is the number of characters in the encoded
-+** string, excluding the "\000" terminator.
-+**
-+** If out==NULL then no output is generated but the routine still returns
-+** the number of characters that would have been generated if out had
-+** not been NULL.
-+*/
-+int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out){
-+  int i, j, e, m;
-+  unsigned char x;
-+  int cnt[256];
-+  if( n<=0 ){
-+    if( out ){
-+      out[0] = 'x';
-+      out[1] = 0;
-+    }
-+    return 1;
-+  }
-+  memset(cnt, 0, sizeof(cnt));
-+  for(i=n-1; i>=0; i--){ cnt[in[i]]++; }
-+  m = n;
-+  for(i=1; i<256; i++){
-+    int sum;
-+    if( i=='\'' ) continue;
-+    sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff];
-+    if( sum<m ){
-+      m = sum;
-+      e = i;
-+      if( m==0 ) break;
-+    }
-+  }
-+  if( out==0 ){
-+    return n+m+1;
-+  }
-+  out[0] = e;
-+  j = 1;
-+  for(i=0; i<n; i++){
-+    x = in[i] - e;
-+    if( x==0 || x==1 || x=='\''){
-+      out[j++] = 1;
-+      x++;
-+    }
-+    out[j++] = x;
-+  }
-+  out[j] = 0;
-+  assert( j==n+m+1 );
-+  return j;
-+}
-+
-+/*
-+** Decode the string "in" into binary data and write it into "out".
-+** This routine reverses the encoding created by sqlite_encode_binary().
-+** The output will always be a few bytes less than the input.  The number
-+** of bytes of output is returned.  If the input is not a well-formed
-+** encoding, -1 is returned.
-+**
-+** The "in" and "out" parameters may point to the same buffer in order
-+** to decode a string in place.
-+*/
-+int sqlite_decode_binary(const unsigned char *in, unsigned char *out){
-+  int i, e;
-+  unsigned char c;
-+  e = *(in++);
-+  if (e == 0) {
-+    return 0;
-+  }
-+  i = 0;
-+  while( (c = *(in++))!=0 ){
-+    if (c == 1) {
-+      c = *(in++) - 1;
-+    }
-+    out[i++] = c + e;
-+  }
-+  return i;
-+}
-+
-+#ifdef ENCODER_TEST
-+#include <stdio.h>
-+/*
-+** The subroutines above are not tested by the usual test suite.  To test
-+** these routines, compile just this one file with a -DENCODER_TEST=1 option
-+** and run the result.
-+*/
-+int main(int argc, char **argv){
-+  int i, j, n, m, nOut, nByteIn, nByteOut;
-+  unsigned char in[30000];
-+  unsigned char out[33000];
-+
-+  nByteIn = nByteOut = 0;
-+  for(i=0; i<sizeof(in); i++){
-+    printf("Test %d: ", i+1);
-+    n = rand() % (i+1);
-+    if( i%100==0 ){
-+      int k;
-+      for(j=k=0; j<n; j++){
-+        /* if( k==0 || k=='\'' ) k++; */
-+        in[j] = k;
-+        k = (k+1)&0xff;
-+      }
-+    }else{
-+      for(j=0; j<n; j++) in[j] = rand() & 0xff;
-+    }
-+    nByteIn += n;
-+    nOut = sqlite_encode_binary(in, n, out);
-+    nByteOut += nOut;
-+    if( nOut!=strlen(out) ){
-+      printf(" ERROR return value is %d instead of %d\n", nOut, strlen(out));
-+      exit(1);
-+    }
-+    if( nOut!=sqlite_encode_binary(in, n, 0) ){
-+      printf(" ERROR actual output size disagrees with predicted size\n");
-+      exit(1);
-+    }
-+    m = (256*n + 1262)/253;
-+    printf("size %d->%d (max %d)", n, strlen(out)+1, m);
-+    if( strlen(out)+1>m ){
-+      printf(" ERROR output too big\n");
-+      exit(1);
-+    }
-+    for(j=0; out[j]; j++){
-+      if( out[j]=='\'' ){
-+        printf(" ERROR contains (')\n");
-+        exit(1);
-+      }
-+    }
-+    j = sqlite_decode_binary(out, out);
-+    if( j!=n ){
-+      printf(" ERROR decode size %d\n", j);
-+      exit(1);
-+    }
-+    if( memcmp(in, out, n)!=0 ){
-+      printf(" ERROR decode mismatch\n");
-+      exit(1);
-+    }
-+    printf(" OK\n");
-+  }
-+  fprintf(stderr,"Finished.  Total encoding: %d->%d bytes\n",
-+          nByteIn, nByteOut);
-+  fprintf(stderr,"Avg size increase: %.3f%%\n",
-+    (nByteOut-nByteIn)*100.0/(double)nByteIn);
-+}
-+#endif /* ENCODER_TEST */
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/expr.c
-@@ -0,0 +1,1662 @@
-+/*
-+** 2001 September 15
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains routines used for analyzing expressions and
-+** for generating VDBE code that evaluates expressions in SQLite.
-+**
-+** $Id$
-+*/
-+#include "sqliteInt.h"
-+#include <ctype.h>
-+
-+/*
-+** Construct a new expression node and return a pointer to it.  Memory
-+** for this node is obtained from sqliteMalloc().  The calling function
-+** is responsible for making sure the node eventually gets freed.
-+*/
-+Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
-+  Expr *pNew;
-+  pNew = sqliteMalloc( sizeof(Expr) );
-+  if( pNew==0 ){
-+    /* When malloc fails, we leak memory from pLeft and pRight */
-+    return 0;
-+  }
-+  pNew->op = op;
-+  pNew->pLeft = pLeft;
-+  pNew->pRight = pRight;
-+  if( pToken ){
-+    assert( pToken->dyn==0 );
-+    pNew->token = *pToken;
-+    pNew->span = *pToken;
-+  }else{
-+    assert( pNew->token.dyn==0 );
-+    assert( pNew->token.z==0 );
-+    assert( pNew->token.n==0 );
-+    if( pLeft && pRight ){
-+      sqliteExprSpan(pNew, &pLeft->span, &pRight->span);
-+    }else{
-+      pNew->span = pNew->token;
-+    }
-+  }
-+  return pNew;
-+}
-+
-+/*
-+** Set the Expr.span field of the given expression to span all
-+** text between the two given tokens.
-+*/
-+void sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
-+  assert( pRight!=0 );
-+  assert( pLeft!=0 );
-+  /* Note: pExpr might be NULL due to a prior malloc failure */
-+  if( pExpr && pRight->z && pLeft->z ){
-+    if( pLeft->dyn==0 && pRight->dyn==0 ){
-+      pExpr->span.z = pLeft->z;
-+      pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z);
-+    }else{
-+      pExpr->span.z = 0;
-+    }
-+  }
-+}
-+
-+/*
-+** Construct a new expression node for a function with multiple
-+** arguments.
-+*/
-+Expr *sqliteExprFunction(ExprList *pList, Token *pToken){
-+  Expr *pNew;
-+  pNew = sqliteMalloc( sizeof(Expr) );
-+  if( pNew==0 ){
-+    /* sqliteExprListDelete(pList); // Leak pList when malloc fails */
-+    return 0;
-+  }
-+  pNew->op = TK_FUNCTION;
-+  pNew->pList = pList;
-+  if( pToken ){
-+    assert( pToken->dyn==0 );
-+    pNew->token = *pToken;
-+  }else{
-+    pNew->token.z = 0;
-+  }
-+  pNew->span = pNew->token;
-+  return pNew;
-+}
-+
-+/*
-+** Recursively delete an expression tree.
-+*/
-+void sqliteExprDelete(Expr *p){
-+  if( p==0 ) return;
-+  if( p->span.dyn ) sqliteFree((char*)p->span.z);
-+  if( p->token.dyn ) sqliteFree((char*)p->token.z);
-+  sqliteExprDelete(p->pLeft);
-+  sqliteExprDelete(p->pRight);
-+  sqliteExprListDelete(p->pList);
-+  sqliteSelectDelete(p->pSelect);
-+  sqliteFree(p);
-+}
-+
-+
-+/*
-+** The following group of routines make deep copies of expressions,
-+** expression lists, ID lists, and select statements.  The copies can
-+** be deleted (by being passed to their respective ...Delete() routines)
-+** without effecting the originals.
-+**
-+** The expression list, ID, and source lists return by sqliteExprListDup(),
-+** sqliteIdListDup(), and sqliteSrcListDup() can not be further expanded 
-+** by subsequent calls to sqlite*ListAppend() routines.
-+**
-+** Any tables that the SrcList might point to are not duplicated.
-+*/
-+Expr *sqliteExprDup(Expr *p){
-+  Expr *pNew;
-+  if( p==0 ) return 0;
-+  pNew = sqliteMallocRaw( sizeof(*p) );
-+  if( pNew==0 ) return 0;
-+  memcpy(pNew, p, sizeof(*pNew));
-+  if( p->token.z!=0 ){
-+    pNew->token.z = sqliteStrNDup(p->token.z, p->token.n);
-+    pNew->token.dyn = 1;
-+  }else{
-+    assert( pNew->token.z==0 );
-+  }
-+  pNew->span.z = 0;
-+  pNew->pLeft = sqliteExprDup(p->pLeft);
-+  pNew->pRight = sqliteExprDup(p->pRight);
-+  pNew->pList = sqliteExprListDup(p->pList);
-+  pNew->pSelect = sqliteSelectDup(p->pSelect);
-+  return pNew;
-+}
-+void sqliteTokenCopy(Token *pTo, Token *pFrom){
-+  if( pTo->dyn ) sqliteFree((char*)pTo->z);
-+  if( pFrom->z ){
-+    pTo->n = pFrom->n;
-+    pTo->z = sqliteStrNDup(pFrom->z, pFrom->n);
-+    pTo->dyn = 1;
-+  }else{
-+    pTo->z = 0;
-+  }
-+}
-+ExprList *sqliteExprListDup(ExprList *p){
-+  ExprList *pNew;
-+  struct ExprList_item *pItem;
-+  int i;
-+  if( p==0 ) return 0;
-+  pNew = sqliteMalloc( sizeof(*pNew) );
-+  if( pNew==0 ) return 0;
-+  pNew->nExpr = pNew->nAlloc = p->nExpr;
-+  pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
-+  if( pItem==0 ){
-+    sqliteFree(pNew);
-+    return 0;
-+  }
-+  for(i=0; i<p->nExpr; i++, pItem++){
-+    Expr *pNewExpr, *pOldExpr;
-+    pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
-+    if( pOldExpr->span.z!=0 && pNewExpr ){
-+      /* Always make a copy of the span for top-level expressions in the
-+      ** expression list.  The logic in SELECT processing that determines
-+      ** the names of columns in the result set needs this information */
-+      sqliteTokenCopy(&pNewExpr->span, &pOldExpr->span);
-+    }
-+    assert( pNewExpr==0 || pNewExpr->span.z!=0 
-+            || pOldExpr->span.z==0 || sqlite_malloc_failed );
-+    pItem->zName = sqliteStrDup(p->a[i].zName);
-+    pItem->sortOrder = p->a[i].sortOrder;
-+    pItem->isAgg = p->a[i].isAgg;
-+    pItem->done = 0;
-+  }
-+  return pNew;
-+}
-+SrcList *sqliteSrcListDup(SrcList *p){
-+  SrcList *pNew;
-+  int i;
-+  int nByte;
-+  if( p==0 ) return 0;
-+  nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
-+  pNew = sqliteMallocRaw( nByte );
-+  if( pNew==0 ) return 0;
-+  pNew->nSrc = pNew->nAlloc = p->nSrc;
-+  for(i=0; i<p->nSrc; i++){
-+    struct SrcList_item *pNewItem = &pNew->a[i];
-+    struct SrcList_item *pOldItem = &p->a[i];
-+    pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase);
-+    pNewItem->zName = sqliteStrDup(pOldItem->zName);
-+    pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
-+    pNewItem->jointype = pOldItem->jointype;
-+    pNewItem->iCursor = pOldItem->iCursor;
-+    pNewItem->pTab = 0;
-+    pNewItem->pSelect = sqliteSelectDup(pOldItem->pSelect);
-+    pNewItem->pOn = sqliteExprDup(pOldItem->pOn);
-+    pNewItem->pUsing = sqliteIdListDup(pOldItem->pUsing);
-+  }
-+  return pNew;
-+}
-+IdList *sqliteIdListDup(IdList *p){
-+  IdList *pNew;
-+  int i;
-+  if( p==0 ) return 0;
-+  pNew = sqliteMallocRaw( sizeof(*pNew) );
-+  if( pNew==0 ) return 0;
-+  pNew->nId = pNew->nAlloc = p->nId;
-+  pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) );
-+  if( pNew->a==0 ) return 0;
-+  for(i=0; i<p->nId; i++){
-+    struct IdList_item *pNewItem = &pNew->a[i];
-+    struct IdList_item *pOldItem = &p->a[i];
-+    pNewItem->zName = sqliteStrDup(pOldItem->zName);
-+    pNewItem->idx = pOldItem->idx;
-+  }
-+  return pNew;
-+}
-+Select *sqliteSelectDup(Select *p){
-+  Select *pNew;
-+  if( p==0 ) return 0;
-+  pNew = sqliteMallocRaw( sizeof(*p) );
-+  if( pNew==0 ) return 0;
-+  pNew->isDistinct = p->isDistinct;
-+  pNew->pEList = sqliteExprListDup(p->pEList);
-+  pNew->pSrc = sqliteSrcListDup(p->pSrc);
-+  pNew->pWhere = sqliteExprDup(p->pWhere);
-+  pNew->pGroupBy = sqliteExprListDup(p->pGroupBy);
-+  pNew->pHaving = sqliteExprDup(p->pHaving);
-+  pNew->pOrderBy = sqliteExprListDup(p->pOrderBy);
-+  pNew->op = p->op;
-+  pNew->pPrior = sqliteSelectDup(p->pPrior);
-+  pNew->nLimit = p->nLimit;
-+  pNew->nOffset = p->nOffset;
-+  pNew->zSelect = 0;
-+  pNew->iLimit = -1;
-+  pNew->iOffset = -1;
-+  return pNew;
-+}
-+
-+
-+/*
-+** Add a new element to the end of an expression list.  If pList is
-+** initially NULL, then create a new expression list.
-+*/
-+ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
-+  if( pList==0 ){
-+    pList = sqliteMalloc( sizeof(ExprList) );
-+    if( pList==0 ){
-+      /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */
-+      return 0;
-+    }
-+    assert( pList->nAlloc==0 );
-+  }
-+  if( pList->nAlloc<=pList->nExpr ){
-+    pList->nAlloc = pList->nAlloc*2 + 4;
-+    pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]));
-+    if( pList->a==0 ){
-+      /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */
-+      pList->nExpr = pList->nAlloc = 0;
-+      return pList;
-+    }
-+  }
-+  assert( pList->a!=0 );
-+  if( pExpr || pName ){
-+    struct ExprList_item *pItem = &pList->a[pList->nExpr++];
-+    memset(pItem, 0, sizeof(*pItem));
-+    pItem->pExpr = pExpr;
-+    if( pName ){
-+      sqliteSetNString(&pItem->zName, pName->z, pName->n, 0);
-+      sqliteDequote(pItem->zName);
-+    }
-+  }
-+  return pList;
-+}
-+
-+/*
-+** Delete an entire expression list.
-+*/
-+void sqliteExprListDelete(ExprList *pList){
-+  int i;
-+  if( pList==0 ) return;
-+  assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
-+  assert( pList->nExpr<=pList->nAlloc );
-+  for(i=0; i<pList->nExpr; i++){
-+    sqliteExprDelete(pList->a[i].pExpr);
-+    sqliteFree(pList->a[i].zName);
-+  }
-+  sqliteFree(pList->a);
-+  sqliteFree(pList);
-+}
-+
-+/*
-+** Walk an expression tree.  Return 1 if the expression is constant
-+** and 0 if it involves variables.
-+**
-+** For the purposes of this function, a double-quoted string (ex: "abc")
-+** is considered a variable but a single-quoted string (ex: 'abc') is
-+** a constant.
-+*/
-+int sqliteExprIsConstant(Expr *p){
-+  switch( p->op ){
-+    case TK_ID:
-+    case TK_COLUMN:
-+    case TK_DOT:
-+    case TK_FUNCTION:
-+      return 0;
-+    case TK_NULL:
-+    case TK_STRING:
-+    case TK_INTEGER:
-+    case TK_FLOAT:
-+    case TK_VARIABLE:
-+      return 1;
-+    default: {
-+      if( p->pLeft && !sqliteExprIsConstant(p->pLeft) ) return 0;
-+      if( p->pRight && !sqliteExprIsConstant(p->pRight) ) return 0;
-+      if( p->pList ){
-+        int i;
-+        for(i=0; i<p->pList->nExpr; i++){
-+          if( !sqliteExprIsConstant(p->pList->a[i].pExpr) ) return 0;
-+        }
-+      }
-+      return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0);
-+    }
-+  }
-+  return 0;
-+}
-+
-+/*
-+** If the given expression codes a constant integer that is small enough
-+** to fit in a 32-bit integer, return 1 and put the value of the integer
-+** in *pValue.  If the expression is not an integer or if it is too big
-+** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
-+*/
-+int sqliteExprIsInteger(Expr *p, int *pValue){
-+  switch( p->op ){
-+    case TK_INTEGER: {
-+      if( sqliteFitsIn32Bits(p->token.z) ){
-+        *pValue = atoi(p->token.z);
-+        return 1;
-+      }
-+      break;
-+    }
-+    case TK_STRING: {
-+      const char *z = p->token.z;
-+      int n = p->token.n;
-+      if( n>0 && z[0]=='-' ){ z++; n--; }
-+      while( n>0 && *z && isdigit(*z) ){ z++; n--; }
-+      if( n==0 && sqliteFitsIn32Bits(p->token.z) ){
-+        *pValue = atoi(p->token.z);
-+        return 1;
-+      }
-+      break;
-+    }
-+    case TK_UPLUS: {
-+      return sqliteExprIsInteger(p->pLeft, pValue);
-+    }
-+    case TK_UMINUS: {
-+      int v;
-+      if( sqliteExprIsInteger(p->pLeft, &v) ){
-+        *pValue = -v;
-+        return 1;
-+      }
-+      break;
-+    }
-+    default: break;
-+  }
-+  return 0;
-+}
-+
-+/*
-+** Return TRUE if the given string is a row-id column name.
-+*/
-+int sqliteIsRowid(const char *z){
-+  if( sqliteStrICmp(z, "_ROWID_")==0 ) return 1;
-+  if( sqliteStrICmp(z, "ROWID")==0 ) return 1;
-+  if( sqliteStrICmp(z, "OID")==0 ) return 1;
-+  return 0;
-+}
-+
-+/*
-+** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
-+** that name in the set of source tables in pSrcList and make the pExpr 
-+** expression node refer back to that source column.  The following changes
-+** are made to pExpr:
-+**
-+**    pExpr->iDb           Set the index in db->aDb[] of the database holding
-+**                         the table.
-+**    pExpr->iTable        Set to the cursor number for the table obtained
-+**                         from pSrcList.
-+**    pExpr->iColumn       Set to the column number within the table.
-+**    pExpr->dataType      Set to the appropriate data type for the column.
-+**    pExpr->op            Set to TK_COLUMN.
-+**    pExpr->pLeft         Any expression this points to is deleted
-+**    pExpr->pRight        Any expression this points to is deleted.
-+**
-+** The pDbToken is the name of the database (the "X").  This value may be
-+** NULL meaning that name is of the form Y.Z or Z.  Any available database
-+** can be used.  The pTableToken is the name of the table (the "Y").  This
-+** value can be NULL if pDbToken is also NULL.  If pTableToken is NULL it
-+** means that the form of the name is Z and that columns from any table
-+** can be used.
-+**
-+** If the name cannot be resolved unambiguously, leave an error message
-+** in pParse and return non-zero.  Return zero on success.
-+*/
-+static int lookupName(
-+  Parse *pParse,      /* The parsing context */
-+  Token *pDbToken,     /* Name of the database containing table, or NULL */
-+  Token *pTableToken,  /* Name of table containing column, or NULL */
-+  Token *pColumnToken, /* Name of the column. */
-+  SrcList *pSrcList,   /* List of tables used to resolve column names */
-+  ExprList *pEList,    /* List of expressions used to resolve "AS" */
-+  Expr *pExpr          /* Make this EXPR node point to the selected column */
-+){
-+  char *zDb = 0;       /* Name of the database.  The "X" in X.Y.Z */
-+  char *zTab = 0;      /* Name of the table.  The "Y" in X.Y.Z or Y.Z */
-+  char *zCol = 0;      /* Name of the column.  The "Z" */
-+  int i, j;            /* Loop counters */
-+  int cnt = 0;         /* Number of matching column names */
-+  int cntTab = 0;      /* Number of matching table names */
-+  sqlite *db = pParse->db;  /* The database */
-+
-+  assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
-+  if( pDbToken && pDbToken->z ){
-+    zDb = sqliteStrNDup(pDbToken->z, pDbToken->n);
-+    sqliteDequote(zDb);
-+  }else{
-+    zDb = 0;
-+  }
-+  if( pTableToken && pTableToken->z ){
-+    zTab = sqliteStrNDup(pTableToken->z, pTableToken->n);
-+    sqliteDequote(zTab);
-+  }else{
-+    assert( zDb==0 );
-+    zTab = 0;
-+  }
-+  zCol = sqliteStrNDup(pColumnToken->z, pColumnToken->n);
-+  sqliteDequote(zCol);
-+  if( sqlite_malloc_failed ){
-+    return 1;  /* Leak memory (zDb and zTab) if malloc fails */
-+  }
-+  assert( zTab==0 || pEList==0 );
-+
-+  pExpr->iTable = -1;
-+  for(i=0; i<pSrcList->nSrc; i++){
-+    struct SrcList_item *pItem = &pSrcList->a[i];
-+    Table *pTab = pItem->pTab;
-+    Column *pCol;
-+
-+    if( pTab==0 ) continue;
-+    assert( pTab->nCol>0 );
-+    if( zTab ){
-+      if( pItem->zAlias ){
-+        char *zTabName = pItem->zAlias;
-+        if( sqliteStrICmp(zTabName, zTab)!=0 ) continue;
-+      }else{
-+        char *zTabName = pTab->zName;
-+        if( zTabName==0 || sqliteStrICmp(zTabName, zTab)!=0 ) continue;
-+        if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
-+          continue;
-+        }
-+      }
-+    }
-+    if( 0==(cntTab++) ){
-+      pExpr->iTable = pItem->iCursor;
-+      pExpr->iDb = pTab->iDb;
-+    }
-+    for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
-+      if( sqliteStrICmp(pCol->zName, zCol)==0 ){
-+        cnt++;
-+        pExpr->iTable = pItem->iCursor;
-+        pExpr->iDb = pTab->iDb;
-+        /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
-+        pExpr->iColumn = j==pTab->iPKey ? -1 : j;
-+        pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
-+        break;
-+      }
-+    }
-+  }
-+
-+  /* If we have not already resolved the name, then maybe 
-+  ** it is a new.* or old.* trigger argument reference
-+  */
-+  if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
-+    TriggerStack *pTriggerStack = pParse->trigStack;
-+    Table *pTab = 0;
-+    if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zTab) == 0 ){
-+      pExpr->iTable = pTriggerStack->newIdx;
-+      assert( pTriggerStack->pTab );
-+      pTab = pTriggerStack->pTab;
-+    }else if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zTab) == 0 ){
-+      pExpr->iTable = pTriggerStack->oldIdx;
-+      assert( pTriggerStack->pTab );
-+      pTab = pTriggerStack->pTab;
-+    }
-+
-+    if( pTab ){ 
-+      int j;
-+      Column *pCol = pTab->aCol;
-+      
-+      pExpr->iDb = pTab->iDb;
-+      cntTab++;
-+      for(j=0; j < pTab->nCol; j++, pCol++) {
-+        if( sqliteStrICmp(pCol->zName, zCol)==0 ){
-+          cnt++;
-+          pExpr->iColumn = j==pTab->iPKey ? -1 : j;
-+          pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
-+          break;
-+        }
-+      }
-+    }
-+  }
-+
-+  /*
-+  ** Perhaps the name is a reference to the ROWID
-+  */
-+  if( cnt==0 && cntTab==1 && sqliteIsRowid(zCol) ){
-+    cnt = 1;
-+    pExpr->iColumn = -1;
-+    pExpr->dataType = SQLITE_SO_NUM;
-+  }
-+
-+  /*
-+  ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
-+  ** might refer to an result-set alias.  This happens, for example, when
-+  ** we are resolving names in the WHERE clause of the following command:
-+  **
-+  **     SELECT a+b AS x FROM table WHERE x<10;
-+  **
-+  ** In cases like this, replace pExpr with a copy of the expression that
-+  ** forms the result set entry ("a+b" in the example) and return immediately.
-+  ** Note that the expression in the result set should have already been
-+  ** resolved by the time the WHERE clause is resolved.
-+  */
-+  if( cnt==0 && pEList!=0 ){
-+    for(j=0; j<pEList->nExpr; j++){
-+      char *zAs = pEList->a[j].zName;
-+      if( zAs!=0 && sqliteStrICmp(zAs, zCol)==0 ){
-+        assert( pExpr->pLeft==0 && pExpr->pRight==0 );
-+        pExpr->op = TK_AS;
-+        pExpr->iColumn = j;
-+        pExpr->pLeft = sqliteExprDup(pEList->a[j].pExpr);
-+        sqliteFree(zCol);
-+        assert( zTab==0 && zDb==0 );
-+        return 0;
-+      }
-+    } 
-+  }
-+
-+  /*
-+  ** If X and Y are NULL (in other words if only the column name Z is
-+  ** supplied) and the value of Z is enclosed in double-quotes, then
-+  ** Z is a string literal if it doesn't match any column names.  In that
-+  ** case, we need to return right away and not make any changes to
-+  ** pExpr.
-+  */
-+  if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
-+    sqliteFree(zCol);
-+    return 0;
-+  }
-+
-+  /*
-+  ** cnt==0 means there was not match.  cnt>1 means there were two or
-+  ** more matches.  Either way, we have an error.
-+  */
-+  if( cnt!=1 ){
-+    char *z = 0;
-+    char *zErr;
-+    zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s";
-+    if( zDb ){
-+      sqliteSetString(&z, zDb, ".", zTab, ".", zCol, 0);
-+    }else if( zTab ){
-+      sqliteSetString(&z, zTab, ".", zCol, 0);
-+    }else{
-+      z = sqliteStrDup(zCol);
-+    }
-+    sqliteErrorMsg(pParse, zErr, z);
-+    sqliteFree(z);
-+  }
-+
-+  /* Clean up and return
-+  */
-+  sqliteFree(zDb);
-+  sqliteFree(zTab);
-+  sqliteFree(zCol);
-+  sqliteExprDelete(pExpr->pLeft);
-+  pExpr->pLeft = 0;
-+  sqliteExprDelete(pExpr->pRight);
-+  pExpr->pRight = 0;
-+  pExpr->op = TK_COLUMN;
-+  sqliteAuthRead(pParse, pExpr, pSrcList);
-+  return cnt!=1;
-+}
-+
-+/*
-+** This routine walks an expression tree and resolves references to
-+** table columns.  Nodes of the form ID.ID or ID resolve into an
-+** index to the table in the table list and a column offset.  The 
-+** Expr.opcode for such nodes is changed to TK_COLUMN.  The Expr.iTable
-+** value is changed to the index of the referenced table in pTabList
-+** plus the "base" value.  The base value will ultimately become the
-+** VDBE cursor number for a cursor that is pointing into the referenced
-+** table.  The Expr.iColumn value is changed to the index of the column 
-+** of the referenced table.  The Expr.iColumn value for the special
-+** ROWID column is -1.  Any INTEGER PRIMARY KEY column is tried as an
-+** alias for ROWID.
-+**
-+** We also check for instances of the IN operator.  IN comes in two
-+** forms:
-+**
-+**           expr IN (exprlist)
-+** and
-+**           expr IN (SELECT ...)
-+**
-+** The first form is handled by creating a set holding the list
-+** of allowed values.  The second form causes the SELECT to generate 
-+** a temporary table.
-+**
-+** This routine also looks for scalar SELECTs that are part of an expression.
-+** If it finds any, it generates code to write the value of that select
-+** into a memory cell.
-+**
-+** Unknown columns or tables provoke an error.  The function returns
-+** the number of errors seen and leaves an error message on pParse->zErrMsg.
-+*/
-+int sqliteExprResolveIds(
-+  Parse *pParse,     /* The parser context */
-+  SrcList *pSrcList, /* List of tables used to resolve column names */
-+  ExprList *pEList,  /* List of expressions used to resolve "AS" */
-+  Expr *pExpr        /* The expression to be analyzed. */
-+){
-+  int i;
-+
-+  if( pExpr==0 || pSrcList==0 ) return 0;
-+  for(i=0; i<pSrcList->nSrc; i++){
-+    assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab );
-+  }
-+  switch( pExpr->op ){
-+    /* Double-quoted strings (ex: "abc") are used as identifiers if
-+    ** possible.  Otherwise they remain as strings.  Single-quoted
-+    ** strings (ex: 'abc') are always string literals.
-+    */
-+    case TK_STRING: {
-+      if( pExpr->token.z[0]=='\'' ) break;
-+      /* Fall thru into the TK_ID case if this is a double-quoted string */
-+    }
-+    /* A lone identifier is the name of a columnd.
-+    */
-+    case TK_ID: {
-+      if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){
-+        return 1;
-+      }
-+      break; 
-+    }
-+  
-+    /* A table name and column name:     ID.ID
-+    ** Or a database, table and column:  ID.ID.ID
-+    */
-+    case TK_DOT: {
-+      Token *pColumn;
-+      Token *pTable;
-+      Token *pDb;
-+      Expr *pRight;
-+
-+      pRight = pExpr->pRight;
-+      if( pRight->op==TK_ID ){
-+        pDb = 0;
-+        pTable = &pExpr->pLeft->token;
-+        pColumn = &pRight->token;
-+      }else{
-+        assert( pRight->op==TK_DOT );
-+        pDb = &pExpr->pLeft->token;
-+        pTable = &pRight->pLeft->token;
-+        pColumn = &pRight->pRight->token;
-+      }
-+      if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){
-+        return 1;
-+      }
-+      break;
-+    }
-+
-+    case TK_IN: {
-+      Vdbe *v = sqliteGetVdbe(pParse);
-+      if( v==0 ) return 1;
-+      if( sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
-+        return 1;
-+      }
-+      if( pExpr->pSelect ){
-+        /* Case 1:     expr IN (SELECT ...)
-+        **
-+        ** Generate code to write the results of the select into a temporary
-+        ** table.  The cursor number of the temporary table has already
-+        ** been put in iTable by sqliteExprResolveInSelect().
-+        */
-+        pExpr->iTable = pParse->nTab++;
-+        sqliteVdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1);
-+        sqliteSelect(pParse, pExpr->pSelect, SRT_Set, pExpr->iTable, 0,0,0);
-+      }else if( pExpr->pList ){
-+        /* Case 2:     expr IN (exprlist)
-+        **
-+        ** Create a set to put the exprlist values in.  The Set id is stored
-+        ** in iTable.
-+        */
-+        int i, iSet;
-+        for(i=0; i<pExpr->pList->nExpr; i++){
-+          Expr *pE2 = pExpr->pList->a[i].pExpr;
-+          if( !sqliteExprIsConstant(pE2) ){
-+            sqliteErrorMsg(pParse,
-+              "right-hand side of IN operator must be constant");
-+            return 1;
-+          }
-+          if( sqliteExprCheck(pParse, pE2, 0, 0) ){
-+            return 1;
-+          }
-+        }
-+        iSet = pExpr->iTable = pParse->nSet++;
-+        for(i=0; i<pExpr->pList->nExpr; i++){
-+          Expr *pE2 = pExpr->pList->a[i].pExpr;
-+          switch( pE2->op ){
-+            case TK_FLOAT:
-+            case TK_INTEGER:
-+            case TK_STRING: {
-+              int addr;
-+              assert( pE2->token.z );
-+              addr = sqliteVdbeOp3(v, OP_SetInsert, iSet, 0,
-+                                  pE2->token.z, pE2->token.n);
-+              sqliteVdbeDequoteP3(v, addr);
-+              break;
-+            }
-+            default: {
-+              sqliteExprCode(pParse, pE2);
-+              sqliteVdbeAddOp(v, OP_SetInsert, iSet, 0);
-+              break;
-+            }
-+          }
-+        }
-+      }
-+      break;
-+    }
-+
-+    case TK_SELECT: {
-+      /* This has to be a scalar SELECT.  Generate code to put the
-+      ** value of this select in a memory cell and record the number
-+      ** of the memory cell in iColumn.
-+      */
-+      pExpr->iColumn = pParse->nMem++;
-+      if( sqliteSelect(pParse, pExpr->pSelect, SRT_Mem, pExpr->iColumn,0,0,0) ){
-+        return 1;
-+      }
-+      break;
-+    }
-+
-+    /* For all else, just recursively walk the tree */
-+    default: {
-+      if( pExpr->pLeft
-+      && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
-+        return 1;
-+      }
-+      if( pExpr->pRight 
-+      && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){
-+        return 1;
-+      }
-+      if( pExpr->pList ){
-+        int i;
-+        ExprList *pList = pExpr->pList;
-+        for(i=0; i<pList->nExpr; i++){
-+          Expr *pArg = pList->a[i].pExpr;
-+          if( sqliteExprResolveIds(pParse, pSrcList, pEList, pArg) ){
-+            return 1;
-+          }
-+        }
-+      }
-+    }
-+  }
-+  return 0;
-+}
-+
-+/*
-+** pExpr is a node that defines a function of some kind.  It might
-+** be a syntactic function like "count(x)" or it might be a function
-+** that implements an operator, like "a LIKE b".  
-+**
-+** This routine makes *pzName point to the name of the function and 
-+** *pnName hold the number of characters in the function name.
-+*/
-+static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
-+  switch( pExpr->op ){
-+    case TK_FUNCTION: {
-+      *pzName = pExpr->token.z;
-+      *pnName = pExpr->token.n;
-+      break;
-+    }
-+    case TK_LIKE: {
-+      *pzName = "like";
-+      *pnName = 4;
-+      break;
-+    }
-+    case TK_GLOB: {
-+      *pzName = "glob";
-+      *pnName = 4;
-+      break;
-+    }
-+    default: {
-+      *pzName = "can't happen";
-+      *pnName = 12;
-+      break;
-+    }
-+  }
-+}
-+
-+/*
-+** Error check the functions in an expression.  Make sure all
-+** function names are recognized and all functions have the correct
-+** number of arguments.  Leave an error message in pParse->zErrMsg
-+** if anything is amiss.  Return the number of errors.
-+**
-+** if pIsAgg is not null and this expression is an aggregate function
-+** (like count(*) or max(value)) then write a 1 into *pIsAgg.
-+*/
-+int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
-+  int nErr = 0;
-+  if( pExpr==0 ) return 0;
-+  switch( pExpr->op ){
-+    case TK_GLOB:
-+    case TK_LIKE:
-+    case TK_FUNCTION: {
-+      int n = pExpr->pList ? pExpr->pList->nExpr : 0;  /* Number of arguments */
-+      int no_such_func = 0;       /* True if no such function exists */
-+      int wrong_num_args = 0;     /* True if wrong number of arguments */
-+      int is_agg = 0;             /* True if is an aggregate function */
-+      int i;
-+      int nId;                    /* Number of characters in function name */
-+      const char *zId;            /* The function name. */
-+      FuncDef *pDef;
-+
-+      getFunctionName(pExpr, &zId, &nId);
-+      pDef = sqliteFindFunction(pParse->db, zId, nId, n, 0);
-+      if( pDef==0 ){
-+        pDef = sqliteFindFunction(pParse->db, zId, nId, -1, 0);
-+        if( pDef==0 ){
-+          no_such_func = 1;
-+        }else{
-+          wrong_num_args = 1;
-+        }
-+      }else{
-+        is_agg = pDef->xFunc==0;
-+      }
-+      if( is_agg && !allowAgg ){
-+        sqliteErrorMsg(pParse, "misuse of aggregate function %.*s()", nId, zId);
-+        nErr++;
-+        is_agg = 0;
-+      }else if( no_such_func ){
-+        sqliteErrorMsg(pParse, "no such function: %.*s", nId, zId);
-+        nErr++;
-+      }else if( wrong_num_args ){
-+        sqliteErrorMsg(pParse,"wrong number of arguments to function %.*s()",
-+             nId, zId);
-+        nErr++;
-+      }
-+      if( is_agg ){
-+        pExpr->op = TK_AGG_FUNCTION;
-+        if( pIsAgg ) *pIsAgg = 1;
-+      }
-+      for(i=0; nErr==0 && i<n; i++){
-+        nErr = sqliteExprCheck(pParse, pExpr->pList->a[i].pExpr,
-+                               allowAgg && !is_agg, pIsAgg);
-+      }
-+      if( pDef==0 ){
-+        /* Already reported an error */
-+      }else if( pDef->dataType>=0 ){
-+        if( pDef->dataType<n ){
-+          pExpr->dataType = 
-+             sqliteExprType(pExpr->pList->a[pDef->dataType].pExpr);
-+        }else{
-+          pExpr->dataType = SQLITE_SO_NUM;
-+        }
-+      }else if( pDef->dataType==SQLITE_ARGS ){
-+        pDef->dataType = SQLITE_SO_TEXT;
-+        for(i=0; i<n; i++){
-+          if( sqliteExprType(pExpr->pList->a[i].pExpr)==SQLITE_SO_NUM ){
-+            pExpr->dataType = SQLITE_SO_NUM;
-+            break;
-+          }
-+        }
-+      }else if( pDef->dataType==SQLITE_NUMERIC ){
-+        pExpr->dataType = SQLITE_SO_NUM;
-+      }else{
-+        pExpr->dataType = SQLITE_SO_TEXT;
-+      }
-+    }
-+    default: {
-+      if( pExpr->pLeft ){
-+        nErr = sqliteExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg);
-+      }
-+      if( nErr==0 && pExpr->pRight ){
-+        nErr = sqliteExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg);
-+      }
-+      if( nErr==0 && pExpr->pList ){
-+        int n = pExpr->pList->nExpr;
-+        int i;
-+        for(i=0; nErr==0 && i<n; i++){
-+          Expr *pE2 = pExpr->pList->a[i].pExpr;
-+          nErr = sqliteExprCheck(pParse, pE2, allowAgg, pIsAgg);
-+        }
-+      }
-+      break;
-+    }
-+  }
-+  return nErr;
-+}
-+
-+/*
-+** Return either SQLITE_SO_NUM or SQLITE_SO_TEXT to indicate whether the
-+** given expression should sort as numeric values or as text.
-+**
-+** The sqliteExprResolveIds() and sqliteExprCheck() routines must have
-+** both been called on the expression before it is passed to this routine.
-+*/
-+int sqliteExprType(Expr *p){
-+  if( p==0 ) return SQLITE_SO_NUM;
-+  while( p ) switch( p->op ){
-+    case TK_PLUS:
-+    case TK_MINUS:
-+    case TK_STAR:
-+    case TK_SLASH:
-+    case TK_AND:
-+    case TK_OR:
-+    case TK_ISNULL:
-+    case TK_NOTNULL:
-+    case TK_NOT:
-+    case TK_UMINUS:
-+    case TK_UPLUS:
-+    case TK_BITAND:
-+    case TK_BITOR:
-+    case TK_BITNOT:
-+    case TK_LSHIFT:
-+    case TK_RSHIFT:
-+    case TK_REM:
-+    case TK_INTEGER:
-+    case TK_FLOAT:
-+    case TK_IN:
-+    case TK_BETWEEN:
-+    case TK_GLOB:
-+    case TK_LIKE:
-+      return SQLITE_SO_NUM;
-+
-+    case TK_STRING:
-+    case TK_NULL:
-+    case TK_CONCAT:
-+    case TK_VARIABLE:
-+      return SQLITE_SO_TEXT;
-+
-+    case TK_LT:
-+    case TK_LE:
-+    case TK_GT:
-+    case TK_GE:
-+    case TK_NE:
-+    case TK_EQ:
-+      if( sqliteExprType(p->pLeft)==SQLITE_SO_NUM ){
-+        return SQLITE_SO_NUM;
-+      }
-+      p = p->pRight;
-+      break;
-+
-+    case TK_AS:
-+      p = p->pLeft;
-+      break;
-+
-+    case TK_COLUMN:
-+    case TK_FUNCTION:
-+    case TK_AGG_FUNCTION:
-+      return p->dataType;
-+
-+    case TK_SELECT:
-+      assert( p->pSelect );
-+      assert( p->pSelect->pEList );
-+      assert( p->pSelect->pEList->nExpr>0 );
-+      p = p->pSelect->pEList->a[0].pExpr;
-+      break;
-+
-+    case TK_CASE: {
-+      if( p->pRight && sqliteExprType(p->pRight)==SQLITE_SO_NUM ){
-+        return SQLITE_SO_NUM;
-+      }
-+      if( p->pList ){
-+        int i;
-+        ExprList *pList = p->pList;
-+        for(i=1; i<pList->nExpr; i+=2){
-+          if( sqliteExprType(pList->a[i].pExpr)==SQLITE_SO_NUM ){
-+            return SQLITE_SO_NUM;
-+          }
-+        }
-+      }
-+      return SQLITE_SO_TEXT;
-+    }
-+
-+    default:
-+      assert( p->op==TK_ABORT );  /* Can't Happen */
-+      break;
-+  }
-+  return SQLITE_SO_NUM;
-+}
-+
-+/*
-+** Generate code into the current Vdbe to evaluate the given
-+** expression and leave the result on the top of stack.
-+*/
-+void sqliteExprCode(Parse *pParse, Expr *pExpr){
-+  Vdbe *v = pParse->pVdbe;
-+  int op;
-+  if( v==0 || pExpr==0 ) return;
-+  switch( pExpr->op ){
-+    case TK_PLUS:     op = OP_Add;      break;
-+    case TK_MINUS:    op = OP_Subtract; break;
-+    case TK_STAR:     op = OP_Multiply; break;
-+    case TK_SLASH:    op = OP_Divide;   break;
-+    case TK_AND:      op = OP_And;      break;
-+    case TK_OR:       op = OP_Or;       break;
-+    case TK_LT:       op = OP_Lt;       break;
-+    case TK_LE:       op = OP_Le;       break;
-+    case TK_GT:       op = OP_Gt;       break;
-+    case TK_GE:       op = OP_Ge;       break;
-+    case TK_NE:       op = OP_Ne;       break;
-+    case TK_EQ:       op = OP_Eq;       break;
-+    case TK_ISNULL:   op = OP_IsNull;   break;
-+    case TK_NOTNULL:  op = OP_NotNull;  break;
-+    case TK_NOT:      op = OP_Not;      break;
-+    case TK_UMINUS:   op = OP_Negative; break;
-+    case TK_BITAND:   op = OP_BitAnd;   break;
-+    case TK_BITOR:    op = OP_BitOr;    break;
-+    case TK_BITNOT:   op = OP_BitNot;   break;
-+    case TK_LSHIFT:   op = OP_ShiftLeft;  break;
-+    case TK_RSHIFT:   op = OP_ShiftRight; break;
-+    case TK_REM:      op = OP_Remainder;  break;
-+    default: break;
-+  }
-+  switch( pExpr->op ){
-+    case TK_COLUMN: {
-+      if( pParse->useAgg ){
-+        sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
-+      }else if( pExpr->iColumn>=0 ){
-+        sqliteVdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
-+      }else{
-+        sqliteVdbeAddOp(v, OP_Recno, pExpr->iTable, 0);
-+      }
-+      break;
-+    }
-+    case TK_STRING:
-+    case TK_FLOAT:
-+    case TK_INTEGER: {
-+      if( pExpr->op==TK_INTEGER && sqliteFitsIn32Bits(pExpr->token.z) ){
-+        sqliteVdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0);
-+      }else{
-+        sqliteVdbeAddOp(v, OP_String, 0, 0);
-+      }
-+      assert( pExpr->token.z );
-+      sqliteVdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
-+      sqliteVdbeDequoteP3(v, -1);
-+      break;
-+    }
-+    case TK_NULL: {
-+      sqliteVdbeAddOp(v, OP_String, 0, 0);
-+      break;
-+    }
-+    case TK_VARIABLE: {
-+      sqliteVdbeAddOp(v, OP_Variable, pExpr->iTable, 0);
-+      break;
-+    }
-+    case TK_LT:
-+    case TK_LE:
-+    case TK_GT:
-+    case TK_GE:
-+    case TK_NE:
-+    case TK_EQ: {
-+      if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
-+        op += 6;  /* Convert numeric opcodes to text opcodes */
-+      }
-+      /* Fall through into the next case */
-+    }
-+    case TK_AND:
-+    case TK_OR:
-+    case TK_PLUS:
-+    case TK_STAR:
-+    case TK_MINUS:
-+    case TK_REM:
-+    case TK_BITAND:
-+    case TK_BITOR:
-+    case TK_SLASH: {
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteExprCode(pParse, pExpr->pRight);
-+      sqliteVdbeAddOp(v, op, 0, 0);
-+      break;
-+    }
-+    case TK_LSHIFT:
-+    case TK_RSHIFT: {
-+      sqliteExprCode(pParse, pExpr->pRight);
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteVdbeAddOp(v, op, 0, 0);
-+      break;
-+    }
-+    case TK_CONCAT: {
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteExprCode(pParse, pExpr->pRight);
-+      sqliteVdbeAddOp(v, OP_Concat, 2, 0);
-+      break;
-+    }
-+    case TK_UMINUS: {
-+      assert( pExpr->pLeft );
-+      if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){
-+        Token *p = &pExpr->pLeft->token;
-+        char *z = sqliteMalloc( p->n + 2 );
-+        sprintf(z, "-%.*s", p->n, p->z);
-+        if( pExpr->pLeft->op==TK_INTEGER && sqliteFitsIn32Bits(z) ){
-+          sqliteVdbeAddOp(v, OP_Integer, atoi(z), 0);
-+        }else{
-+          sqliteVdbeAddOp(v, OP_String, 0, 0);
-+        }
-+        sqliteVdbeChangeP3(v, -1, z, p->n+1);
-+        sqliteFree(z);
-+        break;
-+      }
-+      /* Fall through into TK_NOT */
-+    }
-+    case TK_BITNOT:
-+    case TK_NOT: {
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteVdbeAddOp(v, op, 0, 0);
-+      break;
-+    }
-+    case TK_ISNULL:
-+    case TK_NOTNULL: {
-+      int dest;
-+      sqliteVdbeAddOp(v, OP_Integer, 1, 0);
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      dest = sqliteVdbeCurrentAddr(v) + 2;
-+      sqliteVdbeAddOp(v, op, 1, dest);
-+      sqliteVdbeAddOp(v, OP_AddImm, -1, 0);
-+      break;
-+    }
-+    case TK_AGG_FUNCTION: {
-+      sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
-+      break;
-+    }
-+    case TK_GLOB:
-+    case TK_LIKE:
-+    case TK_FUNCTION: {
-+      ExprList *pList = pExpr->pList;
-+      int nExpr = pList ? pList->nExpr : 0;
-+      FuncDef *pDef;
-+      int nId;
-+      const char *zId;
-+      getFunctionName(pExpr, &zId, &nId);
-+      pDef = sqliteFindFunction(pParse->db, zId, nId, nExpr, 0);
-+      assert( pDef!=0 );
-+      nExpr = sqliteExprCodeExprList(pParse, pList, pDef->includeTypes);
-+      sqliteVdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER);
-+      break;
-+    }
-+    case TK_SELECT: {
-+      sqliteVdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0);
-+      break;
-+    }
-+    case TK_IN: {
-+      int addr;
-+      sqliteVdbeAddOp(v, OP_Integer, 1, 0);
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      addr = sqliteVdbeCurrentAddr(v);
-+      sqliteVdbeAddOp(v, OP_NotNull, -1, addr+4);
-+      sqliteVdbeAddOp(v, OP_Pop, 2, 0);
-+      sqliteVdbeAddOp(v, OP_String, 0, 0);
-+      sqliteVdbeAddOp(v, OP_Goto, 0, addr+6);
-+      if( pExpr->pSelect ){
-+        sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, addr+6);
-+      }else{
-+        sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, addr+6);
-+      }
-+      sqliteVdbeAddOp(v, OP_AddImm, -1, 0);
-+      break;
-+    }
-+    case TK_BETWEEN: {
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
-+      sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);
-+      sqliteVdbeAddOp(v, OP_Ge, 0, 0);
-+      sqliteVdbeAddOp(v, OP_Pull, 1, 0);
-+      sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
-+      sqliteVdbeAddOp(v, OP_Le, 0, 0);
-+      sqliteVdbeAddOp(v, OP_And, 0, 0);
-+      break;
-+    }
-+    case TK_UPLUS:
-+    case TK_AS: {
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      break;
-+    }
-+    case TK_CASE: {
-+      int expr_end_label;
-+      int jumpInst;
-+      int addr;
-+      int nExpr;
-+      int i;
-+
-+      assert(pExpr->pList);
-+      assert((pExpr->pList->nExpr % 2) == 0);
-+      assert(pExpr->pList->nExpr > 0);
-+      nExpr = pExpr->pList->nExpr;
-+      expr_end_label = sqliteVdbeMakeLabel(v);
-+      if( pExpr->pLeft ){
-+        sqliteExprCode(pParse, pExpr->pLeft);
-+      }
-+      for(i=0; i<nExpr; i=i+2){
-+        sqliteExprCode(pParse, pExpr->pList->a[i].pExpr);
-+        if( pExpr->pLeft ){
-+          sqliteVdbeAddOp(v, OP_Dup, 1, 1);
-+          jumpInst = sqliteVdbeAddOp(v, OP_Ne, 1, 0);
-+          sqliteVdbeAddOp(v, OP_Pop, 1, 0);
-+        }else{
-+          jumpInst = sqliteVdbeAddOp(v, OP_IfNot, 1, 0);
-+        }
-+        sqliteExprCode(pParse, pExpr->pList->a[i+1].pExpr);
-+        sqliteVdbeAddOp(v, OP_Goto, 0, expr_end_label);
-+        addr = sqliteVdbeCurrentAddr(v);
-+        sqliteVdbeChangeP2(v, jumpInst, addr);
-+      }
-+      if( pExpr->pLeft ){
-+        sqliteVdbeAddOp(v, OP_Pop, 1, 0);
-+      }
-+      if( pExpr->pRight ){
-+        sqliteExprCode(pParse, pExpr->pRight);
-+      }else{
-+        sqliteVdbeAddOp(v, OP_String, 0, 0);
-+      }
-+      sqliteVdbeResolveLabel(v, expr_end_label);
-+      break;
-+    }
-+    case TK_RAISE: {
-+      if( !pParse->trigStack ){
-+        sqliteErrorMsg(pParse,
-+                       "RAISE() may only be used within a trigger-program");
-+        pParse->nErr++;
-+	return;
-+      }
-+      if( pExpr->iColumn == OE_Rollback ||
-+	  pExpr->iColumn == OE_Abort ||
-+	  pExpr->iColumn == OE_Fail ){
-+	  sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,
-+                           pExpr->token.z, pExpr->token.n);
-+	  sqliteVdbeDequoteP3(v, -1);
-+      } else {
-+	  assert( pExpr->iColumn == OE_Ignore );
-+	  sqliteVdbeOp3(v, OP_Goto, 0, pParse->trigStack->ignoreJump,
-+                           "(IGNORE jump)", 0);
-+      }
-+    }
-+    break;
-+  }
-+}
-+
-+/*
-+** Generate code that pushes the value of every element of the given
-+** expression list onto the stack.  If the includeTypes flag is true,
-+** then also push a string that is the datatype of each element onto
-+** the stack after the value.
-+**
-+** Return the number of elements pushed onto the stack.
-+*/
-+int sqliteExprCodeExprList(
-+  Parse *pParse,     /* Parsing context */
-+  ExprList *pList,   /* The expression list to be coded */
-+  int includeTypes   /* TRUE to put datatypes on the stack too */
-+){
-+  struct ExprList_item *pItem;
-+  int i, n;
-+  Vdbe *v;
-+  if( pList==0 ) return 0;
-+  v = sqliteGetVdbe(pParse);
-+  n = pList->nExpr;
-+  for(pItem=pList->a, i=0; i<n; i++, pItem++){
-+    sqliteExprCode(pParse, pItem->pExpr);
-+    if( includeTypes ){
-+      sqliteVdbeOp3(v, OP_String, 0, 0, 
-+         sqliteExprType(pItem->pExpr)==SQLITE_SO_NUM ? "numeric" : "text",
-+         P3_STATIC);
-+    }
-+  }
-+  return includeTypes ? n*2 : n;
-+}
-+
-+/*
-+** Generate code for a boolean expression such that a jump is made
-+** to the label "dest" if the expression is true but execution
-+** continues straight thru if the expression is false.
-+**
-+** If the expression evaluates to NULL (neither true nor false), then
-+** take the jump if the jumpIfNull flag is true.
-+*/
-+void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
-+  Vdbe *v = pParse->pVdbe;
-+  int op = 0;
-+  if( v==0 || pExpr==0 ) return;
-+  switch( pExpr->op ){
-+    case TK_LT:       op = OP_Lt;       break;
-+    case TK_LE:       op = OP_Le;       break;
-+    case TK_GT:       op = OP_Gt;       break;
-+    case TK_GE:       op = OP_Ge;       break;
-+    case TK_NE:       op = OP_Ne;       break;
-+    case TK_EQ:       op = OP_Eq;       break;
-+    case TK_ISNULL:   op = OP_IsNull;   break;
-+    case TK_NOTNULL:  op = OP_NotNull;  break;
-+    default:  break;
-+  }
-+  switch( pExpr->op ){
-+    case TK_AND: {
-+      int d2 = sqliteVdbeMakeLabel(v);
-+      sqliteExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull);
-+      sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
-+      sqliteVdbeResolveLabel(v, d2);
-+      break;
-+    }
-+    case TK_OR: {
-+      sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
-+      sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
-+      break;
-+    }
-+    case TK_NOT: {
-+      sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
-+      break;
-+    }
-+    case TK_LT:
-+    case TK_LE:
-+    case TK_GT:
-+    case TK_GE:
-+    case TK_NE:
-+    case TK_EQ: {
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteExprCode(pParse, pExpr->pRight);
-+      if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
-+        op += 6;  /* Convert numeric opcodes to text opcodes */
-+      }
-+      sqliteVdbeAddOp(v, op, jumpIfNull, dest);
-+      break;
-+    }
-+    case TK_ISNULL:
-+    case TK_NOTNULL: {
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteVdbeAddOp(v, op, 1, dest);
-+      break;
-+    }
-+    case TK_IN: {
-+      int addr;
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      addr = sqliteVdbeCurrentAddr(v);
-+      sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3);
-+      sqliteVdbeAddOp(v, OP_Pop, 1, 0);
-+      sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4);
-+      if( pExpr->pSelect ){
-+        sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, dest);
-+      }else{
-+        sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, dest);
-+      }
-+      break;
-+    }
-+    case TK_BETWEEN: {
-+      int addr;
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
-+      sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);
-+      addr = sqliteVdbeAddOp(v, OP_Lt, !jumpIfNull, 0);
-+      sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
-+      sqliteVdbeAddOp(v, OP_Le, jumpIfNull, dest);
-+      sqliteVdbeAddOp(v, OP_Integer, 0, 0);
-+      sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
-+      sqliteVdbeAddOp(v, OP_Pop, 1, 0);
-+      break;
-+    }
-+    default: {
-+      sqliteExprCode(pParse, pExpr);
-+      sqliteVdbeAddOp(v, OP_If, jumpIfNull, dest);
-+      break;
-+    }
-+  }
-+}
-+
-+/*
-+** Generate code for a boolean expression such that a jump is made
-+** to the label "dest" if the expression is false but execution
-+** continues straight thru if the expression is true.
-+**
-+** If the expression evaluates to NULL (neither true nor false) then
-+** jump if jumpIfNull is true or fall through if jumpIfNull is false.
-+*/
-+void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
-+  Vdbe *v = pParse->pVdbe;
-+  int op = 0;
-+  if( v==0 || pExpr==0 ) return;
-+  switch( pExpr->op ){
-+    case TK_LT:       op = OP_Ge;       break;
-+    case TK_LE:       op = OP_Gt;       break;
-+    case TK_GT:       op = OP_Le;       break;
-+    case TK_GE:       op = OP_Lt;       break;
-+    case TK_NE:       op = OP_Eq;       break;
-+    case TK_EQ:       op = OP_Ne;       break;
-+    case TK_ISNULL:   op = OP_NotNull;  break;
-+    case TK_NOTNULL:  op = OP_IsNull;   break;
-+    default:  break;
-+  }
-+  switch( pExpr->op ){
-+    case TK_AND: {
-+      sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
-+      sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
-+      break;
-+    }
-+    case TK_OR: {
-+      int d2 = sqliteVdbeMakeLabel(v);
-+      sqliteExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull);
-+      sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
-+      sqliteVdbeResolveLabel(v, d2);
-+      break;
-+    }
-+    case TK_NOT: {
-+      sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
-+      break;
-+    }
-+    case TK_LT:
-+    case TK_LE:
-+    case TK_GT:
-+    case TK_GE:
-+    case TK_NE:
-+    case TK_EQ: {
-+      if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
-+        /* Convert numeric comparison opcodes into text comparison opcodes.
-+        ** This step depends on the fact that the text comparision opcodes are
-+        ** always 6 greater than their corresponding numeric comparison
-+        ** opcodes.
-+        */
-+        assert( OP_Eq+6 == OP_StrEq );
-+        op += 6;
-+      }
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteExprCode(pParse, pExpr->pRight);
-+      sqliteVdbeAddOp(v, op, jumpIfNull, dest);
-+      break;
-+    }
-+    case TK_ISNULL:
-+    case TK_NOTNULL: {
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteVdbeAddOp(v, op, 1, dest);
-+      break;
-+    }
-+    case TK_IN: {
-+      int addr;
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      addr = sqliteVdbeCurrentAddr(v);
-+      sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3);
-+      sqliteVdbeAddOp(v, OP_Pop, 1, 0);
-+      sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4);
-+      if( pExpr->pSelect ){
-+        sqliteVdbeAddOp(v, OP_NotFound, pExpr->iTable, dest);
-+      }else{
-+        sqliteVdbeAddOp(v, OP_SetNotFound, pExpr->iTable, dest);
-+      }
-+      break;
-+    }
-+    case TK_BETWEEN: {
-+      int addr;
-+      sqliteExprCode(pParse, pExpr->pLeft);
-+      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
-+      sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);
-+      addr = sqliteVdbeCurrentAddr(v);
-+      sqliteVdbeAddOp(v, OP_Ge, !jumpIfNull, addr+3);
-+      sqliteVdbeAddOp(v, OP_Pop, 1, 0);
-+      sqliteVdbeAddOp(v, OP_Goto, 0, dest);
-+      sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
-+      sqliteVdbeAddOp(v, OP_Gt, jumpIfNull, dest);
-+      break;
-+    }
-+    default: {
-+      sqliteExprCode(pParse, pExpr);
-+      sqliteVdbeAddOp(v, OP_IfNot, jumpIfNull, dest);
-+      break;
-+    }
-+  }
-+}
-+
-+/*
-+** Do a deep comparison of two expression trees.  Return TRUE (non-zero)
-+** if they are identical and return FALSE if they differ in any way.
-+*/
-+int sqliteExprCompare(Expr *pA, Expr *pB){
-+  int i;
-+  if( pA==0 ){
-+    return pB==0;
-+  }else if( pB==0 ){
-+    return 0;
-+  }
-+  if( pA->op!=pB->op ) return 0;
-+  if( !sqliteExprCompare(pA->pLeft, pB->pLeft) ) return 0;
-+  if( !sqliteExprCompare(pA->pRight, pB->pRight) ) return 0;
-+  if( pA->pList ){
-+    if( pB->pList==0 ) return 0;
-+    if( pA->pList->nExpr!=pB->pList->nExpr ) return 0;
-+    for(i=0; i<pA->pList->nExpr; i++){
-+      if( !sqliteExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){
-+        return 0;
-+      }
-+    }
-+  }else if( pB->pList ){
-+    return 0;
-+  }
-+  if( pA->pSelect || pB->pSelect ) return 0;
-+  if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
-+  if( pA->token.z ){
-+    if( pB->token.z==0 ) return 0;
-+    if( pB->token.n!=pA->token.n ) return 0;
-+    if( sqliteStrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0;
-+  }
-+  return 1;
-+}
-+
-+/*
-+** Add a new element to the pParse->aAgg[] array and return its index.
-+*/
-+static int appendAggInfo(Parse *pParse){
-+  if( (pParse->nAgg & 0x7)==0 ){
-+    int amt = pParse->nAgg + 8;
-+    AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0]));
-+    if( aAgg==0 ){
-+      return -1;
-+    }
-+    pParse->aAgg = aAgg;
-+  }
-+  memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0]));
-+  return pParse->nAgg++;
-+}
-+
-+/*
-+** Analyze the given expression looking for aggregate functions and
-+** for variables that need to be added to the pParse->aAgg[] array.
-+** Make additional entries to the pParse->aAgg[] array as necessary.
-+**
-+** This routine should only be called after the expression has been
-+** analyzed by sqliteExprResolveIds() and sqliteExprCheck().
-+**
-+** If errors are seen, leave an error message in zErrMsg and return
-+** the number of errors.
-+*/
-+int sqliteExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){
-+  int i;
-+  AggExpr *aAgg;
-+  int nErr = 0;
-+
-+  if( pExpr==0 ) return 0;
-+  switch( pExpr->op ){
-+    case TK_COLUMN: {
-+      aAgg = pParse->aAgg;
-+      for(i=0; i<pParse->nAgg; i++){
-+        if( aAgg[i].isAgg ) continue;
-+        if( aAgg[i].pExpr->iTable==pExpr->iTable
-+         && aAgg[i].pExpr->iColumn==pExpr->iColumn ){
-+          break;
-+        }
-+      }
-+      if( i>=pParse->nAgg ){
-+        i = appendAggInfo(pParse);
-+        if( i<0 ) return 1;
-+        pParse->aAgg[i].isAgg = 0;
-+        pParse->aAgg[i].pExpr = pExpr;
-+      }
-+      pExpr->iAgg = i;
-+      break;
-+    }
-+    case TK_AGG_FUNCTION: {
-+      aAgg = pParse->aAgg;
-+      for(i=0; i<pParse->nAgg; i++){
-+        if( !aAgg[i].isAgg ) continue;
-+        if( sqliteExprCompare(aAgg[i].pExpr, pExpr) ){
-+          break;
-+        }
-+      }
-+      if( i>=pParse->nAgg ){
-+        i = appendAggInfo(pParse);
-+        if( i<0 ) return 1;
-+        pParse->aAgg[i].isAgg = 1;
-+        pParse->aAgg[i].pExpr = pExpr;
-+        pParse->aAgg[i].pFunc = sqliteFindFunction(pParse->db,
-+             pExpr->token.z, pExpr->token.n,
-+             pExpr->pList ? pExpr->pList->nExpr : 0, 0);
-+      }
-+      pExpr->iAgg = i;
-+      break;
-+    }
-+    default: {
-+      if( pExpr->pLeft ){
-+        nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft);
-+      }
-+      if( nErr==0 && pExpr->pRight ){
-+        nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pRight);
-+      }
-+      if( nErr==0 && pExpr->pList ){
-+        int n = pExpr->pList->nExpr;
-+        int i;
-+        for(i=0; nErr==0 && i<n; i++){
-+          nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pList->a[i].pExpr);
-+        }
-+      }
-+      break;
-+    }
-+  }
-+  return nErr;
-+}
-+
-+/*
-+** Locate a user function given a name and a number of arguments.
-+** Return a pointer to the FuncDef structure that defines that
-+** function, or return NULL if the function does not exist.
-+**
-+** If the createFlag argument is true, then a new (blank) FuncDef
-+** structure is created and liked into the "db" structure if a
-+** no matching function previously existed.  When createFlag is true
-+** and the nArg parameter is -1, then only a function that accepts
-+** any number of arguments will be returned.
-+**
-+** If createFlag is false and nArg is -1, then the first valid
-+** function found is returned.  A function is valid if either xFunc
-+** or xStep is non-zero.
-+*/
-+FuncDef *sqliteFindFunction(
-+  sqlite *db,        /* An open database */
-+  const char *zName, /* Name of the function.  Not null-terminated */
-+  int nName,         /* Number of characters in the name */
-+  int nArg,          /* Number of arguments.  -1 means any number */
-+  int createFlag     /* Create new entry if true and does not otherwise exist */
-+){
-+  FuncDef *pFirst, *p, *pMaybe;
-+  pFirst = p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, nName);
-+  if( p && !createFlag && nArg<0 ){
-+    while( p && p->xFunc==0 && p->xStep==0 ){ p = p->pNext; }
-+    return p;
-+  }
-+  pMaybe = 0;
-+  while( p && p->nArg!=nArg ){
-+    if( p->nArg<0 && !createFlag && (p->xFunc || p->xStep) ) pMaybe = p;
-+    p = p->pNext;
-+  }
-+  if( p && !createFlag && p->xFunc==0 && p->xStep==0 ){
-+    return 0;
-+  }
-+  if( p==0 && pMaybe ){
-+    assert( createFlag==0 );
-+    return pMaybe;
-+  }
-+  if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){
-+    p->nArg = nArg;
-+    p->pNext = pFirst;
-+    p->dataType = pFirst ? pFirst->dataType : SQLITE_NUMERIC;
-+    sqliteHashInsert(&db->aFunc, zName, nName, (void*)p);
-+  }
-+  return p;
-+}
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/func.c
-@@ -0,0 +1,658 @@
-+/*
-+** 2002 February 23
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains the C functions that implement various SQL
-+** functions of SQLite.  
-+**
-+** There is only one exported symbol in this file - the function
-+** sqliteRegisterBuildinFunctions() found at the bottom of the file.
-+** All other code has file scope.
-+**
-+** $Id$
-+*/
-+#include <ctype.h>
-+#include <math.h>
-+#include <stdlib.h>
-+#include <assert.h>
-+#include "sqliteInt.h"
-+#include "os.h"
-+
-+/*
-+** Implementation of the non-aggregate min() and max() functions
-+*/
-+static void minmaxFunc(sqlite_func *context, int argc, const char **argv){
-+  const char *zBest; 
-+  int i;
-+  int (*xCompare)(const char*, const char*);
-+  int mask;    /* 0 for min() or 0xffffffff for max() */
-+
-+  if( argc==0 ) return;
-+  mask = (int)sqlite_user_data(context);
-+  zBest = argv[0];
-+  if( zBest==0 ) return;
-+  if( argv[1][0]=='n' ){
-+    xCompare = sqliteCompare;
-+  }else{
-+    xCompare = strcmp;
-+  }
-+  for(i=2; i<argc; i+=2){
-+    if( argv[i]==0 ) return;
-+    if( (xCompare(argv[i], zBest)^mask)<0 ){
-+      zBest = argv[i];
-+    }
-+  }
-+  sqlite_set_result_string(context, zBest, -1);
-+}
-+
-+/*
-+** Return the type of the argument.
-+*/
-+static void typeofFunc(sqlite_func *context, int argc, const char **argv){
-+  assert( argc==2 );
-+  sqlite_set_result_string(context, argv[1], -1);
-+}
-+
-+/*
-+** Implementation of the length() function
-+*/
-+static void lengthFunc(sqlite_func *context, int argc, const char **argv){
-+  const char *z;
-+  int len;
-+
-+  assert( argc==1 );
-+  z = argv[0];
-+  if( z==0 ) return;
-+#ifdef SQLITE_UTF8
-+  for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; }
-+#else
-+  len = strlen(z);
-+#endif
-+  sqlite_set_result_int(context, len);
-+}
-+
-+/*
-+** Implementation of the abs() function
-+*/
-+static void absFunc(sqlite_func *context, int argc, const char **argv){
-+  const char *z;
-+  assert( argc==1 );
-+  z = argv[0];
-+  if( z==0 ) return;
-+  if( z[0]=='-' && isdigit(z[1]) ) z++;
-+  sqlite_set_result_string(context, z, -1);
-+}
-+
-+/*
-+** Implementation of the substr() function
-+*/
-+static void substrFunc(sqlite_func *context, int argc, const char **argv){
-+  const char *z;
-+#ifdef SQLITE_UTF8
-+  const char *z2;
-+  int i;
-+#endif
-+  int p1, p2, len;
-+  assert( argc==3 );
-+  z = argv[0];
-+  if( z==0 ) return;
-+  p1 = atoi(argv[1]?argv[1]:0);
-+  p2 = atoi(argv[2]?argv[2]:0);
-+#ifdef SQLITE_UTF8
-+  for(len=0, z2=z; *z2; z2++){ if( (0xc0&*z2)!=0x80 ) len++; }
-+#else
-+  len = strlen(z);
-+#endif
-+  if( p1<0 ){
-+    p1 += len;
-+    if( p1<0 ){
-+      p2 += p1;
-+      p1 = 0;
-+    }
-+  }else if( p1>0 ){
-+    p1--;
-+  }
-+  if( p1+p2>len ){
-+    p2 = len-p1;
-+  }
-+#ifdef SQLITE_UTF8
-+  for(i=0; i<p1 && z[i]; i++){
-+    if( (z[i]&0xc0)==0x80 ) p1++;
-+  }
-+  while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p1++; }
-+  for(; i<p1+p2 && z[i]; i++){
-+    if( (z[i]&0xc0)==0x80 ) p2++;
-+  }
-+  while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; }
-+#endif
-+  if( p2<0 ) p2 = 0;
-+  sqlite_set_result_string(context, &z[p1], p2);
-+}
-+
-+/*
-+** Implementation of the round() function
-+*/
-+static void roundFunc(sqlite_func *context, int argc, const char **argv){
-+  int n;
-+  double r;
-+  char zBuf[100];
-+  assert( argc==1 || argc==2 );
-+  if( argv[0]==0 || (argc==2 && argv[1]==0) ) return;
-+  n = argc==2 ? atoi(argv[1]) : 0;
-+  if( n>30 ) n = 30;
-+  if( n<0 ) n = 0;
-+  r = sqliteAtoF(argv[0], 0);
-+  sprintf(zBuf,"%.*f",n,r);
-+  sqlite_set_result_string(context, zBuf, -1);
-+}
-+
-+/*
-+** Implementation of the upper() and lower() SQL functions.
-+*/
-+static void upperFunc(sqlite_func *context, int argc, const char **argv){
-+  unsigned char *z;
-+  int i;
-+  if( argc<1 || argv[0]==0 ) return;
-+  z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
-+  if( z==0 ) return;
-+  for(i=0; z[i]; i++){
-+    if( islower(z[i]) ) z[i] = toupper(z[i]);
-+  }
-+}
-+static void lowerFunc(sqlite_func *context, int argc, const char **argv){
-+  unsigned char *z;
-+  int i;
-+  if( argc<1 || argv[0]==0 ) return;
-+  z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
-+  if( z==0 ) return;
-+  for(i=0; z[i]; i++){
-+    if( isupper(z[i]) ) z[i] = tolower(z[i]);
-+  }
-+}
-+
-+/*
-+** Implementation of the IFNULL(), NVL(), and COALESCE() functions.  
-+** All three do the same thing.  They return the first non-NULL
-+** argument.
-+*/
-+static void ifnullFunc(sqlite_func *context, int argc, const char **argv){
-+  int i;
-+  for(i=0; i<argc; i++){
-+    if( argv[i] ){
-+      sqlite_set_result_string(context, argv[i], -1);
-+      break;
-+    }
-+  }
-+}
-+
-+/*
-+** Implementation of random().  Return a random integer.  
-+*/
-+static void randomFunc(sqlite_func *context, int argc, const char **argv){
-+  int r;
-+  sqliteRandomness(sizeof(r), &r);
-+  sqlite_set_result_int(context, r);
-+}
-+
-+/*
-+** Implementation of the last_insert_rowid() SQL function.  The return
-+** value is the same as the sqlite_last_insert_rowid() API function.
-+*/
-+static void last_insert_rowid(sqlite_func *context, int arg, const char **argv){
-+  sqlite *db = sqlite_user_data(context);
-+  sqlite_set_result_int(context, sqlite_last_insert_rowid(db));
-+}
-+
-+/*
-+** Implementation of the change_count() SQL function.  The return
-+** value is the same as the sqlite_changes() API function.
-+*/
-+static void change_count(sqlite_func *context, int arg, const char **argv){
-+  sqlite *db = sqlite_user_data(context);
-+  sqlite_set_result_int(context, sqlite_changes(db));
-+}
-+
-+/*
-+** Implementation of the last_statement_change_count() SQL function.  The
-+** return value is the same as the sqlite_last_statement_changes() API function.
-+*/
-+static void last_statement_change_count(sqlite_func *context, int arg,
-+                                        const char **argv){
-+  sqlite *db = sqlite_user_data(context);
-+  sqlite_set_result_int(context, sqlite_last_statement_changes(db));
-+}
-+
-+/*
-+** Implementation of the like() SQL function.  This function implements
-+** the build-in LIKE operator.  The first argument to the function is the
-+** string and the second argument is the pattern.  So, the SQL statements:
-+**
-+**       A LIKE B
-+**
-+** is implemented as like(A,B).
-+*/
-+static void likeFunc(sqlite_func *context, int arg, const char **argv){
-+  if( argv[0]==0 || argv[1]==0 ) return;
-+  sqlite_set_result_int(context, 
-+    sqliteLikeCompare((const unsigned char*)argv[0],
-+                      (const unsigned char*)argv[1]));
-+}
-+
-+/*
-+** 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(A,B).
-+*/
-+static void globFunc(sqlite_func *context, int arg, const char **argv){
-+  if( argv[0]==0 || argv[1]==0 ) return;
-+  sqlite_set_result_int(context,
-+    sqliteGlobCompare((const unsigned char*)argv[0],
-+                      (const unsigned char*)argv[1]));
-+}
-+
-+/*
-+** Implementation of the NULLIF(x,y) function.  The result is the first
-+** argument if the arguments are different.  The result is NULL if the
-+** arguments are equal to each other.
-+*/
-+static void nullifFunc(sqlite_func *context, int argc, const char **argv){
-+  if( argv[0]!=0 && sqliteCompare(argv[0],argv[1])!=0 ){
-+    sqlite_set_result_string(context, argv[0], -1);
-+  }
-+}
-+
-+/*
-+** Implementation of the VERSION(*) function.  The result is the version
-+** of the SQLite library that is running.
-+*/
-+static void versionFunc(sqlite_func *context, int argc, const char **argv){
-+  sqlite_set_result_string(context, sqlite_version, -1);
-+}
-+
-+/*
-+** EXPERIMENTAL - This is not an official function.  The interface may
-+** change.  This function may disappear.  Do not write code that depends
-+** on this function.
-+**
-+** Implementation of the QUOTE() function.  This function takes a single
-+** argument.  If the argument is numeric, the return value is the same as
-+** the argument.  If the argument is NULL, the return value is the string
-+** "NULL".  Otherwise, the argument is enclosed in single quotes with
-+** single-quote escapes.
-+*/
-+static void quoteFunc(sqlite_func *context, int argc, const char **argv){
-+  if( argc<1 ) return;
-+  if( argv[0]==0 ){
-+    sqlite_set_result_string(context, "NULL", 4);
-+  }else if( sqliteIsNumber(argv[0]) ){
-+    sqlite_set_result_string(context, argv[0], -1);
-+  }else{
-+    int i,j,n;
-+    char *z;
-+    for(i=n=0; argv[0][i]; i++){ if( argv[0][i]=='\'' ) n++; }
-+    z = sqliteMalloc( i+n+3 );
-+    if( z==0 ) return;
-+    z[0] = '\'';
-+    for(i=0, j=1; argv[0][i]; i++){
-+      z[j++] = argv[0][i];
-+      if( argv[0][i]=='\'' ){
-+        z[j++] = '\'';
-+      }
-+    }
-+    z[j++] = '\'';
-+    z[j] = 0;
-+    sqlite_set_result_string(context, z, j);
-+    sqliteFree(z);
-+  }
-+}
-+
-+#ifdef SQLITE_SOUNDEX
-+/*
-+** Compute the soundex encoding of a word.
-+*/
-+static void soundexFunc(sqlite_func *context, int argc, const char **argv){
-+  char zResult[8];
-+  const char *zIn;
-+  int i, j;
-+  static const unsigned char iCode[] = {
-+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+    0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
-+    1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
-+    0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
-+    1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
-+  };
-+  assert( argc==1 );
-+  zIn = argv[0];
-+  for(i=0; zIn[i] && !isalpha(zIn[i]); i++){}
-+  if( zIn[i] ){
-+    zResult[0] = toupper(zIn[i]);
-+    for(j=1; j<4 && zIn[i]; i++){
-+      int code = iCode[zIn[i]&0x7f];
-+      if( code>0 ){
-+        zResult[j++] = code + '0';
-+      }
-+    }
-+    while( j<4 ){
-+      zResult[j++] = '0';
-+    }
-+    zResult[j] = 0;
-+    sqlite_set_result_string(context, zResult, 4);
-+  }else{
-+    sqlite_set_result_string(context, "?000", 4);
-+  }
-+}
-+#endif
-+
-+#ifdef SQLITE_TEST
-+/*
-+** This function generates a string of random characters.  Used for
-+** generating test data.
-+*/
-+static void randStr(sqlite_func *context, int argc, const char **argv){
-+  static const unsigned char zSrc[] = 
-+     "abcdefghijklmnopqrstuvwxyz"
-+     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-+     "0123456789"
-+     ".-!,:*^+=_|?/<> ";
-+  int iMin, iMax, n, r, i;
-+  unsigned char zBuf[1000];
-+  if( argc>=1 ){
-+    iMin = atoi(argv[0]);
-+    if( iMin<0 ) iMin = 0;
-+    if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
-+  }else{
-+    iMin = 1;
-+  }
-+  if( argc>=2 ){
-+    iMax = atoi(argv[1]);
-+    if( iMax<iMin ) iMax = iMin;
-+    if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1;
-+  }else{
-+    iMax = 50;
-+  }
-+  n = iMin;
-+  if( iMax>iMin ){
-+    sqliteRandomness(sizeof(r), &r);
-+    r &= 0x7fffffff;
-+    n += r%(iMax + 1 - iMin);
-+  }
-+  assert( n<sizeof(zBuf) );
-+  sqliteRandomness(n, zBuf);
-+  for(i=0; i<n; i++){
-+    zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
-+  }
-+  zBuf[n] = 0;
-+  sqlite_set_result_string(context, zBuf, n);
-+}
-+#endif
-+
-+/*
-+** An instance of the following structure holds the context of a
-+** sum() or avg() aggregate computation.
-+*/
-+typedef struct SumCtx SumCtx;
-+struct SumCtx {
-+  double sum;     /* Sum of terms */
-+  int cnt;        /* Number of elements summed */
-+};
-+
-+/*
-+** Routines used to compute the sum or average.
-+*/
-+static void sumStep(sqlite_func *context, int argc, const char **argv){
-+  SumCtx *p;
-+  if( argc<1 ) return;
-+  p = sqlite_aggregate_context(context, sizeof(*p));
-+  if( p && argv[0] ){
-+    p->sum += sqliteAtoF(argv[0], 0);
-+    p->cnt++;
-+  }
-+}
-+static void sumFinalize(sqlite_func *context){
-+  SumCtx *p;
-+  p = sqlite_aggregate_context(context, sizeof(*p));
-+  sqlite_set_result_double(context, p ? p->sum : 0.0);
-+}
-+static void avgFinalize(sqlite_func *context){
-+  SumCtx *p;
-+  p = sqlite_aggregate_context(context, sizeof(*p));
-+  if( p && p->cnt>0 ){
-+    sqlite_set_result_double(context, p->sum/(double)p->cnt);
-+  }
-+}
-+
-+/*
-+** An instance of the following structure holds the context of a
-+** variance or standard deviation computation.
-+*/
-+typedef struct StdDevCtx StdDevCtx;
-+struct StdDevCtx {
-+  double sum;     /* Sum of terms */
-+  double sum2;    /* Sum of the squares of terms */
-+  int cnt;        /* Number of terms counted */
-+};
-+
-+#if 0   /* Omit because math library is required */
-+/*
-+** Routines used to compute the standard deviation as an aggregate.
-+*/
-+static void stdDevStep(sqlite_func *context, int argc, const char **argv){
-+  StdDevCtx *p;
-+  double x;
-+  if( argc<1 ) return;
-+  p = sqlite_aggregate_context(context, sizeof(*p));
-+  if( p && argv[0] ){
-+    x = sqliteAtoF(argv[0], 0);
-+    p->sum += x;
-+    p->sum2 += x*x;
-+    p->cnt++;
-+  }
-+}
-+static void stdDevFinalize(sqlite_func *context){
-+  double rN = sqlite_aggregate_count(context);
-+  StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p));
-+  if( p && p->cnt>1 ){
-+    double rCnt = cnt;
-+    sqlite_set_result_double(context, 
-+       sqrt((p->sum2 - p->sum*p->sum/rCnt)/(rCnt-1.0)));
-+  }
-+}
-+#endif
-+
-+/*
-+** The following structure keeps track of state information for the
-+** count() aggregate function.
-+*/
-+typedef struct CountCtx CountCtx;
-+struct CountCtx {
-+  int n;
-+};
-+
-+/*
-+** Routines to implement the count() aggregate function.
-+*/
-+static void countStep(sqlite_func *context, int argc, const char **argv){
-+  CountCtx *p;
-+  p = sqlite_aggregate_context(context, sizeof(*p));
-+  if( (argc==0 || argv[0]) && p ){
-+    p->n++;
-+  }
-+}   
-+static void countFinalize(sqlite_func *context){
-+  CountCtx *p;
-+  p = sqlite_aggregate_context(context, sizeof(*p));
-+  sqlite_set_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.
-+*/
-+static void minmaxStep(sqlite_func *context, int argc, const char **argv){
-+  MinMaxCtx *p;
-+  int (*xCompare)(const char*, const char*);
-+  int mask;    /* 0 for min() or 0xffffffff for max() */
-+
-+  assert( argc==2 );
-+  if( argv[0]==0 ) return;  /* Ignore NULL values */
-+  if( argv[1][0]=='n' ){
-+    xCompare = sqliteCompare;
-+  }else{
-+    xCompare = strcmp;
-+  }
-+  mask = (int)sqlite_user_data(context);
-+  assert( mask==0 || mask==-1 );
-+  p = sqlite_aggregate_context(context, sizeof(*p));
-+  if( p==0 || argc<1 ) return;
-+  if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){
-+    int len;
-+    if( p->zBuf[0] ){
-+      sqliteFree(p->z);
-+    }
-+    len = strlen(argv[0]);
-+    if( len < sizeof(p->zBuf)-1 ){
-+      p->z = &p->zBuf[1];
-+      p->zBuf[0] = 0;
-+    }else{
-+      p->z = sqliteMalloc( len+1 );
-+      p->zBuf[0] = 1;
-+      if( p->z==0 ) return;
-+    }
-+    strcpy(p->z, argv[0]);
-+  }
-+}
-+static void minMaxFinalize(sqlite_func *context){
-+  MinMaxCtx *p;
-+  p = sqlite_aggregate_context(context, sizeof(*p));
-+  if( p && p->z && p->zBuf[0]<2 ){
-+    sqlite_set_result_string(context, p->z, strlen(p->z));
-+  }
-+  if( p && p->zBuf[0] ){
-+    sqliteFree(p->z);
-+  }
-+}
-+
-+/*
-+** This function registered all of the above C functions as SQL
-+** functions.  This should be the only routine in this file with
-+** external linkage.
-+*/
-+void sqliteRegisterBuiltinFunctions(sqlite *db){
-+  static struct {
-+     char *zName;
-+     signed char nArg;
-+     signed char dataType;
-+     u8 argType;               /* 0: none.  1: db  2: (-1) */
-+     void (*xFunc)(sqlite_func*,int,const char**);
-+  } aFuncs[] = {
-+    { "min",       -1, SQLITE_ARGS,    0, minmaxFunc },
-+    { "min",        0, 0,              0, 0          },
-+    { "max",       -1, SQLITE_ARGS,    2, minmaxFunc },
-+    { "max",        0, 0,              2, 0          },
-+    { "typeof",     1, SQLITE_TEXT,    0, typeofFunc },
-+    { "length",     1, SQLITE_NUMERIC, 0, lengthFunc },
-+    { "substr",     3, SQLITE_TEXT,    0, substrFunc },
-+    { "abs",        1, SQLITE_NUMERIC, 0, absFunc    },
-+    { "round",      1, SQLITE_NUMERIC, 0, roundFunc  },
-+    { "round",      2, SQLITE_NUMERIC, 0, roundFunc  },
-+    { "upper",      1, SQLITE_TEXT,    0, upperFunc  },
-+    { "lower",      1, SQLITE_TEXT,    0, lowerFunc  },
-+    { "coalesce",  -1, SQLITE_ARGS,    0, ifnullFunc },
-+    { "coalesce",   0, 0,              0, 0          },
-+    { "coalesce",   1, 0,              0, 0          },
-+    { "ifnull",     2, SQLITE_ARGS,    0, ifnullFunc },
-+    { "random",    -1, SQLITE_NUMERIC, 0, randomFunc },
-+    { "like",       2, SQLITE_NUMERIC, 0, likeFunc   },
-+    { "glob",       2, SQLITE_NUMERIC, 0, globFunc   },
-+    { "nullif",     2, SQLITE_ARGS,    0, nullifFunc },
-+    { "sqlite_version",0,SQLITE_TEXT,  0, versionFunc},
-+    { "quote",      1, SQLITE_ARGS,    0, quoteFunc  },
-+    { "last_insert_rowid", 0, SQLITE_NUMERIC, 1, last_insert_rowid },
-+    { "change_count",      0, SQLITE_NUMERIC, 1, change_count      },
-+    { "last_statement_change_count",
-+                           0, SQLITE_NUMERIC, 1, last_statement_change_count },
-+#ifdef SQLITE_SOUNDEX
-+    { "soundex",    1, SQLITE_TEXT,    0, soundexFunc},
-+#endif
-+#ifdef SQLITE_TEST
-+    { "randstr",    2, SQLITE_TEXT,    0, randStr    },
-+#endif
-+  };
-+  static struct {
-+    char *zName;
-+    signed char nArg;
-+    signed char dataType;
-+    u8 argType;
-+    void (*xStep)(sqlite_func*,int,const char**);
-+    void (*xFinalize)(sqlite_func*);
-+  } aAggs[] = {
-+    { "min",    1, 0,              0, minmaxStep,   minMaxFinalize },
-+    { "max",    1, 0,              2, minmaxStep,   minMaxFinalize },
-+    { "sum",    1, SQLITE_NUMERIC, 0, sumStep,      sumFinalize    },
-+    { "avg",    1, SQLITE_NUMERIC, 0, sumStep,      avgFinalize    },
-+    { "count",  0, SQLITE_NUMERIC, 0, countStep,    countFinalize  },
-+    { "count",  1, SQLITE_NUMERIC, 0, countStep,    countFinalize  },
-+#if 0
-+    { "stddev", 1, SQLITE_NUMERIC, 0, stdDevStep,   stdDevFinalize },
-+#endif
-+  };
-+  static const char *azTypeFuncs[] = { "min", "max", "typeof" };
-+  int i;
-+
-+  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
-+    void *pArg;
-+    switch( aFuncs[i].argType ){
-+      case 0:  pArg = 0;           break;
-+      case 1:  pArg = db;          break;
-+      case 2:  pArg = (void*)(-1); break;
-+    }
-+    sqlite_create_function(db, aFuncs[i].zName,
-+           aFuncs[i].nArg, aFuncs[i].xFunc, pArg);
-+    if( aFuncs[i].xFunc ){
-+      sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
-+    }
-+  }
-+  for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
-+    void *pArg;
-+    switch( aAggs[i].argType ){
-+      case 0:  pArg = 0;           break;
-+      case 1:  pArg = db;          break;
-+      case 2:  pArg = (void*)(-1); break;
-+    }
-+    sqlite_create_aggregate(db, aAggs[i].zName,
-+           aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, pArg);
-+    sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType);
-+  }
-+  for(i=0; i<sizeof(azTypeFuncs)/sizeof(azTypeFuncs[0]); i++){
-+    int n = strlen(azTypeFuncs[i]);
-+    FuncDef *p = sqliteHashFind(&db->aFunc, azTypeFuncs[i], n);
-+    while( p ){
-+      p->includeTypes = 1;
-+      p = p->pNext;
-+    }
-+  }
-+  sqliteRegisterDateTimeFunctions(db);
-+}
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/hash.c
-@@ -0,0 +1,356 @@
-+/*
-+** 2001 September 22
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This is the implementation of generic hash-tables
-+** used in SQLite.
-+**
-+** $Id$
-+*/
-+#include "sqliteInt.h"
-+#include <assert.h>
-+
-+/* Turn bulk memory into a hash table object by initializing the
-+** fields of the Hash structure.
-+**
-+** "new" is a pointer to the hash table that is to be initialized.
-+** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER,
-+** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING.  The value of keyClass 
-+** determines what kind of key the hash table will use.  "copyKey" is
-+** true if the hash table should make its own private copy of keys and
-+** false if it should just use the supplied pointer.  CopyKey only makes
-+** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored
-+** for other key classes.
-+*/
-+void sqliteHashInit(Hash *new, int keyClass, int copyKey){
-+  assert( new!=0 );
-+  assert( keyClass>=SQLITE_HASH_INT && keyClass<=SQLITE_HASH_BINARY );
-+  new->keyClass = keyClass;
-+  new->copyKey = copyKey &&
-+                (keyClass==SQLITE_HASH_STRING || keyClass==SQLITE_HASH_BINARY);
-+  new->first = 0;
-+  new->count = 0;
-+  new->htsize = 0;
-+  new->ht = 0;
-+}
-+
-+/* Remove all entries from a hash table.  Reclaim all memory.
-+** Call this routine to delete a hash table or to reset a hash table
-+** to the empty state.
-+*/
-+void sqliteHashClear(Hash *pH){
-+  HashElem *elem;         /* For looping over all elements of the table */
-+
-+  assert( pH!=0 );
-+  elem = pH->first;
-+  pH->first = 0;
-+  if( pH->ht ) sqliteFree(pH->ht);
-+  pH->ht = 0;
-+  pH->htsize = 0;
-+  while( elem ){
-+    HashElem *next_elem = elem->next;
-+    if( pH->copyKey && elem->pKey ){
-+      sqliteFree(elem->pKey);
-+    }
-+    sqliteFree(elem);
-+    elem = next_elem;
-+  }
-+  pH->count = 0;
-+}
-+
-+/*
-+** Hash and comparison functions when the mode is SQLITE_HASH_INT
-+*/
-+static int intHash(const void *pKey, int nKey){
-+  return nKey ^ (nKey<<8) ^ (nKey>>8);
-+}
-+static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
-+  return n2 - n1;
-+}
-+
-+#if 0 /* NOT USED */
-+/*
-+** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
-+*/
-+static int ptrHash(const void *pKey, int nKey){
-+  uptr x = Addr(pKey);
-+  return x ^ (x<<8) ^ (x>>8);
-+}
-+static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
-+  if( pKey1==pKey2 ) return 0;
-+  if( pKey1<pKey2 ) return -1;
-+  return 1;
-+}
-+#endif
-+
-+/*
-+** Hash and comparison functions when the mode is SQLITE_HASH_STRING
-+*/
-+static int strHash(const void *pKey, int nKey){
-+  return sqliteHashNoCase((const char*)pKey, nKey); 
-+}
-+static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
-+  if( n1!=n2 ) return n2-n1;
-+  return sqliteStrNICmp((const char*)pKey1,(const char*)pKey2,n1);
-+}
-+
-+/*
-+** Hash and comparison functions when the mode is SQLITE_HASH_BINARY
-+*/
-+static int binHash(const void *pKey, int nKey){
-+  int h = 0;
-+  const char *z = (const char *)pKey;
-+  while( nKey-- > 0 ){
-+    h = (h<<3) ^ h ^ *(z++);
-+  }
-+  return h & 0x7fffffff;
-+}
-+static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
-+  if( n1!=n2 ) return n2-n1;
-+  return memcmp(pKey1,pKey2,n1);
-+}
-+
-+/*
-+** Return a pointer to the appropriate hash function given the key class.
-+**
-+** The C syntax in this function definition may be unfamilar to some 
-+** programmers, so we provide the following additional explanation:
-+**
-+** The name of the function is "hashFunction".  The function takes a
-+** single parameter "keyClass".  The return value of hashFunction()
-+** is a pointer to another function.  Specifically, the return value
-+** of hashFunction() is a pointer to a function that takes two parameters
-+** with types "const void*" and "int" and returns an "int".
-+*/
-+static int (*hashFunction(int keyClass))(const void*,int){
-+  switch( keyClass ){
-+    case SQLITE_HASH_INT:     return &intHash;
-+    /* case SQLITE_HASH_POINTER: return &ptrHash; // NOT USED */
-+    case SQLITE_HASH_STRING:  return &strHash;
-+    case SQLITE_HASH_BINARY:  return &binHash;;
-+    default: break;
-+  }
-+  return 0;
-+}
-+
-+/*
-+** Return a pointer to the appropriate hash function given the key class.
-+**
-+** For help in interpreted the obscure C code in the function definition,
-+** see the header comment on the previous function.
-+*/
-+static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
-+  switch( keyClass ){
-+    case SQLITE_HASH_INT:     return &intCompare;
-+    /* case SQLITE_HASH_POINTER: return &ptrCompare; // NOT USED */
-+    case SQLITE_HASH_STRING:  return &strCompare;
-+    case SQLITE_HASH_BINARY:  return &binCompare;
-+    default: break;
-+  }
-+  return 0;
-+}
-+
-+
-+/* Resize the hash table so that it cantains "new_size" buckets.
-+** "new_size" must be a power of 2.  The hash table might fail 
-+** to resize if sqliteMalloc() fails.
-+*/
-+static void rehash(Hash *pH, int new_size){
-+  struct _ht *new_ht;            /* The new hash table */
-+  HashElem *elem, *next_elem;    /* For looping over existing elements */
-+  HashElem *x;                   /* Element being copied to new hash table */
-+  int (*xHash)(const void*,int); /* The hash function */
-+
-+  assert( (new_size & (new_size-1))==0 );
-+  new_ht = (struct _ht *)sqliteMalloc( new_size*sizeof(struct _ht) );
-+  if( new_ht==0 ) return;
-+  if( pH->ht ) sqliteFree(pH->ht);
-+  pH->ht = new_ht;
-+  pH->htsize = new_size;
-+  xHash = hashFunction(pH->keyClass);
-+  for(elem=pH->first, pH->first=0; elem; elem = next_elem){
-+    int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
-+    next_elem = elem->next;
-+    x = new_ht[h].chain;
-+    if( x ){
-+      elem->next = x;
-+      elem->prev = x->prev;
-+      if( x->prev ) x->prev->next = elem;
-+      else          pH->first = elem;
-+      x->prev = elem;
-+    }else{
-+      elem->next = pH->first;
-+      if( pH->first ) pH->first->prev = elem;
-+      elem->prev = 0;
-+      pH->first = elem;
-+    }
-+    new_ht[h].chain = elem;
-+    new_ht[h].count++;
-+  }
-+}
-+
-+/* This function (for internal use only) locates an element in an
-+** hash table that matches the given key.  The hash for this key has
-+** already been computed and is passed as the 4th parameter.
-+*/
-+static HashElem *findElementGivenHash(
-+  const Hash *pH,     /* The pH to be searched */
-+  const void *pKey,   /* The key we are searching for */
-+  int nKey,
-+  int h               /* The hash for this key. */
-+){
-+  HashElem *elem;                /* Used to loop thru the element list */
-+  int count;                     /* Number of elements left to test */
-+  int (*xCompare)(const void*,int,const void*,int);  /* comparison function */
-+
-+  if( pH->ht ){
-+    elem = pH->ht[h].chain;
-+    count = pH->ht[h].count;
-+    xCompare = compareFunction(pH->keyClass);
-+    while( count-- && elem ){
-+      if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ 
-+        return elem;
-+      }
-+      elem = elem->next;
-+    }
-+  }
-+  return 0;
-+}
-+
-+/* Remove a single entry from the hash table given a pointer to that
-+** element and a hash on the element's key.
-+*/
-+static void removeElementGivenHash(
-+  Hash *pH,         /* The pH containing "elem" */
-+  HashElem* elem,   /* The element to be removed from the pH */
-+  int h             /* Hash value for the element */
-+){
-+  if( elem->prev ){
-+    elem->prev->next = elem->next; 
-+  }else{
-+    pH->first = elem->next;
-+  }
-+  if( elem->next ){
-+    elem->next->prev = elem->prev;
-+  }
-+  if( pH->ht[h].chain==elem ){
-+    pH->ht[h].chain = elem->next;
-+  }
-+  pH->ht[h].count--;
-+  if( pH->ht[h].count<=0 ){
-+    pH->ht[h].chain = 0;
-+  }
-+  if( pH->copyKey && elem->pKey ){
-+    sqliteFree(elem->pKey);
-+  }
-+  sqliteFree( elem );
-+  pH->count--;
-+}
-+
-+/* Attempt to locate an element of the hash table pH with a key
-+** that matches pKey,nKey.  Return the data for this element if it is
-+** found, or NULL if there is no match.
-+*/
-+void *sqliteHashFind(const Hash *pH, const void *pKey, int nKey){
-+  int h;             /* A hash on key */
-+  HashElem *elem;    /* The element that matches key */
-+  int (*xHash)(const void*,int);  /* The hash function */
-+
-+  if( pH==0 || pH->ht==0 ) return 0;
-+  xHash = hashFunction(pH->keyClass);
-+  assert( xHash!=0 );
-+  h = (*xHash)(pKey,nKey);
-+  assert( (pH->htsize & (pH->htsize-1))==0 );
-+  elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
-+  return elem ? elem->data : 0;
-+}
-+
-+/* Insert an element into the hash table pH.  The key is pKey,nKey
-+** and the data is "data".
-+**
-+** If no element exists with a matching key, then a new
-+** element is created.  A copy of the key is made if the copyKey
-+** flag is set.  NULL is returned.
-+**
-+** If another element already exists with the same key, then the
-+** new data replaces the old data and the old data is returned.
-+** The key is not copied in this instance.  If a malloc fails, then
-+** the new data is returned and the hash table is unchanged.
-+**
-+** If the "data" parameter to this function is NULL, then the
-+** element corresponding to "key" is removed from the hash table.
-+*/
-+void *sqliteHashInsert(Hash *pH, const void *pKey, int nKey, void *data){
-+  int hraw;             /* Raw hash value of the key */
-+  int h;                /* the hash of the key modulo hash table size */
-+  HashElem *elem;       /* Used to loop thru the element list */
-+  HashElem *new_elem;   /* New element added to the pH */
-+  int (*xHash)(const void*,int);  /* The hash function */
-+
-+  assert( pH!=0 );
-+  xHash = hashFunction(pH->keyClass);
-+  assert( xHash!=0 );
-+  hraw = (*xHash)(pKey, nKey);
-+  assert( (pH->htsize & (pH->htsize-1))==0 );
-+  h = hraw & (pH->htsize-1);
-+  elem = findElementGivenHash(pH,pKey,nKey,h);
-+  if( elem ){
-+    void *old_data = elem->data;
-+    if( data==0 ){
-+      removeElementGivenHash(pH,elem,h);
-+    }else{
-+      elem->data = data;
-+    }
-+    return old_data;
-+  }
-+  if( data==0 ) return 0;
-+  new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) );
-+  if( new_elem==0 ) return data;
-+  if( pH->copyKey && pKey!=0 ){
-+    new_elem->pKey = sqliteMallocRaw( nKey );
-+    if( new_elem->pKey==0 ){
-+      sqliteFree(new_elem);
-+      return data;
-+    }
-+    memcpy((void*)new_elem->pKey, pKey, nKey);
-+  }else{
-+    new_elem->pKey = (void*)pKey;
-+  }
-+  new_elem->nKey = nKey;
-+  pH->count++;
-+  if( pH->htsize==0 ) rehash(pH,8);
-+  if( pH->htsize==0 ){
-+    pH->count = 0;
-+    sqliteFree(new_elem);
-+    return data;
-+  }
-+  if( pH->count > pH->htsize ){
-+    rehash(pH,pH->htsize*2);
-+  }
-+  assert( (pH->htsize & (pH->htsize-1))==0 );
-+  h = hraw & (pH->htsize-1);
-+  elem = pH->ht[h].chain;
-+  if( elem ){
-+    new_elem->next = elem;
-+    new_elem->prev = elem->prev;
-+    if( elem->prev ){ elem->prev->next = new_elem; }
-+    else            { pH->first = new_elem; }
-+    elem->prev = new_elem;
-+  }else{
-+    new_elem->next = pH->first;
-+    new_elem->prev = 0;
-+    if( pH->first ){ pH->first->prev = new_elem; }
-+    pH->first = new_elem;
-+  }
-+  pH->ht[h].count++;
-+  pH->ht[h].chain = new_elem;
-+  new_elem->data = data;
-+  return 0;
-+}
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/hash.h
-@@ -0,0 +1,109 @@
-+/*
-+** 2001 September 22
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This is the header file for the generic hash-table implemenation
-+** used in SQLite.
-+**
-+** $Id$
-+*/
-+#ifndef _SQLITE_HASH_H_
-+#define _SQLITE_HASH_H_
-+
-+/* Forward declarations of structures. */
-+typedef struct Hash Hash;
-+typedef struct HashElem HashElem;
-+
-+/* A complete hash table is an instance of the following structure.
-+** The internals of this structure are intended to be opaque -- client
-+** code should not attempt to access or modify the fields of this structure
-+** directly.  Change this structure only by using the routines below.
-+** However, many of the "procedures" and "functions" for modifying and
-+** accessing this structure are really macros, so we can't really make
-+** this structure opaque.
-+*/
-+struct Hash {
-+  char keyClass;          /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */
-+  char copyKey;           /* True if copy of key made on insert */
-+  int count;              /* Number of entries in this table */
-+  HashElem *first;        /* The first element of the array */
-+  int htsize;             /* Number of buckets in the hash table */
-+  struct _ht {            /* the hash table */
-+    int count;               /* Number of entries with this hash */
-+    HashElem *chain;         /* Pointer to first entry with this hash */
-+  } *ht;
-+};
-+
-+/* Each element in the hash table is an instance of the following 
-+** structure.  All elements are stored on a single doubly-linked list.
-+**
-+** Again, this structure is intended to be opaque, but it can't really
-+** be opaque because it is used by macros.
-+*/
-+struct HashElem {
-+  HashElem *next, *prev;   /* Next and previous elements in the table */
-+  void *data;              /* Data associated with this element */
-+  void *pKey; int nKey;    /* Key associated with this element */
-+};
-+
-+/*
-+** There are 4 different modes of operation for a hash table:
-+**
-+**   SQLITE_HASH_INT         nKey is used as the key and pKey is ignored.
-+**
-+**   SQLITE_HASH_POINTER     pKey is used as the key and nKey is ignored.
-+**
-+**   SQLITE_HASH_STRING      pKey points to a string that is nKey bytes long
-+**                           (including the null-terminator, if any).  Case
-+**                           is ignored in comparisons.
-+**
-+**   SQLITE_HASH_BINARY      pKey points to binary data nKey bytes long. 
-+**                           memcmp() is used to compare keys.
-+**
-+** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY
-+** if the copyKey parameter to HashInit is 1.  
-+*/
-+#define SQLITE_HASH_INT       1
-+/* #define SQLITE_HASH_POINTER   2 // NOT USED */
-+#define SQLITE_HASH_STRING    3
-+#define SQLITE_HASH_BINARY    4
-+
-+/*
-+** Access routines.  To delete, insert a NULL pointer.
-+*/
-+void sqliteHashInit(Hash*, int keytype, int copyKey);
-+void *sqliteHashInsert(Hash*, const void *pKey, int nKey, void *pData);
-+void *sqliteHashFind(const Hash*, const void *pKey, int nKey);
-+void sqliteHashClear(Hash*);
-+
-+/*
-+** Macros for looping over all elements of a hash table.  The idiom is
-+** like this:
-+**
-+**   Hash h;
-+**   HashElem *p;
-+**   ...
-+**   for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){
-+**     SomeStructure *pData = sqliteHashData(p);
-+**     // do something with pData
-+**   }
-+*/
-+#define sqliteHashFirst(H)  ((H)->first)
-+#define sqliteHashNext(E)   ((E)->next)
-+#define sqliteHashData(E)   ((E)->data)
-+#define sqliteHashKey(E)    ((E)->pKey)
-+#define sqliteHashKeysize(E) ((E)->nKey)
-+
-+/*
-+** Number of entries in a hash table
-+*/
-+#define sqliteHashCount(H)  ((H)->count)
-+
-+#endif /* _SQLITE_HASH_H_ */
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/insert.c
-@@ -0,0 +1,919 @@
-+/*
-+** 2001 September 15
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains C code routines that are called by the parser
-+** to handle INSERT statements in SQLite.
-+**
-+** $Id$
-+*/
-+#include "sqliteInt.h"
-+
-+/*
-+** This routine is call to handle SQL of the following forms:
-+**
-+**    insert into TABLE (IDLIST) values(EXPRLIST)
-+**    insert into TABLE (IDLIST) select
-+**
-+** The IDLIST following the table name is always optional.  If omitted,
-+** then a list of all columns for the table is substituted.  The IDLIST
-+** appears in the pColumn parameter.  pColumn is NULL if IDLIST is omitted.
-+**
-+** The pList parameter holds EXPRLIST in the first form of the INSERT
-+** statement above, and pSelect is NULL.  For the second form, pList is
-+** NULL and pSelect is a pointer to the select statement used to generate
-+** data for the insert.
-+**
-+** The code generated follows one of three templates.  For a simple
-+** select with data coming from a VALUES clause, the code executes
-+** once straight down through.  The template looks like this:
-+**
-+**         open write cursor to <table> and its indices
-+**         puts VALUES clause expressions onto the stack
-+**         write the resulting record into <table>
-+**         cleanup
-+**
-+** If the statement is of the form
-+**
-+**   INSERT INTO <table> SELECT ...
-+**
-+** And the SELECT clause does not read from <table> at any time, then
-+** the generated code follows this template:
-+**
-+**         goto B
-+**      A: setup for the SELECT
-+**         loop over the tables in the SELECT
-+**           gosub C
-+**         end loop
-+**         cleanup after the SELECT
-+**         goto D
-+**      B: open write cursor to <table> and its indices
-+**         goto A
-+**      C: insert the select result into <table>
-+**         return
-+**      D: cleanup
-+**
-+** The third template is used if the insert statement takes its
-+** values from a SELECT but the data is being inserted into a table
-+** that is also read as part of the SELECT.  In the third form,
-+** we have to use a intermediate table to store the results of
-+** the select.  The template is like this:
-+**
-+**         goto B
-+**      A: setup for the SELECT
-+**         loop over the tables in the SELECT
-+**           gosub C
-+**         end loop
-+**         cleanup after the SELECT
-+**         goto D
-+**      C: insert the select result into the intermediate table
-+**         return
-+**      B: open a cursor to an intermediate table
-+**         goto A
-+**      D: open write cursor to <table> and its indices
-+**         loop over the intermediate table
-+**           transfer values form intermediate table into <table>
-+**         end the loop
-+**         cleanup
-+*/
-+void sqliteInsert(
-+  Parse *pParse,        /* Parser context */
-+  SrcList *pTabList,    /* Name of table into which we are inserting */
-+  ExprList *pList,      /* List of values to be inserted */
-+  Select *pSelect,      /* A SELECT statement to use as the data source */
-+  IdList *pColumn,      /* Column names corresponding to IDLIST. */
-+  int onError           /* How to handle constraint errors */
-+){
-+  Table *pTab;          /* The table to insert into */
-+  char *zTab;           /* Name of the table into which we are inserting */
-+  const char *zDb;      /* Name of the database holding this table */
-+  int i, j, idx;        /* Loop counters */
-+  Vdbe *v;              /* Generate code into this virtual machine */
-+  Index *pIdx;          /* For looping over indices of the table */
-+  int nColumn;          /* Number of columns in the data */
-+  int base;             /* VDBE Cursor number for pTab */
-+  int iCont, iBreak;    /* Beginning and end of the loop over srcTab */
-+  sqlite *db;           /* The main database structure */
-+  int keyColumn = -1;   /* Column that is the INTEGER PRIMARY KEY */
-+  int endOfLoop;        /* Label for the end of the insertion loop */
-+  int useTempTable;     /* Store SELECT results in intermediate table */
-+  int srcTab;           /* Data comes from this temporary cursor if >=0 */
-+  int iSelectLoop;      /* Address of code that implements the SELECT */
-+  int iCleanup;         /* Address of the cleanup code */
-+  int iInsertBlock;     /* Address of the subroutine used to insert data */
-+  int iCntMem;          /* Memory cell used for the row counter */
-+  int isView;           /* True if attempting to insert into a view */
-+
-+  int row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
-+  int before_triggers;        /* True if there are BEFORE triggers */
-+  int after_triggers;         /* True if there are AFTER triggers */
-+  int newIdx = -1;            /* Cursor for the NEW table */
-+
-+  if( pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;
-+  db = pParse->db;
-+
-+  /* Locate the table into which we will be inserting new information.
-+  */
-+  assert( pTabList->nSrc==1 );
-+  zTab = pTabList->a[0].zName;
-+  if( zTab==0 ) goto insert_cleanup;
-+  pTab = sqliteSrcListLookup(pParse, pTabList);
-+  if( pTab==0 ){
-+    goto insert_cleanup;
-+  }
-+  assert( pTab->iDb<db->nDb );
-+  zDb = db->aDb[pTab->iDb].zName;
-+  if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
-+    goto insert_cleanup;
-+  }
-+
-+  /* Ensure that:
-+  *  (a) the table is not read-only, 
-+  *  (b) that if it is a view then ON INSERT triggers exist
-+  */
-+  before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, TK_INSERT, 
-+                                       TK_BEFORE, TK_ROW, 0);
-+  after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, TK_INSERT,
-+                                       TK_AFTER, TK_ROW, 0);
-+  row_triggers_exist = before_triggers || after_triggers;
-+  isView = pTab->pSelect!=0;
-+  if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
-+    goto insert_cleanup;
-+  }
-+  if( pTab==0 ) goto insert_cleanup;
-+
-+  /* If pTab is really a view, make sure it has been initialized.
-+  */
-+  if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
-+    goto insert_cleanup;
-+  }
-+
-+  /* Allocate a VDBE
-+  */
-+  v = sqliteGetVdbe(pParse);
-+  if( v==0 ) goto insert_cleanup;
-+  sqliteBeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb);
-+
-+  /* if there are row triggers, allocate a temp table for new.* references. */
-+  if( row_triggers_exist ){
-+    newIdx = pParse->nTab++;
-+  }
-+
-+  /* Figure out how many columns of data are supplied.  If the data
-+  ** is coming from a SELECT statement, then this step also generates
-+  ** all the code to implement the SELECT statement and invoke a subroutine
-+  ** to process each row of the result. (Template 2.) If the SELECT
-+  ** statement uses the the table that is being inserted into, then the
-+  ** subroutine is also coded here.  That subroutine stores the SELECT
-+  ** results in a temporary table. (Template 3.)
-+  */
-+  if( pSelect ){
-+    /* Data is coming from a SELECT.  Generate code to implement that SELECT
-+    */
-+    int rc, iInitCode;
-+    iInitCode = sqliteVdbeAddOp(v, OP_Goto, 0, 0);
-+    iSelectLoop = sqliteVdbeCurrentAddr(v);
-+    iInsertBlock = sqliteVdbeMakeLabel(v);
-+    rc = sqliteSelect(pParse, pSelect, SRT_Subroutine, iInsertBlock, 0,0,0);
-+    if( rc || pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;
-+    iCleanup = sqliteVdbeMakeLabel(v);
-+    sqliteVdbeAddOp(v, OP_Goto, 0, iCleanup);
-+    assert( pSelect->pEList );
-+    nColumn = pSelect->pEList->nExpr;
-+
-+    /* Set useTempTable to TRUE if the result of the SELECT statement
-+    ** should be written into a temporary table.  Set to FALSE if each
-+    ** row of the SELECT can be written directly into the result table.
-+    **
-+    ** A temp table must be used if the table being updated is also one
-+    ** of the tables being read by the SELECT statement.  Also use a 
-+    ** temp table in the case of row triggers.
-+    */
-+    if( row_triggers_exist ){
-+      useTempTable = 1;
-+    }else{
-+      int addr = sqliteVdbeFindOp(v, OP_OpenRead, pTab->tnum);
-+      useTempTable = 0;
-+      if( addr>0 ){
-+        VdbeOp *pOp = sqliteVdbeGetOp(v, addr-2);
-+        if( pOp->opcode==OP_Integer && pOp->p1==pTab->iDb ){
-+          useTempTable = 1;
-+        }
-+      }
-+    }
-+
-+    if( useTempTable ){
-+      /* Generate the subroutine that SELECT calls to process each row of
-+      ** the result.  Store the result in a temporary table
-+      */
-+      srcTab = pParse->nTab++;
-+      sqliteVdbeResolveLabel(v, iInsertBlock);
-+      sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
-+      sqliteVdbeAddOp(v, OP_NewRecno, srcTab, 0);
-+      sqliteVdbeAddOp(v, OP_Pull, 1, 0);
-+      sqliteVdbeAddOp(v, OP_PutIntKey, srcTab, 0);
-+      sqliteVdbeAddOp(v, OP_Return, 0, 0);
-+
-+      /* The following code runs first because the GOTO at the very top
-+      ** of the program jumps to it.  Create the temporary table, then jump
-+      ** back up and execute the SELECT code above.
-+      */
-+      sqliteVdbeChangeP2(v, iInitCode, sqliteVdbeCurrentAddr(v));
-+      sqliteVdbeAddOp(v, OP_OpenTemp, srcTab, 0);
-+      sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop);
-+      sqliteVdbeResolveLabel(v, iCleanup);
-+    }else{
-+      sqliteVdbeChangeP2(v, iInitCode, sqliteVdbeCurrentAddr(v));
-+    }
-+  }else{
-+    /* This is the case if the data for the INSERT is coming from a VALUES
-+    ** clause
-+    */
-+    SrcList dummy;
-+    assert( pList!=0 );
-+    srcTab = -1;
-+    useTempTable = 0;
-+    assert( pList );
-+    nColumn = pList->nExpr;
-+    dummy.nSrc = 0;
-+    for(i=0; i<nColumn; i++){
-+      if( sqliteExprResolveIds(pParse, &dummy, 0, pList->a[i].pExpr) ){
-+        goto insert_cleanup;
-+      }
-+      if( sqliteExprCheck(pParse, pList->a[i].pExpr, 0, 0) ){
-+        goto insert_cleanup;
-+      }
-+    }
-+  }
-+
-+  /* Make sure the number of columns in the source data matches the number
-+  ** of columns to be inserted into the table.
-+  */
-+  if( pColumn==0 && nColumn!=pTab->nCol ){
-+    sqliteErrorMsg(pParse, 
-+       "table %S has %d columns but %d values were supplied",
-+       pTabList, 0, pTab->nCol, nColumn);
-+    goto insert_cleanup;
-+  }
-+  if( pColumn!=0 && nColumn!=pColumn->nId ){
-+    sqliteErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
-+    goto insert_cleanup;
-+  }
-+
-+  /* If the INSERT statement included an IDLIST term, then make sure
-+  ** all elements of the IDLIST really are columns of the table and 
-+  ** remember the column indices.
-+  **
-+  ** If the table has an INTEGER PRIMARY KEY column and that column
-+  ** is named in the IDLIST, then record in the keyColumn variable
-+  ** the index into IDLIST of the primary key column.  keyColumn is
-+  ** the index of the primary key as it appears in IDLIST, not as
-+  ** is appears in the original table.  (The index of the primary
-+  ** key in the original table is pTab->iPKey.)
-+  */
-+  if( pColumn ){
-+    for(i=0; i<pColumn->nId; i++){
-+      pColumn->a[i].idx = -1;
-+    }
-+    for(i=0; i<pColumn->nId; i++){
-+      for(j=0; j<pTab->nCol; j++){
-+        if( sqliteStrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
-+          pColumn->a[i].idx = j;
-+          if( j==pTab->iPKey ){
-+            keyColumn = i;
-+          }
-+          break;
-+        }
-+      }
-+      if( j>=pTab->nCol ){
-+        if( sqliteIsRowid(pColumn->a[i].zName) ){
-+          keyColumn = i;
-+        }else{
-+          sqliteErrorMsg(pParse, "table %S has no column named %s",
-+              pTabList, 0, pColumn->a[i].zName);
-+          pParse->nErr++;
-+          goto insert_cleanup;
-+        }
-+      }
-+    }
-+  }
-+
-+  /* If there is no IDLIST term but the table has an integer primary
-+  ** key, the set the keyColumn variable to the primary key column index
-+  ** in the original table definition.
-+  */
-+  if( pColumn==0 ){
-+    keyColumn = pTab->iPKey;
-+  }
-+
-+  /* Open the temp table for FOR EACH ROW triggers
-+  */
-+  if( row_triggers_exist ){
-+    sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
-+  }
-+    
-+  /* Initialize the count of rows to be inserted
-+  */
-+  if( db->flags & SQLITE_CountRows ){
-+    iCntMem = pParse->nMem++;
-+    sqliteVdbeAddOp(v, OP_Integer, 0, 0);
-+    sqliteVdbeAddOp(v, OP_MemStore, iCntMem, 1);
-+  }
-+
-+  /* Open tables and indices if there are no row triggers */
-+  if( !row_triggers_exist ){
-+    base = pParse->nTab;
-+    idx = sqliteOpenTableAndIndices(pParse, pTab, base);
-+    pParse->nTab += idx;
-+  }
-+
-+  /* If the data source is a temporary table, then we have to create
-+  ** a loop because there might be multiple rows of data.  If the data
-+  ** source is a subroutine call from the SELECT statement, then we need
-+  ** to launch the SELECT statement processing.
-+  */
-+  if( useTempTable ){
-+    iBreak = sqliteVdbeMakeLabel(v);
-+    sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak);
-+    iCont = sqliteVdbeCurrentAddr(v);
-+  }else if( pSelect ){
-+    sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop);
-+    sqliteVdbeResolveLabel(v, iInsertBlock);
-+  }
-+
-+  /* Run the BEFORE and INSTEAD OF triggers, if there are any
-+  */
-+  endOfLoop = sqliteVdbeMakeLabel(v);
-+  if( before_triggers ){
-+
-+    /* build the NEW.* reference row.  Note that if there is an INTEGER
-+    ** PRIMARY KEY into which a NULL is being inserted, that NULL will be
-+    ** translated into a unique ID for the row.  But on a BEFORE trigger,
-+    ** we do not know what the unique ID will be (because the insert has
-+    ** not happened yet) so we substitute a rowid of -1
-+    */
-+    if( keyColumn<0 ){
-+      sqliteVdbeAddOp(v, OP_Integer, -1, 0);
-+    }else if( useTempTable ){
-+      sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);
-+    }else if( pSelect ){
-+      sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
-+    }else{
-+      sqliteExprCode(pParse, pList->a[keyColumn].pExpr);
-+      sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);
-+      sqliteVdbeAddOp(v, OP_Pop, 1, 0);
-+      sqliteVdbeAddOp(v, OP_Integer, -1, 0);
-+      sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
-+    }
-+
-+    /* Create the new column data
-+    */
-+    for(i=0; i<pTab->nCol; i++){
-+      if( pColumn==0 ){
-+        j = i;
-+      }else{
-+        for(j=0; j<pColumn->nId; j++){
-+          if( pColumn->a[j].idx==i ) break;
-+        }
-+      }
-+      if( pColumn && j>=pColumn->nId ){
-+        sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
-+      }else if( useTempTable ){
-+        sqliteVdbeAddOp(v, OP_Column, srcTab, j); 
-+      }else if( pSelect ){
-+        sqliteVdbeAddOp(v, OP_Dup, nColumn-j-1, 1);
-+      }else{
-+        sqliteExprCode(pParse, pList->a[j].pExpr);
-+      }
-+    }
-+    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
-+    sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
-+
-+    /* Fire BEFORE or INSTEAD OF triggers */
-+    if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, 
-+        newIdx, -1, onError, endOfLoop) ){
-+      goto insert_cleanup;
-+    }
-+  }
-+
-+  /* If any triggers exists, the opening of tables and indices is deferred
-+  ** until now.
-+  */
-+  if( row_triggers_exist && !isView ){
-+    base = pParse->nTab;
-+    idx = sqliteOpenTableAndIndices(pParse, pTab, base);
-+    pParse->nTab += idx;
-+  }
-+
-+  /* Push the record number for the new entry onto the stack.  The
-+  ** record number is a randomly generate integer created by NewRecno
-+  ** except when the table has an INTEGER PRIMARY KEY column, in which
-+  ** case the record number is the same as that column. 
-+  */
-+  if( !isView ){
-+    if( keyColumn>=0 ){
-+      if( useTempTable ){
-+        sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);
-+      }else if( pSelect ){
-+        sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
-+      }else{
-+        sqliteExprCode(pParse, pList->a[keyColumn].pExpr);
-+      }
-+      /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno
-+      ** to generate a unique primary key value.
-+      */
-+      sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);
-+      sqliteVdbeAddOp(v, OP_Pop, 1, 0);
-+      sqliteVdbeAddOp(v, OP_NewRecno, base, 0);
-+      sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
-+    }else{
-+      sqliteVdbeAddOp(v, OP_NewRecno, base, 0);
-+    }
-+
-+    /* Push onto the stack, data for all columns of the new entry, beginning
-+    ** with the first column.
-+    */
-+    for(i=0; i<pTab->nCol; i++){
-+      if( i==pTab->iPKey ){
-+        /* The value of the INTEGER PRIMARY KEY column is always a NULL.
-+        ** Whenever this column is read, the record number will be substituted
-+        ** in its place.  So will fill this column with a NULL to avoid
-+        ** taking up data space with information that will never be used. */
-+        sqliteVdbeAddOp(v, OP_String, 0, 0);
-+        continue;
-+      }
-+      if( pColumn==0 ){
-+        j = i;
-+      }else{
-+        for(j=0; j<pColumn->nId; j++){
-+          if( pColumn->a[j].idx==i ) break;
-+        }
-+      }
-+      if( pColumn && j>=pColumn->nId ){
-+        sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
-+      }else if( useTempTable ){
-+        sqliteVdbeAddOp(v, OP_Column, srcTab, j); 
-+      }else if( pSelect ){
-+        sqliteVdbeAddOp(v, OP_Dup, i+nColumn-j, 1);
-+      }else{
-+        sqliteExprCode(pParse, pList->a[j].pExpr);
-+      }
-+    }
-+
-+    /* Generate code to check constraints and generate index keys and
-+    ** do the insertion.
-+    */
-+    sqliteGenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
-+                                   0, onError, endOfLoop);
-+    sqliteCompleteInsertion(pParse, pTab, base, 0,0,0,
-+                            after_triggers ? newIdx : -1);
-+  }
-+
-+  /* Update the count of rows that are inserted
-+  */
-+  if( (db->flags & SQLITE_CountRows)!=0 ){
-+    sqliteVdbeAddOp(v, OP_MemIncr, iCntMem, 0);
-+  }
-+
-+  if( row_triggers_exist ){
-+    /* Close all tables opened */
-+    if( !isView ){
-+      sqliteVdbeAddOp(v, OP_Close, base, 0);
-+      for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
-+        sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
-+      }
-+    }
-+
-+    /* Code AFTER triggers */
-+    if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1, 
-+          onError, endOfLoop) ){
-+      goto insert_cleanup;
-+    }
-+  }
-+
-+  /* The bottom of the loop, if the data source is a SELECT statement
-+  */
-+  sqliteVdbeResolveLabel(v, endOfLoop);
-+  if( useTempTable ){
-+    sqliteVdbeAddOp(v, OP_Next, srcTab, iCont);
-+    sqliteVdbeResolveLabel(v, iBreak);
-+    sqliteVdbeAddOp(v, OP_Close, srcTab, 0);
-+  }else if( pSelect ){
-+    sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);
-+    sqliteVdbeAddOp(v, OP_Return, 0, 0);
-+    sqliteVdbeResolveLabel(v, iCleanup);
-+  }
-+
-+  if( !row_triggers_exist ){
-+    /* Close all tables opened */
-+    sqliteVdbeAddOp(v, OP_Close, base, 0);
-+    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
-+      sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
-+    }
-+  }
-+
-+  sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
-+  sqliteEndWriteOperation(pParse);
-+
-+  /*
-+  ** Return the number of rows inserted.
-+  */
-+  if( db->flags & SQLITE_CountRows ){
-+    sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows inserted", P3_STATIC);
-+    sqliteVdbeAddOp(v, OP_MemLoad, iCntMem, 0);
-+    sqliteVdbeAddOp(v, OP_Callback, 1, 0);
-+  }
-+
-+insert_cleanup:
-+  sqliteSrcListDelete(pTabList);
-+  if( pList ) sqliteExprListDelete(pList);
-+  if( pSelect ) sqliteSelectDelete(pSelect);
-+  sqliteIdListDelete(pColumn);
-+}
-+
-+/*
-+** Generate code to do a constraint check prior to an INSERT or an UPDATE.
-+**
-+** When this routine is called, the stack contains (from bottom to top)
-+** the following values:
-+**
-+**    1.  The recno of the row to be updated before the update.  This
-+**        value is omitted unless we are doing an UPDATE that involves a
-+**        change to the record number.
-+**
-+**    2.  The recno of the row after the update.
-+**
-+**    3.  The data in the first column of the entry after the update.
-+**
-+**    i.  Data from middle columns...
-+**
-+**    N.  The data in the last column of the entry after the update.
-+**
-+** The old recno shown as entry (1) above is omitted unless both isUpdate
-+** and recnoChng are 1.  isUpdate is true for UPDATEs and false for
-+** INSERTs and recnoChng is true if the record number is being changed.
-+**
-+** The code generated by this routine pushes additional entries onto
-+** the stack which are the keys for new index entries for the new record.
-+** The order of index keys is the same as the order of the indices on
-+** the pTable->pIndex list.  A key is only created for index i if 
-+** aIdxUsed!=0 and aIdxUsed[i]!=0.
-+**
-+** This routine also generates code to check constraints.  NOT NULL,
-+** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
-+** then the appropriate action is performed.  There are five possible
-+** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
-+**
-+**  Constraint type  Action       What Happens
-+**  ---------------  ----------   ----------------------------------------
-+**  any              ROLLBACK     The current transaction is rolled back and
-+**                                sqlite_exec() returns immediately with a
-+**                                return code of SQLITE_CONSTRAINT.
-+**
-+**  any              ABORT        Back out changes from the current command
-+**                                only (do not do a complete rollback) then
-+**                                cause sqlite_exec() to return immediately
-+**                                with SQLITE_CONSTRAINT.
-+**
-+**  any              FAIL         Sqlite_exec() returns immediately with a
-+**                                return code of SQLITE_CONSTRAINT.  The
-+**                                transaction is not rolled back and any
-+**                                prior changes are retained.
-+**
-+**  any              IGNORE       The record number and data is popped from
-+**                                the stack and there is an immediate jump
-+**                                to label ignoreDest.
-+**
-+**  NOT NULL         REPLACE      The NULL value is replace by the default
-+**                                value for that column.  If the default value
-+**                                is NULL, the action is the same as ABORT.
-+**
-+**  UNIQUE           REPLACE      The other row that conflicts with the row
-+**                                being inserted is removed.
-+**
-+**  CHECK            REPLACE      Illegal.  The results in an exception.
-+**
-+** Which action to take is determined by the overrideError parameter.
-+** Or if overrideError==OE_Default, then the pParse->onError parameter
-+** is used.  Or if pParse->onError==OE_Default then the onError value
-+** for the constraint is used.
-+**
-+** The calling routine must open a read/write cursor for pTab with
-+** cursor number "base".  All indices of pTab must also have open
-+** read/write cursors with cursor number base+i for the i-th cursor.
-+** Except, if there is no possibility of a REPLACE action then
-+** cursors do not need to be open for indices where aIdxUsed[i]==0.
-+**
-+** If the isUpdate flag is true, it means that the "base" cursor is
-+** initially pointing to an entry that is being updated.  The isUpdate
-+** flag causes extra code to be generated so that the "base" cursor
-+** is still pointing at the same entry after the routine returns.
-+** Without the isUpdate flag, the "base" cursor might be moved.
-+*/
-+void sqliteGenerateConstraintChecks(
-+  Parse *pParse,      /* The parser context */
-+  Table *pTab,        /* the table into which we are inserting */
-+  int base,           /* Index of a read/write cursor pointing at pTab */
-+  char *aIdxUsed,     /* Which indices are used.  NULL means all are used */
-+  int recnoChng,      /* True if the record number will change */
-+  int isUpdate,       /* True for UPDATE, False for INSERT */
-+  int overrideError,  /* Override onError to this if not OE_Default */
-+  int ignoreDest      /* Jump to this label on an OE_Ignore resolution */
-+){
-+  int i;
-+  Vdbe *v;
-+  int nCol;
-+  int onError;
-+  int addr;
-+  int extra;
-+  int iCur;
-+  Index *pIdx;
-+  int seenReplace = 0;
-+  int jumpInst1, jumpInst2;
-+  int contAddr;
-+  int hasTwoRecnos = (isUpdate && recnoChng);
-+
-+  v = sqliteGetVdbe(pParse);
-+  assert( v!=0 );
-+  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
-+  nCol = pTab->nCol;
-+
-+  /* Test all NOT NULL constraints.
-+  */
-+  for(i=0; i<nCol; i++){
-+    if( i==pTab->iPKey ){
-+      continue;
-+    }
-+    onError = pTab->aCol[i].notNull;
-+    if( onError==OE_None ) continue;
-+    if( overrideError!=OE_Default ){
-+      onError = overrideError;
-+    }else if( pParse->db->onError!=OE_Default ){
-+      onError = pParse->db->onError;
-+    }else if( onError==OE_Default ){
-+      onError = OE_Abort;
-+    }
-+    if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){
-+      onError = OE_Abort;
-+    }
-+    sqliteVdbeAddOp(v, OP_Dup, nCol-1-i, 1);
-+    addr = sqliteVdbeAddOp(v, OP_NotNull, 1, 0);
-+    switch( onError ){
-+      case OE_Rollback:
-+      case OE_Abort:
-+      case OE_Fail: {
-+        char *zMsg = 0;
-+        sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
-+        sqliteSetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName,
-+                        " may not be NULL", (char*)0);
-+        sqliteVdbeChangeP3(v, -1, zMsg, P3_DYNAMIC);
-+        break;
-+      }
-+      case OE_Ignore: {
-+        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
-+        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
-+        break;
-+      }
-+      case OE_Replace: {
-+        sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
-+        sqliteVdbeAddOp(v, OP_Push, nCol-i, 0);
-+        break;
-+      }
-+      default: assert(0);
-+    }
-+    sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
-+  }
-+
-+  /* Test all CHECK constraints
-+  */
-+  /**** TBD ****/
-+
-+  /* If we have an INTEGER PRIMARY KEY, make sure the primary key
-+  ** of the new record does not previously exist.  Except, if this
-+  ** is an UPDATE and the primary key is not changing, that is OK.
-+  */
-+  if( recnoChng ){
-+    onError = pTab->keyConf;
-+    if( overrideError!=OE_Default ){
-+      onError = overrideError;
-+    }else if( pParse->db->onError!=OE_Default ){
-+      onError = pParse->db->onError;
-+    }else if( onError==OE_Default ){
-+      onError = OE_Abort;
-+    }
-+    
-+    if( isUpdate ){
-+      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
-+      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
-+      jumpInst1 = sqliteVdbeAddOp(v, OP_Eq, 0, 0);
-+    }
-+    sqliteVdbeAddOp(v, OP_Dup, nCol, 1);
-+    jumpInst2 = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
-+    switch( onError ){
-+      default: {
-+        onError = OE_Abort;
-+        /* Fall thru into the next case */
-+      }
-+      case OE_Rollback:
-+      case OE_Abort:
-+      case OE_Fail: {
-+        sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError,
-+                         "PRIMARY KEY must be unique", P3_STATIC);
-+        break;
-+      }
-+      case OE_Replace: {
-+        sqliteGenerateRowIndexDelete(pParse->db, v, pTab, base, 0);
-+        if( isUpdate ){
-+          sqliteVdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1);
-+          sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
-+        }
-+        seenReplace = 1;
-+        break;
-+      }
-+      case OE_Ignore: {
-+        assert( seenReplace==0 );
-+        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
-+        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
-+        break;
-+      }
-+    }
-+    contAddr = sqliteVdbeCurrentAddr(v);
-+    sqliteVdbeChangeP2(v, jumpInst2, contAddr);
-+    if( isUpdate ){
-+      sqliteVdbeChangeP2(v, jumpInst1, contAddr);
-+      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
-+      sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
-+    }
-+  }
-+
-+  /* Test all UNIQUE constraints by creating entries for each UNIQUE
-+  ** index and making sure that duplicate entries do not already exist.
-+  ** Add the new records to the indices as we go.
-+  */
-+  extra = -1;
-+  for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
-+    if( aIdxUsed && aIdxUsed[iCur]==0 ) continue;  /* Skip unused indices */
-+    extra++;
-+
-+    /* Create a key for accessing the index entry */
-+    sqliteVdbeAddOp(v, OP_Dup, nCol+extra, 1);
-+    for(i=0; i<pIdx->nColumn; i++){
-+      int idx = pIdx->aiColumn[i];
-+      if( idx==pTab->iPKey ){
-+        sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1);
-+      }else{
-+        sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);
-+      }
-+    }
-+    jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
-+    if( pParse->db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
-+
-+    /* Find out what action to take in case there is an indexing conflict */
-+    onError = pIdx->onError;
-+    if( onError==OE_None ) continue;  /* pIdx is not a UNIQUE index */
-+    if( overrideError!=OE_Default ){
-+      onError = overrideError;
-+    }else if( pParse->db->onError!=OE_Default ){
-+      onError = pParse->db->onError;
-+    }else if( onError==OE_Default ){
-+      onError = OE_Abort;
-+    }
-+    if( seenReplace ){
-+      if( onError==OE_Ignore ) onError = OE_Replace;
-+      else if( onError==OE_Fail ) onError = OE_Abort;
-+    }
-+    
-+
-+    /* Check to see if the new index entry will be unique */
-+    sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);
-+    jumpInst2 = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
-+
-+    /* Generate code that executes if the new index entry is not unique */
-+    switch( onError ){
-+      case OE_Rollback:
-+      case OE_Abort:
-+      case OE_Fail: {
-+        int j, n1, n2;
-+        char zErrMsg[200];
-+        strcpy(zErrMsg, pIdx->nColumn>1 ? "columns " : "column ");
-+        n1 = strlen(zErrMsg);
-+        for(j=0; j<pIdx->nColumn && n1<sizeof(zErrMsg)-30; j++){
-+          char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
-+          n2 = strlen(zCol);
-+          if( j>0 ){
-+            strcpy(&zErrMsg[n1], ", ");
-+            n1 += 2;
-+          }
-+          if( n1+n2>sizeof(zErrMsg)-30 ){
-+            strcpy(&zErrMsg[n1], "...");
-+            n1 += 3;
-+            break;
-+          }else{
-+            strcpy(&zErrMsg[n1], zCol);
-+            n1 += n2;
-+          }
-+        }
-+        strcpy(&zErrMsg[n1], 
-+            pIdx->nColumn>1 ? " are not unique" : " is not unique");
-+        sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0);
-+        break;
-+      }
-+      case OE_Ignore: {
-+        assert( seenReplace==0 );
-+        sqliteVdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0);
-+        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
-+        break;
-+      }
-+      case OE_Replace: {
-+        sqliteGenerateRowDelete(pParse->db, v, pTab, base, 0);
-+        if( isUpdate ){
-+          sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
-+          sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
-+        }
-+        seenReplace = 1;
-+        break;
-+      }
-+      default: assert(0);
-+    }
-+    contAddr = sqliteVdbeCurrentAddr(v);
-+#if NULL_DISTINCT_FOR_UNIQUE
-+    sqliteVdbeChangeP2(v, jumpInst1, contAddr);
-+#endif
-+    sqliteVdbeChangeP2(v, jumpInst2, contAddr);
-+  }
-+}
-+
-+/*
-+** This routine generates code to finish the INSERT or UPDATE operation
-+** that was started by a prior call to sqliteGenerateConstraintChecks.
-+** The stack must contain keys for all active indices followed by data
-+** and the recno for the new entry.  This routine creates the new
-+** entries in all indices and in the main table.
-+**
-+** The arguments to this routine should be the same as the first six
-+** arguments to sqliteGenerateConstraintChecks.
-+*/
-+void sqliteCompleteInsertion(
-+  Parse *pParse,      /* The parser context */
-+  Table *pTab,        /* the table into which we are inserting */
-+  int base,           /* Index of a read/write cursor pointing at pTab */
-+  char *aIdxUsed,     /* Which indices are used.  NULL means all are used */
-+  int recnoChng,      /* True if the record number will change */
-+  int isUpdate,       /* True for UPDATE, False for INSERT */
-+  int newIdx          /* Index of NEW table for triggers.  -1 if none */
-+){
-+  int i;
-+  Vdbe *v;
-+  int nIdx;
-+  Index *pIdx;
-+
-+  v = sqliteGetVdbe(pParse);
-+  assert( v!=0 );
-+  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
-+  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
-+  for(i=nIdx-1; i>=0; i--){
-+    if( aIdxUsed && aIdxUsed[i]==0 ) continue;
-+    sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, 0);
-+  }
-+  sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
-+  if( newIdx>=0 ){
-+    sqliteVdbeAddOp(v, OP_Dup, 1, 0);
-+    sqliteVdbeAddOp(v, OP_Dup, 1, 0);
-+    sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
-+  }
-+  sqliteVdbeAddOp(v, OP_PutIntKey, base,
-+    (pParse->trigStack?0:OPFLAG_NCHANGE) |
-+    (isUpdate?0:OPFLAG_LASTROWID) | OPFLAG_CSCHANGE);
-+  if( isUpdate && recnoChng ){
-+    sqliteVdbeAddOp(v, OP_Pop, 1, 0);
-+  }
-+}
-+
-+/*
-+** Generate code that will open write cursors for a table and for all
-+** indices of that table.  The "base" parameter is the cursor number used
-+** for the table.  Indices are opened on subsequent cursors.
-+**
-+** Return the total number of cursors opened.  This is always at least
-+** 1 (for the main table) plus more for each cursor.
-+*/
-+int sqliteOpenTableAndIndices(Parse *pParse, Table *pTab, int base){
-+  int i;
-+  Index *pIdx;
-+  Vdbe *v = sqliteGetVdbe(pParse);
-+  assert( v!=0 );
-+  sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-+  sqliteVdbeOp3(v, OP_OpenWrite, base, pTab->tnum, pTab->zName, P3_STATIC);
-+  for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
-+    sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
-+    sqliteVdbeOp3(v, OP_OpenWrite, i+base, pIdx->tnum, pIdx->zName, P3_STATIC);
-+  }
-+  return i;
-+}
---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/libsqlite.dsp
-@@ -0,0 +1,353 @@
-+# Microsoft Developer Studio Project File - Name="libsqlite" - Package Owner=<4>

-+# Microsoft Developer Studio Generated Build File, Format Version 6.00

-+# ** DO NOT EDIT **

-+

-+# TARGTYPE "Win32 (x86) Static Library" 0x0104

-+

-+CFG=libsqlite - Win32 Debug_TS

-+!MESSAGE This is not a valid makefile. To build this project using NMAKE,

-+!MESSAGE use the Export Makefile command and run

-+!MESSAGE 

-+!MESSAGE NMAKE /f "libsqlite.mak".

-+!MESSAGE 

-+!MESSAGE You can specify a configuration when running NMAKE

-+!MESSAGE by defining the macro CFG on the command line. For example:

-+!MESSAGE 

-+!MESSAGE NMAKE /f "libsqlite.mak" CFG="libsqlite - Win32 Debug_TS"

-+!MESSAGE 

-+!MESSAGE Possible choices for configuration are:

-+!MESSAGE 

-+!MESSAGE "libsqlite - Win32 Debug_TS" (based on "Win32 (x86) Static Library")

-+!MESSAGE "libsqlite - Win32 Release_TS" (based on "Win32 (x86) Static Library")

-+!MESSAGE "libsqlite - Win32 Release_TSDbg" (based on "Win32 (x86) Static Library")

-+!MESSAGE 

-+

-+# Begin Project

-+# PROP AllowPerConfigDependencies 0

-+# PROP Scc_ProjName ""

-+# PROP Scc_LocalPath ""

-+CPP=cl.exe

-+RSC=rc.exe

-+

-+!IF  "$(CFG)" == "libsqlite - Win32 Debug_TS"

-+

-+# PROP BASE Use_MFC 0

-+# PROP BASE Use_Debug_Libraries 1

-+# PROP BASE Output_Dir "Debug_TS"

-+# PROP BASE Intermediate_Dir "Debug_TS"

-+# PROP BASE Target_Dir ""

-+# PROP Use_MFC 0

-+# PROP Use_Debug_Libraries 1

-+# PROP Output_Dir "..\..\Debug_TS"

-+# PROP Intermediate_Dir "..\..\Debug_TS"

-+# PROP Target_Dir ""

-+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c

-+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /GZ /c

-+# ADD BASE RSC /l 0x406 /d "_DEBUG"

-+# ADD RSC /l 0x406 /d "_DEBUG"

-+BSC32=bscmake.exe

-+# ADD BASE BSC32 /nologo

-+# ADD BSC32 /nologo

-+LIB32=link.exe -lib

-+# ADD BASE LIB32 /nologo

-+# ADD LIB32 /nologo

-+

-+!ELSEIF  "$(CFG)" == "libsqlite - Win32 Release_TS"

-+

-+# PROP BASE Use_MFC 0

-+# PROP BASE Use_Debug_Libraries 0

-+# PROP BASE Output_Dir "Release_TS"

-+# PROP BASE Intermediate_Dir "Release_TS"

-+# PROP BASE Target_Dir ""

-+# PROP Use_MFC 0

-+# PROP Use_Debug_Libraries 0

-+# PROP Output_Dir "..\..\Release_TS"

-+# PROP Intermediate_Dir "..\..\Release_TS"

-+# PROP Target_Dir ""

-+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c

-+# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /c

-+# ADD BASE RSC /l 0x406 /d "NDEBUG"

-+# ADD RSC /l 0x406 /d "NDEBUG"

-+BSC32=bscmake.exe

-+# ADD BASE BSC32 /nologo

-+# ADD BSC32 /nologo

-+LIB32=link.exe -lib

-+# ADD BASE LIB32 /nologo

-+# ADD LIB32 /nologo

-+

-+!ELSEIF  "$(CFG)" == "libsqlite - Win32 Release_TSDbg"

-+

-+# PROP BASE Use_MFC 0

-+# PROP BASE Use_Debug_Libraries 0

-+# PROP BASE Output_Dir "libsqlite___Win32_Release_TSDbg"

-+# PROP BASE Intermediate_Dir "libsqlite___Win32_Release_TSDbg"

-+# PROP BASE Target_Dir ""

-+# PROP Use_MFC 0

-+# PROP Use_Debug_Libraries 0

-+# PROP Output_Dir "..\..\Release_TSDbg"

-+# PROP Intermediate_Dir "..\..\Release_TSDbg"

-+# PROP Target_Dir ""

-+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /c

-+# ADD CPP /nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /c

-+# ADD BASE RSC /l 0x406 /d "NDEBUG"

-+# ADD RSC /l 0x406 /d "NDEBUG"

-+BSC32=bscmake.exe

-+# ADD BASE BSC32 /nologo

-+# ADD BSC32 /nologo

-+LIB32=link.exe -lib

-+# ADD BASE LIB32 /nologo /out:"Release_TS\libsqlite.lib"

-+# ADD LIB32 /nologo

-+

-+!ENDIF 

-+

-+# Begin Target

-+

-+# Name "libsqlite - Win32 Debug_TS"

-+# Name "libsqlite - Win32 Release_TS"

-+# Name "libsqlite - Win32 Release_TSDbg"

-+# Begin Group "Source Files"

-+

-+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"

-+# Begin Source File

-+

-+SOURCE=attach.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=auth.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=btree.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=btree_rb.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=build.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=copy.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=.\date.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=delete.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=encode.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=expr.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=func.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=hash.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=insert.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=main.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=opcodes.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=os.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=pager.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=parse.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=pragma.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=printf.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=random.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=select.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=table.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=tokenize.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=trigger.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=update.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=util.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=vacuum.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=vdbe.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=.\vdbeaux.c

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=where.c

-+# End Source File

-+# End Group

-+# Begin Group "Header Files"

-+

-+# PROP Default_Filter "h;hpp;hxx;hm;inl"

-+# Begin Source File

-+

-+SOURCE=btree.h

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=config_static.w32.h

-+

-+!IF  "$(CFG)" == "libsqlite - Win32 Debug_TS"

-+

-+# Begin Custom Build

-+InputDir=.

-+InputPath=config_static.w32.h

-+

-+"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"

-+	copy $(InputPath) $(InputDir)\config.h

-+

-+# End Custom Build

-+

-+!ELSEIF  "$(CFG)" == "libsqlite - Win32 Release_TS"

-+

-+# Begin Custom Build

-+InputDir=.

-+InputPath=config_static.w32.h

-+

-+"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"

-+	copy $(InputPath) $(InputDir)\config.h

-+

-+# End Custom Build

-+

-+!ELSEIF  "$(CFG)" == "libsqlite - Win32 Release_TSDbg"

-+

-+# Begin Custom Build

-+InputDir=.

-+InputPath=config_static.w32.h

-+

-+"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"

-+	copy $(InputPath) $(InputDir)\config.h

-+

-+# End Custom Build

-+

-+!ENDIF 

-+

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=hash.h

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=opcodes.h

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=os.h

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=pager.h

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=parse.h

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=sqlite.w32.h

-+

-+!IF  "$(CFG)" == "libsqlite - Win32 Debug_TS"

-+

-+# Begin Custom Build

-+InputDir=.

-+InputPath=sqlite.w32.h

-+

-+"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"

-+	copy $(InputPath) $(InputDir)\sqlite.h

-+

-+# End Custom Build

-+

-+!ELSEIF  "$(CFG)" == "libsqlite - Win32 Release_TS"

-+

-+# Begin Custom Build

-+InputDir=.

-+InputPath=sqlite.w32.h

-+

-+"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"

-+	copy $(InputPath) $(InputDir)\sqlite.h

-+

-+# End Custom Build

-+

-+!ELSEIF  "$(CFG)" == "libsqlite - Win32 Release_TSDbg"

-+

-+# Begin Custom Build

-+InputDir=.

-+InputPath=sqlite.w32.h

-+

-+"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"

-+	copy $(InputPath) $(InputDir)\sqlite.h

-+

-+# End Custom Build

-+

-+!ENDIF 

-+

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=sqliteInt.h

-+# End Source File

-+# Begin Source File

-+

-+SOURCE=vdbe.h

-+# End Source File

-+# End Group

-+# End Target

-+# End Project

---- /dev/null
-+++ b/ext/sqlite/libsqlite/src/main.c
-@@ -0,0 +1,1143 @@
-+/*
-+** 2001 September 15
-+**
-+** The author disclaims copyright to this source code.  In place of
-+** a legal notice, here is a blessing:
-+**
-+**    May you do good and not evil.
-+**    May you find forgiveness for yourself and forgive others.
-+**    May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** Main file for the SQLite library.  The routines in this file
-+** implement the programmer interface to the library.  Routines in
-+** other files are for internal use by SQLite and should not be
-+** accessed by users of the library.
-+**
-+** $Id$
-+*/
-+#include "sqliteInt.h"
-+#include "os.h"
-+#include <ctype.h>
-+
-+/*
-+** A pointer to this structure is used to communicate information
-+** from sqliteInit into the sqliteInitCallback.
-+*/
-+typedef struct {
-+  sqlite *db;         /* The database being initialized */
-+  char **pzErrMsg;    /* Error message stored here */
-+} InitData;
-+
-+/*
-+** Fill the InitData structure with an error message that indicates
-+** that the database is corrupt.
-+*/
-+static void corruptSchema(InitData *pData, const char *zExtra){
-+  sqliteSetString(pData->pzErrMsg, "malformed database schema",
-+     zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
-+}
-+
-+/*
-+** This is the callback routine for the code that initializes the
-+** database.  See sqliteInit() below for additional information.
-+**
-+** Each callback contains the following information:
-+**
-+**     argv[0] = "file-format" or "schema-cookie" or "table" or "index"
-+**     argv[1] = table or index name or meta statement type.
-+**     argv[2] = root page number for table or index.  NULL for meta.
-+**     argv[3] = SQL text for a CREATE TABLE or CREATE INDEX statement.
-+**     argv[4] = "1" for temporary files, "0" for main database, "2" or more
-+**               for auxiliary database files.
-+**
-+*/
-+static
-+int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){
-+  InitData *pData = (InitData*)pInit;
-+  int nErr = 0;
-+
-+  assert( argc==5 );
-+  if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */
-+  if( argv[0]==0 ){
-+    corruptSchema(pData, 0);
-+    return 1;
-+  }
-+  switch( argv[0][0] ){
-+    case 'v':
-+    case 'i':
-+    case 't': {  /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
-+      sqlite *db = pData->db;
-+      if( argv[2]==0 || argv[4]==0 ){
-+        corruptSchema(pData, 0);
-+        return 1;
-+      }
-+      if( argv[3] && argv[3][0] ){
-+        /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
-+        ** But because db->init.busy is set to 1, no VDBE code is generated
-+        ** or executed.  All the parser does is build the internal data
-+        ** structures that describe the table, index, or view.
-+        */
-+        char *zErr;
-+        assert( db->init.busy );
-+        db->init.iDb = atoi(argv[4]);
-+        assert( db->init.iDb>=0 && db->init.iDb<db->nDb );
-+        db->init.newTnum = atoi(argv[2]);
-+        if( sqlite_exec(db, argv[3], 0, 0, &zErr) ){
-+          corruptSchema(pData, zErr);
-+          sqlite_freemem(zErr);
-+        }
-+        db->init.iDb = 0;
-+      }else{
-+        /* If the SQL column is blank it means this is an index that
-+        ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
-+        ** constraint for a CREATE TABLE.  The index should have already
-+        ** been created when we processed the CREATE TABLE.  All we have
-+        ** to do here is record the root page number for that index.
-+        */
-+        int iDb;
-+        Index *pIndex;
-+
-+        iDb = atoi(argv[4]);
-+        assert( iDb>=0 && iDb<db->nDb );
-+        pIndex = sqliteFindIndex(db, argv[1], db->aDb[iDb].zName);
-+        if( pIndex==0 || pIndex->tnum!=0 ){
-+          /* This can occur if there exists an index on a TEMP table which
-+          ** has the same name as another index on a permanent index.  Since
-+          ** the permanent table is hidden by the TEMP table, we can also
-+          ** safely ignore the index on the permanent table.
-+          */
-+          /* Do Nothing */;
-+        }else{
-+          pIndex->tnum = atoi(argv[2]);
-+        }
-+      }
-+      break;
-+    }
-+    default: {
-+      /* This can not happen! */
-+      nErr = 1;
-+      assert( nErr==0 );
-+    }
-+  }
-+  return nErr;
-+}
-+
-+/*
-+** This is a callback procedure used to reconstruct a table.  The
-+** name of the table to be reconstructed is passed in as argv[0].
-+**
-+** This routine is used to automatically upgrade a database from
-+** format version 1 or 2 to version 3.  The correct operation of
-+** this routine relys on the fact that no indices are used when
-+** copying a table out to a temporary file.
-+**
-+** The change from version 2 to version 3 occurred between SQLite
-+** version 2.5.6 and 2.6.0 on 2002-July-18.  
-+*/
-+static
-+int upgrade_3_callback(void *pInit, int argc, char **argv, char **NotUsed){
-+  InitData *pData = (InitData*)pInit;
-+  int rc;
-+  Table *pTab;
-+  Trigger *pTrig;
-+  char *zErr = 0;
-+
-+  pTab = sqliteFindTable(pData->db, argv[0], 0);
-+  assert( pTab!=0 );
-+  assert( sqliteStrICmp(pTab->zName, argv[0])==0 );
-+  if( pTab ){
-+    pTrig = pTab->pTrigger;
-+    pTab->pTrigger = 0;  /* Disable all triggers before rebuilding the table */
-+  }
-+  rc = sqlite_exec_printf(pData->db,
-+    "CREATE TEMP TABLE sqlite_x AS SELECT * FROM '%q'; "
-+    "DELETE FROM '%q'; "
-+    "INSERT INTO '%q' SELECT * FROM sqlite_x; "
-+    "DROP TABLE sqlite_x;",
-+    0, 0, &zErr, argv[0], argv[0], argv[0]);
-+  if( zErr ){
-+    if( *pData->pzErrMsg ) sqlite_freemem(*pData->pzErrMsg);
-+    *pData->pzErrMsg = zErr;
-+  }
-+
-+  /* If an error occurred in the SQL above, then the transaction will
-+  ** rollback which will delete the internal symbol tables.  This will
-+  ** cause the structure that pTab points to be deleted.  In case that
-+  ** happened, we need to refetch pTab.
-+  */
-+  pTab = sqliteFindTable(pData->db, argv[0], 0);
-+  if( pTab ){
-+    assert( sqliteStrICmp(pTab->zName, argv[0])==0 );
-+    pTab->pTrigger = pTrig;  /* Re-enable triggers */
-+  }
-+  return rc!=SQLITE_OK;
-+}
-+
-+
-+
-+/*
-+** Attempt to read the database schema and initialize internal
-+** data structures for a single database file.  The index of the
-+** database file is given by iDb.  iDb==0 is used for the main
-+** database.  iDb==1 should never be used.  iDb>=2 is used for
-+** auxiliary databases.  Return one of the SQLITE_ error codes to
-+** indicate success or failure.
-+*/
-+static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
-+  int rc;
-+  BtCursor *curMain;
-+  int size;
-+  Table *pTab;
-+  char const *azArg[6];
-+  char zDbNum[30];
-+  int meta[SQLITE_N_BTREE_META];
-+  InitData initData;
-+  char const *zMasterSchema;
-+  char const *zMasterName;
-+  char *zSql = 0;
-+
-+  /*
-+  ** The master database table has a structure like this
-+  */
-+  static char master_schema[] = 
-+     "CREATE TABLE sqlite_master(\n"
-+     "  type text,\n"
-+     "  name text,\n"
-+     "  tbl_name text,\n"
-+     "  rootpage integer,\n"
-+     "  sql text\n"
-+     ")"
-+  ;
-+  static char temp_master_schema[] = 
-+     "CREATE TEMP TABLE sqlite_temp_master(\n"
-+     "  type text,\n"
-+     "  name text,\n"
-+     "  tbl_name text,\n"
-+     "  rootpage integer,\n"
-+     "  sql text\n"
-+     ")"
-+  ;
-+
-+  assert( iDb>=0 && iDb<db->nDb );
-+
-+  /* zMasterSchema and zInitScript are set to point at the master schema
-+  ** and initialisation script appropriate for the database being
-+  ** initialised. zMasterName is the name of the master table.
-+  */
-+  if( iDb==1 ){
-+    zMasterSchema = temp_master_schema;
-+    zMasterName = TEMP_MASTER_NAME;
-+  }else{
-+    zMasterSchema = master_schema;
-+    zMasterName = MASTER_NAME;
-+  }
-+
-+  /* Construct the schema table.
-+  */
-+  sqliteSafetyOff(db);
-+  azArg[0] = "table";
-+  azArg[1] = zMasterName;
-+  azArg[2] = "2";
-+  azArg[3] = zMasterSchema;
-+  sprintf(zDbNum, "%d", iDb);
-+  azArg[4] = zDbNum;
-+  azArg[5] = 0;
-+  initData.db = db;
-+  initData.pzErrMsg = pzErrMsg;
-+  sqliteInitCallback(&initData, 5, (char **)azArg, 0);
-+  pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
-+  if( pTab ){
-+    pTab->readOnly = 1;
-+  }else{
-+    return SQLITE_NOMEM;
-+  }
-+  sqliteSafetyOn(db);
-+
-+  /* Create a cursor to hold the database open
-+  */
-+  if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
-+  rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);
-+  if( rc ){
-+    sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
-+    return rc;
-+  }
-+
-+  /* Get the database meta information
-+  */
-+  rc = sqliteBtreeGetMeta(db->aDb[iDb].pBt, meta);
-+  if( rc ){
-+    sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
-+    sqliteBtreeCloseCursor(curMain);
-+    return rc;
-+  }
-+  db->aDb[iDb].schema_cookie = meta[1];
-+  if( iDb==0 ){
-+    db->next_cookie = meta[1];
-+    db->file_format = meta[2];
-+    size = meta[3];
-+    if( size==0 ){ size = MAX_PAGES; }
-+    db->cache_size = size;
-+    db->safety_level = meta[4];
-+    if( meta[6]>0 && meta[6]<=2 && db->temp_store==0 ){
-+      db->temp_store = meta[6];
-+    }
-+    if( db->safety_level==0 ) db->safety_level = 2;
-+
-+    /*
-+    **  file_format==1    Version 2.1.0.
-+    **  file_format==2    Version 2.2.0. Add support for INTEGER PRIMARY KEY.
-+    **  file_format==3    Version 2.6.0. Fix empty-string index bug.
-+    **  file_format==4    Version 2.7.0. Add support for separate numeric and
-+    **                    text datatypes.
-+    */
-+    if( db->file_format==0 ){
-+      /* This happens if the database was initially empty */
-+      db->file_format = 4;
-+    }else if( db->file_format>4 ){
-+      sqliteBtreeCloseCursor(curMain);
-+      sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
-+      return SQLITE_ERROR;
-+    }
-+  }else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){
-+    assert( db->file_format>=4 );
-+    if( meta[2]==0 ){
-+      sqliteSetString(pzErrMsg, "cannot attach empty database: ",
-+         db->aDb[iDb].zName, (char*)0);
-+    }else{
-+      sqliteSetString(pzErrMsg, "incompatible file format in auxiliary "
-+         "database: ", db->aDb[iDb].zName, (char*)0);
-+    }
-+    sqliteBtreeClose(db->aDb[iDb].pBt);
-+    db->aDb[iDb].pBt = 0;
-+    return SQLITE_FORMAT;
-+  }
-+  sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size);
-+  sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);
-+
-+  /* Read the schema information out of the schema tables
-+  */
-+  assert( db->init.busy );
-+  sqliteSafetyOff(db);
-+
-+  /* The following SQL will read the schema from the master tables.
-+  ** The first version works with SQLite file formats 2 or greater.
-+  ** The second version is for format 1 files.
-+  **
-+  ** Beginning with file format 2, the rowid for new table entries
-+  ** (including entries in sqlite_master) is an increasing integer.
-+  ** So for file format 2 and later, we can play back sqlite_master
-+  ** and all the CREATE statements will appear in the right order.
-+  ** But with file format 1, table entries were random and so we
-+  ** have to make sure the CREATE TABLEs occur before their corresponding
-+  ** CREATE INDEXs.  (We don't have to deal with CREATE VIEW or
-+  ** CREATE TRIGGER in file format 1 because those constructs did
-+  ** not exist then.) 
-+  */
-+  if( db->file_format>=2 ){
-+    sqliteSetString(&zSql, 
-+        "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
-+       db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
-+  }else{
-+    sqliteSetString(&zSql, 
-+        "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
-+       db->aDb[iDb].zName, "\".", zMasterName, 
-+       " WHERE type IN ('table', 'index')"
-+       " ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);
-+  }
-+  rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
-+
-+  sqliteFree(zSql);
-+  sqliteSafetyOn(db);
-+  sqliteBtreeCloseCursor(curMain);
-+  if( sqlite_malloc_failed ){
-+    sqliteSetString(pzErrMsg, "out of memory", (char*)0);
-+    rc = SQLITE_NOMEM;
-+    sqliteResetInternalSchema(db, 0);
-+  }
-+  if( rc==SQLITE_OK ){
-+    DbSetProperty(db, iDb, DB_SchemaLoaded);
-+  }else{
-+    sqliteResetInternalSchema(db, iDb);
-+  }
-+  return rc;
-+}
-+
-+/*
-+** Initialize all database files - the main database file, the file
-+** used to store temporary tables, and any additional database files
-+** created using ATTACH statements.  Return a success code.  If an
-+** error occurs, write an error message into *pzErrMsg.
-+**
-+** After the database is initialized, the SQLITE_Initialized
-+** bit is set in the flags field of the sqlite structure.  An
-+** attempt is made to initialize the database as soon as it
-+** is opened.  If that fails (perhaps because another process
-+** has the sqlite_master table locked) than another attempt
-+** is made the first time the database is accessed.
-+*/
-+int sqliteInit(sqlite *db, char **pzErrMsg){
-+  int i, rc;
-+  
-+  if( db->init.busy ) return SQLITE_OK;
-+  assert( (db->flags & SQLITE_Initialized)==0 );
-+  rc = SQLITE_OK;
-+  db->init.busy = 1;
-+  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
-+    if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
-+    rc = sqliteInitOne(db, i, pzErrMsg);
-+    if( rc ){
-+      sqliteResetInternalSchema(db, i);
-+    }
-+  }
-+
-+  /* Once all the other databases have been initialised, load the schema
-+  ** for the TEMP database. This is loaded last, as the TEMP database
-+  ** schema may contain references to objects in other databases.
-+  */
-+  if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
-+    rc = sqliteInitOne(db, 1, pzErrMsg);
-+    if( rc ){
-+      sqliteResetInternalSchema(db, 1);
-+    }
-+  }
-+
-+  db->init.busy = 0;
-+  if( rc==SQLITE_OK ){
-+    db->flags |= SQLITE_Initialized;
-+    sqliteCommitInternalChanges(db);
-+  }
-+
-+  /* If the database is in formats 1 or 2, then upgrade it to
-+  ** version 3.  This will reconstruct all indices.  If the
-+  ** upgrade fails for any reason (ex: out of disk space, database
-+  ** is read only, interrupt received, etc.) then fail the init.
-+  */
-+  if( rc==SQLITE_OK && db->file_format<3 ){
-+    char *zErr = 0;
-+    InitData initData;
-+    int meta[SQLITE_N_BTREE_META];
-+
-+    db->magic = SQLITE_MAGIC_OPEN;
-+    initData.db = db;
-+    initData.pzErrMsg = &zErr;
-+    db->file_format = 3;
-+    rc = sqlite_exec(db,
-+      "BEGIN; SELECT name FROM sqlite_master WHERE type='table';",
-+      upgrade_3_callback,
-+      &initData,
-+      &zErr);
-+    if( rc==SQLITE_OK ){
-+      sqliteBtreeGetMeta(db->aDb[0].pBt, meta);
-+      meta[2] = 4;
-+      sqliteBtreeUpdateMeta(db->aDb[0].pBt, meta);
-+      sqlite_exec(db, "COMMIT", 0, 0, 0);
-+    }
-+    if( rc!=SQLITE_OK ){
-+      sqliteSetString(pzErrMsg, 
-+        "unable to upgrade database to the version 2.6 format",
-+        zErr ? ": " : 0, zErr, (char*)0);
-+    }
-+    sqlite_freemem(zErr);
-+  }
-+
-+  if( rc!=SQLITE_OK ){
-+    db->flags &= ~SQLITE_Initialized;
-+  }
-+  return rc;
-+}
-+
-+/*
-+** The version of the library
-+*/
-+const char rcsid[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $";
-+const char sqlite_version[] = SQLITE_VERSION;
-+
-+/*
-+** Does the library expect data to be encoded as UTF-8 or iso8859?  The
-+** following global constant always lets us know.
-+*/
-+#ifdef SQLITE_UTF8
-+const char sqlite_encoding[] = "UTF-8";
-+#else
-+const char sqlite_encoding[] = "iso8859";
-+#endif
-+
-+/*
-+** Open a new SQLite database.  Construct an "sqlite" structure to define
-+** the state of this database and return a pointer to that structure.
-+**
-+** An attempt is made to initialize the in-memory data structures that
-+** hold the database schema.  But if this fails (because the schema file
-+** is locked) then that step is deferred until the first call to
-+** sqlite_exec().
-+*/
-+sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
-+  sqlite *db;
-+  int rc, i;
-+
-+  /* Allocate the sqlite data structure */
-+  db = sqliteMalloc( sizeof(sqlite) );
-+  if( pzErrMsg ) *pzErrMsg = 0;
-+  if( db==0 ) goto no_mem_on_open;
-+  db->onError = OE_Default;
-+  db->priorNewRowid = 0;
-+  db->magic = SQLITE_MAGIC_BUSY;
-+  db->nDb = 2;
-+  db->aDb = db->aDbStatic;
-+  /* db->flags |= SQLITE_ShortColNames; */
-+  sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
-+  for(i=0; i<db->nDb; i++){
-+    sqliteHashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0);
-+    sqliteHashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0);
-+    sqliteHashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0);
-+    sqliteHashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
-+  }
-+  
-+  /* Open the backend database driver */
-+  if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
-+    db->temp_store = 2;
-+  }
-+  rc = sqliteBtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt);
-+  if( rc!=SQLITE_OK ){
-+    switch( rc ){
-+      default: {
-+        sqliteSetString(pzErrMsg, "unable to open database: ",
-+           zFilename, (char*)0);
-+      }
-+    }
-+    sqliteFree(db);
-+    sqliteStrRealloc(pzErrMsg);
-+    return 0;
-+  }
-+  db->aDb[0].zName = "main";
-+  db->aDb[1].zName = "temp";
-+
-+  /* Attempt to read the schema */
-+  sqliteRegisterBuiltinFunctions(db);
-+  rc = sqliteInit(db, pzErrMsg);
-+  db->magic = SQLITE_MAGIC_OPEN;
-+  if( sqlite_malloc_failed ){
-+    sqlite_close(db);
-+    goto no_mem_on_open;
-+  }else if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
-+    sqlite_close(db);
-+    sqliteStrRealloc(pzErrMsg);
-+    return 0;
-+  }else if( pzErrMsg ){
-+    sqliteFree(*pzErrMsg);
-+    *pzErrMsg = 0;
-+  }
-+
-+  /* Return a pointer to the newly opened database structure */
-+  return db;
-+
-+no_mem_on_open:
-+  sqliteSetString(pzErrMsg, "out of memory", (char*)0);
-+  sqliteStrRealloc(pzErrMsg);
-+  return 0;
-+}
-+
-+/*
-+** Return the ROWID of the most recent insert
-+*/
-+int sqlite_last_insert_rowid(sqlite *db){
-+  return db->lastRowid;
-+}
-+
-+/*
-+** Return the number of changes in the most recent call to sqlite_exec().
-+*/
-+int sqlite_changes(sqlite *db){
-+  return db->nChange;
-+}
-+
-+/*
-+** Return the number of changes produced by the last INSERT, UPDATE, or
-+** DELETE statement to complete execution. The count does not include
-+** changes due to SQL statements executed in trigger programs that were
-+** triggered by that statement
-+*/
-+int sqlite_last_statement_changes(sqlite *db){
-+  return db->lsChange;
-+}
-+
-+/*
-+** Close an existing SQLite database
-+*/
-+void sqlite_close(sqlite *db){
-+  HashElem *i;
-+  int j;
-+  db->want_to_close = 1;
-+  if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){
-+    /* printf("DID NOT CLOSE\n"); fflush(stdout); */
-+    return;
-+  }
-+  db->magic = SQLITE_MAGIC_CLOSED;
-+  for(j=0; j<db->nDb; j++){
-+    struct Db *pDb = &db->aDb[j];
-+    if( pDb->pBt ){
-+      sqliteBtreeClose(pDb->pBt);
-+      pDb->pBt = 0;
-+    }
-+  }
-+  sqliteResetInternalSchema(db, 0);
-+  assert( db->nDb<=2 );
-+  assert( db->aDb==db->aDbStatic );
-+  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
-+    FuncDef *pFunc, *pNext;
-+    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
-+      pNext = pFunc->pNext;
-+      sqliteFree(pFunc);
-+    }
-+  }
-+  sqliteHashClear(&db->aFunc);
-+  sqliteFree(db);
-+}
-+
-+/*
-+** Rollback all database files.
-+*/
-+void sqliteRollbackAll(sqlite *db){
-+  int i;
-+  for(i=0; i<db->nDb; i++){
-+    if( db->aDb[i].pBt ){
-+      sqliteBtreeRollback(db->aDb[i].pBt);
-+      db->aDb[i].inTrans = 0;
-+    }
-+  }
-+  sqliteResetInternalSchema(db, 0);
-+  /* sqliteRollbackInternalChanges(db); */
-+}
-+
-+/*
-+** Execute SQL code.  Return one of the SQLITE_ success/failure
-+** codes.  Also write an error message into memory obtained from
-+** malloc() and make *pzErrMsg point to that message.
-+**
-+** If the SQL is a query, then for each row in the query result
-+** the xCallback() function is called.  pArg becomes the first
-+** argument to xCallback().  If xCallback=NULL then no callback
-+** is invoked, even for queries.
-+*/
-+int sqlite_exec(
-+  sqlite *db,                 /* The database on which the SQL executes */
-+  const char *zSql,           /* The SQL to be executed */
-+  sqlite_callback xCallback,  /* Invoke this callback routine */
-+  void *pArg,                 /* First argument to xCallback() */
-+  char **pzErrMsg             /* Write error messages here */
-+){
-+  int rc = SQLITE_OK;
-+  const char *zLeftover;
-+  sqlite_vm *pVm;
-+  int nRetry = 0;
-+  int nChange = 0;
-+  int nCallback;
-+
-+  if( zSql==0 ) return SQLITE_OK;
-+  while( rc==SQLITE_OK && zSql[0] ){
-+    pVm = 0;
-+    rc = sqlite_compile(db, zSql, &zLeftover, &pVm, pzErrMsg);
-+    if( rc!=SQLITE_OK ){
-+      assert( pVm==0 || sqlite_malloc_failed );
-+      return rc;
-+    }
-+    if( pVm==0 ){
-+      /* This happens if the zSql input contained only whitespace */
-+      break;
-+    }
-+    db->nChange += nChange;
-+    nCallback = 0;
-+    while(1){
-+      int nArg;
-+      char **azArg, **azCol;
-+      rc = sqlite_step(pVm, &nArg, (const char***)&azArg,(const char***)&azCol);
-+      if( rc==SQLITE_ROW ){
-+        if( xCallback!=0 && xCallback(pArg, nArg, azArg, azCol) ){
-+          sqlite_finalize(pVm, 0);
-+          return SQLITE_ABORT;
-+        }
-+        nCallback++;
-+      }else{
-+        if( rc==SQLITE_DONE && nCallback==0
-+          && (db->flags & SQLITE_NullCallback)!=0 && xCallback!=0 ){
-+          xCallback(pArg, nArg, azArg, azCol);
-+        }
-+        rc = sqlite_finalize(pVm, pzErrMsg);
-+        if( rc==SQLITE_SCHEMA && nRetry<2 ){
-+          nRetry++;
-+          rc = SQLITE_OK;
-+          break;
-+        }
-+        if( db->pVdbe==0 ){
-+          nChange = db->nChange;
-+        }
-+        nRetry = 0;
-+        zSql = zLeftover;
-+        while( isspace(zSql[0]) ) zSql++;
-+        break;
-+      }
-+    }
-+  }
-+  return rc;
-+}
-+
-+
-+/*
-+** Compile a single statement of SQL into a virtual machine.  Return one
-+** of the SQLITE_ success/failure codes.  Also write an error message into
-+** memory obtained from malloc() and make *pzErrMsg point to that message.
-+*/
-+int sqlite_compile(
-+  sqlite *db,                 /* The database on which the SQL executes */
-+  const char *zSql,           /* The SQL to be executed */
-+  const char **pzTail,        /* OUT: Next statement after the first */
-+  sqlite_vm **ppVm,           /* OUT: The virtual machine */
-+  char **pzErrMsg             /* OUT: Write error messages here */
-+){
-+  Parse sParse;
-+
-+  if( pzErrMsg ) *pzErrMsg = 0;
-+  if( sqliteSafetyOn(db) ) goto exec_misuse;
-+  if( !db->init.busy ){
-+    if( (db->flags & SQLITE_Initialized)==0 ){
-+      int rc, cnt = 1;
-+      while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY
-+         && db->xBusyCallback
-+         && db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){}
-+      if( rc!=SQLITE_OK ){
-+        sqliteStrRealloc(pzErrMsg);
-+        sqliteSafetyOff(db);
-+        return rc;
-+      }
-+      if( pzErrMsg ){
-+        sqliteFree(*pzErrMsg);
-+        *pzErrMsg = 0;
-+      }
-+    }
-+    if( db->file_format<3 ){
-+      sqliteSafetyOff(db);
-+      sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0);
-+      return SQLITE_ERROR;
-+    }
-+  }
-+  assert( (db->flags & SQLITE_Initialized)!=0 || db->init.busy );
-+  if( db->pVdbe==0 ){ db->nChange = 0; }
-+  memset(&sParse, 0, sizeof(sParse));
-+  sParse.db = db;
-+  sqliteRunParser(&sParse, zSql, pzErrMsg);
-+  if( db->xTrace && !db->init.busy ){
-+    /* Trace only the statment that was compiled.
-+    ** Make a copy of that part of the SQL string since zSQL is const
-+    ** and we must pass a zero terminated string to the trace function
-+    ** The copy is unnecessary if the tail pointer is pointing at the
-+    ** beginnig or end of the SQL string.
-+    */
-+    if( sParse.zTail && sParse.zTail!=zSql && *sParse.zTail ){
-+      char *tmpSql = sqliteStrNDup(zSql, sParse.zTail - zSql);
-+      if( tmpSql ){
-+        db->xTrace(db->pTraceArg, tmpSql);
-+        free(tmpSql);
-+      }else{
-+        /* If a memory error occurred during the copy,
-+        ** trace entire SQL string and fall through to the
-+        ** sqlite_malloc_failed test to report the error.
-+        */
-+        db->xTrace(db->pTraceArg, zSql); 
-+      }
-+    }else{
-+      db->xTrace(db->pTraceArg, zSql); 
-+    }
-+  }
-+  if( sqlite_malloc_failed ){
-+    sqliteSetString(pzErrMsg, "out of memory", (char*)0);
-+    sParse.rc = SQLITE_NOMEM;
-+    sqliteRollbackAll(db);
-+    sqliteResetInternalSchema(db, 0);
-+    db->flags &= ~SQLITE_InTrans;
-+  }
-+  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
-+  if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){
-+    sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), (char*)0);
-+  }
-+  sqliteStrRealloc(pzErrMsg);
-+  if( sParse.rc==SQLITE_SCHEMA ){
-+    sqliteResetInternalSchema(db, 0);
-+  }
-+  assert( ppVm );
-+  *ppVm = (sqlite_vm*)sParse.pVdbe;
-+  if( pzTail ) *pzTail = sParse.zTail;
-+  if( sqliteSafetyOff(db) ) goto exec_misuse;
-+  return sParse.rc;
-+
-+exec_misuse:
-+  if( pzErrMsg ){
-+    *pzErrMsg = 0;
-+    sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
-+    sqliteStrRealloc(pzErrMsg);
-+  }
-+  return SQLITE_MISUSE;
-+}
-+
-+
-+/*
-+** The following routine destroys a virtual machine that is created by
-+** the sqlite_compile() routine.
-+**
-+** The integer returned is an SQLITE_ success/failure code that describes
-+** the result of executing the virtual machine.  An error message is
-+** written into memory obtained from malloc and *pzErrMsg is made to
-+** point to that error if pzErrMsg is not NULL.  The calling routine
-+** should use sqlite_freemem() to delete the message when it has finished
-+** with it.
-+*/
-+int sqlite_finalize(
-+  sqlite_vm *pVm,            /* The virtual machine to be destroyed */
-+  char **pzErrMsg            /* OUT: Write error messages here */
-+){
-+  int rc = sqliteVdbeFinalize((Vdbe*)pVm, pzErrMsg);
-+  sqliteStrRealloc(pzErrMsg);
-+  return rc;
-+}
-+
-+/*
-+** Terminate the current execution of a virtual machine then
-+** reset the virtual machine back to its starting state so that it
-+** can be reused.  Any error message resulting from the prior execution
-+** is written into *pzErrMsg.  A success code from the prior execution
-+** is returned.
-+*/
-+int sqlite_reset(
-+  sqlite_vm *pVm,            /* The virtual machine to be destroyed */
-+  char **pzErrMsg            /* OUT: Write error messages here */
-+){
-+  int rc = sqliteVdbeReset((Vdbe*)pVm, pzErrMsg);
-+  sqliteVdbeMakeReady((Vdbe*)pVm, -1, 0);
-+  sqliteStrRealloc(pzErrMsg);
-+  return rc;
-+}
-+
-+/*
-+** Return a static string that describes the kind of error specified in the
-+** argument.
-+*/
-+const char *sqlite_error_string(int rc){
-+  const char *z;
-+  switch( rc ){
-+    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;
-+    case SQLITE_LOCKED:     z = "database table is locked";              break;
-+    case SQLITE_NOMEM:      z = "out of memory";                         break;
-+    case SQLITE_READONLY:   z = "attempt to write a readonly database";  break;
-+    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_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;
-+    case SQLITE_NOLFS:      z = "kernel lacks large file support";       break;
-+    case SQLITE_AUTH:       z = "authorization denied";                  break;
-+    case SQLITE_FORMAT:     z = "auxiliary database format error";       break;
-+    case SQLITE_RANGE:      z = "bind index out of range";               break;
-+    case SQLITE_NOTADB:     z = "file is encrypted or is not a database";break;
-+    default:                z = "unknown error";                         break;
-+  }
-+  return z;
-+}
-+
-+/*
-+** This routine implements a busy callback that sleeps and tries
-+** again until a timeout value is reached.  The timeout value is
-+** an integer number of milliseconds passed in as the first
-+** argument.
-+*/
-+static int sqliteDefaultBusyCallback(
-+ void *Timeout,           /* Maximum amount of time to wait */
-+ const char *NotUsed,     /* The name of the table that is busy */
-+ int count                /* Number of times table has been busy */
-+){
-+#if SQLITE_MIN_SLEEP_MS==1
-+  static const char delays[] =
-+     { 1, 2, 5, 10, 15, 20, 25, 25,  25,  50,  50,  50, 100};
-+  static const short int totals[] =
-+     { 0, 1, 3,  8, 18, 33, 53, 78, 103, 128, 178, 228, 287};
-+# define NDELAY (sizeof(delays)/sizeof(delays[0]))
-+  int timeout = (int)(long)Timeout;
-+  int delay, prior;
-+
-+  if( count <= NDELAY ){
-+    delay = delays[count-1];
-+    prior = totals[count-1];
-+  }else{
-+    delay = delays[NDELAY-1];
-+    prior = totals[NDELAY-1] + delay*(count-NDELAY-1);
-+  }
-+  if( prior + delay > timeout ){
-+    delay = timeout - prior;
-+    if( delay<=0 ) return 0;
-+  }
-+  sqliteOsSleep(delay);
-+  return 1;
-+#else
-+  int timeout = (int)(long)Timeout;
-+  if( (count+1)*1000 > timeout ){
-+    return 0;
-+  }
-+  sqliteOsSleep(1000);
-+  return 1;
-+#endif
-+}
-+
-+/*
-+** This routine sets the busy callback for an Sqlite database to the
-+** given callback function with the given argument.
-+*/
-+void sqlite_busy_handler(
-+  sqlite *db,
-+  int (*xBusy)(void*,const char*,int),
-+  void *pArg
-+){
-+  db->xBusyCallback = xBusy;
-+  db->pBusyArg = pArg;
-+}
-+
-+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
-+/*
-+** This routine sets the progress callback for an Sqlite database to the
-+** given callback function with the given argument. The progress callback will
-+** be invoked every nOps opcodes.
-+*/
-+void sqlite_progress_handler(
-+  sqlite *db, 
-+  int nOps,
-+  int (*xProgress)(void*), 
-+  void *pArg
-+){
-+  if( nOps>0 ){
-+    db->xProgress = xProgress;
-+    db->nProgressOps = nOps;
-+    db->pProgressArg = pArg;
-+  }else{
-+    db->xProgress = 0;
-+    db->nProgressOps = 0;
-+    db->pProgressArg = 0;
-+  }
-+}
-+#endif
-+
-+
-+/*
-+** This routine installs a default busy handler that waits for the
-+** specified number of milliseconds before returning 0.
-+*/
-+void sqlite_busy_timeout(sqlite *db, int ms){
-+  if( ms>0 ){
-+    sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)(long)ms);
-+  }else{
-+    sqlite_busy_handler(db, 0, 0);
-+  }
-+}
-+
-+/*
-+** Cause any pending operation to stop at its earliest opportunity.
-+*/
-+void sqlite_interrupt(sqlite *db){
-+  db->flags |= SQLITE_Interrupt;
-+}
-+
-+/*
-+** Windows systems should call this routine to free memory that
-+** is returned in the in the errmsg parameter of sqlite_open() when
-+** SQLite is a DLL.  For some reason, it does not work to call free()
-+** directly.
-+**
-+** Note that we need to call free() not sqliteFree() here, since every
-+** string that is exported from SQLite should have already passed through
-+** sqliteStrRealloc().
-+*/
-+void sqlite_freemem(void *p){ free(p); }
-+
-+/*
-+** Windows systems need functions to call to return the sqlite_version
-+** and sqlite_encoding strings since they are unable to access constants
-+** within DLLs.
-+*/
-+const char *sqlite_libversion(void){ return sqlite_version; }
-+const char *sqlite_libencoding(void){ return sqlite_encoding; }
-+
-+/*
-+** Create new user-defined functions.  The sqlite_create_function()
-+** routine creates a regular function and sqlite_create_aggregate()
-+** creates an aggregate function.
-+**
-+** Passing a NULL xFunc argument or NULL xStep and xFinalize arguments
-+** disables the function.  Calling sqlite_create_function() with the
-+** same name and number of arguments as a prior call to
-+** sqlite_create_aggregate() disables the prior call to
-+** sqlite_create_aggregate(), and vice versa.
-+**
-+** If nArg is -1 it means that this function will accept any number
-+** of arguments, including 0.  The maximum allowed value of nArg is 127.
-+*/
-+int sqlite_create_function(
-+  sqlite *db,          /* Add the function to this database connection */
-+  const char *zName,   /* Name of the function to add */
-+  int nArg,            /* Number of arguments */
-+  void (*xFunc)(sqlite_func*,int,const char**),  /* The implementation */
-+  void *pUserData      /* User data */
-+){
-+  FuncDef *p;
-+  int nName;
-+  if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1;
-+  if( nArg<-1 || nArg>127 ) return 1;
-+  nName = strlen(zName);
-+  if( nName>255 ) return 1;
-+  p = sqliteFindFunction(db, zName, nName, nArg, 1);
-+  if( p==0 ) return 1;
-+  p->xFunc = xFunc;
-+  p->xStep = 0;
-+  p->xFinalize = 0;
-+  p->pUserData = pUserData;
-+  return 0;
-+}
-+int sqlite_create_aggregate(
-+  sqlite *db,          /* Add the function to this database connection */
-+  const char *zName,   /* Name of the function to add */
-+  int nArg,            /* Number of arguments */
-+  void (*xStep)(sqlite_func*,int,const char**), /* The step function */
-+  void (*xFinalize)(sqlite_func*),              /* The finalizer */
-+  void *pUserData      /* User data */
-+){
-+  FuncDef *p;
-+  int nName;
-+  if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1;
-+  if( nArg<-1 || nArg>127 ) return 1;
-+  nName = strlen(zName);
-+  if( nName>255 ) return 1;
-+  p = sqliteFindFunction(db, zName, nName, nArg, 1);
-+  if( p==0 ) return 1;
-+  p->xFunc = 0;
-+  p->xStep = xStep;
-+  p->xFinalize = xFinalize;
-+  p->pUserData = pUserData;
-+  return 0;
-+}
-+
-+/*
-+** Change the datatype for all functions with a given name.  See the
-+** header comment for the prototype of this function in sqlite.h for
-+** additional information.
-+*