libgda r3205 - in trunk: . doc/C doc/C/tmpl libgda libgda/sqlite/sqlite-src libgda/sqlite/virtual tests/value-holders



Author: vivien
Date: Mon Sep 15 18:30:05 2008
New Revision: 3205
URL: http://svn.gnome.org/viewvc/libgda?rev=3205&view=rev

Log:
2008-09-15  Vivien Malerba <malerba gnome-db org>

	* doc/C: documentation improvements regarding data validation and programmer's control
	* libgda/gda-holder.[ch]: renamed the "before-change" signal to "validate-change" (and changed
	its return value)
	* libgda/gda-set.[ch]:
	  - changed the "before-holder-change" to "validate_holder_change"(and changed
	    its return value)
	  - added a "validate-set" signal
	  - the gda_set_is_valid() method has been changed to emit the "validate-set" signal
	    before it returns a value.
	* libgda/gda-data-model-iter.[ch]: removed the "row-to-change" signal (it now uses the
	GdaSet::validate-set signal), and the gda_data_model_iter_can_be_moved() method
	* libgda/gda-server-operation.c:
	* libgda/gda-data-model.c: adaptations to the API Changes
	* libgda/gda-data-proxy.[ch]:
	  - adaptations to the API Changes,
	  - renamed the	"pre-changes-applied" signal to "validate-row-changes" (and changed
	    its return value)
	  - renamed the "post-changes-applied" signal to "row-changes-applied"
	  - bug correction in gda_data_proxy_get_n_rows()
	* libgda/gda-marshal.list: new signals' signatures
	* libgda/gda-data-comparator.c: added assertions
	* libgda/gda-connection.c: don't remove items from a GHashTable while in g_hash_table_foreach(),
	this is probably the reason for bug #545979
	* libgda/gda-value.c: corrected the gda_value_differ() function
	* libgda/sqlite/virtual/gda-vprovider-data-model.c: corrected the virtualNext() method which
	moves SQLite's internal cursor forward
	* libgda/gda-data-model-iter.[ch]: renamed gda_data_model_iter_set_at_row() to
	gda_data_model_iter_move_at_row()
	* libgda/Makefile.am:
	* libgda/gda-data-model-iter-extra.h: new file
	* libgda/gda-data-model-extra.h:
	* libgda/gda-data-model-private.h:
	* libgda/gda-data-model-import.c:
	* libgda/gda-data-model.c:
	* libgda/gda-data-proxy.c:
	* libgda/gda-data-select.c:
	* libgda/sqlite/virtual/virtual-test.c:
	  - moved the code which implements the GdaDataModelIter
	    movements (forward, backward and to a row) to the gda-data-model-iter.c file
	  - renamed gda_data_model_move_iter_at_row_default() to gda_data_model_iter_move_at_row_default()
	  - renamed gda_data_model_move_iter_next_default() to gda_data_model_iter_move_next_default()
	  - renamed gda_data_model_move_iter_prev_default() to gda_data_model_iter_move_prev_default()
	* libgda/sqlite/sqlite-src/: up to version 3.6.2
	* tests/value-holders/: adaptations to the API Changes


Added:
   trunk/doc/C/data_validation.xml
   trunk/doc/C/data_validation_holder.dia   (contents, props changed)
   trunk/doc/C/data_validation_holder.png   (contents, props changed)
   trunk/doc/C/data_validation_proxy.dia   (contents, props changed)
   trunk/doc/C/data_validation_proxy.png   (contents, props changed)
   trunk/doc/C/data_validation_set.dia   (contents, props changed)
   trunk/doc/C/data_validation_set.png   (contents, props changed)
   trunk/libgda/gda-data-model-iter-extra.h
Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/doc/C/Makefile.am
   trunk/doc/C/howto.xml
   trunk/doc/C/libgda-4.0-docs.sgml
   trunk/doc/C/libgda-4.0-sections.txt
   trunk/doc/C/tmpl/gda-data-model-iter.sgml
   trunk/doc/C/tmpl/gda-data-proxy.sgml
   trunk/doc/C/tmpl/gda-holder.sgml
   trunk/doc/C/tmpl/gda-set.sgml
   trunk/doc/C/tmpl/gda-value.sgml
   trunk/libgda/Makefile.am
   trunk/libgda/gda-connection.c
   trunk/libgda/gda-data-comparator.c
   trunk/libgda/gda-data-model-extra.h
   trunk/libgda/gda-data-model-import.c
   trunk/libgda/gda-data-model-iter.c
   trunk/libgda/gda-data-model-iter.h
   trunk/libgda/gda-data-model-private.h
   trunk/libgda/gda-data-model.c
   trunk/libgda/gda-data-proxy.c
   trunk/libgda/gda-data-proxy.h
   trunk/libgda/gda-data-select.c
   trunk/libgda/gda-holder.c
   trunk/libgda/gda-holder.h
   trunk/libgda/gda-marshal.list
   trunk/libgda/gda-server-operation.c
   trunk/libgda/gda-set.c
   trunk/libgda/gda-set.h
   trunk/libgda/gda-value.c
   trunk/libgda/sqlite/sqlite-src/PragmasPatch
   trunk/libgda/sqlite/sqlite-src/sqlite3.c
   trunk/libgda/sqlite/sqlite-src/sqlite3.h
   trunk/libgda/sqlite/virtual/gda-vprovider-data-model.c
   trunk/libgda/sqlite/virtual/virtual-test.c
   trunk/tests/value-holders/check_holder.c
   trunk/tests/value-holders/check_set.c

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Mon Sep 15 18:30:05 2008
@@ -1,5 +1,5 @@
 
- - bug fixes: #549953
+ - bug fixes: #549953, #535633, #551058
 
 libgda 3.99.3, 2008-07-06
 

Modified: trunk/doc/C/Makefile.am
==============================================================================
--- trunk/doc/C/Makefile.am	(original)
+++ trunk/doc/C/Makefile.am	Mon Sep 15 18:30:05 2008
@@ -50,7 +50,8 @@
 	architecture.png parts.png stmt-unknown.png stmt-select.png stmt-insert1.png stmt-insert2.png \
 	stmt-update.png stmt-compound.png information_schema.png \
 	MetaStore1.png MetaStore2.png i_s_data_types.png \
-	writable_data_model.png GdaDataModelIter.png
+	writable_data_model.png GdaDataModelIter.png \
+	data_validation_holder.png data_validation_proxy.png data_validation_set.png
 
 # Extra options to supply to gtkdoc-fixref
 FIXXREF_OPTIONS=
@@ -60,7 +61,7 @@
 # Other files to distribute
 EXTRA_DIST += examples/full_example.c installation.xml limitations.xml migration.xml migration2.xml \
 	server-operation.xml gettingstarted.xml virtual.xml virtual-notice.xml store-meta-type.xml \
-	prov-writing.xml i_s_doc.xml howto.xml gda-sql-manual.xml \
+	prov-writing.xml i_s_doc.xml howto.xml gda-sql-manual.xml data_validation.xml \
 	DataModels.svg \
 	architecture.svg parts.svg stmt-unknown.svg stmt-select.svg stmt-insert1.svg stmt-insert2.svg \
 	stmt-update.svg stmt-compound.svg information_schema.svg

Added: trunk/doc/C/data_validation.xml
==============================================================================
--- (empty file)
+++ trunk/doc/C/data_validation.xml	Mon Sep 15 18:30:05 2008
@@ -0,0 +1,128 @@
+<sect1 id="data-validation">
+  <title>Custom data validation</title>
+  <para>
+    &LIBGDA; allows the programmer to specify some rules of his own to control data changes (for example
+    business rules). This section details the various control points, how to implement them, and how or when
+    they are invoked.
+  </para>
+
+  <sect2 id="data-validation-GdaHolder">
+    <title>GdaHolder controls</title>
+    <para>
+      The <link linkend="GdaHolder">GdaHolder</link> object holds a single value 
+      (as a <link linkend="GValue">GValue</link>). When that value is to be modified, using for example
+      <link linkend="gda-holder-set-value">gda_holder_set_value()</link>, 
+      then the proposed new value's validation process is executed:
+      <orderedlist>
+	<listitem><para>it is determined if the proposed new value is of the correct type and
+	    if it respects the holder's policy (for example a NULL value won't be accepted if 
+	    the holder can't be NULL). If the proposed value does not respect the policy, then
+	    the value change will be rejected</para></listitem>
+	<listitem><para>the <link linkend="GdaHolder-validate-change">"validate-change"</link> signal is
+	    emitted. If any handler for this signal returns a pointer to a filled <link linkend="GError">GError</link>
+	    structure, then the signal's propagation is stopped and the value change will be rejected.</para></listitem>
+      </orderedlist>
+    </para>
+    <para>
+      An example illustrating how to use the <link linkend="GdaHolder-validate-change">"validate-change"</link> signal
+      is:
+      <programlisting>
+static GError *
+my_validate_change_cb (GdaHolder *h, const GValue *value, gpointer data)
+{
+        GError *error = NULL;
+
+        /* for example check that value is inferior to 5 and not NULL */
+        if (gda_value_is_null (value)) 
+                g_set_error (&amp;error, 0, 0, "NULL values are not allowed!");
+        else if (g_value_get_int (value) &gt;= 5)
+                g_set_error (&amp;error, 0, 0, "Value sould be inferior to 5");
+
+        return error;
+}
+
+{
+        GdaHolder *holder;
+        GError *error = NULL;
+        [...]
+        g_signal_connect (G_OBJECT (holder), "validate-change",
+                G_CALLBACK (my_validate_change_cb), NULL);
+        if (! gda_holder_set_value (holder, value, &amp;error)) {
+                g_print ("Error: %s\n", error->message);
+                g_error_free (error);
+		[...]
+	}
+}
+      </programlisting>
+    </para>
+    <para>
+      <mediaobject>
+	<imageobject role="html">
+          <imagedata fileref="data_validation_holder.png" format="PNG" contentwidth="100mm"/>
+	</imageobject>
+	<textobject>
+          <phrase>GdaHolder's value change control</phrase>
+	</textobject>
+      </mediaobject>
+    </para>
+  </sect2>
+
+  <sect2 id="data-validation-GdaSet">
+    <title>GdaSet controls</title>
+    <para>
+      The <link linkend="GdaSet">GdaSet</link> object is an ordered list (or vector) of values,
+      each represented by a <link linkend="GdaHolder">GdaHolder</link> object. One can place controls
+      at two key events:
+      <itemizedlist>
+	<listitem><para>
+	    When any value of a <link linkend="GdaHolder">GdaHolder</link> changes, where
+	    the <link linkend="GdaSet-validate-holder-change">"validate-holder-change"</link> signal is
+	    emitted. If any handler for this signal returns a pointer to a filled <link linkend="GError">GError</link>
+	    structure, then the signal's propagation is stopped and the value change will be rejected. This
+	    key event allows one to control each holder's value change as they occur.
+	</para></listitem>
+	<listitem><para>
+	    When the <link linkend="gda-set-is-valid">gda_set_is_valid()</link> method is called, where
+	    the <link linkend="GdaSet-validate-set">"validate-set"</link> signal is
+	    emitted. If any handler for this signal returns a pointer to a filled <link linkend="GError">GError</link>
+	    structure, then the signal's propagation is stopped and the calling method will return the generated
+	    error. This key event allows one to control the validity of a set of values altogether (for example
+	    before writing to a table).
+	</para></listitem>
+      </itemizedlist>
+    </para>
+    <para>
+      <mediaobject>
+	<imageobject role="html">
+          <imagedata fileref="data_validation_set.png" format="PNG" contentwidth="180mm"/>
+	</imageobject>
+	<textobject>
+          <phrase>GdaSet's changes controls</phrase>
+	</textobject>
+      </mediaobject>
+    </para>
+  </sect2>
+
+  <sect2 id="data-validation-GdaDataProxy">
+    <title>GdaDataProxy controls</title>
+    <para>
+      The <link linkend="GdaDataProxy">GdaDataProxy</link> data model allows one to store temporary modifications
+      to a data model, and then apply (write to the proxied data model) those modifications row by row. Before
+      applying any row modification, the <link linkend="GdaDataProxy">GdaDataProxy</link> data model emits
+      the <link linkend="GdaDataProxy::validate-row-changes">"validate-row-changes"</link> signal, and
+      if handler for this signal returns a pointer to a filled <link linkend="GError">GError</link>
+      structure, then the signal's propagation is stopped and the row's modifications are not applied.
+    </para>
+    <para>
+      <mediaobject>
+	<imageobject role="html">
+          <imagedata fileref="data_validation_proxy.png" format="PNG" contentwidth="100mm"/>
+	</imageobject>
+	<textobject>
+          <phrase>GdaDataProxy's changes controls</phrase>
+	</textobject>
+      </mediaobject>
+    </para>
+  </sect2>
+  
+</sect1>

Added: trunk/doc/C/data_validation_holder.dia
==============================================================================
Binary file. No diff available.

Added: trunk/doc/C/data_validation_holder.png
==============================================================================
Binary file. No diff available.

Added: trunk/doc/C/data_validation_proxy.dia
==============================================================================
Binary file. No diff available.

Added: trunk/doc/C/data_validation_proxy.png
==============================================================================
Binary file. No diff available.

Added: trunk/doc/C/data_validation_set.dia
==============================================================================
Binary file. No diff available.

Added: trunk/doc/C/data_validation_set.png
==============================================================================
Binary file. No diff available.

Modified: trunk/doc/C/howto.xml
==============================================================================
--- trunk/doc/C/howto.xml	(original)
+++ trunk/doc/C/howto.xml	Mon Sep 15 18:30:05 2008
@@ -431,5 +431,16 @@
     </para>
   </sect1>
 
+  <sect1>
+    <title>Control value's assignment to various objects</title>
+    <para>
+      &LIBGDA; has builtin support to allow the programmer to control what values are acceptable 
+      for some objects which hold values (namely the <link linkend="GdaHolder">GdaHolder</link>,
+      <link linkend="GdaSet">GdaSet</link> and <link linkend="GdaDataProxy">GdaDataProxy</link> objects).
+      For more information about this topic, see the <link linkend="data-validation">custom data validation</link>
+      section.
+    </para>
+  </sect1>
+
 </chapter>
 

Modified: trunk/doc/C/libgda-4.0-docs.sgml
==============================================================================
--- trunk/doc/C/libgda-4.0-docs.sgml	(original)
+++ trunk/doc/C/libgda-4.0-docs.sgml	Mon Sep 15 18:30:05 2008
@@ -38,6 +38,7 @@
 <!ENTITY examples SYSTEM "gettingstarted.xml">
 <!ENTITY migration SYSTEM "migration.xml">
 <!ENTITY migration2 SYSTEM "migration2.xml">
+<!ENTITY data-validation SYSTEM "data_validation.xml">
 <!ENTITY limitations SYSTEM "limitations.xml">
 <!ENTITY libgda-GdaCommand SYSTEM "xml/gda-command.xml">
 <!ENTITY libgda-config SYSTEM "xml/gda-config.xml">
@@ -569,6 +570,7 @@
 	</itemizedlist>
       </para>
       &libgda-GValue;
+      &data-validation;
       &libgda-GdaBlobOp;
       &libgda-GdaDataModel;
       &libgda-GdaColumn;

Modified: trunk/doc/C/libgda-4.0-sections.txt
==============================================================================
--- trunk/doc/C/libgda-4.0-sections.txt	(original)
+++ trunk/doc/C/libgda-4.0-sections.txt	Mon Sep 15 18:30:05 2008
@@ -377,7 +377,7 @@
 gda_data_model_iter_get_value_at
 gda_data_model_iter_get_value_for_field
 gda_data_model_iter_is_valid
-gda_data_model_iter_set_at_row
+gda_data_model_iter_move_at_row
 gda_data_model_iter_move_next
 gda_data_model_iter_move_prev
 gda_data_model_iter_get_row

Modified: trunk/doc/C/tmpl/gda-data-model-iter.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-data-model-iter.sgml	(original)
+++ trunk/doc/C/tmpl/gda-data-model-iter.sgml	Mon Sep 15 18:30:05 2008
@@ -33,7 +33,7 @@
   gda_data_model_iter_move_next() which moves to the first row).
 </para>
 <para>
-  The gda_data_model_iter_set_at_row() method, if the iterator can be moved both forward and backwards, can move the 
+  The gda_data_model_iter_move_at_row() method, if the iterator can be moved both forward and backwards, can move the 
   iterator to a specific row (sometimes faster than moving it forward or backwards a number of times).
 </para>
 <para>
@@ -77,15 +77,6 @@
 @gdadatamodeliter: the object which received the signal.
 @arg1: 
 
-<!-- ##### SIGNAL GdaDataModelIter::row-to-change ##### -->
-<para>
-
-</para>
-
- gdadatamodeliter: the object which received the signal.
- arg1: 
- Returns: 
-
 <!-- ##### ARG GdaDataModelIter:current-row ##### -->
 <para>
 
@@ -135,7 +126,7 @@
 @Returns: 
 
 
-<!-- ##### FUNCTION gda_data_model_iter_set_at_row ##### -->
+<!-- ##### FUNCTION gda_data_model_iter_move_at_row ##### -->
 <para>
 
 </para>

Modified: trunk/doc/C/tmpl/gda-data-proxy.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-data-proxy.sgml	(original)
+++ trunk/doc/C/tmpl/gda-data-proxy.sgml	Mon Sep 15 18:30:05 2008
@@ -57,7 +57,7 @@
 
 @gdadataproxy: the object which received the signal.
 
-<!-- ##### SIGNAL GdaDataProxy::post-changes-applied ##### -->
+<!-- ##### SIGNAL GdaDataProxy::row-changes-applied ##### -->
 <para>
 
 </para>
@@ -66,7 +66,7 @@
 @arg1: 
 @arg2: 
 
-<!-- ##### SIGNAL GdaDataProxy::pre-changes-applied ##### -->
+<!-- ##### SIGNAL GdaDataProxy::row-delete-changed ##### -->
 <para>
 
 </para>
@@ -74,9 +74,8 @@
 @gdadataproxy: the object which received the signal.
 @arg1: 
 @arg2: 
- Returns: 
 
-<!-- ##### SIGNAL GdaDataProxy::row-delete-changed ##### -->
+<!-- ##### SIGNAL GdaDataProxy::sample-changed ##### -->
 <para>
 
 </para>
@@ -85,22 +84,23 @@
 @arg1: 
 @arg2: 
 
-<!-- ##### SIGNAL GdaDataProxy::sample-changed ##### -->
+<!-- ##### SIGNAL GdaDataProxy::sample-size-changed ##### -->
 <para>
 
 </para>
 
 @gdadataproxy: the object which received the signal.
 @arg1: 
- arg2: 
 
-<!-- ##### SIGNAL GdaDataProxy::sample-size-changed ##### -->
+<!-- ##### SIGNAL GdaDataProxy::validate-row-changes ##### -->
 <para>
 
 </para>
 
 @gdadataproxy: the object which received the signal.
 @arg1: 
+ arg2: 
+ Returns: 
 
 <!-- ##### ARG GdaDataProxy:defer-sync ##### -->
 <para>
@@ -131,8 +131,8 @@
 @row_delete_changed: 
 @sample_size_changed: 
 @sample_changed: 
- pre_changes_applied: 
- post_changes_applied: 
+ validate_row_changes: 
+ row_changes_applied: 
 
 <!-- ##### STRUCT GdaDataProxyPrivate ##### -->
 <para>

Modified: trunk/doc/C/tmpl/gda-holder.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-holder.sgml	(original)
+++ trunk/doc/C/tmpl/gda-holder.sgml	Mon Sep 15 18:30:05 2008
@@ -24,28 +24,28 @@
 </para>
 
 
-<!-- ##### SIGNAL GdaHolder::before-change ##### -->
+<!-- ##### SIGNAL GdaHolder::changed ##### -->
 <para>
 
 </para>
 
 @gdaholder: the object which received the signal.
- arg1: 
- Returns: 
 
-<!-- ##### SIGNAL GdaHolder::changed ##### -->
+<!-- ##### SIGNAL GdaHolder::source-changed ##### -->
 <para>
 
 </para>
 
 @gdaholder: the object which received the signal.
 
-<!-- ##### SIGNAL GdaHolder::source-changed ##### -->
+<!-- ##### SIGNAL GdaHolder::validate-change ##### -->
 <para>
 
 </para>
 
 @gdaholder: the object which received the signal.
+ arg1: 
+ Returns: 
 
 <!-- ##### ARG GdaHolder:description ##### -->
 <para>

Modified: trunk/doc/C/tmpl/gda-set.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-set.sgml	(original)
+++ trunk/doc/C/tmpl/gda-set.sgml	Mon Sep 15 18:30:05 2008
@@ -29,17 +29,15 @@
 </para>
 
 
-<!-- ##### SIGNAL GdaSet::before-holder-change ##### -->
+<!-- ##### SIGNAL GdaSet::holder-attr-changed ##### -->
 <para>
-  
+
 </para>
 
 @gdaset: the object which received the signal.
 @arg1: 
- arg2: 
- Returns: 
 
-<!-- ##### SIGNAL GdaSet::holder-attr-changed ##### -->
+<!-- ##### SIGNAL GdaSet::holder-changed ##### -->
 <para>
 
 </para>
@@ -47,7 +45,7 @@
 @gdaset: the object which received the signal.
 @arg1: 
 
-<!-- ##### SIGNAL GdaSet::holder-changed ##### -->
+<!-- ##### SIGNAL GdaSet::holder-plugin-changed ##### -->
 <para>
 
 </para>
@@ -55,20 +53,30 @@
 @gdaset: the object which received the signal.
 @arg1: 
 
-<!-- ##### SIGNAL GdaSet::holder-plugin-changed ##### -->
+<!-- ##### SIGNAL GdaSet::public-data-changed ##### -->
+<para>
+
+</para>
+
+ gdaset: the object which received the signal.
+
+<!-- ##### SIGNAL GdaSet::validate-holder-change ##### -->
 <para>
 
 </para>
 
 @gdaset: the object which received the signal.
 @arg1: 
+ arg2: 
+ Returns: 
 
-<!-- ##### SIGNAL GdaSet::public-data-changed ##### -->
+<!-- ##### SIGNAL GdaSet::validate-set ##### -->
 <para>
 
 </para>
 
 @gdaset: the object which received the signal.
+ Returns: 
 
 <!-- ##### ARG GdaSet:description ##### -->
 <para>
@@ -144,6 +152,7 @@
 </para>
 
 @set: 
+ error: 
 @Returns: 
 
 

Modified: trunk/doc/C/tmpl/gda-value.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-value.sgml	(original)
+++ trunk/doc/C/tmpl/gda-value.sgml	Mon Sep 15 18:30:05 2008
@@ -1,8 +1,8 @@
 <!-- ##### SECTION Title ##### -->
-Gda Value
+A single Value
 
 <!-- ##### SECTION Short_Description ##### -->
-Single value stored in a #GdaDataModel
+Assorted functions for dealing with #GValue values.
 
 <!-- ##### SECTION Long_Description ##### -->
 <para>

Modified: trunk/libgda/Makefile.am
==============================================================================
--- trunk/libgda/Makefile.am	(original)
+++ trunk/libgda/Makefile.am	Mon Sep 15 18:30:05 2008
@@ -41,6 +41,7 @@
 	gda-data-model-extra.h \
 	gda-data-model-import.h \
 	gda-data-model-iter.h \
+	gda-data-model-iter-extra.h \
 	gda-data-model-private.h \
 	gda-data-model-query.h \
 	gda-data-access-wrapper.h \

Modified: trunk/libgda/gda-connection.c
==============================================================================
--- trunk/libgda/gda-connection.c	(original)
+++ trunk/libgda/gda-connection.c	Mon Sep 15 18:30:05 2008
@@ -246,9 +246,10 @@
 	cnc->priv->auto_clear_events_list = TRUE;
 	cnc->priv->events_list = NULL;
 	cnc->priv->trans_status = NULL; /* no transaction yet */
+	cnc->priv->prepared_stmts = NULL;
 }
 
-static void prepared_stms_foreach_func (GdaStatement *gda_stmt, GdaStatement *prepared_stmt, GdaConnection *cnc);
+static void prepared_stms_foreach_func (GdaStatement *gda_stmt, GdaPStmt *prepared_stmt, GdaConnection *cnc);
 static void
 gda_connection_dispose (GObject *object)
 {
@@ -894,10 +895,11 @@
 	g_return_if_fail (GDA_IS_CONNECTION (cnc));
 	g_return_if_fail (cnc->priv);
 
-	if (! cnc->priv->is_open)
-		return;
-
 	gda_connection_lock ((GdaLockable*) cnc);
+	if (! cnc->priv->is_open) {
+		gda_connection_unlock ((GdaLockable*) cnc);
+		return;
+	}
 
 	/* get rid of prepared statements to avoid problems */
 	if (cnc->priv->prepared_stmts) {
@@ -3673,15 +3675,15 @@
  * Prepared statements handling
  */
 
-static void prepared_stms_stmt_destroyed_cb (GdaStatement *gda_stmt, GdaConnection *cnc);
+static void prepared_stmts_stmt_reset_cb (GdaStatement *gda_stmt, GdaConnection *cnc);
 static void statement_weak_notify_cb (GdaConnection *cnc, GdaStatement *stmt);
 
 static void 
-prepared_stms_stmt_destroyed_cb (GdaStatement *gda_stmt, GdaConnection *cnc)
+prepared_stmts_stmt_reset_cb (GdaStatement *gda_stmt, GdaConnection *cnc)
 {
 	gda_connection_lock ((GdaLockable*) cnc);
 
-	g_signal_handlers_disconnect_by_func (gda_stmt, G_CALLBACK (prepared_stms_stmt_destroyed_cb), cnc);
+	g_signal_handlers_disconnect_by_func (gda_stmt, G_CALLBACK (prepared_stmts_stmt_reset_cb), cnc);
 	g_object_weak_unref (G_OBJECT (gda_stmt), (GWeakNotify) statement_weak_notify_cb, cnc);
 	g_assert (cnc->priv->prepared_stmts);
 	g_hash_table_remove (cnc->priv->prepared_stmts, gda_stmt);
@@ -3690,6 +3692,13 @@
 }
 
 static void
+prepared_stms_foreach_func (GdaStatement *gda_stmt, GdaPStmt *prepared_stmt, GdaConnection *cnc)
+{
+	g_signal_handlers_disconnect_by_func (gda_stmt, G_CALLBACK (prepared_stmts_stmt_reset_cb), cnc);
+	g_object_weak_unref (G_OBJECT (gda_stmt), (GWeakNotify) statement_weak_notify_cb, cnc);
+}
+
+static void
 statement_weak_notify_cb (GdaConnection *cnc, GdaStatement *stmt)
 {
 	gda_connection_lock ((GdaLockable*) cnc);
@@ -3718,6 +3727,7 @@
 {
 	g_return_if_fail (GDA_IS_CONNECTION (cnc));
 	g_return_if_fail (cnc->priv);
+	g_return_if_fail (GDA_IS_STATEMENT (gda_stmt));
 	g_return_if_fail (GDA_IS_PSTMT (prepared_stmt));
 
 	gda_connection_lock ((GdaLockable*) cnc);
@@ -3726,10 +3736,11 @@
 		cnc->priv->prepared_stmts = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
 	g_hash_table_remove (cnc->priv->prepared_stmts, gda_stmt);
 	g_hash_table_insert (cnc->priv->prepared_stmts, gda_stmt, prepared_stmt);
+	g_object_ref (prepared_stmt);
 	
 	/* destroy the prepared statement if gda_stmt is destroyed, or changes */
 	g_object_weak_ref (G_OBJECT (gda_stmt), (GWeakNotify) statement_weak_notify_cb, cnc);
-	g_signal_connect (G_OBJECT (gda_stmt), "reset", G_CALLBACK (prepared_stms_stmt_destroyed_cb), cnc);
+	g_signal_connect (G_OBJECT (gda_stmt), "reset", G_CALLBACK (prepared_stmts_stmt_reset_cb), cnc);
 
 	gda_connection_unlock ((GdaLockable*) cnc);
 }
@@ -3777,17 +3788,10 @@
 	gda_connection_lock ((GdaLockable*) cnc);
 	g_return_if_fail (GDA_IS_CONNECTION (cnc));
 	if (gda_connection_get_prepared_statement (cnc, gda_stmt))
-		prepared_stms_stmt_destroyed_cb (gda_stmt, cnc);
+		prepared_stmts_stmt_reset_cb (gda_stmt, cnc);
 	gda_connection_unlock ((GdaLockable*) cnc);
 }
 
-static void
-prepared_stms_foreach_func (GdaStatement *gda_stmt, GdaStatement *prepared_stmt, GdaConnection *cnc)
-{
-	prepared_stms_stmt_destroyed_cb (gda_stmt, cnc);
-}
-
-
 /*
  * Provider's specific connection data management
  */

Modified: trunk/libgda/gda-data-comparator.c
==============================================================================
--- trunk/libgda/gda-data-comparator.c	(original)
+++ trunk/libgda/gda-data-comparator.c	Mon Sep 15 18:30:05 2008
@@ -478,7 +478,9 @@
 
 	/* actual differences computations : rows to insert / update */
 	onrows = gda_data_model_get_n_rows (comp->priv->old_model);
+	g_assert (onrows >= 0);
 	nnrows = gda_data_model_get_n_rows (comp->priv->new_model);
+	g_assert (nnrows >= 0);
 	rows_to_del = g_new (gboolean, onrows);
 	memset (rows_to_del, TRUE, sizeof (gboolean) * onrows);
 	for (i = 0; i < nnrows; i++) {

Modified: trunk/libgda/gda-data-model-extra.h
==============================================================================
--- trunk/libgda/gda-data-model-extra.h	(original)
+++ trunk/libgda/gda-data-model-extra.h	Mon Sep 15 18:30:05 2008
@@ -35,9 +35,6 @@
 void     gda_data_model_row_removed         (GdaDataModel *model, gint row);
 void     gda_data_model_reset               (GdaDataModel *model);
 
-gboolean gda_data_model_move_iter_at_row_default (GdaDataModel *model, GdaDataModelIter *iter, gint row);
-gboolean gda_data_model_move_iter_next_default   (GdaDataModel *model, GdaDataModelIter *iter);
-gboolean gda_data_model_move_iter_prev_default   (GdaDataModel *model, GdaDataModelIter *iter);
 G_END_DECLS
 
 #endif

Modified: trunk/libgda/gda-data-model-import.c
==============================================================================
--- trunk/libgda/gda-data-model-import.c	(original)
+++ trunk/libgda/gda-data-model-import.c	Mon Sep 15 18:30:05 2008
@@ -46,6 +46,7 @@
 #include <libgda/gda-data-model-extra.h>
 #include <libgda/gda-data-access-wrapper.h>
 #include <libgda/gda-data-model-iter.h>
+#include <libgda/gda-data-model-iter-extra.h>
 #include <libgda/gda-holder.h>
 #include <libgda/gda-set.h>
 #include <libgda/gda-data-model-private.h> /* For gda_data_model_add_data_from_xml_node() */
@@ -1811,7 +1812,7 @@
 
 	/* if there is a random access model, then use it */
 	if (imodel->priv->format == FORMAT_XML_NODE)
-		return gda_data_model_move_iter_next_default (model, iter);
+		return gda_data_model_iter_move_next_default (model, iter);
 
 	/* fetch the next row if necessary */
 	switch (imodel->priv->format) {
@@ -1907,7 +1908,7 @@
 
 	/* if there is a random access model, then use it */
 	if (imodel->priv->format == FORMAT_XML_NODE)
-		return gda_data_model_move_iter_prev_default (model, iter);
+		return gda_data_model_iter_move_prev_default (model, iter);
 
 	/* fetch the previous row if necessary */
 	switch (imodel->priv->format) {

Added: trunk/libgda/gda-data-model-iter-extra.h
==============================================================================
--- (empty file)
+++ trunk/libgda/gda-data-model-iter-extra.h	Mon Sep 15 18:30:05 2008
@@ -0,0 +1,35 @@
+/* gda-data-model-iter-extra.h
+ *
+ * Copyright (C) 2008 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GDA_DATA_MODEL_ITER_EXTRA_H_
+#define __GDA_DATA_MODEL_ITER_EXTRA_H_
+
+#include "gda-data-model-iter.h"
+
+G_BEGIN_DECLS
+
+gboolean gda_data_model_iter_move_at_row_default (GdaDataModel *model, GdaDataModelIter *iter, gint row);
+gboolean gda_data_model_iter_move_next_default   (GdaDataModel *model, GdaDataModelIter *iter);
+gboolean gda_data_model_iter_move_prev_default   (GdaDataModel *model, GdaDataModelIter *iter);
+
+G_END_DECLS
+
+#endif

Modified: trunk/libgda/gda-data-model-iter.c
==============================================================================
--- trunk/libgda/gda-data-model-iter.c	(original)
+++ trunk/libgda/gda-data-model-iter.c	Mon Sep 15 18:30:05 2008
@@ -21,6 +21,7 @@
 #include <glib/gi18n-lib.h>
 #include <string.h>
 #include "gda-data-model-iter.h"
+#include "gda-data-model-iter-extra.h"
 #include "gda-data-model.h"
 #include "gda-data-model-private.h"
 #include "gda-holder.h"
@@ -50,7 +51,7 @@
 static void model_row_updated_cb (GdaDataModel *model, gint row, GdaDataModelIter *iter);
 static void model_row_removed_cb (GdaDataModel *model, gint row, GdaDataModelIter *iter);
 
-static GError *before_holder_change_cb (GdaSet *paramlist, GdaHolder *param, const GValue *new_value);
+static GError *validate_holder_change_cb (GdaSet *paramlist, GdaHolder *param, const GValue *new_value);
 static void holder_attr_changed_cb (GdaSet *paramlist, GdaHolder *param);
 
 /* get a pointer to the parents to be able to cvalue their destructor */
@@ -59,13 +60,12 @@
 /* signals */
 enum
 {
-	ROW_TO_CHANGE,
         ROW_CHANGED,
 	END_OF_DATA,
         LAST_SIGNAL
 };
 
-static gint gda_data_model_iter_signals[LAST_SIGNAL] = { 0, 0, 0 };
+static gint gda_data_model_iter_signals[LAST_SIGNAL] = { 0, 0 };
 
 /* properties */
 enum
@@ -124,26 +124,6 @@
 	return type;
 }
 
-static gboolean
-row_to_change_accumulator (GSignalInvocationHint *ihint,
-			   GValue *return_accu,
-			   const GValue *handler_return,
-			   gpointer data)
-{
-	gboolean thisvalue;
-
-	thisvalue = g_value_get_boolean (handler_return);
-	g_value_set_boolean (return_accu, thisvalue);
-
-	return thisvalue; /* stop signal if 'thisvalue' is FALSE */
-}
-
-static gboolean
-m_row_to_change (GdaDataModelIter *iter, gint row)
-{
-	return TRUE; /* defaults allows row to change */
-}
-
 static void
 gda_data_model_iter_class_init (GdaDataModelIterClass *class)
 {
@@ -152,13 +132,6 @@
 
 	parent_class = g_type_class_peek_parent (class);
 
-	gda_data_model_iter_signals [ROW_TO_CHANGE] =
-                g_signal_new ("row-to-change",
-                              G_TYPE_FROM_CLASS (object_class),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdaDataModelIterClass, row_to_change),
-                              row_to_change_accumulator, NULL,
-                              gda_marshal_BOOLEAN__INT, G_TYPE_BOOLEAN, 1, G_TYPE_INT);
 	gda_data_model_iter_signals [ROW_CHANGED] =
                 g_signal_new ("row-changed",
                               G_TYPE_FROM_CLASS (object_class),
@@ -174,13 +147,12 @@
                               NULL, NULL,
                               g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
 
-	class->row_to_change = m_row_to_change;
 	class->row_changed = NULL;
 	class->end_of_data = NULL;
 
 	object_class->dispose = gda_data_model_iter_dispose;
 	object_class->finalize = gda_data_model_iter_finalize;
-	paramlist_class->before_holder_change = before_holder_change_cb;
+	paramlist_class->validate_holder_change = validate_holder_change_cb;
 	paramlist_class->holder_attr_changed = holder_attr_changed_cb;
 
 	/* Properties */
@@ -224,7 +196,7 @@
 	/* sync parameters with the new values in row */
 	if (iter->priv->row == row) {
 		iter->priv->keep_param_changes = TRUE;
-		gda_data_model_move_iter_at_row (iter->priv->data_model, iter, row);
+		gda_data_model_iter_move_at_row (iter, row);
 		iter->priv->keep_param_changes = FALSE;
 	}
 }
@@ -240,7 +212,7 @@
 	 * then make all the parameters invalid */
 	if (iter->priv->row == row) {
 		gda_data_model_iter_invalidate_contents (iter);
-		gda_data_model_iter_set_at_row (iter, -1);
+		gda_data_model_iter_move_at_row (iter, -1);
 	}
 	else {
 		/* shift iter's row by one to keep good numbers */
@@ -255,7 +227,7 @@
  * paramlist is an iter for, return an error if the data model could not be modified
  */
 static GError *
-before_holder_change_cb (GdaSet *paramlist, GdaHolder *param, const GValue *new_value)
+validate_holder_change_cb (GdaSet *paramlist, GdaHolder *param, const GValue *new_value)
 {
 	GdaDataModelIter *iter;
 	gint col;
@@ -290,9 +262,9 @@
 		g_signal_handler_unblock (iter->priv->data_model, iter->priv->model_changes_signals [1]);
 	}
 
-	if (!error && ((GdaSetClass *) parent_class)->before_holder_change)
+	if (!error && ((GdaSetClass *) parent_class)->validate_holder_change)
 		/* for the parent class */
-		return ((GdaSetClass *) parent_class)->before_holder_change (paramlist, param, new_value);
+		return ((GdaSetClass *) parent_class)->validate_holder_change (paramlist, param, new_value);
 
 	return error;
 }
@@ -590,36 +562,7 @@
 }
 
 /**
- * gda_data_model_iter_can_be_moved
- * @iter: a #GdaDataModelIter object
- *
- * Tells if @iter can point to another row. Note the @iter by itself will not refuse
- * a row change, but that the row change may be refused by another object using
- * @iter.
- *
- * Returns: TRUE if the row represented by @iter can be changed
- */
-gboolean
-gda_data_model_iter_can_be_moved (GdaDataModelIter *iter)
-{
-	gboolean move_ok = TRUE;
-
-	g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
-	g_return_val_if_fail (iter->priv, FALSE);
-
-	if (!gda_data_model_iter_is_valid (iter))
-		return TRUE;
-
-	/* optionally validate the row change */
-	g_signal_emit (G_OBJECT (iter),
-		       gda_data_model_iter_signals[ROW_TO_CHANGE],
-		       0, iter->priv->row, &move_ok);
-
-	return move_ok;
-}
-
-/**
- * gda_data_model_iter_set_at_row
+ * gda_data_model_iter_move_at_row
  * @iter: a #GdaDataModelIter object
  * @row: the row to set @iter to
  *
@@ -634,7 +577,7 @@
  * Returns: TRUE if no error occurred
  */
 gboolean
-gda_data_model_iter_set_at_row (GdaDataModelIter *iter, gint row)
+gda_data_model_iter_move_at_row (GdaDataModelIter *iter, gint row)
 {
 	g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
 	g_return_val_if_fail (iter->priv, FALSE);
@@ -648,11 +591,87 @@
 		}
 		return TRUE;
 	}
-	else
-		return gda_data_model_move_iter_at_row (iter->priv->data_model, iter, row);
+	else {
+		GdaDataModel *model;
+		if ((gda_data_model_iter_get_row (iter) >= 0) &&
+		    (gda_data_model_iter_get_row (iter) != row) && 
+		    ! gda_set_is_valid ((GdaSet*) iter, NULL))
+			return FALSE;
+		
+		model = iter->priv->data_model;
+		if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_at_row)
+			return (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_at_row) (model, iter, row);
+		else {
+			/* default method */
+			return gda_data_model_iter_move_at_row_default (model, iter, row);
+		}
+	}
+}
+
+static void
+set_param_attributes (GdaHolder *holder, GdaValueAttribute flags)
+{
+	if (flags & GDA_VALUE_ATTR_IS_DEFAULT)
+		gda_holder_set_value_to_default (holder);
+
+	if (flags & GDA_VALUE_ATTR_IS_NULL)
+		gda_holder_set_value (holder, NULL, NULL);
+	if (flags & GDA_VALUE_ATTR_DATA_NON_VALID)
+		gda_holder_force_invalid (holder);
 }
 
 /**
+ * gda_data_model_iter_move_at_row_default
+ */
+gboolean
+gda_data_model_iter_move_at_row_default (GdaDataModel *model, GdaDataModelIter *iter, gint row)
+{
+	/* default method */
+	GSList *list;
+	gint col;
+	GdaDataModel *test;
+	gboolean update_model;
+	
+	g_return_val_if_fail (GDA_IS_DATA_MODEL (model), FALSE);
+
+	if (! (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM))
+		return FALSE;
+
+	/* validity tests */
+	if ((row < 0) || (row >= gda_data_model_get_n_rows (model))) {
+		gda_data_model_iter_invalidate_contents (iter);
+		g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
+		return FALSE;
+	}
+		
+	g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
+	
+	g_object_get (G_OBJECT (iter), "data-model", &test, NULL);
+	g_return_val_if_fail (test == model, FALSE);
+	g_object_unref (test);
+	
+	/* actual sync. */
+	g_object_get (G_OBJECT (iter), "update-model", &update_model, NULL);
+	g_object_set (G_OBJECT (iter), "update-model", FALSE, NULL);
+	for (col = 0, list = ((GdaSet *) iter)->holders; list; col++, list = list->next) {
+		const GValue *cvalue;
+		cvalue = gda_data_model_get_value_at (model, col, row, NULL);
+		if (!cvalue || 
+		    !gda_holder_set_value ((GdaHolder*) list->data, cvalue, NULL)) {
+			g_object_set (G_OBJECT (iter), "current-row", row, 
+				      "update-model", update_model, NULL);
+			gda_data_model_iter_invalidate_contents (iter);
+			return FALSE;
+		}
+		set_param_attributes ((GdaHolder*) list->data, 
+				      gda_data_model_get_attributes_at (model, col, row));
+	}
+	g_object_set (G_OBJECT (iter), "current-row", row, "update-model", update_model, NULL);
+	return TRUE;
+}
+
+
+/**
  * gda_data_model_iter_move_next
  * @iter: a #GdaDataModelIter object
  *
@@ -671,10 +690,71 @@
 gboolean
 gda_data_model_iter_move_next (GdaDataModelIter *iter)
 {
+	GdaDataModel *model;
 	g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
 	g_return_val_if_fail (iter->priv, FALSE);
 
-	return gda_data_model_move_iter_next (iter->priv->data_model, iter);
+	if ((gda_data_model_iter_get_row (iter) >= 0) &&
+	    ! gda_set_is_valid ((GdaSet*) iter, NULL))
+		return FALSE;
+
+	model = iter->priv->data_model;
+	if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_next)
+		return (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_next) (model, iter);
+	else 
+		/* default method */
+		return gda_data_model_iter_move_next_default (model, iter);
+}
+
+/**
+ * gda_data_model_iter_move_next_default
+ */
+gboolean
+gda_data_model_iter_move_next_default (GdaDataModel *model, GdaDataModelIter *iter)
+{
+	GSList *list;
+	gint col;
+	gint row;
+	GdaDataModel *test;
+	gboolean update_model;
+	
+	/* validity tests */
+	if (! (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM))
+		return FALSE;
+	
+	g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
+	
+	g_object_get (G_OBJECT (iter), "data-model", &test, NULL);
+	g_return_val_if_fail (test == model, FALSE);
+	g_object_unref (test);
+
+	g_object_get (G_OBJECT (iter), "current-row", &row, NULL);
+	row++;
+	if (row >= gda_data_model_get_n_rows (model)) {
+		gda_data_model_iter_invalidate_contents (iter);
+		g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
+		return FALSE;
+	}
+	
+	/* actual sync. */
+	g_object_get (G_OBJECT (iter), "update-model", &update_model, NULL);
+	g_object_set (G_OBJECT (iter), "update-model", FALSE, NULL);
+	for (col = 0, list = ((GdaSet *) iter)->holders; list; col++, list = list->next) {
+		const GValue *cvalue;
+		cvalue = gda_data_model_get_value_at (model, col, row, NULL);
+		if (!cvalue || 
+		    !gda_holder_set_value ((GdaHolder *) list->data, cvalue, NULL)) {
+			g_object_set (G_OBJECT (iter), "current-row", row, 
+				      "update-model", update_model, NULL);
+			gda_data_model_iter_invalidate_contents (iter);
+			return FALSE;
+		}
+		set_param_attributes ((GdaHolder *) list->data, 
+				      gda_data_model_get_attributes_at (model, col, row));
+	}
+	g_object_set (G_OBJECT (iter), "current-row", row, 
+		      "update-model", update_model, NULL);
+	return TRUE;
 }
 
 /**
@@ -696,13 +776,76 @@
 gboolean
 gda_data_model_iter_move_prev (GdaDataModelIter *iter)
 {
+	GdaDataModel *model;
+
 	g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
 	g_return_val_if_fail (iter->priv, FALSE);
 
-	return gda_data_model_move_iter_prev (iter->priv->data_model, iter);
+	if ((gda_data_model_iter_get_row (iter) >= 0) &&
+	    ! gda_set_is_valid ((GdaSet*) iter, NULL))
+		return FALSE;
+
+	model = iter->priv->data_model;
+	if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_prev)
+		return (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_prev) (model, iter);
+	else 
+		/* default method */
+		return gda_data_model_iter_move_prev_default (model, iter);
 }
 
 /**
+ * gda_data_model_iter_move_prev_default
+ */
+gboolean
+gda_data_model_iter_move_prev_default (GdaDataModel *model, GdaDataModelIter *iter)
+{
+	GSList *list;
+	gint col;
+	gint row;
+	GdaDataModel *test;
+	gboolean update_model;
+	
+	/* validity tests */
+	if (! (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM))
+		return FALSE;
+	
+	g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
+	
+	g_object_get (G_OBJECT (iter), "data-model", &test, NULL);
+	g_return_val_if_fail (test == model, FALSE);
+	g_object_unref (test);
+
+	g_object_get (G_OBJECT (iter), "current-row", &row, NULL);
+	row--;
+	if (row < 0) {
+		gda_data_model_iter_invalidate_contents (iter);
+		g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
+		return FALSE;
+	}
+	
+	/* actual sync. */
+	g_object_get (G_OBJECT (iter), "update-model", &update_model, NULL);
+	g_object_set (G_OBJECT (iter), "update-model", FALSE, NULL);
+	for (col = 0, list = ((GdaSet *) iter)->holders; list; col++, list = list->next) {
+		const GValue *cvalue;
+		cvalue = gda_data_model_get_value_at (model, col, row, NULL);
+		if (!cvalue || 
+		    !gda_holder_set_value ((GdaHolder*) list->data, cvalue, NULL)) {
+			g_object_set (G_OBJECT (iter), "current-row", row, 
+				      "update-model", update_model, NULL);
+			gda_data_model_iter_invalidate_contents (iter);
+			return FALSE;
+		}
+		set_param_attributes ((GdaHolder*) list->data,
+				      gda_data_model_get_attributes_at (model, col, row));
+	}
+	g_object_set (G_OBJECT (iter), "current-row", row, 
+		      "update-model", update_model, NULL);
+	return TRUE;
+}
+
+
+/**
  * gda_data_model_iter_get_row
  * @iter: a #GdaDataModelIter object
  *

Modified: trunk/libgda/gda-data-model-iter.h
==============================================================================
--- trunk/libgda/gda-data-model-iter.h	(original)
+++ trunk/libgda/gda-data-model-iter.h	Mon Sep 15 18:30:05 2008
@@ -55,7 +55,6 @@
 {
 	GdaSetClass                parent_class;
 
-	gboolean                (* row_to_change)    (GdaDataModelIter *iter, gint row);
 	void                    (* row_changed)      (GdaDataModelIter *iter, gint row);
 	void                    (* end_of_data)      (GdaDataModelIter *iter);
 };
@@ -65,12 +64,11 @@
 const GValue     *gda_data_model_iter_get_value_at         (GdaDataModelIter *iter, gint col);
 const GValue     *gda_data_model_iter_get_value_for_field  (GdaDataModelIter *iter, const gchar *field_name);
 
-gboolean          gda_data_model_iter_set_at_row           (GdaDataModelIter *iter, gint row);
+gboolean          gda_data_model_iter_move_at_row          (GdaDataModelIter *iter, gint row);
 gboolean          gda_data_model_iter_move_next            (GdaDataModelIter *iter);
 gboolean          gda_data_model_iter_move_prev            (GdaDataModelIter *iter);
 gint              gda_data_model_iter_get_row              (GdaDataModelIter *iter);
 
-gboolean          gda_data_model_iter_can_be_moved         (GdaDataModelIter *iter);
 void              gda_data_model_iter_invalidate_contents  (GdaDataModelIter *iter);
 gboolean          gda_data_model_iter_is_valid             (GdaDataModelIter *iter);
 

Modified: trunk/libgda/gda-data-model-private.h
==============================================================================
--- trunk/libgda/gda-data-model-private.h	(original)
+++ trunk/libgda/gda-data-model-private.h	Mon Sep 15 18:30:05 2008
@@ -38,10 +38,6 @@
 								     const gint *rows, gint nb_rows, const gchar *name);
 gboolean                      gda_data_model_add_data_from_xml_node (GdaDataModel *model, xmlNodePtr node, GError **error);
 
-gboolean                      gda_data_model_move_iter_at_row       (GdaDataModel *model, GdaDataModelIter *iter, gint row);
-gboolean                      gda_data_model_move_iter_next         (GdaDataModel *model, GdaDataModelIter *iter);
-gboolean                      gda_data_model_move_iter_prev         (GdaDataModel *model, GdaDataModelIter *iter);
-
 G_END_DECLS
 
 #endif

Modified: trunk/libgda/gda-data-model.c
==============================================================================
--- trunk/libgda/gda-data-model.c	(original)
+++ trunk/libgda/gda-data-model.c	Mon Sep 15 18:30:05 2008
@@ -751,9 +751,9 @@
  * rows in @model.
  *
  * The row the returned #GdaDataModelIter represents is undefined. For models which can be accessed 
- * randomly the correspoding row can be set using gda_data_model_move_iter_at_row(), 
+ * randomly the correspoding row can be set using gda_data_model_iter_move_at_row(), 
  * and for models which are accessible sequentially only then the first row will be
- * fetched using gda_data_model_move_iter_next().
+ * fetched using gda_data_model_iter_move_next().
  *
  * Returns: a new #GdaDataModelIter object, or %NULL if an error occurred
  */
@@ -770,240 +770,6 @@
 }
 
 /**
- * gda_data_model_move_iter_at_row
- * @model: a #GdaDataModel object.
- * @iter: a #GdaDataModelIter object
- * @row: row number.
- *
- * Sets @iter to represent the @row row. @iter must be a valid iterator object obtained
- * using the gda_data_model_create_iter() method.
- *
- * Returns: TRUE if no error occurred
- */
-gboolean
-gda_data_model_move_iter_at_row (GdaDataModel *model, GdaDataModelIter *iter, gint row)
-{
-	g_return_val_if_fail (GDA_IS_DATA_MODEL (model), FALSE);
-
-	if ((gda_data_model_iter_get_row (iter) != row) && ! gda_data_model_iter_can_be_moved (iter))
-		return FALSE;
-
-	if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_at_row)
-		return (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_at_row) (model, iter, row);
-	else 
-		/* default method */
-		return gda_data_model_move_iter_at_row_default (model, iter, row);
-}
-
-static void set_param_attributes (GdaHolder *holder, GdaValueAttribute flags);
-
-gboolean
-gda_data_model_move_iter_at_row_default (GdaDataModel *model, GdaDataModelIter *iter, gint row)
-{
-	/* default method */
-	GSList *list;
-	gint col;
-	GdaDataModel *test;
-	gboolean update_model;
-	
-	g_return_val_if_fail (GDA_IS_DATA_MODEL (model), FALSE);
-
-	if (! (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM))
-		return FALSE;
-
-	/* validity tests */
-	if ((row < 0) || (row >= gda_data_model_get_n_rows (model))) {
-		gda_data_model_iter_invalidate_contents (iter);
-		g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
-		return FALSE;
-	}
-		
-	g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
-	
-	g_object_get (G_OBJECT (iter), "data-model", &test, NULL);
-	g_return_val_if_fail (test == model, FALSE);
-	g_object_unref (test);
-	
-	/* actual sync. */
-	g_object_get (G_OBJECT (iter), "update-model", &update_model, NULL);
-	g_object_set (G_OBJECT (iter), "update-model", FALSE, NULL);
-	for (col = 0, list = ((GdaSet *) iter)->holders; list; col++, list = list->next) {
-		const GValue *cvalue;
-		cvalue = gda_data_model_get_value_at (model, col, row, NULL);
-		if (!cvalue || 
-		    !gda_holder_set_value ((GdaHolder*) list->data, cvalue, NULL)) {
-			g_object_set (G_OBJECT (iter), "current-row", row, 
-				      "update-model", update_model, NULL);
-			gda_data_model_iter_invalidate_contents (iter);
-			return FALSE;
-		}
-		set_param_attributes ((GdaHolder*) list->data, 
-				      gda_data_model_get_attributes_at (model, col, row));
-	}
-	g_object_set (G_OBJECT (iter), "current-row", row, "update-model", update_model, NULL);
-	return TRUE;
-}
-
-static void
-set_param_attributes (GdaHolder *holder, GdaValueAttribute flags)
-{
-	if (flags & GDA_VALUE_ATTR_IS_DEFAULT)
-		gda_holder_set_value_to_default (holder);
-
-	if (flags & GDA_VALUE_ATTR_IS_NULL)
-		gda_holder_set_value (holder, NULL, NULL);
-	if (flags & GDA_VALUE_ATTR_DATA_NON_VALID)
-		gda_holder_force_invalid (holder);
-}
-
-/**
- * gda_data_model_move_iter_next
- * @model: a #GdaDataModel object.
- * @iter: a #GdaDataModelIter object
- *
- * Sets @iter to the next available row in @model. @iter must be a valid iterator object obtained
- * using the gda_data_model_create_iter() method.
- *
- * Returns: TRUE if no error occurred
- */
-gboolean
-gda_data_model_move_iter_next (GdaDataModel *model, GdaDataModelIter *iter)
-{
-	g_return_val_if_fail (GDA_IS_DATA_MODEL (model), FALSE);
-
-	if (! gda_data_model_iter_can_be_moved (iter))
-		return FALSE;
-
-	if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_next)
-		return (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_next) (model, iter);
-	else 
-		/* default method */
-		return gda_data_model_move_iter_next_default (model, iter);
-}
-
-gboolean
-gda_data_model_move_iter_next_default (GdaDataModel *model, GdaDataModelIter *iter)
-{
-	GSList *list;
-	gint col;
-	gint row;
-	GdaDataModel *test;
-	gboolean update_model;
-	
-	/* validity tests */
-	if (! (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM))
-		return FALSE;
-	
-	g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
-	
-	g_object_get (G_OBJECT (iter), "data-model", &test, NULL);
-	g_return_val_if_fail (test == model, FALSE);
-	g_object_unref (test);
-
-	g_object_get (G_OBJECT (iter), "current-row", &row, NULL);
-	row++;
-	if (row >= gda_data_model_get_n_rows (model)) {
-		gda_data_model_iter_invalidate_contents (iter);
-		g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
-		return FALSE;
-	}
-	
-	/* actual sync. */
-	g_object_get (G_OBJECT (iter), "update-model", &update_model, NULL);
-	g_object_set (G_OBJECT (iter), "update-model", FALSE, NULL);
-	for (col = 0, list = ((GdaSet *) iter)->holders; list; col++, list = list->next) {
-		const GValue *cvalue;
-		cvalue = gda_data_model_get_value_at (model, col, row, NULL);
-		if (!cvalue || 
-		    !gda_holder_set_value ((GdaHolder *) list->data, cvalue, NULL)) {
-			g_object_set (G_OBJECT (iter), "current-row", row, 
-				      "update-model", update_model, NULL);
-			gda_data_model_iter_invalidate_contents (iter);
-			return FALSE;
-		}
-		set_param_attributes ((GdaHolder *) list->data, 
-				      gda_data_model_get_attributes_at (model, col, row));
-	}
-	g_object_set (G_OBJECT (iter), "current-row", row, 
-		      "update-model", update_model, NULL);
-	return TRUE;
-}
-
-/**
- * gda_data_model_move_iter_prev
- * @model: a #GdaDataModel object.
- * @iter: a #GdaDataModelIter object
- *
- * Sets @iter to the previous available row in @model. @iter must be a valid iterator object obtained
- * using the gda_data_model_create_iter() method.
- *
- * Returns: TRUE if no error occurred
- */
-gboolean
-gda_data_model_move_iter_prev (GdaDataModel *model, GdaDataModelIter *iter)
-{
-	g_return_val_if_fail (GDA_IS_DATA_MODEL (model), FALSE);
-
-	if (! gda_data_model_iter_can_be_moved (iter))
-		return FALSE;
-
-	if (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_prev)
-		return (GDA_DATA_MODEL_GET_CLASS (model)->i_iter_prev) (model, iter);
-	else 
-		/* default method */
-		return gda_data_model_move_iter_prev_default (model, iter);
-}
-
-gboolean
-gda_data_model_move_iter_prev_default (GdaDataModel *model, GdaDataModelIter *iter)
-{
-	GSList *list;
-	gint col;
-	gint row;
-	GdaDataModel *test;
-	gboolean update_model;
-	
-	/* validity tests */
-	if (! (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM))
-		return FALSE;
-	
-	g_return_val_if_fail (GDA_IS_DATA_MODEL_ITER (iter), FALSE);
-	
-	g_object_get (G_OBJECT (iter), "data-model", &test, NULL);
-	g_return_val_if_fail (test == model, FALSE);
-	g_object_unref (test);
-
-	g_object_get (G_OBJECT (iter), "current-row", &row, NULL);
-	row--;
-	if (row < 0) {
-		gda_data_model_iter_invalidate_contents (iter);
-		g_object_set (G_OBJECT (iter), "current-row", -1, NULL);
-		return FALSE;
-	}
-	
-	/* actual sync. */
-	g_object_get (G_OBJECT (iter), "update-model", &update_model, NULL);
-	g_object_set (G_OBJECT (iter), "update-model", FALSE, NULL);
-	for (col = 0, list = ((GdaSet *) iter)->holders; list; col++, list = list->next) {
-		const GValue *cvalue;
-		cvalue = gda_data_model_get_value_at (model, col, row, NULL);
-		if (!cvalue || 
-		    !gda_holder_set_value ((GdaHolder*) list->data, cvalue, NULL)) {
-			g_object_set (G_OBJECT (iter), "current-row", row, 
-				      "update-model", update_model, NULL);
-			gda_data_model_iter_invalidate_contents (iter);
-			return FALSE;
-		}
-		set_param_attributes ((GdaHolder*) list->data,
-				      gda_data_model_get_attributes_at (model, col, row));
-	}
-	g_object_set (G_OBJECT (iter), "current-row", row, 
-		      "update-model", update_model, NULL);
-	return TRUE;
-}
-
-
-/**
  * gda_data_model_append_values
  * @model: a #GdaDataModel object.
  * @values: #GList of #GValue* representing the row to add.  The

Modified: trunk/libgda/gda-data-proxy.c
==============================================================================
--- trunk/libgda/gda-data-proxy.c	(original)
+++ trunk/libgda/gda-data-proxy.c	Mon Sep 15 18:30:05 2008
@@ -97,8 +97,8 @@
         ROW_DELETE_CHANGED,
 	SAMPLE_SIZE_CHANGED,
 	SAMPLE_CHANGED,
-	PRE_CHANGES_APPLIED,
-	POST_CHANGES_APPLIED,
+	VALIDATE_ROW_CHANGES,
+	ROW_CHANGES_APPLIED,
 	FILTER_CHANGED,
         LAST_SIGNAL
 };
@@ -513,23 +513,23 @@
 }
 
 static gboolean
-pre_changes_accumulator (GSignalInvocationHint *ihint,
-			 GValue *return_accu,
-			 const GValue *handler_return,
-			 gpointer data)
+validate_row_changes_accumulator (GSignalInvocationHint *ihint,
+				  GValue *return_accu,
+				  const GValue *handler_return,
+				  gpointer data)
 {
-        gboolean thisvalue;
+	GError *error;
 
-        thisvalue = g_value_get_boolean (handler_return);
-        g_value_set_boolean (return_accu, thisvalue);
+        error = g_value_get_pointer (handler_return); 
+        g_value_set_pointer (return_accu, error);
 
-        return thisvalue; /* stop signal if 'thisvalue' is FALSE */
+        return error ? FALSE : TRUE; /* stop signal if 'thisvalue' is FALSE */
 }
 
-static gboolean
-m_pre_changes_applied (GdaDataProxy *proxy, gint row, gint proxied_row)
+static GError *
+m_validate_row_changes (GdaDataProxy *proxy, gint row, gint proxied_row)
 {
-        return TRUE; /* defaults allows changes */
+        return NULL; /* defaults allows changes */
 }
 
 static void
@@ -561,18 +561,18 @@
                               G_STRUCT_OFFSET (GdaDataProxyClass, sample_changed),
                               NULL, NULL,
 			      gda_marshal_VOID__INT_INT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
-	gda_data_proxy_signals [PRE_CHANGES_APPLIED] =
-		g_signal_new ("pre-changes-applied",
+	gda_data_proxy_signals [VALIDATE_ROW_CHANGES] =
+		g_signal_new ("validate-row-changes",
                               G_TYPE_FROM_CLASS (object_class),
                               G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdaDataProxyClass, pre_changes_applied),
-                              pre_changes_accumulator, NULL,
-                              gda_marshal_BOOLEAN__INT_INT, G_TYPE_BOOLEAN, 2, G_TYPE_INT, G_TYPE_INT);
-	gda_data_proxy_signals [POST_CHANGES_APPLIED] =
-		g_signal_new ("post-changes-applied",
+                              G_STRUCT_OFFSET (GdaDataProxyClass, validate_row_changes),
+                              validate_row_changes_accumulator, NULL,
+                              gda_marshal_POINTER__INT_INT, G_TYPE_POINTER, 2, G_TYPE_INT, G_TYPE_INT);
+	gda_data_proxy_signals [ROW_CHANGES_APPLIED] =
+		g_signal_new ("row-changes-applied",
                               G_TYPE_FROM_CLASS (object_class),
                               G_SIGNAL_RUN_FIRST,
-                              G_STRUCT_OFFSET (GdaDataProxyClass, post_changes_applied),
+                              G_STRUCT_OFFSET (GdaDataProxyClass, row_changes_applied),
                               NULL, NULL,
 			      gda_marshal_VOID__INT_INT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
 	gda_data_proxy_signals [FILTER_CHANGED] = 
@@ -586,8 +586,8 @@
 	class->row_delete_changed = NULL;
 	class->sample_size_changed = NULL;
 	class->sample_changed = NULL;
-	class->pre_changes_applied = m_pre_changes_applied;
-	class->post_changes_applied = NULL;
+	class->validate_row_changes = m_validate_row_changes;
+	class->row_changes_applied = NULL;
 
 	/* virtual functions */
 	object_class->dispose = gda_data_proxy_dispose;
@@ -706,6 +706,10 @@
 {
 	if (proxy->priv->all_modifs) {
 		gda_data_proxy_cancel_all_changes (proxy);
+		g_assert (! proxy->priv->all_modifs);
+	}
+
+	if (proxy->priv->modify_rows) {
 		g_hash_table_destroy (proxy->priv->modify_rows);
 		proxy->priv->modify_rows = NULL;
 	}
@@ -1841,8 +1845,8 @@
 commit_row_modif (GdaDataProxy *proxy, RowModif *rm, gboolean adjust_display, GError **error)
 {
 	gboolean err = FALSE;
-	gboolean mod_ok;
 	gint proxy_row;
+	GError *lerror = NULL;
 
 	if (!rm)
 		return TRUE;
@@ -1852,22 +1856,21 @@
 
 	/*
 	 * Steps in this procedure:
-	 * -1- send the "pre-changes-applied" signal, and abort if return value is FALSE
+	 * -1- send the "validate-row-changes" signal, and abort if return value is FALSE
 	 * -2- apply desired modification (which _should_ trigger "row_{inserted,removed,updated}" signals from
 	 *     the proxied model)
 	 * -3- if no error then destroy the RowModif which has just been applied
 	 *     and refresh displayed chunks if @adjust_display is set to TRUE
-	 * -4- send the "post-changes-applied" signal
+	 * -4- send the "row-changes-applied" signal
 	 */
 	proxy_row = row_modif_to_proxy_row (proxy, rm);
 
 	/* validate the changes to this row */
         g_signal_emit (G_OBJECT (proxy),
-                       gda_data_proxy_signals[PRE_CHANGES_APPLIED],
-                       0, proxy_row, rm->model_row, &mod_ok);
-	if (!mod_ok) {
-		g_set_error (error, GDA_DATA_PROXY_ERROR, GDA_DATA_PROXY_COMMIT_CANCELLED,
-			     _("Modifications cancelled"));
+                       gda_data_proxy_signals[VALIDATE_ROW_CHANGES],
+                       0, proxy_row, rm->model_row, &lerror);
+	if (lerror) {
+		g_propagate_error (error, lerror);
 		return FALSE;
 	}
 
@@ -1983,7 +1986,7 @@
 
 				/* signal row actually changed */
 				g_signal_emit (G_OBJECT (proxy),
-					       gda_data_proxy_signals[POST_CHANGES_APPLIED],
+					       gda_data_proxy_signals[ROW_CHANGES_APPLIED],
 					       0, proxy_row, -1);
 			}
 			else if ((proxy->priv->catched_inserted_row < 0) &&
@@ -2006,7 +2009,7 @@
 	if (!err && rm) {
 		/* signal row actually changed */
 		g_signal_emit (G_OBJECT (proxy),
-			       gda_data_proxy_signals[POST_CHANGES_APPLIED],
+			       gda_data_proxy_signals[ROW_CHANGES_APPLIED],
 			       0, proxy_row, rm->model_row);
 		
 		/* get rid of the commited change; if the changes have been applied correctly, @rm should
@@ -2369,7 +2372,7 @@
 			repl_row = index;
 			if (!iter) 
 				iter = gda_data_model_create_iter (proxy->priv->model);
-			if (!gda_data_model_iter_set_at_row (iter, repl_row))
+			if (!gda_data_model_iter_move_at_row (iter, repl_row))
 				repl_row = -1;
 		}
 
@@ -2828,7 +2831,6 @@
 		if (! vcnc) {
 			g_set_error (error, GDA_DATA_PROXY_ERROR, GDA_DATA_PROXY_FILTER_ERROR,
 				     _("Could not create virtual connection"));
-			g_object_unref (vcnc);
 			proxy->priv->force_direct_mapping = FALSE;
 			goto clean_previous_filter;
 		}
@@ -3163,7 +3165,7 @@
 		else
 			return -1; /* unknown number of rows */
 	}
-	if (proxy->priv->add_null_entry)
+	if (!proxy->priv->force_direct_mapping && proxy->priv->add_null_entry)
 		nbrows += 1;
 
 	return nbrows;
@@ -3297,7 +3299,8 @@
 			else {
 				/* non existing row, return NULL */
 				g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ROW_OUT_OF_RANGE_ERROR,
-					     _("Row %d out of range (0-%d)"), proxy_row, gda_data_model_get_n_rows (model) - 1);
+					     _("Row %d out of range (0-%d)"), proxy_row, 
+					     gda_data_model_get_n_rows (model) - 1);
 				retval = NULL;
 			}
 		}
@@ -3328,7 +3331,8 @@
 			else {
 				/* non existing row, return NULL */
 				g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ROW_OUT_OF_RANGE_ERROR,
-					     _("Row %d out of range (0-%d)"), proxy_row, gda_data_model_get_n_rows (model) - 1);
+					     _("Row %d out of range (0-%d)"), proxy_row, 
+					     gda_data_model_get_n_rows (model) - 1);
 				retval = NULL;
 			}
 		}

Modified: trunk/libgda/gda-data-proxy.h
==============================================================================
--- trunk/libgda/gda-data-proxy.h	(original)
+++ trunk/libgda/gda-data-proxy.h	Mon Sep 15 18:30:05 2008
@@ -65,8 +65,8 @@
 	void                 (* sample_size_changed)  (GdaDataProxy *proxy, gint sample_size);
 	void                 (* sample_changed)       (GdaDataProxy *proxy, gint sample_start, gint sample_end);
 
-	gboolean             (* pre_changes_applied)  (GdaDataProxy *proxy, gint row, gint proxied_row);
-	void                 (* post_changes_applied) (GdaDataProxy *proxy, gint row, gint proxied_row);
+	GError              *(* validate_row_changes) (GdaDataProxy *proxy, gint row, gint proxied_row);
+	void                 (* row_changes_applied)  (GdaDataProxy *proxy, gint row, gint proxied_row);
 };
 
 GType             gda_data_proxy_get_type                 (void) G_GNUC_CONST;

Modified: trunk/libgda/gda-data-select.c
==============================================================================
--- trunk/libgda/gda-data-select.c	(original)
+++ trunk/libgda/gda-data-select.c	Mon Sep 15 18:30:05 2008
@@ -23,6 +23,7 @@
 #include <glib/gi18n-lib.h>
 #include <libgda/gda-data-model.h>
 #include <libgda/gda-data-model-iter.h>
+#include <libgda/gda-data-model-iter-extra.h>
 #include <libgda/gda-data-model-private.h>
 #include <string.h>
 #include "gda-data-select.h"
@@ -1644,7 +1645,7 @@
 	g_return_val_if_fail (CLASS (model)->fetch_next, FALSE);
 
 	if (imodel->priv->usage_flags & GDA_DATA_MODEL_ACCESS_RANDOM) 
-		return gda_data_model_move_iter_next_default (model, iter);
+		return gda_data_model_iter_move_next_default (model, iter);
 
 	g_return_val_if_fail (iter, FALSE);
         g_return_val_if_fail (imodel->priv->iter == iter, FALSE);
@@ -1693,7 +1694,7 @@
 	g_return_val_if_fail (CLASS (model)->fetch_prev, FALSE);
 
 	if (imodel->priv->usage_flags & GDA_DATA_MODEL_ACCESS_RANDOM) 
-		return gda_data_model_move_iter_prev_default (model, iter);
+		return gda_data_model_iter_move_prev_default (model, iter);
 
         g_return_val_if_fail (iter, FALSE);
         g_return_val_if_fail (imodel->priv->iter == iter, FALSE);
@@ -1743,7 +1744,7 @@
 
 	int_row = external_to_internal_row (imodel, row, NULL);
 	if (imodel->priv->usage_flags & GDA_DATA_MODEL_ACCESS_RANDOM) 
-		return gda_data_model_move_iter_at_row_default (model, iter, row);
+		return gda_data_model_iter_move_at_row_default (model, iter, row);
 
         g_return_val_if_fail (iter, FALSE);
         g_return_val_if_fail (imodel->priv->iter == iter, FALSE);

Modified: trunk/libgda/gda-holder.c
==============================================================================
--- trunk/libgda/gda-holder.c	(original)
+++ trunk/libgda/gda-holder.c	Mon Sep 15 18:30:05 2008
@@ -57,7 +57,7 @@
 {
 	CHANGED,
         SOURCE_CHANGED,
-	BEFORE_CHANGE,
+	VALIDATE_CHANGE,
         LAST_SIGNAL
 };
 
@@ -143,7 +143,7 @@
 }
 
 static gboolean
-before_change_accumulator (GSignalInvocationHint *ihint,
+validate_change_accumulator (GSignalInvocationHint *ihint,
 			   GValue *return_accu,
 			   const GValue *handler_return,
 			   gpointer data)
@@ -157,7 +157,7 @@
 }
 
 static GError *
-m_before_change (GdaHolder *holder, const GValue *new_value)
+m_validate_change (GdaHolder *holder, const GValue *new_value)
 {
 	return NULL;
 }
@@ -194,17 +194,17 @@
 	 * Return value: NULL if @holder is allowed to change its value to @new_value, or a #GError
 	 * otherwise.
 	 */
-	gda_holder_signals[BEFORE_CHANGE] =
-		g_signal_new ("before-change",
+	gda_holder_signals[VALIDATE_CHANGE] =
+		g_signal_new ("validate-change",
                               G_TYPE_FROM_CLASS (object_class),
                               G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GdaHolderClass, before_change),
-                              before_change_accumulator, NULL,
+                              G_STRUCT_OFFSET (GdaHolderClass, validate_change),
+                              validate_change_accumulator, NULL,
                               gda_marshal_POINTER__POINTER, G_TYPE_POINTER, 1, G_TYPE_POINTER);
 
         class->changed = NULL;
         class->source_changed = NULL;
-        class->before_change = m_before_change;
+        class->validate_change = m_validate_change;
 
 	/* virtual functions */
 	object_class->dispose = gda_holder_dispose;
@@ -751,7 +751,7 @@
  * Note2: if @holder can't accept the @value value, then this method returns FALSE, and @holder will be left
  * in an invalid state.
  *
- * Note3: before the change is accepted by @holder, the "before-change" signal will be emitted (the value
+ * Note3: before the change is accepted by @holder, the "validate-change" signal will be emitted (the value
  * of which can prevent the change from happening) which can be connected to to have a greater control
  * of which values @holder can have, or implement some business rules.
  *
@@ -829,7 +829,7 @@
  * Note1: if @holder can't accept the @value value, then this method returns FALSE, and @holder will be left
  * in an invalid state.
  *
- * Note2: before the change is accepted by @holder, the "before-change" signal will be emitted (the value
+ * Note2: before the change is accepted by @holder, the "validate-change" signal will be emitted (the value
  * of which can prevent the change from happening) which can be connected to to have a greater control
  * of which values @holder can have, or implement some business rules.
  *
@@ -906,7 +906,7 @@
 
 	/* check if we are allowed to change value */
 	GError *lerror = NULL;
-	g_signal_emit (holder, gda_holder_signals[BEFORE_CHANGE], 0, value, &lerror);
+	g_signal_emit (holder, gda_holder_signals[VALIDATE_CHANGE], 0, value, &lerror);
 	if (lerror) {
 		/* change refused by signal callback */
 		g_propagate_error (error, lerror);

Modified: trunk/libgda/gda-holder.h
==============================================================================
--- trunk/libgda/gda-holder.h	(original)
+++ trunk/libgda/gda-holder.h	Mon Sep 15 18:30:05 2008
@@ -56,7 +56,7 @@
 	GObjectClass               parent_class;
 	void                     (*changed)          (GdaHolder *holder);
 	void                     (*source_changed)   (GdaHolder *holder);
-	GError                  *(*before_change)    (GdaHolder *holder, const GValue *new_value);
+	GError                  *(*validate_change)  (GdaHolder *holder, const GValue *new_value);
 };
 
 GType               gda_holder_get_type                (void) G_GNUC_CONST;

Modified: trunk/libgda/gda-marshal.list
==============================================================================
--- trunk/libgda/gda-marshal.list	(original)
+++ trunk/libgda/gda-marshal.list	Mon Sep 15 18:30:05 2008
@@ -38,8 +38,8 @@
 VOID:INT,BOOLEAN
 VOID:STRING,INT
 VOID:ENUM,POINTER
-BOOLEAN:INT
-BOOLEAN:INT,INT
+POINTER:INT,INT
+POINTER:VOID
 POINTER:POINTER
 BOOLEAN:POINTER
 POINTER:OBJECT,POINTER

Modified: trunk/libgda/gda-server-operation.c
==============================================================================
--- trunk/libgda/gda-server-operation.c	(original)
+++ trunk/libgda/gda-server-operation.c	Mon Sep 15 18:30:05 2008
@@ -2106,8 +2106,7 @@
 
 	if (!xml_file) {
 		/* basic validity test */
-		list = op->priv->allnodes;
-		while (list && valid) {
+		for (list = op->priv->allnodes; list; list = list->next) {
 			Node *node;
 			
 			node = NODE (list->data);
@@ -2122,22 +2121,16 @@
 						valid = FALSE;
 						g_set_error (error, 0, 0,
 							     _("Missing required value for '%s'"), path);
+						break;
 					}
 					g_free (path);
 				}
 				else if (node->type == GDA_SERVER_OPERATION_NODE_PARAMLIST) {
-					valid = gda_set_is_valid (node->d.plist);
-					if (!valid) {
-						gchar *path;
-
-						path = node_get_complete_path (op, node);
-						g_set_error (error, 0, 0,
-							     _("Missing required value for list of parameters '%s'"), path);
-						g_free (path);
-					}
+					valid = gda_set_is_valid (node->d.plist, error);
+					if (!valid)
+						break;
 				}
 			}
-			list = list->next;
 		}
 	}
 	else {

Modified: trunk/libgda/gda-set.c
==============================================================================
--- trunk/libgda/gda-set.c	(original)
+++ trunk/libgda/gda-set.c	Mon Sep 15 18:30:05 2008
@@ -51,7 +51,7 @@
 static void set_remove_source (GdaSet *set, GdaSetSource *source);
 
 static void changed_holder_cb (GdaHolder *holder, GdaSet *dataset);
-static GError *before_change_holder_cb (GdaHolder *holder, const GValue *value, GdaSet *dataset);
+static GError *validate_change_holder_cb (GdaHolder *holder, const GValue *value, GdaSet *dataset);
 static void source_changed_holder_cb (GdaHolder *holder, GdaSet *dataset);
 static void notify_holder_cb (GdaHolder *holder, GParamSpec *pspec, GdaSet *dataset);
 
@@ -78,11 +78,12 @@
 	PUBLIC_DATA_CHANGED,
 	HOLDER_PLUGIN_CHANGED,
 	HOLDER_ATTR_CHANGED,
-	BEFORE_HOLDER_CHANGE,
+	VALIDATE_HOLDER_CHANGE,
+	VALIDATE_SET,
 	LAST_SIGNAL
 };
 
-static gint gda_set_signals[LAST_SIGNAL] = { 0, 0, 0, 0, 0 };
+static gint gda_set_signals[LAST_SIGNAL] = { 0, 0, 0, 0, 0, 0};
 
 
 /* private structure */
@@ -197,7 +198,7 @@
 }
 
 static gboolean
-before_holder_change_accumulator (GSignalInvocationHint *ihint,
+validate_accumulator (GSignalInvocationHint *ihint,
 				  GValue *return_accu,
 				  const GValue *handler_return,
 				  gpointer data)
@@ -211,7 +212,13 @@
 }
 
 static GError *
-m_before_holder_change (GdaSet *set, GdaHolder *holder, const GValue *new_value)
+m_validate_holder_change (GdaSet *set, GdaHolder *holder, const GValue *new_value)
+{
+	return NULL;
+}
+
+static GError *
+m_validate_set (GdaSet *set)
 {
 	return NULL;
 }
@@ -233,7 +240,7 @@
 			      GDA_TYPE_HOLDER);
 
 	/**
-	 * GdaSet::before-holder-change:
+	 * GdaSet::validate-holder-change:
 	 * @set: the object which received the signal
 	 * @holder: the #GdaHolder which is going to change
 	 * @new_value: the proposed new value for @holder
@@ -244,14 +251,31 @@
 	 * Return value: NULL if @holder is allowed to change its value to @new_value, or a #GError
 	 * otherwise.
 	 */
-	gda_set_signals[BEFORE_HOLDER_CHANGE] =
-		g_signal_new ("before-holder-change",
+	gda_set_signals[VALIDATE_HOLDER_CHANGE] =
+		g_signal_new ("validate-holder-change",
 			      G_TYPE_FROM_CLASS (object_class),
 			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (GdaSetClass, before_holder_change),
-			      before_holder_change_accumulator, NULL,
+			      G_STRUCT_OFFSET (GdaSetClass, validate_holder_change),
+			      validate_accumulator, NULL,
 			      gda_marshal_POINTER__OBJECT_POINTER, G_TYPE_POINTER, 2,
 			      GDA_TYPE_HOLDER, G_TYPE_POINTER);
+	/**
+	 * GdaSet::validate-set:
+	 * @set: the object which received the signal
+	 * 
+	 * Gets emitted when gda_set_is_valid() is called, use
+	 * this signal to control which combination of values @set's holder can have (for example to implement some business rules)
+	 *
+	 * Return value: NULL if @set's contents has been validated, or a #GError
+	 * otherwise.
+	 */
+	gda_set_signals[VALIDATE_SET] =
+		g_signal_new ("validate-set",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GdaSetClass, validate_set),
+			      validate_accumulator, NULL,
+			      gda_marshal_POINTER__VOID, G_TYPE_POINTER, 0);
 	gda_set_signals[HOLDER_PLUGIN_CHANGED] =
 		g_signal_new ("holder-plugin-changed",
 			      G_TYPE_FROM_CLASS (object_class),
@@ -277,7 +301,8 @@
 			      gda_marshal_VOID__VOID, G_TYPE_NONE, 0);
 
 	class->holder_changed = NULL;
-	class->before_holder_change = m_before_holder_change;
+	class->validate_holder_change = m_validate_holder_change;
+	class->validate_set = m_validate_set;
 	class->holder_plugin_changed = NULL;
 	class->holder_attr_changed = NULL;
 	class->public_data_changed = NULL;
@@ -925,7 +950,7 @@
 	g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
 					      G_CALLBACK (changed_holder_cb), set);
 	g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
-					      G_CALLBACK (before_change_holder_cb), set);
+					      G_CALLBACK (validate_change_holder_cb), set);
 	g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
 					      G_CALLBACK (source_changed_holder_cb), set);
 	g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
@@ -980,16 +1005,16 @@
 }
 
 static GError *
-before_change_holder_cb (GdaHolder *holder, const GValue *value, GdaSet *set)
+validate_change_holder_cb (GdaHolder *holder, const GValue *value, GdaSet *set)
 {
-	/* signal the holder before-change */
+	/* signal the holder validate-change */
 	GError *error = NULL;
 #ifdef GDA_DEBUG_signal
-	g_print (">> 'BEFORE_HOLDER_CHANGE' from %s\n", __FUNCTION__);
+	g_print (">> 'VALIDATE_HOLDER_CHANGE' from %s\n", __FUNCTION__);
 #endif
-	g_signal_emit (G_OBJECT (set), gda_set_signals[BEFORE_HOLDER_CHANGE], 0, holder, value, &error);
+	g_signal_emit (G_OBJECT (set), gda_set_signals[VALIDATE_HOLDER_CHANGE], 0, holder, value, &error);
 #ifdef GDA_DEBUG_signal
-	g_print ("<< 'BEFORE_HOLDER_CHANGED' from %s\n", __FUNCTION__);
+	g_print ("<< 'VALIDATE_HOLDER_CHANGED' from %s\n", __FUNCTION__);
 #endif
 	return error;
 }
@@ -1030,7 +1055,7 @@
 			g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
 				G_CALLBACK (changed_holder_cb), set);
 			g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
-				G_CALLBACK (before_change_holder_cb), set);
+				G_CALLBACK (validate_change_holder_cb), set);
 			g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
 				G_CALLBACK (source_changed_holder_cb), set);
 			g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
@@ -1332,8 +1357,8 @@
 		g_object_ref (holder);
 		g_signal_connect (G_OBJECT (holder), "changed",
 				  G_CALLBACK (changed_holder_cb), set);
-		g_signal_connect (G_OBJECT (holder), "before-change",
-				  G_CALLBACK (before_change_holder_cb), set);
+		g_signal_connect (G_OBJECT (holder), "validate-change",
+				  G_CALLBACK (validate_change_holder_cb), set);
 		g_signal_connect (G_OBJECT (holder), "source-changed",
 				  G_CALLBACK (source_changed_holder_cb), set);
 		g_signal_connect (G_OBJECT (holder), "notify",
@@ -1399,13 +1424,18 @@
 /**
  * gda_set_is_valid
  * @set: a #GdaSet object
+ * @error: a place to store validation errors, or %NULL
  *
- * Tells if all the set's holders have valid data
+ * This method tells if all @set's #GdaHolder objects are valid, and if
+ * they represent a valid combination of values, as defined by rules
+ * external to Libgda: the "validate-set" signal is emitted and if none of the signal handlers return an
+ * error, then the returned value is TRUE, otherwise the return value is FALSE as soon as a signal handler
+ * returns an error.
  *
  * Returns: TRUE if the set is valid
  */
 gboolean
-gda_set_is_valid (GdaSet *set)
+gda_set_is_valid (GdaSet *set, GError **error)
 {
 	GSList *holders;
 	gboolean retval = TRUE;
@@ -1414,9 +1444,28 @@
 	g_return_val_if_fail (set->priv, FALSE);
 
 	for (holders = set->holders; holders && retval; holders = g_slist_next (holders)) {
-		if (!gda_holder_is_valid ((GdaHolder*) holders->data)) 
+		if (!gda_holder_is_valid ((GdaHolder*) holders->data)) {
+			g_set_error (error, GDA_SET_ERROR, GDA_SET_INVALID_ERROR,
+			     _("One or more values are invalid"));
 			retval = FALSE;
+		}
 		
+	if (retval) {
+		/* signal the holder validate-set */
+		GError *lerror = NULL;
+#ifdef GDA_DEBUG_signal
+		g_print (">> 'VALIDATE_SET' from %s\n", __FUNCTION__);
+#endif
+		g_signal_emit (G_OBJECT (set), gda_set_signals[VALIDATE_SET], 0, &lerror);
+#ifdef GDA_DEBUG_signal
+		g_print ("<< 'VALIDATE_SET' from %s\n", __FUNCTION__);
+#endif
+		if (lerror) {
+			g_propagate_error (error, lerror);
+			retval = FALSE;
+		}
+	}
+
 #ifdef GDA_DEBUG_NO
 		g_print ("== HOLDER %p: valid= %d, value=%s\n", holders->data, gda_holder_is_valid (GDA_HOLDER (holders->data)),
 			 gda_holder_get_value (GDA_HOLDER (holders->data)) ?

Modified: trunk/libgda/gda-set.h
==============================================================================
--- trunk/libgda/gda-set.h	(original)
+++ trunk/libgda/gda-set.h	Mon Sep 15 18:30:05 2008
@@ -40,7 +40,8 @@
 typedef enum
 {
 	GDA_SET_XML_SPEC_ERROR,
-	GDA_SET_HOLDER_NOT_FOUND_ERROR
+	GDA_SET_HOLDER_NOT_FOUND_ERROR,
+	GDA_SET_INVALID_ERROR
 } GdaSetError;
 
 typedef enum {
@@ -117,7 +118,8 @@
 {
 	GObjectClass            parent_class;
 
-	GError               *(*before_holder_change)  (GdaSet *set, GdaHolder *holder, const GValue *new_value);
+	GError               *(*validate_holder_change)(GdaSet *set, GdaHolder *holder, const GValue *new_value);
+	GError               *(*validate_set)          (GdaSet *set);
 	void                  (*holder_changed)        (GdaSet *set, GdaHolder *holder);
 	void                  (*holder_plugin_changed) (GdaSet *set, GdaHolder *holder);
 	void                  (*holder_attr_changed)   (GdaSet *set, GdaHolder *holder);
@@ -139,7 +141,7 @@
 gboolean      gda_set_add_holder               (GdaSet *set, GdaHolder *holder);
 void          gda_set_remove_holder            (GdaSet *set, GdaHolder *holder);
 void          gda_set_merge_with_set           (GdaSet *set, GdaSet *set_to_merge);
-gboolean      gda_set_is_valid                 (GdaSet *set);
+gboolean      gda_set_is_valid                 (GdaSet *set, GError **error);
 
 /* public data lookup functions */
 GdaSetNode   *gda_set_get_node                 (GdaSet *set, GdaHolder *param);

Modified: trunk/libgda/gda-value.c
==============================================================================
--- trunk/libgda/gda-value.c	(original)
+++ trunk/libgda/gda-value.c	Mon Sep 15 18:30:05 2008
@@ -1882,7 +1882,9 @@
 		const GdaBinary *binary1 = gda_value_get_binary (value1);
 		const GdaBinary *binary2 = gda_value_get_binary (value2);
 		if (binary1 && binary2 && (binary1->binary_length == binary2->binary_length))
-			return bcmp (binary1->data, binary2->data, binary1->binary_length) ;
+			return bcmp (binary1->data, binary2->data, binary1->binary_length);
+		else
+			return 1;
 	}
 
 	else if (type == GDA_TYPE_BLOB) {
@@ -1893,6 +1895,7 @@
 				return bcmp (((GdaBinary *)blob1)->data, ((GdaBinary *)blob2)->data, 
 					     ((GdaBinary *)blob1)->binary_length);
 		}
+		return 1;
 	}
 
 	else if (type == G_TYPE_DATE) {
@@ -1902,6 +1905,7 @@
 		d2 = (GDate *) g_value_get_boxed (value2);
 		if (d1 && d2)
 			return g_date_compare (d1, d2);
+		return 1;
 	}
 
 	else if (type == GDA_TYPE_GEOMETRIC_POINT) {
@@ -1910,6 +1914,7 @@
 		p2 = gda_value_get_geometric_point (value2);
 		if (p1 && p2)
 			return bcmp (p1, p2, sizeof (GdaGeometricPoint));
+		return 1;
 	}
 
 	else if (type == G_TYPE_OBJECT) {
@@ -1935,6 +1940,7 @@
 		num2 = gda_value_get_numeric (value2);
                 if (num1 && num2)
 			return strcmp (num1->number, num2->number);
+		return 1;
 	}
 	
 	else if (type == G_TYPE_STRING)	{
@@ -1943,6 +1949,7 @@
 		str2 = g_value_get_string (value2);
 		if (str1 && str2)
 			return strcmp (str1, str2);
+		return 1;
 	}
 	
 	else if (type == GDA_TYPE_TIME) {
@@ -1951,6 +1958,7 @@
 		t2 = gda_value_get_time (value2);
 		if (t1 && t2)
 			return bcmp (t1, t2, sizeof (GdaTime));
+		return 1;
 	}
 
 	else if (type == GDA_TYPE_TIMESTAMP) {
@@ -1959,6 +1967,7 @@
 		ts2 = gda_value_get_timestamp (value2);
 		if (ts1 && ts2)
 			return bcmp (ts1, ts2, sizeof (GdaTimestamp));
+		return 1;
 	}
 
 	else if ((type == G_TYPE_INT) ||

Modified: trunk/libgda/sqlite/sqlite-src/PragmasPatch
==============================================================================
--- trunk/libgda/sqlite/sqlite-src/PragmasPatch	(original)
+++ trunk/libgda/sqlite/sqlite-src/PragmasPatch	Mon Sep 15 18:30:05 2008
@@ -1,6 +1,6 @@
---- sqlite3.c.orig	2008-08-28 21:24:44.000000000 +0200
-+++ sqlite3.c	2008-08-28 21:24:51.000000000 +0200
-@@ -65313,6 +65313,48 @@
+--- sqlite3.c.orig	2008-08-30 18:23:34.000000000 +0200
++++ sqlite3.c	2008-09-15 12:03:08.000000000 +0200
+@@ -66756,6 +66756,48 @@
  
  #ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
    /*

Modified: trunk/libgda/sqlite/sqlite-src/sqlite3.c
==============================================================================
--- trunk/libgda/sqlite/sqlite-src/sqlite3.c	(original)
+++ trunk/libgda/sqlite/sqlite-src/sqlite3.c	Mon Sep 15 18:30:05 2008
@@ -1,6 +1,6 @@
 /******************************************************************************
 ** This file is an amalgamation of many separate C source files from SQLite
-** version 3.6.1.  By combining all the individual C code files into this 
+** version 3.6.2.  By combining all the individual C code files into this 
 ** single large file, the entire code can be compiled as a one translation
 ** unit.  This allows many compilers to do optimizations that would not be
 ** possible if the files were compiled separately.  Performance improvements
@@ -11,13 +11,13 @@
 ** programs, you need this file and the "sqlite3.h" header file that defines
 ** the programming interface to the SQLite library.  (If you do not have 
 ** the "sqlite3.h" header file at hand, you will find a copy in the first
-** 6279 lines past this header comment.)  Additional code files may be
+** 6312 lines past this header comment.)  Additional code files may be
 ** needed if you want a wrapper to interface SQLite with your choice of
 ** programming language.  The code for the "sqlite3" command-line shell
 ** is also in a separate file.  This file contains only code for the core
 ** SQLite library.
 **
-** This amalgamation was generated on 2008-08-05 21:36:42 UTC.
+** This amalgamation was generated on 2008-08-30 16:23:32 UTC.
 */
 #define SQLITE_CORE 1
 #define SQLITE_AMALGAMATION 1
@@ -41,7 +41,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.752 2008/08/04 20:13:27 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.764 2008/08/29 18:42:30 rse Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -425,6 +425,9 @@
 #  define _XOPEN_SOURCE 500  /* Needed to enable pthread recursive mutexes */
 #endif
 
+/*
+** The TCL headers are only needed when compiling the TCL bindings.
+*/
 #if defined(SQLITE_TCL) || defined(TCLSH)
 # include <tcl.h>
 #endif
@@ -474,7 +477,7 @@
 ** the version number) and changes its name to "sqlite3.h" as
 ** part of the build process.
 **
-** @(#) $Id: sqlite.h.in,v 1.387 2008/08/05 17:53:23 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.394 2008/08/25 21:23:02 drh Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -496,6 +499,31 @@
 #endif
 
 /*
+** Add the ability to mark interfaces as deprecated.
+*/
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+  /* GCC added the deprecated attribute in version 3.1 */
+  #define SQLITE_DEPRECATED __attribute__ ((deprecated))
+#elif defined(_MSC_VER)
+  #define SQLITE_DEPRECATED __declspec(deprecated)
+#else
+  #define SQLITE_DEPRECATED
+#endif
+
+/*
+** Add the ability to mark interfaces as experimental.
+*/
+#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+  /* I can confirm that it does not work on version 4.1.0... */
+  /* First appears in GCC docs for version 4.3.0 */
+  #define SQLITE_EXPERIMENTAL __attribute__ ((warning ("is experimental")))
+#elif defined(_MSC_VER)
+  #define SQLITE_EXPERIMENTAL __declspec(deprecated("was declared experimental"))
+#else
+  #define SQLITE_EXPERIMENTAL
+#endif
+
+/*
 ** Ensure these symbols were not defined by some previous header file.
 */
 #ifdef SQLITE_VERSION
@@ -535,8 +563,8 @@
 **          with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z
 **          are the major version, minor version, and release number.
 */
-#define SQLITE_VERSION         "3.6.1"
-#define SQLITE_VERSION_NUMBER  3006001
+#define SQLITE_VERSION         "3.6.2"
+#define SQLITE_VERSION_NUMBER  3006002
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
@@ -935,6 +963,7 @@
 #define SQLITE_IOERR_NOMEM             (SQLITE_IOERR | (12<<8))
 #define SQLITE_IOERR_ACCESS            (SQLITE_IOERR | (13<<8))
 #define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8))
+#define SQLITE_IOERR_LOCK              (SQLITE_IOERR | (15<<8))
 
 /*
 ** CAPI3REF: Flags For File Open Operations {H10230} <H11120> <H12700>
@@ -957,6 +986,7 @@
 #define SQLITE_OPEN_SUBJOURNAL       0x00002000
 #define SQLITE_OPEN_MASTER_JOURNAL   0x00004000
 #define SQLITE_OPEN_NOMUTEX          0x00008000
+#define SQLITE_OPEN_FULLMUTEX        0x00010000
 
 /*
 ** CAPI3REF: Device Characteristics {H10240} <H11120>
@@ -1410,7 +1440,7 @@
 ** If the option is unknown or SQLite is unable to set the option
 ** then this routine returns a non-zero [error code].
 */
-SQLITE_API int sqlite3_config(int, ...);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
 
 /*
 ** CAPI3REF: Configure database connections  {H10180} <S20000>
@@ -1431,7 +1461,7 @@
 ** New verbs are likely to be added in future releases of SQLite.
 ** Additional arguments depend on the verb.
 */
-SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_config(sqlite3*, int op, ...);
 
 /*
 ** CAPI3REF: Memory Allocation Routines {H10155} <S20120>
@@ -2520,6 +2550,11 @@
 ** previous call.  Disable the authorizer by installing a NULL callback.
 ** The authorizer is disabled by default.
 **
+** When [sqlite3_prepare_v2()] is used to prepare a statement, the
+** statement might be reprepared during [sqlite3_step()] due to a 
+** schema change.  Hence, the application should ensure that the
+** correct authorizer callback remains in place during the [sqlite3_step()].
+**
 ** Note that the authorizer callback is invoked only during
 ** [sqlite3_prepare()] or its variants.  Authorization is not
 ** performed during statement evaluation in [sqlite3_step()].
@@ -2530,11 +2565,11 @@
 **          authorizer callback with database connection D.
 **
 ** {H12502} The authorizer callback is invoked as SQL statements are
-**          being compiled.
+**          being parseed and compiled.
 **
 ** {H12503} If the authorizer callback returns any value other than
 **          [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY], then
-**          the [sqlite3_prepare_v2()] or equivalent call that caused
+**          the application interface call that caused
 **          the authorizer callback to run shall fail with an
 **          [SQLITE_ERROR] error code and an appropriate error message.
 **
@@ -2542,7 +2577,7 @@
 **          described is processed normally.
 **
 ** {H12505} When the authorizer callback returns [SQLITE_DENY], the
-**          [sqlite3_prepare_v2()] or equivalent call that caused the
+**          application interface call that caused the
 **          authorizer callback to run shall fail
 **          with an [SQLITE_ERROR] error code and an error message
 **          explaining that access is denied.
@@ -2616,21 +2651,21 @@
 ** INVARIANTS:
 **
 ** {H12551} The second parameter to an
-**          [sqlite3_set_authorizer | authorizer callback] is always an integer
+**          [sqlite3_set_authorizer | authorizer callback] shall be an integer
 **          [SQLITE_COPY | authorizer code] that specifies what action
 **          is being authorized.
 **
 ** {H12552} The 3rd and 4th parameters to the
 **          [sqlite3_set_authorizer | authorization callback]
-**          will be parameters or NULL depending on which
+**          shall be parameters or NULL depending on which
 **          [SQLITE_COPY | authorizer code] is used as the second parameter.
 **
 ** {H12553} The 5th parameter to the
-**          [sqlite3_set_authorizer | authorizer callback] is the name
+**          [sqlite3_set_authorizer | authorizer callback] shall be the name
 **          of the database (example: "main", "temp", etc.) if applicable.
 **
 ** {H12554} The 6th parameter to the
-**          [sqlite3_set_authorizer | authorizer callback] is the name
+**          [sqlite3_set_authorizer | authorizer callback] shall be the name
 **          of the inner-most trigger or view that is responsible for
 **          the access attempt or NULL if this access attempt is directly from
 **          top-level SQL code.
@@ -2690,16 +2725,17 @@
 **
 ** INVARIANTS:
 **
-** {H12281} The callback function registered by [sqlite3_trace()] is
+** {H12281} The callback function registered by [sqlite3_trace()] 
+**          shall be invoked
 **          whenever an SQL statement first begins to execute and
 **          whenever a trigger subprogram first begins to run.
 **
-** {H12282} Each call to [sqlite3_trace()] overrides the previously
+** {H12282} Each call to [sqlite3_trace()] shall override the previously
 **          registered trace callback.
 **
-** {H12283} A NULL trace callback disables tracing.
+** {H12283} A NULL trace callback shall disable tracing.
 **
-** {H12284} The first argument to the trace callback is a copy of
+** {H12284} The first argument to the trace callback shall be a copy of
 **          the pointer which was the 3rd argument to [sqlite3_trace()].
 **
 ** {H12285} The second argument to the trace callback is a
@@ -2723,8 +2759,8 @@
 **          of the number of nanoseconds of wall-clock time required to
 **          run the SQL statement from start to finish.
 */
-SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
-SQLITE_API void *sqlite3_profile(sqlite3*,
+SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
+SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
    void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
 
 /*
@@ -2893,11 +2929,11 @@
 **          reading and writing if possible, or for reading only if the
 **          file is write protected by the operating system.
 **
-** {H12713} If the G parameter to [sqlite3_open(v2(F,D,G,V)] omits the
+** {H12713} If the G parameter to [sqlite3_open_v2(F,D,G,V)] omits the
 **          bit value [SQLITE_OPEN_CREATE] and the database does not
 **          previously exist, an error is returned.
 **
-** {H12714} If the G parameter to [sqlite3_open(v2(F,D,G,V)] contains the
+** {H12714} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
 **          bit value [SQLITE_OPEN_CREATE] and the database does not
 **          previously exist, then an attempt is made to create and
 **          initialize the database.
@@ -4391,12 +4427,12 @@
 ** the use of these functions.  To help encourage people to avoid
 ** using these functions, we are not going to tell you want they do.
 */
-SQLITE_API int sqlite3_aggregate_count(sqlite3_context*);
-SQLITE_API int sqlite3_expired(sqlite3_stmt*);
-SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
-SQLITE_API int sqlite3_global_recover(void);
-SQLITE_API void sqlite3_thread_cleanup(void);
-SQLITE_API int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
+SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
 
 /*
 ** CAPI3REF: Obtaining SQL Function Parameter Values {H15100} <S20200>
@@ -5821,7 +5857,7 @@
 ** This interface is experimental and is subject to change or
 ** removal in future releases of SQLite.
 */
-SQLITE_API int sqlite3_create_module(
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module(
   sqlite3 *db,               /* SQLite connection to register module with */
   const char *zName,         /* Name of the module */
   const sqlite3_module *,    /* Methods for the module */
@@ -5836,7 +5872,7 @@
 ** except that it allows a destructor function to be specified. It is
 ** even more experimental than the rest of the virtual tables API.
 */
-SQLITE_API int sqlite3_create_module_v2(
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
   sqlite3 *db,               /* SQLite connection to register module with */
   const char *zName,         /* Name of the module */
   const sqlite3_module *,    /* Methods for the module */
@@ -5908,7 +5944,7 @@
 ** This interface is experimental and is subject to change or
 ** removal in future releases of SQLite.
 */
-SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
 
 /*
 ** CAPI3REF: Overload A Function For A Virtual Table {H18300} <S20400>
@@ -5929,7 +5965,7 @@
 ** This API should be considered part of the virtual table interface,
 ** which is experimental and subject to change.
 */
-SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
 
 /*
 ** The interface to the virtual-table mechanism defined above (back up
@@ -6586,7 +6622,7 @@
 **
 ** See also: [sqlite3_db_status()]
 */
-SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
 
 /*
 ** CAPI3REF: Database Connection Status {H17201} <S60200>
@@ -6606,7 +6642,7 @@
 **
 ** See also: [sqlite3_status()].
 */
-SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
 
 /*
 ** CAPI3REF: Status Parameters {H17250} <H17200>
@@ -6987,12 +7023,11 @@
 #define TK_ILLEGAL                        144
 #define TK_SPACE                          145
 #define TK_UNCLOSED_STRING                146
-#define TK_COMMENT                        147
-#define TK_FUNCTION                       148
-#define TK_COLUMN                         149
-#define TK_AGG_FUNCTION                   150
-#define TK_AGG_COLUMN                     151
-#define TK_CONST_FUNC                     152
+#define TK_FUNCTION                       147
+#define TK_COLUMN                         148
+#define TK_AGG_FUNCTION                   149
+#define TK_AGG_COLUMN                     150
+#define TK_CONST_FUNC                     151
 
 /************** End of parse.h ***********************************************/
 /************** Continuing where we left off in sqliteInt.h ******************/
@@ -7133,7 +7168,7 @@
 typedef UINT16_TYPE u16;           /* 2-byte unsigned integer */
 typedef INT16_TYPE i16;            /* 2-byte signed integer */
 typedef UINT8_TYPE u8;             /* 1-byte unsigned integer */
-typedef UINT8_TYPE i8;             /* 1-byte signed integer */
+typedef INT8_TYPE i8;              /* 1-byte signed integer */
 
 /*
 ** Macros to determine whether the machine is big or little endian,
@@ -7222,6 +7257,7 @@
 typedef struct ExprList ExprList;
 typedef struct FKey FKey;
 typedef struct FuncDef FuncDef;
+typedef struct FuncDefHash FuncDefHash;
 typedef struct IdList IdList;
 typedef struct Index Index;
 typedef struct KeyClass KeyClass;
@@ -7240,6 +7276,8 @@
 typedef struct TriggerStack TriggerStack;
 typedef struct TriggerStep TriggerStep;
 typedef struct Trigger Trigger;
+typedef struct UnpackedRecord UnpackedRecord;
+typedef struct Walker Walker;
 typedef struct WhereInfo WhereInfo;
 typedef struct WhereLevel WhereLevel;
 
@@ -7265,7 +7303,7 @@
 ** subsystem.  See comments in the source code for a detailed description
 ** of what each interface routine does.
 **
-** @(#) $Id: btree.h,v 1.102 2008/07/11 21:02:54 drh Exp $
+** @(#) $Id: btree.h,v 1.103 2008/08/13 19:11:48 drh Exp $
 */
 #ifndef _BTREE_H_
 #define _BTREE_H_
@@ -7374,8 +7412,6 @@
 SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
 SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);
 
-struct UnpackedRecord;  /* Forward declaration.  Definition in vdbeaux.c. */
-
 SQLITE_PRIVATE int sqlite3BtreeCursor(
   Btree*,                              /* BTree containing table to open */
   int iTable,                          /* Index of root page */
@@ -7389,11 +7425,17 @@
 SQLITE_PRIVATE int sqlite3BtreeMoveto(
   BtCursor*,
   const void *pKey,
-  struct UnpackedRecord *pUnKey,
   i64 nKey,
   int bias,
   int *pRes
 );
+SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
+  BtCursor*,
+  UnpackedRecord *pUnKey,
+  i64 intKey,
+  int bias,
+  int *pRes
+);
 SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
 SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*);
 SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
@@ -7491,7 +7533,7 @@
 ** or VDBE.  The VDBE implements an abstract machine that runs a
 ** simple program to access and modify the underlying database.
 **
-** $Id: vdbe.h,v 1.135 2008/08/01 20:10:08 drh Exp $
+** $Id: vdbe.h,v 1.138 2008/08/20 22:06:48 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -7509,7 +7551,6 @@
 */
 typedef struct VdbeFunc VdbeFunc;
 typedef struct Mem Mem;
-typedef struct UnpackedRecord UnpackedRecord;
 
 /*
 ** A single instruction of the virtual machine has an opcode
@@ -7844,7 +7885,8 @@
 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
 SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int);
 #endif
-SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int);
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,
+                                        UnpackedRecord*,int);
 SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
 SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
 
@@ -7880,7 +7922,7 @@
 ** subsystem.  The page cache subsystem reads and writes a file a page
 ** at a time and provides a journal for rollback.
 **
-** @(#) $Id: pager.h,v 1.77 2008/07/16 18:17:56 danielk1977 Exp $
+** @(#) $Id: pager.h,v 1.81 2008/08/27 15:16:34 danielk1977 Exp $
 */
 
 #ifndef _PAGER_H_
@@ -7937,9 +7979,8 @@
 ** See source code comments for a detailed description of the following
 ** routines:
 */
-SQLITE_PRIVATE int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int);
+SQLITE_PRIVATE int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, void(*)(DbPage*), int,int,int);
 SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler);
-SQLITE_PRIVATE void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int));
 SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int));
 SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u16*);
 SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
@@ -7963,7 +8004,7 @@
 SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager*);
 SQLITE_PRIVATE int sqlite3PagerStmtRollback(Pager*);
 SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage*);
-SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*);
+SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage*);
 SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
 SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int);
 SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*);
@@ -7980,10 +8021,7 @@
 SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
 SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
 SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager);
-
-#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
-SQLITE_PRIVATE   int sqlite3PagerReleaseMemory(int);
-#endif
+SQLITE_PRIVATE void sqlite3PagerAlwaysRollback(Pager *pPager);
 
 #ifdef SQLITE_HAS_CODEC
 SQLITE_PRIVATE   void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
@@ -8012,6 +8050,177 @@
 
 /************** End of pager.h ***********************************************/
 /************** Continuing where we left off in sqliteInt.h ******************/
+/************** Include pcache.h in the middle of sqliteInt.h ****************/
+/************** Begin file pcache.h ******************************************/
+/*
+** 2008 August 05
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the sqlite page cache
+** subsystem. 
+**
+** @(#) $Id: pcache.h,v 1.9 2008/08/29 09:10:03 danielk1977 Exp $
+*/
+
+#ifndef _PCACHE_H_
+
+typedef struct PgHdr PgHdr;
+typedef struct PCache PCache;
+
+/*
+** Every page in the cache is controlled by an instance of the following
+** structure.
+*/
+struct PgHdr {
+  void *pData;                   /* Content of this page */
+  void *pExtra;                  /* Extra content */
+  PgHdr *pDirty;                 /* Transient list of dirty pages */
+  Pgno pgno;                     /* Page number for this page */
+  Pager *pPager;                 /* The pager this page is part of */
+#ifdef SQLITE_CHECK_PAGES
+  u32 pageHash;                  /* Hash of page content */
+#endif
+  u16 flags;                     /* PGHDR flags defined below */
+  /**********************************************************************
+  ** Elements above are public.  All that follows is private to pcache.c
+  ** and should not be accessed by other modules.
+  */
+  i16 nRef;                      /* Number of users of this page */
+  PCache *pCache;                /* Cache that owns this page */
+  void *apSave[2];               /* Journal entries for in-memory databases */
+  /**********************************************************************
+  ** Elements above are accessible at any time by the owner of the cache
+  ** without the need for a mutex.  The elements that follow can only be
+  ** accessed while holding the SQLITE_MUTEX_STATIC_LRU mutex.
+  */
+  PgHdr *pNextHash, *pPrevHash;  /* Hash collision chain for PgHdr.pgno */
+  PgHdr *pNext, *pPrev;          /* List of clean or dirty pages */
+  PgHdr *pNextLru, *pPrevLru;    /* Part of global LRU list */
+};
+
+/* Bit values for PgHdr.flags */
+#define PGHDR_IN_JOURNAL        0x001  /* Page is in rollback journal */
+#define PGHDR_IN_STMTJRNL       0x002  /* Page is in the statement journal */
+#define PGHDR_DIRTY             0x004  /* Page has changed */
+#define PGHDR_NEED_SYNC         0x008  /* Peed to fsync this page */
+#define PGHDR_NEED_READ         0x020  /* Content is unread */
+#define PGHDR_IS_INIT           0x040  /* pData is initialized */
+#define PGHDR_REUSE_UNLIKELY    0x080  /* Hint: Reuse is unlikely */
+#define PGHDR_DONT_WRITE        0x100  /* Do not write content to disk */
+
+/* Initialize and shutdown the page cache subsystem */
+SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
+SQLITE_PRIVATE void sqlite3PcacheShutdown(void);
+
+/* Page cache buffer management:
+** These routines implement SQLITE_CONFIG_PAGECACHE.
+*/
+SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n);
+SQLITE_PRIVATE void *sqlite3PCacheMalloc(int sz);
+SQLITE_PRIVATE void sqlite3PCacheFree(void*);
+
+/* Create a new pager cache.
+** Under memory stress, invoke xStress to try to make pages clean.
+** Only clean and unpinned pages can be reclaimed.
+*/
+SQLITE_PRIVATE void sqlite3PcacheOpen(
+  int szPage,                    /* Size of every page */
+  int szExtra,                   /* Extra space associated with each page */
+  int bPurgeable,                /* True if pages are on backing store */
+  void (*xDestroy)(PgHdr *),     /* Called to destroy a page */
+  int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */
+  void *pStress,                 /* Argument to xStress */
+  PCache *pToInit                /* Preallocated space for the PCache */
+);
+
+/* Modify the page-size after the cache has been created. */
+SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *, int);
+
+/* Return the size in bytes of a PCache object.  Used to preallocate
+** storage space.
+*/
+SQLITE_PRIVATE int sqlite3PcacheSize(void);
+
+/* One release per successful fetch.  Page is pinned until released.
+** Reference counted. 
+*/
+SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**);
+SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*);
+
+SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*);         /* Remove page from cache */
+SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*);    /* Make sure page is marked dirty */
+SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*);    /* Mark a single page as clean */
+SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*);    /* Mark all dirty list pages as clean */
+
+/* Change a page number.  Used by incr-vacuum. */
+SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno);
+
+/* Remove all pages with pgno>x.  Reset the cache if x==0 */
+SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x);
+
+/* Routines used to implement transactions on memory-only databases. */
+SQLITE_PRIVATE int sqlite3PcachePreserve(PgHdr*, int);    /* Preserve current page content */
+SQLITE_PRIVATE void sqlite3PcacheCommit(PCache*, int);    /* Drop preserved copy */
+SQLITE_PRIVATE void sqlite3PcacheRollback(PCache*, int);  /* Rollback to preserved copy */
+
+/* Get a list of all dirty pages in the cache, sorted by page number */
+SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*);
+
+/* Reset and close the cache object */
+SQLITE_PRIVATE void sqlite3PcacheClose(PCache*);
+
+/* Set flags on all pages in the page cache */
+SQLITE_PRIVATE void sqlite3PcacheSetFlags(PCache*, int andMask, int orMask);
+
+/* Assert flags settings on all pages.  Debugging only */
+SQLITE_PRIVATE void sqlite3PcacheAssertFlags(PCache*, int trueMask, int falseMask);
+
+/* Return true if the number of dirty pages is 0 or 1 */
+SQLITE_PRIVATE int sqlite3PcacheZeroOrOneDirtyPages(PCache*);
+
+/* Discard the contents of the cache */
+SQLITE_PRIVATE int sqlite3PcacheClear(PCache*);
+
+/* Return the total number of outstanding page references */
+SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*);
+
+/* Increment the reference count of an existing page */
+SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*);
+
+/* Return the total number of pages stored in the cache */
+SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*);
+
+/* Iterate through all pages currently stored in the cache. This interface
+** is only available if SQLITE_CHECK_PAGES is defined when the library is 
+** built.
+*/
+SQLITE_PRIVATE void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *));
+
+/* Set and get the suggested cache-size for the specified pager-cache.
+**
+** If no global maximum is configured, then the system attempts to limit
+** the total number of pages cached by purgeable pager-caches to the sum
+** of the suggested cache-sizes.
+*/
+SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *);
+SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int);
+
+/* Try to return memory used by the pcache module to the main memory heap */
+SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int);
+
+SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*);
+
+#endif /* _PCACHE_H_ */
+
+/************** End of pcache.h **********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
 
 /************** Include os.h in the middle of sqliteInt.h ********************/
 /************** Begin file os.h **********************************************/
@@ -8477,7 +8686,7 @@
   u8 bMalloced;           /* True if pStart obtained from sqlite3_malloc() */
   int nOut;               /* Number of buffers currently checked out */
   int mxOut;              /* Highwater mark for nOut */
-  LookasideSlot *pFree;   /* List if available buffers */
+  LookasideSlot *pFree;   /* List of available buffers */
   void *pStart;           /* First byte of available memory space */
   void *pEnd;             /* First byte past end of available space */
 };
@@ -8486,6 +8695,16 @@
 };
 
 /*
+** A hash table for function definitions.
+**
+** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
+** Collisions are on the FuncDef.pHash chain.
+*/
+struct FuncDefHash {
+  FuncDef *a[23];       /* Hash table for functions */
+};
+
+/*
 ** Each database is an instance of the following structure.
 **
 ** The sqlite.lastRowid records the last insert rowid generated by an
@@ -8581,7 +8800,7 @@
   sqlite3_vtab **aVTrans;       /* Virtual tables with open transactions */
   int nVTrans;                  /* Allocated size of aVTrans */
 #endif
-  Hash aFunc;                   /* All functions that can be in SQL exprs */
+  FuncDefHash aFunc;            /* Hash table of connection functions */
   Hash aCollSeq;                /* All collating sequences */
   BusyHandler busyHandler;      /* Busy callback */
   int busyTimeout;              /* Busy handler timeout, in msec */
@@ -8646,7 +8865,7 @@
 ** points to a linked list of these structures.
 */
 struct FuncDef {
-  i16 nArg;            /* Number of arguments.  -1 means unlimited */
+  i8 nArg;             /* Number of arguments.  -1 means unlimited */
   u8 iPrefEnc;         /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */
   u8 needCollSeq;      /* True if sqlite3GetFuncCollSeq() might be called */
   u8 flags;            /* Some combination of SQLITE_FUNC_* */
@@ -8655,10 +8874,51 @@
   void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */
   void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */
   void (*xFinalize)(sqlite3_context*);                /* Aggregate finializer */
-  char zName[1];       /* SQL name of the function.  MUST BE LAST */
+  char *zName;         /* SQL name of the function. */
+  FuncDef *pHash;      /* Next with a different name but the same hash */
 };
 
 /*
+** Possible values for FuncDef.flags
+*/
+#define SQLITE_FUNC_LIKE     0x01  /* Candidate for the LIKE optimization */
+#define SQLITE_FUNC_CASE     0x02  /* Case-sensitive LIKE-type function */
+#define SQLITE_FUNC_EPHEM    0x04  /* Ephermeral.  Delete with VDBE */
+
+/*
+** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
+** used to create the initializers for the FuncDef structures.
+**
+**   FUNCTION(zName, nArg, iArg, bNC, xFunc)
+**     Used to create a scalar function definition of a function zName 
+**     implemented by C function xFunc that accepts nArg arguments. The
+**     value passed as iArg is cast to a (void*) and made available
+**     as the user-data (sqlite3_user_data()) for the function. If 
+**     argument bNC is true, then the FuncDef.needCollate flag is set.
+**
+**   AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
+**     Used to create an aggregate function definition implemented by
+**     the C functions xStep and xFinal. The first four parameters
+**     are interpreted in the same way as the first 4 parameters to
+**     FUNCTION().
+**
+**   LIKEFUNC(zName, nArg, pArg, flags)
+**     Used to create a scalar function definition of a function zName 
+**     that accepts nArg arguments and is implemented by a call to C 
+**     function likeFunc. Argument pArg is cast to a (void *) and made
+**     available as the function user-data (sqlite3_user_data()). The
+**     FuncDef.flags variable is set to the value passed as the flags
+**     parameter.
+*/
+#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
+  {nArg, SQLITE_UTF8, bNC, 0, SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName}
+#define LIKEFUNC(zName, nArg, arg, flags) \
+  {nArg, SQLITE_UTF8, 0, flags, (void *)arg, 0, likeFunc, 0, 0, #zName}
+#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
+  {nArg, SQLITE_UTF8, nc, 0, SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal, #zName}
+
+
+/*
 ** Each SQLite module (virtual table definition) is defined by an
 ** instance of the following structure, stored in the sqlite3.aModule
 ** hash table.
@@ -8671,13 +8931,6 @@
 };
 
 /*
-** Possible values for FuncDef.flags
-*/
-#define SQLITE_FUNC_LIKE   0x01  /* Candidate for the LIKE optimization */
-#define SQLITE_FUNC_CASE   0x02  /* Case-sensitive LIKE-type function */
-#define SQLITE_FUNC_EPHEM  0x04  /* Ephermeral.  Delete with VDBE */
-
-/*
 ** information about each column of an SQL table is held in an instance
 ** of this structure.
 */
@@ -8725,7 +8978,7 @@
 };
 
 /*
-** Allowed values of CollSeq flags:
+** Allowed values of CollSeq.type:
 */
 #define SQLITE_COLL_BINARY  1  /* The default memcmp() collating sequence */
 #define SQLITE_COLL_NOCASE  2  /* The built-in NOCASE collating sequence */
@@ -8743,7 +8996,7 @@
 **
 ** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and
 ** 't' for SQLITE_AFF_TEXT.  But we can save a little space and improve
-** the speed a little by number the values consecutively.  
+** the speed a little by numbering the values consecutively.  
 **
 ** But rather than start with 0 or 1, we begin with 'a'.  That way,
 ** when multiple affinity types are concatenated into a string and
@@ -8789,14 +9042,14 @@
 ** that the datatype of the PRIMARY KEY must be INTEGER for this field to
 ** be set.  An INTEGER PRIMARY KEY is used as the rowid for each row of
 ** the table.  If a table has no INTEGER PRIMARY KEY, then a random rowid
-** is generated for each row of the table.  Table.hasPrimKey is true if
+** is generated for each row of the table.  TF_HasPrimaryKey is set if
 ** the table has any PRIMARY KEY, INTEGER or otherwise.
 **
 ** Table.tnum is the page number for the root BTree page of the table in the
 ** database file.  If Table.iDb is the index of the database table backend
 ** in sqlite.aDb[].  0 is for the main database and 1 is for the file that
-** holds temporary tables and indices.  If Table.isEphem
-** is true, then the table is stored in a file that is automatically deleted
+** holds temporary tables and indices.  If TF_Ephemeral is set
+** then the table is stored in a file that is automatically deleted
 ** when the VDBE cursor to the table is closed.  In this case Table.tnum 
 ** refers VDBE cursor number that holds the table open, not to the root
 ** page number.  Transient tables are used to hold the results of a
@@ -8804,47 +9057,54 @@
 ** of a SELECT statement.
 */
 struct Table {
-  sqlite3 *db;     /* Associated database connection.  Might be NULL. */
-  char *zName;     /* Name of the table */
-  int nCol;        /* Number of columns in this table */
-  Column *aCol;    /* Information about each column */
-  int iPKey;       /* If not less then 0, use aCol[iPKey] as the primary key */
-  Index *pIndex;   /* List of SQL indexes on this table. */
-  int tnum;        /* Root BTree node for this table (see note above) */
-  Select *pSelect; /* NULL for tables.  Points to definition if a view. */
-  int nRef;          /* Number of pointers to this Table */
-  Trigger *pTrigger; /* List of SQL triggers on this table */
-  FKey *pFKey;       /* Linked list of all foreign keys in this table */
-  char *zColAff;     /* String defining the affinity of each column */
+  sqlite3 *db;         /* Associated database connection.  Might be NULL. */
+  char *zName;         /* Name of the table or view */
+  int iPKey;           /* If not negative, use aCol[iPKey] as the primary key */
+  int nCol;            /* Number of columns in this table */
+  Column *aCol;        /* Information about each column */
+  Index *pIndex;       /* List of SQL indexes on this table. */
+  int tnum;            /* Root BTree node for this table (see note above) */
+  Select *pSelect;     /* NULL for tables.  Points to definition if a view. */
+  u16 nRef;            /* Number of pointers to this Table */
+  u8 tabFlags;         /* Mask of TF_* values */
+  u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */
+  Trigger *pTrigger;   /* List of SQL triggers on this table */
+  FKey *pFKey;         /* Linked list of all foreign keys in this table */
+  char *zColAff;       /* String defining the affinity of each column */
 #ifndef SQLITE_OMIT_CHECK
-  Expr *pCheck;      /* The AND of all CHECK constraints */
+  Expr *pCheck;        /* The AND of all CHECK constraints */
 #endif
 #ifndef SQLITE_OMIT_ALTERTABLE
-  int addColOffset;  /* Offset in CREATE TABLE statement to add a new column */
+  int addColOffset;    /* Offset in CREATE TABLE stmt to add a new column */
 #endif
-  u8 readOnly;     /* True if this table should not be written by the user */
-  u8 isEphem;      /* True if created using OP_OpenEphermeral */
-  u8 hasPrimKey;   /* True if there exists a primary key */
-  u8 keyConf;      /* What to do in case of uniqueness conflict on iPKey */
-  u8 autoInc;      /* True if the integer primary key is autoincrement */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  u8 isVirtual;             /* True if this is a virtual table */
-  u8 isCommit;              /* True once the CREATE TABLE has been committed */
-  Module *pMod;             /* Pointer to the implementation of the module */
-  sqlite3_vtab *pVtab;      /* Pointer to the module instance */
-  int nModuleArg;           /* Number of arguments to the module */
-  char **azModuleArg;       /* Text of all module args. [0] is module name */
+  Module *pMod;        /* Pointer to the implementation of the module */
+  sqlite3_vtab *pVtab; /* Pointer to the module instance */
+  int nModuleArg;      /* Number of arguments to the module */
+  char **azModuleArg;  /* Text of all module args. [0] is module name */
 #endif
-  Schema *pSchema;          /* Schema that contains this table */
+  Schema *pSchema;     /* Schema that contains this table */
 };
 
 /*
+** Allowed values for Tabe.tabFlags.
+*/
+#define TF_Readonly        0x01    /* Read-only system table */
+#define TF_Ephemeral       0x02    /* An emphermal table */
+#define TF_HasPrimaryKey   0x04    /* Table has a primary key */
+#define TF_Autoincrement   0x08    /* Integer primary key is autoincrement */
+#define TF_Virtual         0x10    /* Is a virtual table */
+#define TF_NeedMetadata    0x20    /* aCol[].zType and aCol[].pColl missing */
+
+
+
+/*
 ** Test to see whether or not a table is a virtual table.  This is
 ** done as a macro so that it will be optimized out when virtual
 ** table support is omitted from the build.
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-#  define IsVirtual(X)      ((X)->isVirtual)
+#  define IsVirtual(X)      (((X)->tabFlags & TF_Virtual)!=0)
 #  define IsHiddenColumn(X) ((X)->isHidden)
 #else
 #  define IsVirtual(X)      0
@@ -8936,22 +9196,46 @@
 ** An instance of the following structure is passed as the first
 ** argument to sqlite3VdbeKeyCompare and is used to control the 
 ** comparison of the two index keys.
-**
-** If the KeyInfo.incrKey value is true and the comparison would
-** otherwise be equal, then return a result as if the second key
-** were larger.
 */
 struct KeyInfo {
   sqlite3 *db;        /* The database connection */
   u8 enc;             /* Text encoding - one of the TEXT_Utf* values */
-  u8 incrKey;         /* Increase 2nd key by epsilon before comparison */
-  u8 prefixIsEqual;   /* Treat a prefix as equal */
-  int nField;         /* Number of entries in aColl[] */
+  u16 nField;         /* Number of entries in aColl[] */
   u8 *aSortOrder;     /* If defined an aSortOrder[i] is true, sort DESC */
   CollSeq *aColl[1];  /* Collating sequence for each term of the key */
 };
 
 /*
+** An instance of the following structure holds information about a
+** single index record that has already been parsed out into individual
+** values.
+**
+** A record is an object that contains one or more fields of data.
+** Records are used to store the content of a table row and to store
+** the key of an index.  A blob encoding of a record is created by
+** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
+** OP_Column opcode.
+**
+** This structure holds a record that has already been disassembled
+** into its constitutent fields.
+*/
+struct UnpackedRecord {
+  KeyInfo *pKeyInfo;  /* Collation and sort-order information */
+  u16 nField;         /* Number of entries in apMem[] */
+  u16 flags;          /* Boolean settings.  UNPACKED_... below */
+  Mem *aMem;          /* Values */
+};
+
+/*
+** Allowed values of UnpackedRecord.flags
+*/
+#define UNPACKED_NEED_FREE     0x0001  /* Memory is from sqlite3Malloc() */
+#define UNPACKED_NEED_DESTROY  0x0002  /* apMem[]s should all be destroyed */
+#define UNPACKED_IGNORE_ROWID  0x0004  /* Ignore trailing rowid on key1 */
+#define UNPACKED_INCRKEY       0x0008  /* Make this key an epsilon larger */
+#define UNPACKED_PREFIX_MATCH  0x0010  /* A prefix match is considered OK */
+
+/*
 ** Each SQL index is represented in memory by an
 ** instance of the following structure.
 **
@@ -9114,7 +9398,7 @@
   int iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
   Select *pSelect;       /* When the expression is a sub-select.  Also the
                          ** right side of "<expr> IN (<select>)" */
-  Table *pTab;           /* Table for OP_Column expressions. */
+  Table *pTab;           /* Table for TK_COLUMN expressions. */
 #if SQLITE_MAX_EXPR_DEPTH>0
   int nHeight;           /* Height of the tree headed by this node */
 #endif
@@ -9160,8 +9444,9 @@
     Expr *pExpr;           /* The list of expressions */
     char *zName;           /* Token associated with this expression */
     u8 sortOrder;          /* 1 for DESC or 0 for ASC */
-    u8 isAgg;              /* True if this is an aggregate like count(*) */
     u8 done;               /* A flag to indicate when processing is finished */
+    u16 iCol;              /* For ORDER BY, column number in result set */
+    u16 iAlias;            /* Index into Parse.aAlias[] for zName */
   } *a;                  /* One entry for each expression */
 };
 
@@ -9375,12 +9660,8 @@
 struct Select {
   ExprList *pEList;      /* The fields of the result */
   u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
-  u8 isDistinct;         /* True if the DISTINCT keyword is present */
-  u8 isResolved;         /* True once sqlite3SelectResolve() has run. */
-  u8 isAgg;              /* True if this is an aggregate query */
-  u8 usesEphm;           /* True if uses an OpenEphemeral opcode */
-  u8 disallowOrderBy;    /* Do not allow an ORDER BY to be attached if TRUE */
   char affinity;         /* MakeRecord with this affinity for SRT_Set */
+  u16 selFlags;          /* Various SF_* values */
   SrcList *pSrc;         /* The FROM clause */
   Expr *pWhere;          /* The WHERE clause */
   ExprList *pGroupBy;    /* The GROUP BY clause */
@@ -9396,7 +9677,20 @@
 };
 
 /*
-** The results of a select can be distributed in several ways.
+** Allowed values for Select.selFlags.  The "SF" prefix stands for
+** "Select Flag".
+*/
+#define SF_Distinct        0x0001  /* Output should be DISTINCT */
+#define SF_Resolved        0x0002  /* Identifiers have been resolved */
+#define SF_Aggregate       0x0004  /* Contains aggregate functions */
+#define SF_UsesEphemeral   0x0008  /* Uses the OpenEphemeral opcode */
+#define SF_Expanded        0x0010  /* sqlite3SelectExpand() called on this */
+#define SF_HasTypeInfo     0x0020  /* FROM subqueries have Table metadata */
+
+
+/*
+** The results of a select can be distributed in several ways.  The
+** "SRT" prefix means "SELECT Result Type".
 */
 #define SRT_Union        1  /* Store result as keys in an index */
 #define SRT_Except       2  /* Remove result from a UNION index */
@@ -9406,7 +9700,7 @@
 /* The ORDER BY clause is ignored for all of the above */
 #define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard)
 
-#define SRT_Callback     5  /* Invoke a callback with each row of result */
+#define SRT_Output       5  /* Output each row of result */
 #define SRT_Mem          6  /* Store result in a memory cell */
 #define SRT_Set          7  /* Store results as keys in an index */
 #define SRT_Table        8  /* Store result as data with an automatic rowid */
@@ -9489,6 +9783,8 @@
   int nVarExpr;        /* Number of used slots in apVarExpr[] */
   int nVarExprAlloc;   /* Number of allocated slots in apVarExpr[] */
   Expr **apVarExpr;    /* Pointers to :aaa and $aaaa wildcard expressions */
+  int nAlias;          /* Number of aliased result set columns */
+  int *aAlias;         /* Register used to hold aliased result */
   u8 explain;          /* True if the EXPLAIN flag is found on the query */
   Token sErrToken;     /* The token at which the error occurred */
   Token sNameToken;    /* Token with unqualified schema object name */
@@ -9730,11 +10026,40 @@
   int isInit;                       /* True after initialization has finished */
   int isMallocInit;                 /* True after malloc is initialized */
   sqlite3_mutex *pInitMutex;        /* Mutex used by sqlite3_initialize() */
+  int nRefInitMutex;                /* Number of users of pInitMutex */
   int nSmall;                       /* alloc size threshold used by mem6.c */
   int mxParserStack;                /* maximum depth of the parser stack */
 };
 
 /*
+** Context pointer passed down through the tree-walk.
+*/
+struct Walker {
+  int (*xExprCallback)(Walker*, Expr*);     /* Callback for expressions */
+  int (*xSelectCallback)(Walker*,Select*);  /* Callback for SELECTs */
+  Parse *pParse;                            /* Parser context.  */
+  union {                                   /* Extra data for callback */
+    NameContext *pNC;                          /* Naming context */
+    int i;                                     /* Integer value */
+  } u;
+};
+
+/* Forward declarations */
+SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
+SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
+SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
+SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
+SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
+
+/*
+** Return code from the parse-tree walking primitives and their
+** callbacks.
+*/
+#define WRC_Continue    0
+#define WRC_Prune       1
+#define WRC_Abort       2
+
+/*
 ** Assuming zIn points to the first byte of a UTF-8 character,
 ** advance zIn to point to the first byte of the next UTF-8 character.
 */
@@ -9797,7 +10122,6 @@
 SQLITE_PRIVATE   int sqlite3MutexEnd(void);
 #endif
 
-SQLITE_PRIVATE void sqlite3StatusReset(void);
 SQLITE_PRIVATE int sqlite3StatusValue(int);
 SQLITE_PRIVATE void sqlite3StatusAdd(int, int);
 SQLITE_PRIVATE void sqlite3StatusSet(int, int);
@@ -9842,7 +10166,7 @@
 SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3*, int);
 SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
 SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*);
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
 SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
 SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
 SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*);
@@ -9885,7 +10209,7 @@
 SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
                         Token*, int, int);
 SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
-SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*);
+SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
 SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                          Expr*,ExprList*,int,Expr*,Expr*);
 SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
@@ -9920,7 +10244,6 @@
 SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*);
 SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
 SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*);
-SQLITE_PRIVATE int sqlite3ExprResolveNames(NameContext *, Expr *);
 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
 SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
@@ -9952,9 +10275,12 @@
 SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*);
 SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*);
 SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*);
+SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
 SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
 SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*);
-SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(sqlite3*);
+SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void);
+SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void);
+SQLITE_PRIVATE int sqlite3GetBuiltinFunction(const char *, int, FuncDef **);
 #ifdef SQLITE_DEBUG
 SQLITE_PRIVATE   int sqlite3SafetyOn(sqlite3*);
 SQLITE_PRIVATE   int sqlite3SafetyOff(sqlite3*);
@@ -9965,7 +10291,7 @@
 SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
 SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
 SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
-SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Select*, Expr*, int);
+SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
 
 #ifndef SQLITE_OMIT_TRIGGER
 SQLITE_PRIVATE   void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
@@ -10018,7 +10344,6 @@
 SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
 SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
 SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*);
-SQLITE_API char *sqlite3_snprintf(int,char*,const char*,...);
 SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
 SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *, int);
 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
@@ -10092,6 +10417,7 @@
 #ifndef SQLITE_AMALGAMATION
 SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
 SQLITE_PRIVATE struct Sqlite3Config sqlite3Config;
+SQLITE_PRIVATE FuncDefHash sqlite3GlobalFunctions;
 #endif
 SQLITE_PRIVATE void sqlite3RootPageMoved(Db*, int, int);
 SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
@@ -10101,7 +10427,10 @@
 SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
 SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
 SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *, Expr *, int);
-SQLITE_PRIVATE int sqlite3SelectResolve(Parse *, Select *, NameContext *);
+SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
+SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int);
 SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
 SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
@@ -10223,9 +10552,11 @@
 #if SQLITE_MAX_EXPR_DEPTH>0
 SQLITE_PRIVATE   void sqlite3ExprSetHeight(Parse *pParse, Expr *p);
 SQLITE_PRIVATE   int sqlite3SelectExprHeight(Select *);
+SQLITE_PRIVATE   int sqlite3ExprCheckHeight(Parse*, int);
 #else
   #define sqlite3ExprSetHeight(x,y)
   #define sqlite3SelectExprHeight(x) 0
+  #define sqlite3ExprCheckHeight(x,y)
 #endif
 
 SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*);
@@ -10271,7 +10602,7 @@
 **
 ** This file contains definitions of global variables and contants.
 **
-** $Id: global.c,v 1.4 2008/07/28 19:34:53 drh Exp $
+** $Id: global.c,v 1.6 2008/08/21 20:21:35 drh Exp $
 */
 
 
@@ -10334,6 +10665,14 @@
    /* Other fields all default to zero */
 };
 
+
+/*
+** Hash table for global functions - functions common to all
+** database connections.  After initialization, this table is
+** read-only.
+*/
+SQLITE_PRIVATE FuncDefHash sqlite3GlobalFunctions;
+
 /************** End of global.c **********************************************/
 /************** Begin file status.c ******************************************/
 /*
@@ -10351,7 +10690,7 @@
 ** This module implements the sqlite3_status() interface and related
 ** functionality.
 **
-** $Id: status.c,v 1.7 2008/08/05 17:53:23 drh Exp $
+** $Id: status.c,v 1.8 2008/08/12 15:21:12 drh Exp $
 */
 
 /*
@@ -10364,14 +10703,6 @@
 
 
 /*
-** Reset the status records.  This routine is called by
-** sqlite3_initialize().
-*/
-SQLITE_PRIVATE void sqlite3StatusReset(void){
-  memset(&sqlite3Stat, 0, sizeof(sqlite3Stat));
-}
-
-/*
 ** Return the current value of a status parameter.
 */
 SQLITE_PRIVATE int sqlite3StatusValue(int op){
@@ -10467,7 +10798,7 @@
 ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
 ** All other code has file scope.
 **
-** $Id: date.c,v 1.87 2008/07/28 19:34:53 drh Exp $
+** $Id: date.c,v 1.88 2008/08/21 20:21:35 drh Exp $
 **
 ** SQLite processes all times and dates as Julian Day numbers.  The
 ** dates and times are stored as the number of days since noon
@@ -11500,44 +11831,28 @@
 ** functions.  This should be the only routine in this file with
 ** external linkage.
 */
-SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
+SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
+  static FuncDef aDateTimeFuncs[] = {
 #ifndef SQLITE_OMIT_DATETIME_FUNCS
-  static const struct {
-     char *zName;
-     int nArg;
-     void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
-  } aFuncs[] = {
-    { "julianday", -1, juliandayFunc   },
-    { "date",      -1, dateFunc        },
-    { "time",      -1, timeFunc        },
-    { "datetime",  -1, datetimeFunc    },
-    { "strftime",  -1, strftimeFunc    },
-    { "current_time",       0, ctimeFunc      },
-    { "current_timestamp",  0, ctimestampFunc },
-    { "current_date",       0, cdateFunc      },
-  };
-  int i;
-
-  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
-    sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
-        SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
-  }
+    FUNCTION(julianday,        -1, 0, 0, juliandayFunc ),
+    FUNCTION(date,             -1, 0, 0, dateFunc      ),
+    FUNCTION(time,             -1, 0, 0, timeFunc      ),
+    FUNCTION(datetime,         -1, 0, 0, datetimeFunc  ),
+    FUNCTION(strftime,         -1, 0, 0, strftimeFunc  ),
+    FUNCTION(current_time,      0, 0, 0, ctimeFunc     ),
+    FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
+    FUNCTION(current_date,      0, 0, 0, cdateFunc     ),
 #else
-  static const struct {
-     char *zName;
-     char *zFormat;
-  } aFuncs[] = {
-    { "current_time", "%H:%M:%S" },
-    { "current_date", "%Y-%m-%d" },
-    { "current_timestamp", "%Y-%m-%d %H:%M:%S" }
+    FUNCTION(current_time,      0, "%H:%M:%S",          0, currentTimeFunc),
+    FUNCTION(current_timestamp, 0, "%Y-%m-%d",          0, currentTimeFunc),
+    FUNCTION(current_date,      0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
+#endif
   };
   int i;
 
-  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
-    sqlite3CreateFunc(db, aFuncs[i].zName, 0, SQLITE_UTF8, 
-        aFuncs[i].zFormat, currentTimeFunc, 0, 0);
+  for(i=0; i<ArraySize(aDateTimeFuncs); i++){
+    sqlite3FuncDefInsert(&sqlite3GlobalFunctions, &aDateTimeFuncs[i]);
   }
-#endif
 }
 
 /************** End of date.c ************************************************/
@@ -12064,7 +12379,7 @@
 ** This file contains implementations of the low-level memory allocation
 ** routines specified in the sqlite3_mem_methods object.
 **
-** $Id: mem2.c,v 1.37 2008/07/25 08:49:00 danielk1977 Exp $
+** $Id: mem2.c,v 1.38 2008/08/12 15:04:59 danielk1977 Exp $
 */
 
 /*
@@ -12080,7 +12395,7 @@
   extern int backtrace(void**,int);
   extern void backtrace_symbols_fd(void*const*,int,int);
 #else
-# define backtrace(A,B) 0
+# define backtrace(A,B) 1
 # define backtrace_symbols_fd(A,B,C)
 #endif
 
@@ -15323,7 +15638,7 @@
 **
 ** Memory allocation functions used throughout sqlite.
 **
-** $Id: malloc.c,v 1.34 2008/08/05 17:53:23 drh Exp $
+** $Id: malloc.c,v 1.37 2008/08/29 17:56:13 danielk1977 Exp $
 */
 
 /*
@@ -15370,8 +15685,11 @@
 */
 SQLITE_API int sqlite3_release_memory(int n){
 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  int nRet = sqlite3VdbeReleaseMemory(n);
-  nRet += sqlite3PagerReleaseMemory(n-nRet);
+  int nRet = 0;
+#if 0
+  nRet += sqlite3VdbeReleaseMemory(n);
+#endif
+  nRet += sqlite3PcacheReleaseMemory(n-nRet);
   return nRet;
 #else
   return SQLITE_OK;
@@ -15617,10 +15935,10 @@
     }else{
       int i;
       i = mem0.aScratchFree[--mem0.nScratchFree];
-      sqlite3_mutex_leave(mem0.mutex);
       i *= sqlite3Config.szScratch;
       sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
       sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
+      sqlite3_mutex_leave(mem0.mutex);
       p = (void*)&((char*)sqlite3Config.pScratch)[i];
     }
   }
@@ -15690,6 +16008,7 @@
 ** and that memory is of the right size and is not completely
 ** consumed.  Otherwise, failover to sqlite3Malloc().
 */
+#if 0
 SQLITE_PRIVATE void *sqlite3PageMalloc(int n){
   void *p;
   assert( n>0 );
@@ -15770,6 +16089,7 @@
     }
   }
 }
+#endif
 
 /*
 ** TRUE if p is a lookaside memory allocation from db
@@ -16058,7 +16378,7 @@
 ** an historical reference.  Most of the "enhancements" have been backed
 ** out so that the functionality is now the same as standard printf().
 **
-** $Id: printf.c,v 1.93 2008/07/28 19:34:53 drh Exp $
+** $Id: printf.c,v 1.94 2008/08/22 14:08:36 drh Exp $
 **
 **************************************************************************
 **
@@ -16298,7 +16618,6 @@
   const et_info *infop;      /* Pointer to the appropriate info structure */
   char buf[etBUFSIZE];       /* Conversion buffer */
   char prefix;               /* Prefix character.  "+" or "-" or " " or '\0'. */
-  etByte errorflag = 0;      /* True if an error is encountered */
   etByte xtype;              /* Conversion paradigm */
   char *zExtra;              /* Extra memory used for etTCLESCAPE conversions */
 #ifndef SQLITE_OMIT_FLOATING_POINT
@@ -16322,7 +16641,6 @@
       if( c==0 ) break;
     }
     if( (c=(*++fmt))==0 ){
-      errorflag = 1;
       sqlite3StrAccumAppend(pAccum, "%", 1);
       break;
     }
@@ -17125,7 +17443,7 @@
 ** This file contains routines used to translate between UTF-8, 
 ** UTF-16, UTF-16BE, and UTF-16LE.
 **
-** $Id: utf.c,v 1.63 2008/07/29 11:25:14 danielk1977 Exp $
+** $Id: utf.c,v 1.65 2008/08/12 15:04:59 danielk1977 Exp $
 **
 ** Notes on UTF-8:
 **
@@ -17167,7 +17485,7 @@
 ** 6000 lines long) it was split up into several smaller files and
 ** this header information was factored out.
 **
-** $Id: vdbeInt.h,v 1.153 2008/08/02 03:50:39 drh Exp $
+** $Id: vdbeInt.h,v 1.154 2008/08/13 19:11:48 drh Exp $
 */
 #ifndef _VDBEINT_H_
 #define _VDBEINT_H_
@@ -17223,13 +17541,11 @@
   Bool deferredMoveto;  /* A call to sqlite3BtreeMoveto() is needed */
   Bool isTable;         /* True if a table requiring integer keys */
   Bool isIndex;         /* True if an index containing keys only - no data */
-  u8 bogusIncrKey;      /* Something for pIncrKey to point to if pKeyInfo==0 */
   i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
   Btree *pBt;           /* Separate file holding temporary table */
   int nData;            /* Number of bytes in pData */
   char *pData;          /* Data for a NEW or OLD pseudo-table */
   i64 iKey;             /* Key for the NEW or OLD pseudo-table row */
-  u8 *pIncrKey;         /* Pointer to pKeyInfo->incrKey */
   KeyInfo *pKeyInfo;    /* Info about index keys needed by index cursors */
   int nField;           /* Number of fields in the header */
   i64 seqCount;         /* Sequence counter */
@@ -17494,28 +17810,6 @@
 };
 
 /*
-** An instance of the following structure holds information about a
-** single index record that has already been parsed out into individual
-** values.
-**
-** A record is an object that contains one or more fields of data.
-** Records are used to store the content of a table row and to store
-** the key of an index.  A blob encoding of a record is created by
-** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
-** OP_Column opcode.
-**
-** This structure holds a record that has already been disassembled
-** into its constitutent fields.
-*/
-struct UnpackedRecord {
-  KeyInfo *pKeyInfo;  /* Collation and sort-order information */
-  u16 nField;         /* Number of entries in apMem[] */
-  u8 needFree;        /* True if memory obtained from sqlite3_malloc() */
-  u8 needDestroy;     /* True if apMem[]s should be destroyed on close */
-  Mem *aMem;          /* Values */
-};
-
-/*
 ** The following are allowed values for Vdbe.magic
 */
 #define VDBE_MAGIC_INIT     0x26bceaa5    /* Building a VDBE program */
@@ -17539,10 +17833,9 @@
 SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
 
 int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
-SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord *,int,const unsigned char*,int*);
+SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord*,int*);
 SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
 SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
-SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8*, int, int*);
 SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
 SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
 SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
@@ -17966,7 +18259,7 @@
 SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
   unsigned char *zOut = zIn;
   unsigned char *zStart = zIn;
-  unsigned char *zTerm;
+  unsigned char *zTerm = &zIn[strlen((char *)zIn)];
   u32 c;
 
   while( zIn[0] ){
@@ -18043,7 +18336,7 @@
 ** It checks that the primitives for serializing and deserializing
 ** characters in each encoding are inverses of each other.
 */
-SQLITE_PRIVATE void sqlite3UtfSelfTest(){
+SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
   unsigned int i, t;
   unsigned char zBuf[20];
   unsigned char *z;
@@ -19637,7 +19930,7 @@
 **
 ** This file contains code that is specific to OS/2.
 **
-** $Id: os_os2.c,v 1.55 2008/07/29 18:49:29 pweilbacher Exp $
+** $Id: os_os2.c,v 1.56 2008/08/22 13:47:57 pweilbacher Exp $
 */
 
 
@@ -20602,7 +20895,7 @@
   int *pOutFlags                /* Status return flags */
 ){
   HFILE h;
-  ULONG ulFileAttribute = 0;
+  ULONG ulFileAttribute = FILE_NORMAL;
   ULONG ulOpenFlags = 0;
   ULONG ulOpenMode = 0;
   os2File *pFile = (os2File*)id;
@@ -20627,7 +20920,6 @@
 
   OSTRACE2( "OPEN want %d\n", flags );
 
-  /*ulOpenMode = flags & SQLITE_OPEN_READWRITE ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY;*/
   if( flags & SQLITE_OPEN_READWRITE ){
     ulOpenMode |= OPEN_ACCESS_READWRITE;
     OSTRACE1( "OPEN read/write\n" );
@@ -20636,7 +20928,6 @@
     OSTRACE1( "OPEN read only\n" );
   }
 
-  /*ulOpenFlags = flags & SQLITE_OPEN_CREATE ? OPEN_ACTION_CREATE_IF_NEW : OPEN_ACTION_FAIL_IF_NEW;*/
   if( flags & SQLITE_OPEN_CREATE ){
     ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
     OSTRACE1( "OPEN open new/create\n" );
@@ -20645,7 +20936,6 @@
     OSTRACE1( "OPEN open existing\n" );
   }
 
-  /*ulOpenMode |= flags & SQLITE_OPEN_MAIN_DB ? OPEN_SHARE_DENYNONE : OPEN_SHARE_DENYWRITE;*/
   if( flags & SQLITE_OPEN_MAIN_DB ){
     ulOpenMode |= OPEN_SHARE_DENYNONE;
     OSTRACE1( "OPEN share read/write\n" );
@@ -20654,18 +20944,15 @@
     OSTRACE1( "OPEN share read only\n" );
   }
 
-  if( flags & (SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TEMP_JOURNAL
-               | SQLITE_OPEN_SUBJOURNAL) ){
+  if( flags & SQLITE_OPEN_DELETEONCLOSE ){
     char pathUtf8[CCHMAXPATH];
 #ifdef NDEBUG /* when debugging we want to make sure it is deleted */
     ulFileAttribute = FILE_HIDDEN;
 #endif
-    ulFileAttribute = FILE_NORMAL;
     os2FullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 );
     pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
     OSTRACE1( "OPEN hidden/delete on close file attributes\n" );
   }else{
-    ulFileAttribute = FILE_ARCHIVED | FILE_NORMAL;
     pFile->pathToDel = NULL;
     OSTRACE1( "OPEN normal file attribute\n" );
   }
@@ -20990,7 +21277,7 @@
 **
 ** This file contains code that is specific to Unix systems.
 **
-** $Id: os_unix.c,v 1.195 2008/07/30 17:28:04 drh Exp $
+** $Id: os_unix.c,v 1.198 2008/08/22 18:41:37 aswift Exp $
 */
 #if SQLITE_OS_UNIX              /* This file is used on unix only */
 
@@ -21088,6 +21375,7 @@
 #if SQLITE_THREADSAFE
   pthread_t tid;            /* The thread that "owns" this unixFile */
 #endif
+  int lastErrno;            /* The unix errno from the last I/O error */
 };
 
 /*
@@ -21578,6 +21866,12 @@
 #define LOCKING_STYLE_AFP          5
 
 /*
+** Only set the lastErrno if the error code is a real error and not 
+** a normal expected return code of SQLITE_BUSY or SQLITE_OK
+*/
+#define IS_LOCK_ERROR(x)  ((x != SQLITE_OK) && (x != SQLITE_BUSY))
+
+/*
 ** Helper functions to obtain and relinquish the global mutex.
 */
 static void enterMutex(){
@@ -21823,7 +22117,11 @@
     { "hfs",    LOCKING_STYLE_POSIX },
     { "ufs",    LOCKING_STYLE_POSIX },
     { "afpfs",  LOCKING_STYLE_AFP },
+#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
+    { "smbfs",  LOCKING_STYLE_AFP },
+#else
     { "smbfs",  LOCKING_STYLE_FLOCK },
+#endif
     { "msdos",  LOCKING_STYLE_DOTFILE },
     { "webdav", LOCKING_STYLE_NONE },
     { 0, 0 }
@@ -21835,7 +22133,7 @@
     return LOCKING_STYLE_NONE;
   }
   if( pVfs->pAppData ){
-    return (int)pVfs->pAppData;
+    return SQLITE_PTR_TO_INT(pVfs->pAppData);
   }
 
   if( statfs(filePath, &fsInfo) != -1 ){
@@ -22331,13 +22629,77 @@
 }
 
 /*
+** This routine translates a standard POSIX errno code into something
+** useful to the clients of the sqlite3 functions.  Specifically, it is
+** intended to translate a variety of "try again" errors into SQLITE_BUSY
+** and a variety of "please close the file descriptor NOW" errors into 
+** SQLITE_IOERR
+** 
+** Errors during initialization of locks, or file system support for locks,
+** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
+*/
+static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
+  switch (posixError) {
+  case 0: 
+    return SQLITE_OK;
+    
+  case EAGAIN:
+  case ETIMEDOUT:
+  case EBUSY:
+  case EINTR:
+  case ENOLCK:  
+    /* random NFS retry error, unless during file system support 
+     * introspection, in which it actually means what it says */
+    return SQLITE_BUSY;
+    
+  case EACCES: 
+    /* EACCES is like EAGAIN during locking operations, but not any other time*/
+    if( (sqliteIOErr == SQLITE_IOERR_LOCK) || 
+	(sqliteIOErr == SQLITE_IOERR_UNLOCK) || 
+	(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
+	(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
+      return SQLITE_BUSY;
+    }
+    /* else fall through */
+  case EPERM: 
+    return SQLITE_PERM;
+    
+  case EDEADLK:
+    return SQLITE_IOERR_BLOCKED;
+    
+#if EOPNOTSUPP!=ENOTSUP
+  case EOPNOTSUPP: 
+    /* something went terribly awry, unless during file system support 
+     * introspection, in which it actually means what it says */
+#endif
+  case ENOTSUP: 
+    /* invalid fd, unless during file system support introspection, in which 
+     * it actually means what it says */
+  case EIO:
+  case EBADF:
+  case EINVAL:
+  case ENOTCONN:
+  case ENODEV:
+  case ENXIO:
+  case ENOENT:
+  case ESTALE:
+  case ENOSYS:
+    /* these should force the client to close the file and reconnect */
+    
+  default: 
+    return sqliteIOErr;
+  }
+}
+
+/*
 ** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, return
-** non-zero.  If the file is unlocked or holds only SHARED locks, then
-** return zero.
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero.  The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
 */
 static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
-  int r = 0;
+  int rc = SQLITE_OK;
+  int reserved = 0;
   unixFile *pFile = (unixFile*)id;
 
   SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
@@ -22347,28 +22709,31 @@
 
   /* Check if a thread in this process holds such a lock */
   if( pFile->pLock->locktype>SHARED_LOCK ){
-    r = 1;
+    reserved = 1;
   }
 
   /* Otherwise see if some other process holds it.
   */
-  if( !r ){
+  if( !reserved ){
     struct flock lock;
     lock.l_whence = SEEK_SET;
     lock.l_start = RESERVED_BYTE;
     lock.l_len = 1;
     lock.l_type = F_WRLCK;
-    fcntl(pFile->h, F_GETLK, &lock);
-    if( lock.l_type!=F_UNLCK ){
-      r = 1;
+    if (-1 == fcntl(pFile->h, F_GETLK, &lock)) {
+      int tErrno = errno;
+      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
+      pFile->lastErrno = tErrno;
+    } else if( lock.l_type!=F_UNLCK ){
+      reserved = 1;
     }
   }
   
   leaveMutex();
-  OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
+  OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
 
-  *pResOut = r;
-  return SQLITE_OK;
+  *pResOut = reserved;
+  return rc;
 }
 
 /*
@@ -22514,7 +22879,11 @@
     lock.l_start = PENDING_BYTE;
     s = fcntl(pFile->h, F_SETLK, &lock);
     if( s==(-1) ){
-      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
+      int tErrno = errno;
+      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+      if( IS_LOCK_ERROR(rc) ){
+        pFile->lastErrno = tErrno;
+      }
       goto end_lock;
     }
   }
@@ -22524,24 +22893,36 @@
   ** operating system calls for the specified lock.
   */
   if( locktype==SHARED_LOCK ){
+    int tErrno = 0;
     assert( pLock->cnt==0 );
     assert( pLock->locktype==0 );
 
     /* Now get the read-lock */
     lock.l_start = SHARED_FIRST;
     lock.l_len = SHARED_SIZE;
-    s = fcntl(pFile->h, F_SETLK, &lock);
-
+    if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){
+      tErrno = errno;
+    }
     /* Drop the temporary PENDING lock */
     lock.l_start = PENDING_BYTE;
     lock.l_len = 1L;
     lock.l_type = F_UNLCK;
     if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
-      rc = SQLITE_IOERR_UNLOCK;  /* This should never happen */
-      goto end_lock;
+      if( s != -1 ){
+        /* This could happen with a network mount */
+        tErrno = errno; 
+        rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); 
+        if( IS_LOCK_ERROR(rc) ){
+          pFile->lastErrno = tErrno;
+        }
+        goto end_lock;
+      }
     }
     if( s==(-1) ){
-      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
+      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+      if( IS_LOCK_ERROR(rc) ){
+        pFile->lastErrno = tErrno;
+      }
     }else{
       pFile->locktype = SHARED_LOCK;
       pFile->pOpen->nLock++;
@@ -22571,7 +22952,11 @@
     }
     s = fcntl(pFile->h, F_SETLK, &lock);
     if( s==(-1) ){
-      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
+      int tErrno = errno;
+      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+      if( IS_LOCK_ERROR(rc) ){
+        pFile->lastErrno = tErrno;
+      }
     }
   }
   
@@ -22630,7 +23015,12 @@
       lock.l_start = SHARED_FIRST;
       lock.l_len = SHARED_SIZE;
       if( fcntl(h, F_SETLK, &lock)==(-1) ){
-        rc = SQLITE_IOERR_RDLOCK;
+        int tErrno = errno;
+        rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
+        if( IS_LOCK_ERROR(rc) ){
+          pFile->lastErrno = tErrno;
+        }
+				goto end_unlock;
       }
     }
     lock.l_type = F_UNLCK;
@@ -22640,7 +23030,12 @@
     if( fcntl(h, F_SETLK, &lock)!=(-1) ){
       pLock->locktype = SHARED_LOCK;
     }else{
-      rc = SQLITE_IOERR_UNLOCK;
+      int tErrno = errno;
+      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+      if( IS_LOCK_ERROR(rc) ){
+        pFile->lastErrno = tErrno;
+      }
+			goto end_unlock;
     }
   }
   if( locktype==NO_LOCK ){
@@ -22661,8 +23056,13 @@
       if( fcntl(h, F_SETLK, &lock)!=(-1) ){
         pLock->locktype = NO_LOCK;
       }else{
-        rc = SQLITE_IOERR_UNLOCK;
+        int tErrno = errno;
+				rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+        if( IS_LOCK_ERROR(rc) ){
+          pFile->lastErrno = tErrno;
+        }
         pLock->cnt = 1;
+				goto end_unlock;
       }
     }
 
@@ -22685,6 +23085,8 @@
       }
     }
   }
+	
+end_unlock:
   leaveMutex();
   if( rc==SQLITE_OK ) pFile->locktype = locktype;
   return rc;
@@ -22772,14 +23174,11 @@
 #define afpfsByteRangeLock2FSCTL        _IOWR('z', 23, struct ByteRangeLockPB2)
 
 /* 
-** Return 0 on success, 1 on failure.  To match the behavior of the 
-** normal posix file locking (used in unixLock for example), we should 
-** provide 'richer' return codes - specifically to differentiate between
-** 'file busy' and 'file system error' results.
-*/
+ ** Return SQLITE_OK on success, SQLITE_BUSY on failure.
+ */
 static int _AFPFSSetLock(
   const char *path, 
-  int fd, 
+  unixFile *pFile, 
   unsigned long long offset, 
   unsigned long long length, 
   int setLockFlag
@@ -22791,55 +23190,63 @@
   pb.startEndFlag = 0;
   pb.offset = offset;
   pb.length = length; 
-  pb.fd = fd;
+  pb.fd = pFile->h;
   OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n", 
-    (setLockFlag?"ON":"OFF"), fd, offset, length);
+    (setLockFlag?"ON":"OFF"), pFile->h, offset, length);
   err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
   if ( err==-1 ) {
-    OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno, 
-      strerror(errno));
-    return 1; /* error */
+    int rc;
+    int tErrno = errno;
+    OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, tErrno, strerror(tErrno));
+    rc = sqliteErrorFromPosixError(tErrno, setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK); /* error */
+    if( IS_LOCK_ERROR(rc) ){
+      pFile->lastErrno = tErrno;
+    }
+    return rc;
   } else {
-    return 0;
+    return SQLITE_OK;
   }
 }
 
-/*
- ** This routine checks if there is a RESERVED lock held on the specified
- ** file by this or any other process. If such a lock is held, return
- ** non-zero.  If the file is unlocked or holds only SHARED locks, then
- ** return zero.
- */
+/* AFP-style reserved lock checking following the behavior of 
+** unixCheckReservedLock, see the unixCheckReservedLock function comments */
 static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
-  int r = 0;
+  int rc = SQLITE_OK;
+  int reserved = 0;
   unixFile *pFile = (unixFile*)id;
   
-  assert( pFile ); 
+  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+  
+  assert( pFile );
   afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
   
   /* Check if a thread in this process holds such a lock */
   if( pFile->locktype>SHARED_LOCK ){
-    r = 1;
+    reserved = 1;
   }
   
   /* Otherwise see if some other process holds it.
    */
-  if ( !r ) {
-    /* lock the byte */
-    int failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1);  
-    if (failed) {
-      /* if we failed to get the lock then someone else must have it */
-      r = 1;
-    } else {
+  if( !reserved ){
+    /* lock the RESERVED byte */
+    int lrc = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);  
+    if( SQLITE_OK==lrc ){
       /* if we succeeded in taking the reserved lock, unlock it to restore
       ** the original state */
-      _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0);
+      lrc = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1, 0);
+    } else {
+      /* if we failed to get the lock then someone else must have it */
+      reserved = 1;
+    }
+    if( IS_LOCK_ERROR(lrc) ){
+      rc=lrc;
     }
   }
-  OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
   
-  *pResOut = r;
-  return SQLITE_OK;
+  OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
+  
+  *pResOut = reserved;
+  return rc;
 }
 
 /* AFP-style locking following the behavior of unixLock, see the unixLock 
@@ -22889,9 +23296,9 @@
       || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)
   ){
     int failed;
-    failed = _AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 1);
+    failed = _AFPFSSetLock(context->filePath, pFile, PENDING_BYTE, 1, 1);
     if (failed) {
-      rc = SQLITE_BUSY;
+      rc = failed;
       goto afp_end_lock;
     }
   }
@@ -22900,23 +23307,29 @@
   ** operating system calls for the specified lock.
   */
   if( locktype==SHARED_LOCK ){
-    int lk, failed;
+    int lk, lrc1, lrc2, lrc1Errno;
     
-    /* Now get the read-lock */
+    /* Now get the read-lock SHARED_LOCK */
     /* note that the quality of the randomness doesn't matter that much */
     lk = random(); 
     context->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
-    failed = _AFPFSSetLock(context->filePath, pFile->h, 
-      SHARED_FIRST+context->sharedLockByte, 1, 1);
-    
-    /* Drop the temporary PENDING lock */
-    if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)) {
-      rc = SQLITE_IOERR_UNLOCK;  /* This should never happen */
-      goto afp_end_lock;
+    lrc1 = _AFPFSSetLock(context->filePath, pFile, 
+          SHARED_FIRST+context->sharedLockByte, 1, 1);
+    if( IS_LOCK_ERROR(lrc1) ){
+      lrc1Errno = pFile->lastErrno;
     }
+    /* Drop the temporary PENDING lock */
+    lrc2 = _AFPFSSetLock(context->filePath, pFile, PENDING_BYTE, 1, 0);
     
-    if( failed ){
-      rc = SQLITE_BUSY;
+    if( IS_LOCK_ERROR(lrc1) ) {
+      pFile->lastErrno = lrc1Errno;
+      rc = lrc1;
+      goto afp_end_lock;
+    } else if( IS_LOCK_ERROR(lrc2) ){
+      rc = lrc2;
+      goto afp_end_lock;
+    } else if( lrc1 != SQLITE_OK ) {
+      rc = lrc1;
     } else {
       pFile->locktype = SHARED_LOCK;
     }
@@ -22929,7 +23342,7 @@
     assert( 0!=pFile->locktype );
     if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {
         /* Acquire a RESERVED lock */
-        failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1);
+        failed = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);
     }
     if (!failed && locktype == EXCLUSIVE_LOCK) {
       /* Acquire an EXCLUSIVE lock */
@@ -22937,22 +23350,21 @@
       /* Remove the shared lock before trying the range.  we'll need to 
       ** reestablish the shared lock if we can't get the  afpUnlock
       */
-      if (!_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST +
-                         context->sharedLockByte, 1, 0)) {
+      if (!(failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST +
+                         context->sharedLockByte, 1, 0))) {
         /* now attemmpt to get the exclusive lock range */
-        failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST, 
+        failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST, 
                                SHARED_SIZE, 1);
-        if (failed && _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST +
-                                    context->sharedLockByte, 1, 1)) {
-          rc = SQLITE_IOERR_RDLOCK; /* this should never happen */
+        if (failed && (failed = _AFPFSSetLock(context->filePath, pFile, 
+                       SHARED_FIRST + context->sharedLockByte, 1, 1))) {
+          rc = failed;
         }
       } else {
-        /* */
-        rc = SQLITE_IOERR_UNLOCK; /* this should never happen */
+        rc = failed; 
       }
     }
-    if( failed && rc == SQLITE_OK){
-      rc = SQLITE_BUSY;
+    if( failed ){
+      rc = failed;
     }
   }
   
@@ -22984,7 +23396,7 @@
   assert( pFile );
   OSTRACE5("UNLOCK  %d %d was %d pid=%d\n", pFile->h, locktype,
          pFile->locktype, getpid());
-  
+
   assert( locktype<=SHARED_LOCK );
   if( pFile->locktype<=locktype ){
     return SQLITE_OK;
@@ -22993,45 +23405,46 @@
     return SQLITE_MISUSE;
   }
   enterMutex();
+  int failed = SQLITE_OK;
   if( pFile->locktype>SHARED_LOCK ){
     if( locktype==SHARED_LOCK ){
-      int failed = 0;
 
       /* unlock the exclusive range - then re-establish the shared lock */
       if (pFile->locktype==EXCLUSIVE_LOCK) {
-        failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST, 
+        failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST, 
                                  SHARED_SIZE, 0);
         if (!failed) {
           /* successfully removed the exclusive lock */
-          if (_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST+
-                            context->sharedLockByte, 1, 1)) {
+          if ((failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST+
+                            context->sharedLockByte, 1, 1))) {
             /* failed to re-establish our shared lock */
-            rc = SQLITE_IOERR_RDLOCK; /* This should never happen */
+            rc = failed;
           }
         } else {
-          /* This should never happen - failed to unlock the exclusive range */
-          rc = SQLITE_IOERR_UNLOCK;
+          rc = failed;
         } 
       }
     }
     if (rc == SQLITE_OK && pFile->locktype>=PENDING_LOCK) {
-      if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)){
+      if ((failed = _AFPFSSetLock(context->filePath, pFile, 
+                                  PENDING_BYTE, 1, 0))){
         /* failed to release the pending lock */
-        rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+        rc = failed; 
       }
     } 
     if (rc == SQLITE_OK && pFile->locktype>=RESERVED_LOCK) {
-      if (_AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0)) {
+      if ((failed = _AFPFSSetLock(context->filePath, pFile, 
+                                  RESERVED_BYTE, 1, 0))) {
         /* failed to release the reserved lock */
-        rc = SQLITE_IOERR_UNLOCK;  /* This should never happen */
+        rc = failed;  
       }
     } 
   }
   if( locktype==NO_LOCK ){
-    int failed = _AFPFSSetLock(context->filePath, pFile->h, 
+    int failed = _AFPFSSetLock(context->filePath, pFile, 
                                SHARED_FIRST + context->sharedLockByte, 1, 0);
     if (failed) {
-      rc = SQLITE_IOERR_UNLOCK;  /* This should never happen */
+      rc = failed;  
     }
   }
   if (rc == SQLITE_OK)
@@ -23060,27 +23473,62 @@
 */
 typedef void flockLockingContext;
 
+/* flock-style reserved lock checking following the behavior of 
+ ** unixCheckReservedLock, see the unixCheckReservedLock function comments */
 static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
-  int r = 1;
+  int rc = SQLITE_OK;
+  int reserved = 0;
   unixFile *pFile = (unixFile*)id;
   
-  if (pFile->locktype != RESERVED_LOCK) {
+  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+  
+  assert( pFile );
+  
+  /* Check if a thread in this process holds such a lock */
+  if( pFile->locktype>SHARED_LOCK ){
+    reserved = 1;
+  }
+  
+  /* Otherwise see if some other process holds it. */
+  if( !reserved ){
     /* attempt to get the lock */
-    int rc = flock(pFile->h, LOCK_EX | LOCK_NB);
-    if (!rc) {
+    int lrc = flock(pFile->h, LOCK_EX | LOCK_NB);
+    if( !lrc ){
       /* got the lock, unlock it */
-      flock(pFile->h, LOCK_UN);
-      r = 0;  /* no one has it reserved */
+      lrc = flock(pFile->h, LOCK_UN);
+      if ( lrc ) {
+        int tErrno = errno;
+        /* unlock failed with an error */
+        lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); 
+        if( IS_LOCK_ERROR(lrc) ){
+          pFile->lastErrno = tErrno;
+          rc = lrc;
+        }
+      }
+    } else {
+      int tErrno = errno;
+      reserved = 1;
+      /* someone else might have it reserved */
+      lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); 
+      if( IS_LOCK_ERROR(lrc) ){
+        pFile->lastErrno = tErrno;
+        rc = lrc;
+      }
     }
   }
+  OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
 
-  *pResOut = r;
-  return SQLITE_OK;
+  *pResOut = reserved;
+  return rc;
 }
 
 static int flockLock(sqlite3_file *id, int locktype) {
+  int rc = SQLITE_OK;
+  int lrc;
   unixFile *pFile = (unixFile*)id;
-  
+
+  assert( pFile );
+
   /* if we already have a lock, it is exclusive.  
   ** Just adjust level and punt on outta here. */
   if (pFile->locktype > NO_LOCK) {
@@ -23089,20 +23537,29 @@
   }
   
   /* grab an exclusive lock */
-  int rc = flock(pFile->h, LOCK_EX | LOCK_NB);
-  if (rc) {
+  
+  if (flock(pFile->h, LOCK_EX | LOCK_NB)) {
+    int tErrno = errno;
     /* didn't get, must be busy */
-    return SQLITE_BUSY;
+    rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+    if( IS_LOCK_ERROR(rc) ){
+      pFile->lastErrno = tErrno;
+    }
   } else {
     /* got it, set the type and return ok */
     pFile->locktype = locktype;
-    return SQLITE_OK;
   }
+  OSTRACE4("LOCK    %d %s %s\n", pFile->h, locktypeName(locktype), 
+           rc==SQLITE_OK ? "ok" : "failed");
+  return rc;
 }
 
 static int flockUnlock(sqlite3_file *id, int locktype) {
   unixFile *pFile = (unixFile*)id;
   
+  assert( pFile );
+  OSTRACE5("UNLOCK  %d %d was %d pid=%d\n", pFile->h, locktype,
+           pFile->locktype, getpid());
   assert( locktype<=SHARED_LOCK );
   
   /* no-op if possible */
@@ -23118,9 +23575,14 @@
   
   /* no, really, unlock. */
   int rc = flock(pFile->h, LOCK_UN);
-  if (rc)
-    return SQLITE_IOERR_UNLOCK;
-  else {
+  if (rc) {
+    int r, tErrno = errno;
+    r = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+    if( IS_LOCK_ERROR(r) ){
+      pFile->lastErrno = tErrno;
+    }
+    return r;
+  } else {
     pFile->locktype = NO_LOCK;
     return SQLITE_OK;
   }
@@ -23138,27 +23600,50 @@
 
 #pragma mark Old-School .lock file based locking
 
+/* Dotlock-style reserved lock checking following the behavior of 
+** unixCheckReservedLock, see the unixCheckReservedLock function comments */
 static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
-  int r = 1;
+  int rc = SQLITE_OK;
+  int reserved = 0;
   unixFile *pFile = (unixFile*)id;
-  char *zLockFile = (char *)pFile->lockingContext;
 
-  if (pFile->locktype != RESERVED_LOCK) {
+  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+  
+  assert( pFile );
+
+  /* Check if a thread in this process holds such a lock */
+  if( pFile->locktype>SHARED_LOCK ){
+    reserved = 1;
+  }
+  
+  /* Otherwise see if some other process holds it. */
+  if( !reserved ){
+    char *zLockFile = (char *)pFile->lockingContext;
     struct stat statBuf;
-    if (lstat(zLockFile, &statBuf) != 0){
+    
+    if( lstat(zLockFile, &statBuf)==0 ){
+      /* file exists, someone else has the lock */
+      reserved = 1;
+    }else{
       /* file does not exist, we could have it if we want it */
-      r = 0;
+			int tErrno = errno;
+      if( ENOENT != tErrno ){
+        rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
+        pFile->lastErrno = tErrno;
+      }
     }
   }
+  OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
 
-  *pResOut = r;
-  return SQLITE_OK;
+  *pResOut = reserved;
+  return rc;
 }
 
 static int dotlockLock(sqlite3_file *id, int locktype) {
   unixFile *pFile = (unixFile*)id;
   int fd;
   char *zLockFile = (char *)pFile->lockingContext;
+  int rc=SQLITE_OK;
 
   /* if we already have a lock, it is exclusive.  
   ** Just adjust level and punt on outta here. */
@@ -23167,32 +23652,48 @@
     
     /* Always update the timestamp on the old file */
     utimes(zLockFile, NULL);
-    return SQLITE_OK;
+    rc = SQLITE_OK;
+    goto dotlock_end_lock;
   }
   
   /* check to see if lock file already exists */
   struct stat statBuf;
   if (lstat(zLockFile,&statBuf) == 0){
-    return SQLITE_BUSY; /* it does, busy */
+    rc = SQLITE_BUSY; /* it does, busy */
+    goto dotlock_end_lock;
   }
   
   /* grab an exclusive lock */
   fd = open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
   if( fd<0 ){
     /* failed to open/create the file, someone else may have stolen the lock */
-    return SQLITE_BUSY; 
-  }
+    int tErrno = errno;
+    if( EEXIST == tErrno ){
+      rc = SQLITE_BUSY;
+    } else {
+      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+      if( IS_LOCK_ERROR(rc) ){
+	pFile->lastErrno = tErrno;
+      }
+    }
+    goto dotlock_end_lock;
+  } 
   close(fd);
   
   /* got it, set the type and return ok */
   pFile->locktype = locktype;
-  return SQLITE_OK;
+
+ dotlock_end_lock:
+  return rc;
 }
 
 static int dotlockUnlock(sqlite3_file *id, int locktype) {
   unixFile *pFile = (unixFile*)id;
   char *zLockFile = (char *)pFile->lockingContext;
 
+  assert( pFile );
+  OSTRACE5("UNLOCK  %d %d was %d pid=%d\n", pFile->h, locktype,
+	   pFile->locktype, getpid());
   assert( locktype<=SHARED_LOCK );
   
   /* no-op if possible */
@@ -23207,7 +23708,16 @@
   }
   
   /* no, really, unlock. */
-  unlink(zLockFile);
+  if (unlink(zLockFile) ) {
+    int rc, tErrno = errno;
+    if( ENOENT != tErrno ){
+      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+    }
+    if( IS_LOCK_ERROR(rc) ){
+      pFile->lastErrno = tErrno;
+    }
+    return rc; 
+  }
   pFile->locktype = NO_LOCK;
   return SQLITE_OK;
 }
@@ -23409,7 +23919,8 @@
       break;
 #endif
   }
-
+  
+  pNew->lastErrno = 0;
   if( rc!=SQLITE_OK ){
     if( dirfd>=0 ) close(dirfd);
     close(h);
@@ -26140,9 +26651,9 @@
 #endif /* SQLITE_OMIT_BUILTIN_TEST */
 
 /************** End of bitvec.c **********************************************/
-/************** Begin file pager.c *******************************************/
+/************** Begin file pcache.c ******************************************/
 /*
-** 2001 September 15
+** 2008 August 05
 **
 ** The author disclaims copyright to this source code.  In place of
 ** a legal notice, here is a blessing:
@@ -26152,3413 +26663,3782 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This is the implementation of the page cache subsystem or "pager".
-** 
-** The pager is used to access a database disk file.  It implements
-** atomic commit and rollback through the use of a journal file that
-** is separate from the database file.  The pager also implements file
-** locking to prevent two processes from writing the same database
-** file simultaneously, or one process from reading the database while
-** another is writing.
+** This file implements that page cache.
 **
-** @(#) $Id: pager.c,v 1.469 2008/08/02 03:50:39 drh Exp $
+** @(#) $Id: pcache.c,v 1.24 2008/08/29 09:10:03 danielk1977 Exp $
 */
-#ifndef SQLITE_OMIT_DISKIO
 
 /*
-** Macros for troubleshooting.  Normally turned off
+** A complete page cache is an instance of this structure.
+**
+** A cache may only be deleted by its owner and while holding the
+** SQLITE_MUTEX_STATUS_LRU mutex.
+*/
+struct PCache {
+  /*********************************************************************
+  ** The first group of elements may be read or written at any time by
+  ** the cache owner without holding the mutex.  No thread other than the
+  ** cache owner is permitted to access these elements at any time.
+  */
+  PgHdr *pDirty, *pDirtyTail;         /* List of dirty pages in LRU order */
+  PgHdr *pSynced;                     /* Last synced page in dirty page list */
+  int nRef;                           /* Number of pinned pages */
+  int nPinned;                        /* Number of pinned and/or dirty pages */
+  int nMax;                           /* Configured cache size */
+  int nMin;                           /* Configured minimum cache size */
+  /**********************************************************************
+  ** The next group of elements are fixed when the cache is created and
+  ** may not be changed afterwards.  These elements can read at any time by
+  ** the cache owner or by any thread holding the the mutex.  Non-owner
+  ** threads must hold the mutex when reading these elements to prevent
+  ** the entire PCache object from being deleted during the read.
+  */
+  int szPage;                         /* Size of every page in this cache */
+  int szExtra;                        /* Size of extra space for each page */
+  int bPurgeable;                     /* True if pages are on backing store */
+  void (*xDestroy)(PgHdr*);           /* Called when refcnt goes 1->0 */
+  int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
+  void *pStress;                      /* Argument to xStress */
+  /**********************************************************************
+  ** The final group of elements can only be accessed while holding the
+  ** mutex.  Both the cache owner and any other thread must hold the mutex
+  ** to read or write any of these elements.
+  */
+  int nPage;                          /* Total number of pages in apHash */
+  int nHash;                          /* Number of slots in apHash[] */
+  PgHdr **apHash;                     /* Hash table for fast lookup by pgno */
+  PgHdr *pClean;                      /* List of clean pages in use */
+};
+
+/*
+** Free slots in the page block allocator
 */
-#if 0
-#define sqlite3DebugPrintf printf
-#define PAGERTRACE1(X)       sqlite3DebugPrintf(X)
-#define PAGERTRACE2(X,Y)     sqlite3DebugPrintf(X,Y)
-#define PAGERTRACE3(X,Y,Z)   sqlite3DebugPrintf(X,Y,Z)
-#define PAGERTRACE4(X,Y,Z,W) sqlite3DebugPrintf(X,Y,Z,W)
-#define PAGERTRACE5(X,Y,Z,W,V) sqlite3DebugPrintf(X,Y,Z,W,V)
+typedef struct PgFreeslot PgFreeslot;
+struct PgFreeslot {
+  PgFreeslot *pNext;  /* Next free slot */
+};
+
+/*
+** Global data for the page cache.
+*/
+static struct PCacheGlobal {
+  int isInit;                         /* True when initialized */
+  sqlite3_mutex *mutex;               /* static mutex MUTEX_STATIC_LRU */
+
+  int nMaxPage;                       /* Sum of nMaxPage for purgeable caches */
+  int nMinPage;                       /* Sum of nMinPage for purgeable caches */
+  int nCurrentPage;                   /* Number of purgeable pages allocated */
+  PgHdr *pLruHead, *pLruTail;         /* LRU list of unused clean pgs */
+
+  /* Variables related to SQLITE_CONFIG_PAGECACHE settings. */
+  int szSlot;                         /* Size of each free slot */
+  void *pStart, *pEnd;                /* Bounds of pagecache malloc range */
+  PgFreeslot *pFree;                  /* Free page blocks */
+} pcache = {0};
+
+/*
+** All global variables used by this module (all of which are grouped 
+** together in global structure "pcache" above) are protected by the static 
+** SQLITE_MUTEX_STATIC_LRU mutex. A pointer to this mutex is stored in
+** variable "pcache.mutex".
+**
+** Some elements of the PCache and PgHdr structures are protected by the 
+** SQLITE_MUTEX_STATUS_LRU mutex and other are not.  The protected
+** elements are grouped at the end of the structures and are clearly
+** marked.
+**
+** Use the following macros must surround all access (read or write)
+** of protected elements.  The mutex is not recursive and may not be
+** entered more than once.  The pcacheMutexHeld() macro should only be
+** used within an assert() to verify that the mutex is being held.
+*/
+#define pcacheEnterMutex() sqlite3_mutex_enter(pcache.mutex)
+#define pcacheExitMutex()  sqlite3_mutex_leave(pcache.mutex)
+#define pcacheMutexHeld()  sqlite3_mutex_held(pcache.mutex)
+
+/*
+** Some of the assert() macros in this code are too expensive to run
+** even during normal debugging.  Use them only rarely on long-running
+** tests.  Enable the expensive asserts using the
+** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
+*/
+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+# define expensive_assert(X)  assert(X)
 #else
-#define PAGERTRACE1(X)
-#define PAGERTRACE2(X,Y)
-#define PAGERTRACE3(X,Y,Z)
-#define PAGERTRACE4(X,Y,Z,W)
-#define PAGERTRACE5(X,Y,Z,W,V)
+# define expensive_assert(X)
 #endif
 
+/********************************** Linked List Management ********************/
+
+#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
 /*
-** The following two macros are used within the PAGERTRACEX() macros above
-** to print out file-descriptors. 
-**
-** PAGERID() takes a pointer to a Pager struct as its argument. The
-** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
-** struct as its argument.
+** This routine verifies that the number of entries in the hash table
+** is pCache->nPage.  This routine is used within assert() statements
+** only and is therefore disabled during production builds.
 */
-#define PAGERID(p) ((int)(p->fd))
-#define FILEHANDLEID(fd) ((int)fd)
+static int pcacheCheckHashCount(PCache *pCache){
+  int i;
+  int nPage = 0;
+  for(i=0; i<pCache->nHash; i++){
+    PgHdr *p;
+    for(p=pCache->apHash[i]; p; p=p->pNextHash){
+      nPage++;
+    }
+  }
+  assert( nPage==pCache->nPage );
+  return 1;
+}
+#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
 
+
+#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
 /*
-** The page cache as a whole is always in one of the following
-** states:
-**
-**   PAGER_UNLOCK        The page cache is not currently reading or 
-**                       writing the database file.  There is no
-**                       data held in memory.  This is the initial
-**                       state.
-**
-**   PAGER_SHARED        The page cache is reading the database.
-**                       Writing is not permitted.  There can be
-**                       multiple readers accessing the same database
-**                       file at the same time.
-**
-**   PAGER_RESERVED      This process has reserved the database for writing
-**                       but has not yet made any changes.  Only one process
-**                       at a time can reserve the database.  The original
-**                       database file has not been modified so other
-**                       processes may still be reading the on-disk
-**                       database file.
-**
-**   PAGER_EXCLUSIVE     The page cache is writing the database.
-**                       Access is exclusive.  No other processes or
-**                       threads can be reading or writing while one
-**                       process is writing.
-**
-**   PAGER_SYNCED        The pager moves to this state from PAGER_EXCLUSIVE
-**                       after all dirty pages have been written to the
-**                       database file and the file has been synced to
-**                       disk. All that remains to do is to remove or
-**                       truncate the journal file and the transaction 
-**                       will be committed.
+** Based on the current value of PCache.nRef and the contents of the
+** PCache.pDirty list, return the expected value of the PCache.nPinned
+** counter. This is only used in debugging builds, as follows:
 **
-** The page cache comes up in PAGER_UNLOCK.  The first time a
-** sqlite3PagerGet() occurs, the state transitions to PAGER_SHARED.
-** After all pages have been released using sqlite_page_unref(),
-** the state transitions back to PAGER_UNLOCK.  The first time
-** that sqlite3PagerWrite() is called, the state transitions to
-** PAGER_RESERVED.  (Note that sqlite3PagerWrite() can only be
-** called on an outstanding page which means that the pager must
-** be in PAGER_SHARED before it transitions to PAGER_RESERVED.)
-** PAGER_RESERVED means that there is an open rollback journal.
-** The transition to PAGER_EXCLUSIVE occurs before any changes
-** are made to the database file, though writes to the rollback
-** journal occurs with just PAGER_RESERVED.  After an sqlite3PagerRollback()
-** or sqlite3PagerCommitPhaseTwo(), the state can go back to PAGER_SHARED,
-** or it can stay at PAGER_EXCLUSIVE if we are in exclusive access mode.
+**   expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
 */
-#define PAGER_UNLOCK      0
-#define PAGER_SHARED      1   /* same as SHARED_LOCK */
-#define PAGER_RESERVED    2   /* same as RESERVED_LOCK */
-#define PAGER_EXCLUSIVE   4   /* same as EXCLUSIVE_LOCK */
-#define PAGER_SYNCED      5
+static int pcachePinnedCount(PCache *pCache){
+  PgHdr *p;
+  int nPinned = pCache->nRef;
+  for(p=pCache->pDirty; p; p=p->pNext){
+    if( p->nRef==0 ){
+      nPinned++;
+    }
+  }
+  return nPinned;
+}
+#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
 
-/*
-** If the SQLITE_BUSY_RESERVED_LOCK macro is set to true at compile-time,
-** then failed attempts to get a reserved lock will invoke the busy callback.
-** This is off by default.  To see why, consider the following scenario:
-** 
-** Suppose thread A already has a shared lock and wants a reserved lock.
-** Thread B already has a reserved lock and wants an exclusive lock.  If
-** both threads are using their busy callbacks, it might be a long time
-** be for one of the threads give up and allows the other to proceed.
-** But if the thread trying to get the reserved lock gives up quickly
-** (if it never invokes its busy callback) then the contention will be
-** resolved quickly.
-*/
-#ifndef SQLITE_BUSY_RESERVED_LOCK
-# define SQLITE_BUSY_RESERVED_LOCK 0
-#endif
 
+#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
 /*
-** This macro rounds values up so that if the value is an address it
-** is guaranteed to be an address that is aligned to an 8-byte boundary.
+** Check that the pCache->pSynced variable is set correctly. If it
+** is not, either fail an assert or return zero. Otherwise, return
+** non-zero. This is only used in debugging builds, as follows:
+**
+**   expensive_assert( pcacheCheckSynced(pCache) );
 */
-#define FORCE_ALIGNMENT(X)   (((X)+7)&~7)
+static int pcacheCheckSynced(PCache *pCache){
+  PgHdr *p = pCache->pDirtyTail;
+  for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pPrev){
+    assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
+  }
+  return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
+}
+#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
+
 
-typedef struct PgHdr PgHdr;
 
 /*
-** Each pager stores all currently unreferenced pages in a list sorted
-** in least-recently-used (LRU) order (i.e. the first item on the list has 
-** not been referenced in a long time, the last item has been recently
-** used). An instance of this structure is included as part of each
-** pager structure for this purpose (variable Pager.lru).
-**
-** Additionally, if memory-management is enabled, all unreferenced pages 
-** are stored in a global LRU list (global variable sqlite3LruPageList).
-**
-** In both cases, the PagerLruList.pFirstSynced variable points to
-** the first page in the corresponding list that does not require an
-** fsync() operation before its memory can be reclaimed. If no such
-** page exists, PagerLruList.pFirstSynced is set to NULL.
-*/
-typedef struct PagerLruList PagerLruList;
-struct PagerLruList {
-  PgHdr *pFirst;         /* First page in LRU list */
-  PgHdr *pLast;          /* Last page in LRU list (the most recently used) */
-  PgHdr *pFirstSynced;   /* First page in list with PgHdr.needSync==0 */
-};
+** Remove a page from its hash table (PCache.apHash[]).
+*/
+static void pcacheRemoveFromHash(PgHdr *pPage){
+  assert( pcacheMutexHeld() );
+  if( pPage->pPrevHash ){
+    pPage->pPrevHash->pNextHash = pPage->pNextHash;
+  }else{
+    PCache *pCache = pPage->pCache;
+    u32 h = pPage->pgno % pCache->nHash;
+    assert( pCache->apHash[h]==pPage );
+    pCache->apHash[h] = pPage->pNextHash;
+  }
+  if( pPage->pNextHash ){
+    pPage->pNextHash->pPrevHash = pPage->pPrevHash;
+  }
+  pPage->pCache->nPage--;
+  expensive_assert( pcacheCheckHashCount(pPage->pCache) );
+}
 
 /*
-** The following structure contains the next and previous pointers used
-** to link a PgHdr structure into a PagerLruList linked list. 
+** Insert a page into the hash table
+**
+** The mutex must be held by the caller.
 */
-typedef struct PagerLruLink PagerLruLink;
-struct PagerLruLink {
-  PgHdr *pNext;
-  PgHdr *pPrev;
-};
+static void pcacheAddToHash(PgHdr *pPage){
+  PCache *pCache = pPage->pCache;
+  u32 h = pPage->pgno % pCache->nHash;
+  assert( pcacheMutexHeld() );
+  pPage->pNextHash = pCache->apHash[h];
+  pPage->pPrevHash = 0;
+  if( pCache->apHash[h] ){
+    pCache->apHash[h]->pPrevHash = pPage;
+  }
+  pCache->apHash[h] = pPage;
+  pCache->nPage++;
+  expensive_assert( pcacheCheckHashCount(pCache) );
+}
 
 /*
-** Each in-memory image of a page begins with the following header.
-** This header is only visible to this pager module.  The client
-** code that calls pager sees only the data that follows the header.
-**
-** Client code should call sqlite3PagerWrite() on a page prior to making
-** any modifications to that page.  The first time sqlite3PagerWrite()
-** is called, the original page contents are written into the rollback
-** journal and PgHdr.inJournal and PgHdr.needSync are set.  Later, once
-** the journal page has made it onto the disk surface, PgHdr.needSync
-** is cleared.  The modified page cannot be written back into the original
-** database file until the journal pages has been synced to disk and the
-** PgHdr.needSync has been cleared.
-**
-** The PgHdr.dirty flag is set when sqlite3PagerWrite() is called and
-** is cleared again when the page content is written back to the original
-** database file.
-**
-** Details of important structure elements:
-**
-** needSync
-**
-**     If this is true, this means that it is not safe to write the page
-**     content to the database because the original content needed
-**     for rollback has not by synced to the main rollback journal.
-**     The original content may have been written to the rollback journal
-**     but it has not yet been synced.  So we cannot write to the database
-**     file because power failure might cause the page in the journal file
-**     to never reach the disk.  It is as if the write to the journal file
-**     does not occur until the journal file is synced.
-**     
-**     This flag is false if the page content exactly matches what
-**     currently exists in the database file.  The needSync flag is also
-**     false if the original content has been written to the main rollback
-**     journal and synced.  If the page represents a new page that has
-**     been added onto the end of the database during the current
-**     transaction, the needSync flag is true until the original database
-**     size in the journal header has been synced to disk.
-**
-** inJournal
-**
-**     This is true if the original page has been written into the main
-**     rollback journal.  This is always false for new pages added to
-**     the end of the database file during the current transaction.
-**     And this flag says nothing about whether or not the journal
-**     has been synced to disk.  For pages that are in the original
-**     database file, the following expression should always be true:
-**
-**       inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno)
-**
-**     The pPager->pInJournal object is only valid for the original
-**     pages of the database, not new pages that are added to the end
-**     of the database, so obviously the above expression cannot be
-**     valid for new pages.  For new pages inJournal is always 0.
-**
-** dirty
-**
-**     When true, this means that the content of the page has been
-**     modified and needs to be written back to the database file.
-**     If false, it means that either the content of the page is
-**     unchanged or else the content is unimportant and we do not
-**     care whether or not it is preserved.
-**
-** alwaysRollback
-**
-**     This means that the sqlite3PagerDontRollback() API should be
-**     ignored for this page.  The DontRollback() API attempts to say
-**     that the content of the page on disk is unimportant (it is an
-**     unused page on the freelist) so that it is unnecessary to 
-**     rollback changes to this page because the content of the page
-**     can change without changing the meaning of the database.  This
-**     flag overrides any DontRollback() attempt.  This flag is set
-**     when a page that originally contained valid data is added to
-**     the freelist.  Later in the same transaction, this page might
-**     be pulled from the freelist and reused for something different
-**     and at that point the DontRollback() API will be called because
-**     pages taken from the freelist do not need to be protected by
-**     the rollback journal.  But this flag says that the page was
-**     not originally part of the freelist so that it still needs to
-**     be rolled back in spite of any subsequent DontRollback() calls.
-**
-** needRead 
-**
-**     This flag means (when true) that the content of the page has
-**     not yet been loaded from disk.  The in-memory content is just
-**     garbage.  (Actually, we zero the content, but you should not
-**     make any assumptions about the content nevertheless.)  If the
-**     content is needed in the future, it should be read from the
-**     original database file.
+** Attempt to increase the size the hash table to contain
+** at least nHash buckets.
 */
-struct PgHdr {
-  Pager *pPager;                 /* The pager to which this page belongs */
-  Pgno pgno;                     /* The page number for this page */
-  PgHdr *pNextHash, *pPrevHash;  /* Hash collision chain for PgHdr.pgno */
-  PagerLruLink free;             /* Next and previous free pages */
-  PgHdr *pNextAll;               /* A list of all pages */
-  u8 inJournal;                  /* TRUE if has been written to journal */
-  u8 dirty;                      /* TRUE if we need to write back changes */
-  u8 needSync;                   /* Sync journal before writing this page */
-  u8 alwaysRollback;             /* Disable DontRollback() for this page */
-  u8 needRead;                   /* Read content if PagerWrite() is called */
-  short int nRef;                /* Number of users of this page */
-  PgHdr *pDirty, *pPrevDirty;    /* Dirty pages */
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  PgHdr *pPrevAll;               /* A list of all pages */
-  PagerLruLink gfree;            /* Global list of nRef==0 pages */
-#endif
-#ifdef SQLITE_CHECK_PAGES
-  u32 pageHash;
+static int pcacheResizeHash(PCache *pCache, int nHash){
+  PgHdr *p;
+  PgHdr **pNew;
+  assert( pcacheMutexHeld() );
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
+  if( nHash*sizeof(PgHdr*)>SQLITE_MALLOC_SOFT_LIMIT ){
+    nHash = SQLITE_MALLOC_SOFT_LIMIT/sizeof(PgHdr *);
+  }
 #endif
-  void *pData;                   /* Page data */
-  /* Pager.nExtra bytes of local data appended to this header */
-};
+  pcacheExitMutex();
+  pNew = (PgHdr **)sqlite3Malloc(sizeof(PgHdr*)*nHash);
+  pcacheEnterMutex();
+  if( !pNew ){
+    return SQLITE_NOMEM;
+  }
+  memset(pNew, 0, sizeof(PgHdr *)*nHash);
+  sqlite3_free(pCache->apHash);
+  pCache->apHash = pNew;
+  pCache->nHash = nHash;
+  pCache->nPage = 0;
+ 
+  for(p=pCache->pClean; p; p=p->pNext){
+    pcacheAddToHash(p);
+  }
+  for(p=pCache->pDirty; p; p=p->pNext){
+    pcacheAddToHash(p);
+  }
+  return SQLITE_OK;
+}
 
 /*
-** For an in-memory only database, some extra information is recorded about
-** each page so that changes can be rolled back.  (Journal files are not
-** used for in-memory databases.)  The following information is added to
-** the end of every EXTRA block for in-memory databases.
-**
-** This information could have been added directly to the PgHdr structure.
-** But then it would take up an extra 8 bytes of storage on every PgHdr
-** even for disk-based databases.  Splitting it out saves 8 bytes.  This
-** is only a savings of 0.8% but those percentages add up.
-*/
-typedef struct PgHistory PgHistory;
-struct PgHistory {
-  u8 *pOrig;     /* Original page text.  Restore to this on a full rollback */
-  u8 *pStmt;     /* Text as it was at the beginning of the current statement */
-  PgHdr *pNextStmt, *pPrevStmt;  /* List of pages in the statement journal */
-  u8 inStmt;                     /* TRUE if in the statement subjournal */
-};
+** Remove a page from a linked list that is headed by *ppHead.
+** *ppHead is either PCache.pClean or PCache.pDirty.
+*/
+static void pcacheRemoveFromList(PgHdr **ppHead, PgHdr *pPage){
+  int isDirtyList = (ppHead==&pPage->pCache->pDirty);
+  assert( ppHead==&pPage->pCache->pClean || ppHead==&pPage->pCache->pDirty );
+  assert( pcacheMutexHeld() || ppHead!=&pPage->pCache->pClean );
+
+  if( pPage->pPrev ){
+    pPage->pPrev->pNext = pPage->pNext;
+  }else{
+    assert( *ppHead==pPage );
+    *ppHead = pPage->pNext;
+  }
+  if( pPage->pNext ){
+    pPage->pNext->pPrev = pPage->pPrev;
+  }
+
+  if( isDirtyList ){
+    PCache *pCache = pPage->pCache;
+    assert( pPage->pNext || pCache->pDirtyTail==pPage );
+    if( !pPage->pNext ){
+      pCache->pDirtyTail = pPage->pPrev;
+    }
+    if( pCache->pSynced==pPage ){
+      PgHdr *pSynced = pPage->pPrev;
+      while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
+        pSynced = pSynced->pPrev;
+      }
+      pCache->pSynced = pSynced;
+    }
+  }
+}
 
 /*
-** A macro used for invoking the codec if there is one
+** Add a page from a linked list that is headed by *ppHead.
+** *ppHead is either PCache.pClean or PCache.pDirty.
 */
-#ifdef SQLITE_HAS_CODEC
-# define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); }
-# define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D))
-#else
-# define CODEC1(P,D,N,X) /* NO-OP */
-# define CODEC2(P,D,N,X) ((char*)D)
-#endif
+static void pcacheAddToList(PgHdr **ppHead, PgHdr *pPage){
+  int isDirtyList = (ppHead==&pPage->pCache->pDirty);
+  assert( ppHead==&pPage->pCache->pClean || ppHead==&pPage->pCache->pDirty );
+
+  if( (*ppHead) ){
+    (*ppHead)->pPrev = pPage;
+  }
+  pPage->pNext = *ppHead;
+  pPage->pPrev = 0;
+  *ppHead = pPage;
+
+  if( isDirtyList ){
+    PCache *pCache = pPage->pCache;
+    if( !pCache->pDirtyTail ){
+      assert( pPage->pNext==0 );
+      pCache->pDirtyTail = pPage;
+    }
+    if( !pCache->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
+      pCache->pSynced = pPage;
+    }
+  }
+}
 
 /*
-** Convert a pointer to a PgHdr into a pointer to its data
-** and back again.
+** Remove a page from the global LRU list
 */
-#define PGHDR_TO_DATA(P)    ((P)->pData)
-#define PGHDR_TO_EXTRA(G,P) ((void*)&((G)[1]))
-#define PGHDR_TO_HIST(P,PGR)  \
-            ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->nExtra])
+static void pcacheRemoveFromLruList(PgHdr *pPage){
+  assert( sqlite3_mutex_held(pcache.mutex) );
+  assert( (pPage->flags&PGHDR_DIRTY)==0 );
+  if( pPage->pCache->bPurgeable==0 ) return;
+  if( pPage->pNextLru ){
+    assert( pcache.pLruTail!=pPage );
+    pPage->pNextLru->pPrevLru = pPage->pPrevLru;
+  }else{
+    assert( pcache.pLruTail==pPage );
+    pcache.pLruTail = pPage->pPrevLru;
+  }
+  if( pPage->pPrevLru ){
+    assert( pcache.pLruHead!=pPage );
+    pPage->pPrevLru->pNextLru = pPage->pNextLru;
+  }else{
+    assert( pcache.pLruHead==pPage );
+    pcache.pLruHead = pPage->pNextLru;
+  }
+}
 
 /*
-** A open page cache is an instance of the following structure.
-**
-** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, or
-** or SQLITE_FULL. Once one of the first three errors occurs, it persists
-** and is returned as the result of every major pager API call.  The
-** SQLITE_FULL return code is slightly different. It persists only until the
-** next successful rollback is performed on the pager cache. Also,
-** SQLITE_FULL does not affect the sqlite3PagerGet() and sqlite3PagerLookup()
-** APIs, they may still be used successfully.
+** Add a page to the global LRU list.  The page is normally added
+** to the front of the list so that it will be the last page recycled.
+** However, if the PGHDR_REUSE_UNLIKELY bit is set, the page is added
+** to the end of the LRU list so that it will be the next to be recycled.
 */
-struct Pager {
-  sqlite3_vfs *pVfs;          /* OS functions to use for IO */
-  u8 journalOpen;             /* True if journal file descriptors is valid */
-  u8 journalStarted;          /* True if header of journal is synced */
-  u8 useJournal;              /* Use a rollback journal on this file */
-  u8 noReadlock;              /* Do not bother to obtain readlocks */
-  u8 stmtOpen;                /* True if the statement subjournal is open */
-  u8 stmtInUse;               /* True we are in a statement subtransaction */
-  u8 stmtAutoopen;            /* Open stmt journal when main journal is opened*/
-  u8 noSync;                  /* Do not sync the journal if true */
-  u8 fullSync;                /* Do extra syncs of the journal for robustness */
-  u8 sync_flags;              /* One of SYNC_NORMAL or SYNC_FULL */
-  u8 state;                   /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */
-  u8 tempFile;                /* zFilename is a temporary file */
-  u8 readOnly;                /* True for a read-only database */
-  u8 needSync;                /* True if an fsync() is needed on the journal */
-  u8 dirtyCache;              /* True if cached pages have changed */
-  u8 alwaysRollback;          /* Disable DontRollback() for all pages */
-  u8 memDb;                   /* True to inhibit all file I/O */
-  u8 setMaster;               /* True if a m-j name has been written to jrnl */
-  u8 doNotSync;               /* Boolean. While true, do not spill the cache */
-  u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
-  u8 journalMode;             /* On of the PAGER_JOURNALMODE_* values */
-  u8 dbModified;              /* True if there are any changes to the Db */
-  u8 changeCountDone;         /* Set after incrementing the change-counter */
-  u32 vfsFlags;               /* Flags for sqlite3_vfs.xOpen() */
-  int errCode;                /* One of several kinds of errors */
-  int dbSize;                 /* Number of pages in the file */
-  int origDbSize;             /* dbSize before the current change */
-  int stmtSize;               /* Size of database (in pages) at stmt_begin() */
-  int nRec;                   /* Number of pages written to the journal */
-  u32 cksumInit;              /* Quasi-random value added to every checksum */
-  int stmtNRec;               /* Number of records in stmt subjournal */
-  int nExtra;                 /* Add this many bytes to each in-memory page */
-  int pageSize;               /* Number of bytes in a page */
-  int nPage;                  /* Total number of in-memory pages */
-  int nRef;                   /* Number of in-memory pages with PgHdr.nRef>0 */
-  int mxPage;                 /* Maximum number of pages to hold in cache */
-  Pgno mxPgno;                /* Maximum allowed size of the database */
-  Bitvec *pInJournal;         /* One bit for each page in the database file */
-  Bitvec *pInStmt;            /* One bit for each page in the database */
-  char *zFilename;            /* Name of the database file */
-  char *zJournal;             /* Name of the journal file */
-  char *zDirectory;           /* Directory hold database and journal files */
-  sqlite3_file *fd, *jfd;     /* File descriptors for database and journal */
-  sqlite3_file *stfd;         /* File descriptor for the statement subjournal*/
-  BusyHandler *pBusyHandler;  /* Pointer to sqlite.busyHandler */
-  PagerLruList lru;           /* LRU list of free pages */
-  PgHdr *pAll;                /* List of all pages */
-  PgHdr *pStmt;               /* List of pages in the statement subjournal */
-  PgHdr *pDirty;              /* List of all dirty pages */
-  i64 journalOff;             /* Current byte offset in the journal file */
-  i64 journalHdr;             /* Byte offset to previous journal header */
-  i64 stmtHdrOff;             /* First journal header written this statement */
-  i64 stmtCksum;              /* cksumInit when statement was started */
-  i64 stmtJSize;              /* Size of journal at stmt_begin() */
-  int sectorSize;             /* Assumed sector size during rollback */
-#ifdef SQLITE_TEST
-  int nHit, nMiss;            /* Cache hits and missing */
-  int nRead, nWrite;          /* Database pages read/written */
-#endif
-  void (*xDestructor)(DbPage*,int); /* Call this routine when freeing pages */
-  void (*xReiniter)(DbPage*,int);   /* Call this routine when reloading pages */
-#ifdef SQLITE_HAS_CODEC
-  void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
-  void *pCodecArg;            /* First argument to xCodec() */
-#endif
-  int nHash;                  /* Size of the pager hash table */
-  PgHdr **aHash;              /* Hash table to map page number to PgHdr */
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  Pager *pNext;               /* Doubly linked list of pagers on which */
-  Pager *pPrev;               /* sqlite3_release_memory() will work */
-  volatile int iInUseMM;      /* Non-zero if unavailable to MM */
-  volatile int iInUseDB;      /* Non-zero if in sqlite3_release_memory() */
-#endif
-  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
-  char dbFileVers[16];        /* Changes whenever database file changes */
-  i64 journalSizeLimit;       /* Size limit for persistent journal files */
-};
+static void pcacheAddToLruList(PgHdr *pPage){
+  assert( sqlite3_mutex_held(pcache.mutex) );
+  assert( (pPage->flags&PGHDR_DIRTY)==0 );
+  if( pPage->pCache->bPurgeable==0 ) return;
+  if( pcache.pLruTail && (pPage->flags & PGHDR_REUSE_UNLIKELY)!=0 ){
+    /* If reuse is unlikely.  Put the page at the end of the LRU list
+    ** where it will be recycled sooner rather than later. 
+    */
+    assert( pcache.pLruHead );
+    pPage->pNextLru = 0;
+    pPage->pPrevLru = pcache.pLruTail;
+    pcache.pLruTail->pNextLru = pPage;
+    pcache.pLruTail = pPage;
+    pPage->flags &= ~PGHDR_REUSE_UNLIKELY;
+  }else{
+    /* If reuse is possible. the page goes at the beginning of the LRU
+    ** list so that it will be the last to be recycled.
+    */
+    if( pcache.pLruHead ){
+      pcache.pLruHead->pPrevLru = pPage;
+    }
+    pPage->pNextLru = pcache.pLruHead;
+    pcache.pLruHead = pPage;
+    pPage->pPrevLru = 0;
+    if( pcache.pLruTail==0 ){
+      pcache.pLruTail = pPage;
+    }
+  }
+}
 
-/*
-** The following global variables hold counters used for
-** testing purposes only.  These variables do not exist in
-** a non-testing build.  These variables are not thread-safe.
+/*********************************************** Memory Allocation ***********
+**
+** Initialize the page cache memory pool.
+**
+** This must be called at start-time when no page cache lines are
+** checked out. This function is not threadsafe.
 */
-#ifdef SQLITE_TEST
-SQLITE_API int sqlite3_pager_readdb_count = 0;    /* Number of full pages read from DB */
-SQLITE_API int sqlite3_pager_writedb_count = 0;   /* Number of full pages written to DB */
-SQLITE_API int sqlite3_pager_writej_count = 0;    /* Number of pages written to journal */
-SQLITE_API int sqlite3_pager_pgfree_count = 0;    /* Number of cache pages freed */
-# define PAGER_INCR(v)  v++
-#else
-# define PAGER_INCR(v)
-#endif
+SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
+  PgFreeslot *p;
+  sz &= ~7;
+  pcache.szSlot = sz;
+  pcache.pStart = pBuf;
+  pcache.pFree = 0;
+  while( n-- ){
+    p = (PgFreeslot*)pBuf;
+    p->pNext = pcache.pFree;
+    pcache.pFree = p;
+    pBuf = (void*)&((char*)pBuf)[sz];
+  }
+  pcache.pEnd = pBuf;
+}
 
 /*
-** The following variable points to the head of a double-linked list
-** of all pagers that are eligible for page stealing by the
-** sqlite3_release_memory() interface.  Access to this list is
-** protected by the SQLITE_MUTEX_STATIC_MEM2 mutex.
-*/
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-static Pager *sqlite3PagerList = 0;
-static PagerLruList sqlite3LruPageList = {0, 0, 0};
-#endif
+** Allocate a page cache line.  Look in the page cache memory pool first
+** and use an element from it first if available.  If nothing is available
+** in the page cache memory pool, go to the general purpose memory allocator.
+*/
+void *pcacheMalloc(int sz, PCache *pCache){
+  assert( sqlite3_mutex_held(pcache.mutex) );
+  if( sz<=pcache.szSlot && pcache.pFree ){
+    PgFreeslot *p = pcache.pFree;
+    pcache.pFree = p->pNext;
+    sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, sz);
+    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
+    return (void*)p;
+  }else{
+    void *p;
+
+    /* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the
+    ** global pcache mutex and unlock the pager-cache object pCache. This is 
+    ** so that if the attempt to allocate a new buffer causes the the 
+    ** configured soft-heap-limit to be breached, it will be possible to
+    ** reclaim memory from this pager-cache.
+    */
+    pcacheExitMutex();
+    p = sqlite3Malloc(sz);
+    pcacheEnterMutex();
 
+    if( p ){
+      sz = sqlite3MallocSize(p);
+      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
+    }
+    return p;
+  }
+}
+SQLITE_PRIVATE void *sqlite3PageMalloc(sz){
+  void *p;
+  pcacheEnterMutex();
+  p = pcacheMalloc(sz, 0);
+  pcacheExitMutex();
+  return p;
+}
 
 /*
-** Journal files begin with the following magic string.  The data
-** was obtained from /dev/random.  It is used only as a sanity check.
-**
-** Since version 2.8.0, the journal format contains additional sanity
-** checking information.  If the power fails while the journal is begin
-** written, semi-random garbage data might appear in the journal
-** file after power is restored.  If an attempt is then made
-** to roll the journal back, the database could be corrupted.  The additional
-** sanity checking data is an attempt to discover the garbage in the
-** journal and ignore it.
-**
-** The sanity checking information for the new journal format consists
-** of a 32-bit checksum on each page of data.  The checksum covers both
-** the page number and the pPager->pageSize bytes of data for the page.
-** This cksum is initialized to a 32-bit random value that appears in the
-** journal file right after the header.  The random initializer is important,
-** because garbage data that appears at the end of a journal is likely
-** data that was once in other files that have now been deleted.  If the
-** garbage data came from an obsolete journal file, the checksums might
-** be correct.  But by initializing the checksum to random value which
-** is different for every journal, we minimize that risk.
+** Release a pager memory allocation
 */
-static const unsigned char aJournalMagic[] = {
-  0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7,
-};
+void pcacheFree(void *p){
+  assert( sqlite3_mutex_held(pcache.mutex) );
+  if( p==0 ) return;
+  if( p>=pcache.pStart && p<pcache.pEnd ){
+    PgFreeslot *pSlot;
+    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
+    pSlot = (PgFreeslot*)p;
+    pSlot->pNext = pcache.pFree;
+    pcache.pFree = pSlot;
+  }else{
+    int iSize = sqlite3MallocSize(p);
+    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
+    sqlite3_free(p);
+  }
+}
+SQLITE_PRIVATE void sqlite3PageFree(void *p){
+  pcacheEnterMutex();
+  pcacheFree(p);
+  pcacheExitMutex();
+}
 
 /*
-** The size of the header and of each page in the journal is determined
-** by the following macros.
+** Allocate a new page.
 */
-#define JOURNAL_PG_SZ(pPager)  ((pPager->pageSize) + 8)
+static PgHdr *pcachePageAlloc(PCache *pCache){
+  PgHdr *p;
+  int sz = sizeof(*p) + pCache->szPage + pCache->szExtra;
+  assert( sqlite3_mutex_held(pcache.mutex) );
+  p = pcacheMalloc(sz, pCache);
+  if( p==0 ) return 0;
+  memset(p, 0, sizeof(PgHdr));
+  p->pData = (void*)&p[1];
+  p->pExtra = (void*)&((char*)p->pData)[pCache->szPage];
+  if( pCache->bPurgeable ){
+    pcache.nCurrentPage++;
+  }
+  return p;
+}
 
 /*
-** The journal header size for this pager. In the future, this could be
-** set to some value read from the disk controller. The important
-** characteristic is that it is the same size as a disk sector.
+** Deallocate a page
 */
-#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
+static void pcachePageFree(PgHdr *p){
+  assert( sqlite3_mutex_held(pcache.mutex) );
+  if( p->pCache->bPurgeable ){
+    pcache.nCurrentPage--;
+  }
+  pcacheFree(p->apSave[0]);
+  pcacheFree(p->apSave[1]);
+  pcacheFree(p);
+}
 
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
 /*
-** The macro MEMDB is true if we are dealing with an in-memory database.
-** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
-** the value of MEMDB will be a constant and the compiler will optimize
-** out code that would never execute.
+** Return the number of bytes that will be returned to the heap when
+** the argument is passed to pcachePageFree().
 */
-#ifdef SQLITE_OMIT_MEMORYDB
-# define MEMDB 0
-#else
-# define MEMDB pPager->memDb
+static int pcachePageSize(PgHdr *p){
+  assert( sqlite3_mutex_held(pcache.mutex) );
+  assert( !pcache.pStart );
+  assert( p->apSave[0]==0 );
+  assert( p->apSave[1]==0 );
+  assert( p && p->pCache );
+  return sqlite3MallocSize(p);
+}
 #endif
 
 /*
-** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
-** reserved for working around a windows/posix incompatibility). It is
-** used in the journal to signify that the remainder of the journal file 
-** is devoted to storing a master journal name - there are no more pages to
-** roll back. See comments for function writeMasterJournal() for details.
+** Attempt to 'recycle' a page from the global LRU list. Only clean,
+** unreferenced pages from purgeable caches are eligible for recycling.
+**
+** This function removes page pcache.pLruTail from the global LRU list,
+** and from the hash-table and PCache.pClean list of the owner pcache.
+** There should be no other references to the page.
+**
+** A pointer to the recycled page is returned, or NULL if no page is
+** eligible for recycling.
 */
-/* #define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize)) */
-#define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1)
+static PgHdr *pcacheRecyclePage(){
+  PgHdr *p = 0;
+  assert( sqlite3_mutex_held(pcache.mutex) );
+
+  if( (p=pcache.pLruTail) ){
+    assert( (p->flags&PGHDR_DIRTY)==0 );
+    pcacheRemoveFromLruList(p);
+    pcacheRemoveFromHash(p);
+    pcacheRemoveFromList(&p->pCache->pClean, p);
+  }
+
+  return p;
+}
 
 /*
-** The maximum legal page number is (2^31 - 1).
+** Obtain space for a page. Try to recycle an old page if the limit on the 
+** number of pages has been reached. If the limit has not been reached or
+** there are no pages eligible for recycling, allocate a new page.
+**
+** Return a pointer to the new page, or NULL if an OOM condition occurs.
 */
-#define PAGER_MAX_PGNO 2147483647
+static int pcacheRecycleOrAlloc(PCache *pCache, PgHdr **ppPage){
+  PgHdr *p = 0;
 
-/*
-** The pagerEnter() and pagerLeave() routines acquire and release
-** a mutex on each pager.  The mutex is recursive.
+  int szPage = pCache->szPage;
+  int szExtra = pCache->szExtra;
+
+  assert( pcache.isInit );
+  assert( sqlite3_mutex_held(pcache.mutex) );
+
+  *ppPage = 0;
+
+  /* If we have reached the limit for pinned/dirty pages, and there is at
+  ** least one dirty page, invoke the xStress callback to cause a page to
+  ** become clean.
+  */
+  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+  expensive_assert( pcacheCheckSynced(pCache) );
+  if( pCache->xStress
+   && pCache->pDirty
+   && pCache->nPinned>=(pcache.nMaxPage+pCache->nMin-pcache.nMinPage)
+  ){
+    PgHdr *pPg;
+    assert(pCache->pDirtyTail);
+
+    for(pPg=pCache->pSynced; 
+        pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); 
+        pPg=pPg->pPrev
+    );
+    if( !pPg ){
+      for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pPrev);
+    }
+    if( pPg ){
+      int rc;
+      pcacheExitMutex();
+      rc = pCache->xStress(pCache->pStress, pPg);
+      pcacheEnterMutex();
+      if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
+        return rc;
+      }
+    }
+  }
+
+  /* If the global page limit has been reached, try to recycle a page. */
+  if( pCache->bPurgeable && pcache.nCurrentPage>=pcache.nMaxPage ){
+    p = pcacheRecyclePage();
+  }
+
+  /* If a page has been recycled but it is the wrong size, free it. */
+  if( p && (p->pCache->szPage!=szPage || p->pCache->szPage!=szExtra) ){
+    pcachePageFree(p);
+    p = 0;
+  }
+
+  if( !p ){
+    p = pcachePageAlloc(pCache);
+  }
+
+  *ppPage = p;
+  return (p?SQLITE_OK:SQLITE_NOMEM);
+}
+
+/*************************************************** General Interfaces ******
 **
-** This is a special-purpose mutex.  It only provides mutual exclusion
-** between the Btree and the Memory Management sqlite3_release_memory()
-** function.  It does not prevent, for example, two Btrees from accessing
-** the same pager at the same time.  Other general-purpose mutexes in
-** the btree layer handle that chore.
+** Initialize and shutdown the page cache subsystem. Neither of these 
+** functions are threadsafe.
 */
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  static void pagerEnter(Pager *p){
-    p->iInUseDB++;
-    if( p->iInUseMM && p->iInUseDB==1 ){
-#ifndef SQLITE_MUTEX_NOOP
-      sqlite3_mutex *mutex;
-      mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
-#endif
-      p->iInUseDB = 0;
-      sqlite3_mutex_enter(mutex);
-      p->iInUseDB = 1;
-      sqlite3_mutex_leave(mutex);
-    }
-    assert( p->iInUseMM==0 );
-  }
-  static void pagerLeave(Pager *p){
-    p->iInUseDB--;
-    assert( p->iInUseDB>=0 );
+SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
+  assert( pcache.isInit==0 );
+  memset(&pcache, 0, sizeof(pcache));
+  if( sqlite3Config.bCoreMutex ){
+    /* No need to check the return value of sqlite3_mutex_alloc(). 
+    ** Allocating a static mutex cannot fail.
+    */
+    pcache.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
   }
-#else
-# define pagerEnter(X)
-# define pagerLeave(X)
-#endif
+  pcache.isInit = 1;
+  return SQLITE_OK;
+}
+SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
+  memset(&pcache, 0, sizeof(pcache));
+}
 
 /*
-** Add page pPg to the end of the linked list managed by structure
-** pList (pPg becomes the last entry in the list - the most recently 
-** used). Argument pLink should point to either pPg->free or pPg->gfree,
-** depending on whether pPg is being added to the pager-specific or
-** global LRU list.
+** Return the size in bytes of a PCache object.
 */
-static void listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){
-  pLink->pNext = 0;
-  pLink->pPrev = pList->pLast;
+SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
 
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  assert(pLink==&pPg->free || pLink==&pPg->gfree);
-  assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList);
-#endif
+/*
+** Create a new PCache object.  Storage space to hold the object
+** has already been allocated and is passed in as the p pointer.
+*/
+SQLITE_PRIVATE void sqlite3PcacheOpen(
+  int szPage,                  /* Size of every page */
+  int szExtra,                 /* Extra space associated with each page */
+  int bPurgeable,              /* True if pages are on backing store */
+  void (*xDestroy)(PgHdr*),    /* Called to destroy a page */
+  int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
+  void *pStress,               /* Argument to xStress */
+  PCache *p                    /* Preallocated space for the PCache */
+){
+  assert( pcache.isInit );
+  memset(p, 0, sizeof(PCache));
+  p->szPage = szPage;
+  p->szExtra = szExtra;
+  p->bPurgeable = bPurgeable;
+  p->xDestroy = xDestroy;
+  p->xStress = xStress;
+  p->pStress = pStress;
+  p->nMax = 100;
+  p->nMin = 10;
 
-  if( pList->pLast ){
-    int iOff = (char *)pLink - (char *)pPg;
-    PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)[iOff]);
-    pLastLink->pNext = pPg;
-  }else{
-    assert(!pList->pFirst);
-    pList->pFirst = pPg;
+  pcacheEnterMutex();
+  if( bPurgeable ){
+    pcache.nMaxPage += p->nMax;
+    pcache.nMinPage += p->nMin;
   }
 
-  pList->pLast = pPg;
-  if( !pList->pFirstSynced && pPg->needSync==0 ){
-    pList->pFirstSynced = pPg;
-  }
+  pcacheExitMutex();
 }
 
 /*
-** Remove pPg from the list managed by the structure pointed to by pList.
-**
-** Argument pLink should point to either pPg->free or pPg->gfree, depending 
-** on whether pPg is being added to the pager-specific or global LRU list.
+** Change the page size for PCache object.  This can only happen
+** when the cache is empty.
 */
-static void listRemove(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){
-  int iOff = (char *)pLink - (char *)pPg;
+SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
+  assert(pCache->nPage==0);
+  pCache->szPage = szPage;
+}
 
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  assert(pLink==&pPg->free || pLink==&pPg->gfree);
-  assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList);
-#endif
+/*
+** Try to obtain a page from the cache.
+*/
+SQLITE_PRIVATE int sqlite3PcacheFetch(
+  PCache *pCache,       /* Obtain the page from this cache */
+  Pgno pgno,            /* Page number to obtain */
+  int createFlag,       /* If true, create page if it does not exist already */
+  PgHdr **ppPage        /* Write the page here */
+){
+  int rc = SQLITE_OK;
+  PgHdr *pPage = 0;
 
-  if( pPg==pList->pFirst ){
-    pList->pFirst = pLink->pNext;
-  }
-  if( pPg==pList->pLast ){
-    pList->pLast = pLink->pPrev;
-  }
-  if( pLink->pPrev ){
-    PagerLruLink *pPrevLink = (PagerLruLink *)(&((u8 *)pLink->pPrev)[iOff]);
-    pPrevLink->pNext = pLink->pNext;
-  }
-  if( pLink->pNext ){
-    PagerLruLink *pNextLink = (PagerLruLink *)(&((u8 *)pLink->pNext)[iOff]);
-    pNextLink->pPrev = pLink->pPrev;
+  assert( pcache.isInit );
+  assert( pCache!=0 );
+  assert( pgno>0 );
+  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+
+  pcacheEnterMutex();
+
+  /* Search the hash table for the requested page. Exit early if it is found. */
+  if( pCache->apHash ){
+    u32 h = pgno % pCache->nHash;
+    for(pPage=pCache->apHash[h]; pPage; pPage=pPage->pNextHash){
+      if( pPage->pgno==pgno ){
+        if( pPage->nRef==0 ){
+          if( 0==(pPage->flags&PGHDR_DIRTY) ){
+            pcacheRemoveFromLruList(pPage);
+            pCache->nPinned++;
+          }
+          pCache->nRef++;
+        }
+        pPage->nRef++;
+        break;
+      }
+    }
   }
-  if( pPg==pList->pFirstSynced ){
-    PgHdr *p = pLink->pNext;
-    while( p && p->needSync ){
-      PagerLruLink *pL = (PagerLruLink *)(&((u8 *)p)[iOff]);
-      p = pL->pNext;
+
+  if( !pPage && createFlag ){
+    if( pCache->nHash<=pCache->nPage ){
+      rc = pcacheResizeHash(pCache, pCache->nHash<256 ? 256 : pCache->nHash*2);
+    }
+    if( rc==SQLITE_OK ){
+      rc = pcacheRecycleOrAlloc(pCache, &pPage);
+    }
+    if( rc==SQLITE_OK ){
+      pPage->pPager = 0;
+      pPage->flags = 0;
+      pPage->pDirty = 0;
+      pPage->pgno = pgno;
+      pPage->pCache = pCache;
+      pPage->nRef = 1;
+      pCache->nRef++;
+      pCache->nPinned++;
+      pcacheAddToList(&pCache->pClean, pPage);
+      pcacheAddToHash(pPage);
     }
-    pList->pFirstSynced = p;
   }
 
-  pLink->pNext = pLink->pPrev = 0;
+  pcacheExitMutex();
+
+  *ppPage = pPage;
+  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+  assert( pPage || !createFlag || rc!=SQLITE_OK );
+  return rc;
 }
 
-/* 
-** Add page pPg to the list of free pages for the pager. If 
-** memory-management is enabled, also add the page to the global 
-** list of free pages.
+/*
+** Dereference a page.  When the reference count reaches zero,
+** move the page to the LRU list if it is clean.
 */
-static void lruListAdd(PgHdr *pPg){
-  listAdd(&pPg->pPager->lru, &pPg->free, pPg);
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  if( !pPg->pPager->memDb ){
-    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
-    listAdd(&sqlite3LruPageList, &pPg->gfree, pPg);
-    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr *p){
+  assert( p->nRef>0 );
+  p->nRef--;
+  if( p->nRef==0 ){
+    PCache *pCache = p->pCache;
+    if( p->pCache->xDestroy ){
+      p->pCache->xDestroy(p);
+    }
+    pCache->nRef--;
+    if( (p->flags&PGHDR_DIRTY)==0 ){
+      pCache->nPinned--;
+      pcacheEnterMutex();
+      if( pcache.nCurrentPage>pcache.nMaxPage ){
+        pcacheRemoveFromList(&pCache->pClean, p);
+        pcacheRemoveFromHash(p);
+        pcachePageFree(p);
+      }else{
+        pcacheAddToLruList(p);
+      }
+      pcacheExitMutex();
+    }else{
+      /* Move the page to the head of the caches dirty list. */
+      pcacheRemoveFromList(&pCache->pDirty, p);
+      pcacheAddToList(&pCache->pDirty, p);
+    }
   }
-#endif
 }
 
-/* 
-** Remove page pPg from the list of free pages for the associated pager.
-** If memory-management is enabled, also remove pPg from the global list
-** of free pages.
+SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){
+  assert(p->nRef>0);
+  p->nRef++;
+}
+
+/*
+** Drop a page from the cache. There must be exactly one reference to the
+** page. This function deletes that reference, so after it returns the
+** page pointed to by p is invalid.
+*/
+SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){
+  PCache *pCache;
+  assert( p->nRef==1 );
+  assert( 0==(p->flags&PGHDR_DIRTY) );
+  pCache = p->pCache;
+  pCache->nRef--;
+  pCache->nPinned--;
+  pcacheEnterMutex();
+  pcacheRemoveFromList(&pCache->pClean, p);
+  pcacheRemoveFromHash(p);
+  pcachePageFree(p);
+  pcacheExitMutex();
+}
+
+/*
+** Make sure the page is marked as dirty.  If it isn't dirty already,
+** make it so.
+*/
+SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
+  PCache *pCache;
+  p->flags &= ~PGHDR_DONT_WRITE;
+  if( p->flags & PGHDR_DIRTY ) return;
+  assert( (p->flags & PGHDR_DIRTY)==0 );
+  assert( p->nRef>0 );
+  pCache = p->pCache;
+  pcacheEnterMutex();
+  pcacheRemoveFromList(&pCache->pClean, p);
+  pcacheAddToList(&pCache->pDirty, p);
+  pcacheExitMutex();
+  p->flags |= PGHDR_DIRTY;
+}
+
+void pcacheMakeClean(PgHdr *p){
+  PCache *pCache = p->pCache;
+  assert( p->apSave[0]==0 && p->apSave[1]==0 );
+  assert( p->flags & PGHDR_DIRTY );
+  pcacheRemoveFromList(&pCache->pDirty, p);
+  pcacheAddToList(&pCache->pClean, p);
+  p->flags &= ~PGHDR_DIRTY;
+  if( p->nRef==0 ){
+    pcacheAddToLruList(p);
+    pCache->nPinned--;
+  }
+  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+}
+
+/*
+** Make sure the page is marked as clean.  If it isn't clean already,
+** make it so.
 */
-static void lruListRemove(PgHdr *pPg){
-  listRemove(&pPg->pPager->lru, &pPg->free, pPg);
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  if( !pPg->pPager->memDb ){
-    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
-    listRemove(&sqlite3LruPageList, &pPg->gfree, pPg);
-    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){
+  if( (p->flags & PGHDR_DIRTY) ){
+    pcacheEnterMutex();
+    pcacheMakeClean(p);
+    pcacheExitMutex();
   }
-#endif
 }
 
-/* 
-** This function is called just after the needSync flag has been cleared
-** from all pages managed by pPager (usually because the journal file
-** has just been synced). It updates the pPager->lru.pFirstSynced variable
-** and, if memory-management is enabled, the sqlite3LruPageList.pFirstSynced
-** variable also.
+/*
+** Make every page in the cache clean.
 */
-static void lruListSetFirstSynced(Pager *pPager){
-  pPager->lru.pFirstSynced = pPager->lru.pFirst;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  if( !pPager->memDb ){
-    PgHdr *p;
-    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
-    for(p=sqlite3LruPageList.pFirst; p && p->needSync; p=p->gfree.pNext);
-    assert(p==pPager->lru.pFirstSynced || p==sqlite3LruPageList.pFirstSynced);
-    sqlite3LruPageList.pFirstSynced = p;
-    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){
+  PgHdr *p;
+  pcacheEnterMutex();
+  while( (p = pCache->pDirty)!=0 ){
+    assert( p->apSave[0]==0 && p->apSave[1]==0 );
+    pcacheRemoveFromList(&pCache->pDirty, p);
+    p->flags &= ~PGHDR_DIRTY;
+    pcacheAddToList(&pCache->pClean, p);
+    if( p->nRef==0 ){
+      pcacheAddToLruList(p);
+      pCache->nPinned--;
+    }
   }
-#endif
+  sqlite3PcacheAssertFlags(pCache, 0, PGHDR_DIRTY);
+  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+  pcacheExitMutex();
 }
 
 /*
-** Return true if page *pPg has already been written to the statement
-** journal (or statement snapshot has been created, if *pPg is part
-** of an in-memory database).
+** Change the page number of page p to newPgno. If newPgno is 0, then the
+** page object is added to the clean-list and the PGHDR_REUSE_UNLIKELY 
+** flag set.
 */
-static int pageInStatement(PgHdr *pPg){
-  Pager *pPager = pPg->pPager;
-  if( MEMDB ){
-    return PGHDR_TO_HIST(pPg, pPager)->inStmt;
-  }else{
-    return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
+SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
+  assert( p->nRef>0 );
+  pcacheEnterMutex();
+  pcacheRemoveFromHash(p);
+  p->pgno = newPgno;
+  if( newPgno==0 ){
+    p->flags |= PGHDR_REUSE_UNLIKELY;
+    pcacheFree(p->apSave[0]);
+    pcacheFree(p->apSave[1]);
+    p->apSave[0] = 0;
+    p->apSave[1] = 0;
+    if( (p->flags & PGHDR_DIRTY) ){
+      pcacheMakeClean(p);
+    }
   }
+  pcacheAddToHash(p);
+  pcacheExitMutex();
 }
 
 /*
-** Change the size of the pager hash table to N.  N must be a power
-** of two.
+** Remove all content from a page cache
 */
-static void pager_resize_hash_table(Pager *pPager, int N){
-  PgHdr **aHash, *pPg;
-  assert( N>0 && (N&(N-1))==0 );
-#ifdef SQLITE_MALLOC_SOFT_LIMIT
-  if( N*sizeof(aHash[0])>SQLITE_MALLOC_SOFT_LIMIT ){
-    N = SQLITE_MALLOC_SOFT_LIMIT/sizeof(aHash[0]);
+void pcacheClear(PCache *pCache){
+  PgHdr *p, *pNext;
+  assert( sqlite3_mutex_held(pcache.mutex) );
+  for(p=pCache->pClean; p; p=pNext){
+    pNext = p->pNext;
+    pcacheRemoveFromLruList(p);
+    pcachePageFree(p);
   }
-  if( N==pPager->nHash ) return;
-#endif
-  pagerLeave(pPager);
-  if( pPager->aHash!=0 ) sqlite3BeginBenignMalloc();
-  aHash = sqlite3MallocZero( sizeof(aHash[0])*N );
-  if( pPager->aHash!=0 ) sqlite3EndBenignMalloc();
-  pagerEnter(pPager);
-  if( aHash==0 ){
-    /* Failure to rehash is not an error.  It is only a performance hit. */
-    return;
+  for(p=pCache->pDirty; p; p=pNext){
+    pNext = p->pNext;
+    pcachePageFree(p);
   }
-  sqlite3_free(pPager->aHash);
-  pPager->nHash = N;
-  pPager->aHash = aHash;
-  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
-    int h;
-    if( pPg->pgno==0 ){
-      assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
-      continue;
+  pCache->pClean = 0;
+  pCache->pDirty = 0;
+  pCache->pDirtyTail = 0;
+  pCache->nPage = 0;
+  pCache->nPinned = 0;
+  memset(pCache->apHash, 0, pCache->nHash*sizeof(pCache->apHash[0]));
+}
+
+
+/*
+** Drop every cache entry whose page number is greater than "pgno".
+*/
+SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
+  PgHdr *p, *pNext;
+  PgHdr *pDirty = pCache->pDirty;
+  pcacheEnterMutex();
+  for(p=pCache->pClean; p||pDirty; p=pNext){
+    if( !p ){
+      p = pDirty;
+      pDirty = 0;
     }
-    h = pPg->pgno & (N-1);
-    pPg->pNextHash = aHash[h];
-    if( aHash[h] ){
-      aHash[h]->pPrevHash = pPg;
+    pNext = p->pNext;
+    if( p->pgno>pgno ){
+      if( p->nRef==0 ){
+        pcacheRemoveFromHash(p);
+        if( p->flags&PGHDR_DIRTY ){
+          pcacheRemoveFromList(&pCache->pDirty, p);
+          pCache->nPinned--;
+        }else{
+          pcacheRemoveFromList(&pCache->pClean, p);
+          pcacheRemoveFromLruList(p);
+        }
+        pcachePageFree(p);
+      }else{
+        /* If there are references to the page, it cannot be freed. In this
+        ** case, zero the page content instead.
+        */
+        memset(p->pData, 0, pCache->szPage);
+      }
     }
-    aHash[h] = pPg;
-    pPg->pPrevHash = 0;
   }
+  pcacheExitMutex();
 }
 
 /*
-** Read a 32-bit integer from the given file descriptor.  Store the integer
-** that is read in *pRes.  Return SQLITE_OK if everything worked, or an
-** error code is something goes wrong.
-**
-** All values are stored on disk as big-endian.
+** If there are currently more than pcache.nMaxPage pages allocated, try
+** to recycle pages to reduce the number allocated to pcache.nMaxPage.
 */
-static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){
-  unsigned char ac[4];
-  int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
-  if( rc==SQLITE_OK ){
-    *pRes = sqlite3Get4byte(ac);
+static void pcacheEnforceMaxPage(){
+  PgHdr *p;
+  assert( sqlite3_mutex_held(pcache.mutex) );
+  while( pcache.nCurrentPage>pcache.nMaxPage && (p = pcacheRecyclePage()) ){
+    pcachePageFree(p);
   }
-  return rc;
 }
 
 /*
-** Write a 32-bit integer into a string buffer in big-endian byte order.
+** Close a cache.
 */
-#define put32bits(A,B)  sqlite3Put4byte((u8*)A,B)
+SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
+  pcacheEnterMutex();
+
+  /* Free all the pages used by this pager and remove them from the LRU list. */
+  pcacheClear(pCache);
+  if( pCache->bPurgeable ){
+    pcache.nMaxPage -= pCache->nMax;
+    pcache.nMinPage -= pCache->nMin;
+    pcacheEnforceMaxPage();
+  }
+  sqlite3_free(pCache->apHash);
+  pcacheExitMutex();
+}
 
 /*
-** Write a 32-bit integer into the given file descriptor.  Return SQLITE_OK
-** on success or an error code is something goes wrong.
+** Preserve the content of the page.  It is assumed that the content
+** has not been preserved already.
+**
+** If idJournal==0 then this is for the overall transaction.
+** If idJournal==1 then this is for the statement journal.
+**
+** This routine is used for in-memory databases only.
+**
+** Return SQLITE_OK or SQLITE_NOMEM if a memory allocation fails.
 */
-static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
-  char ac[4];
-  put32bits(ac, val);
-  return sqlite3OsWrite(fd, ac, 4, offset);
+SQLITE_PRIVATE int sqlite3PcachePreserve(PgHdr *p, int idJournal){
+  void *x;
+  int sz;
+  assert( p->pCache->bPurgeable==0 );
+  assert( p->apSave[idJournal]==0 );
+  sz = p->pCache->szPage;
+  p->apSave[idJournal] = x = sqlite3PageMalloc( sz );
+  if( x==0 ) return SQLITE_NOMEM;
+  memcpy(x, p->pData, sz);
+  return SQLITE_OK;
 }
 
 /*
-** If file pFd is open, call sqlite3OsUnlock() on it.
+** Commit a change previously preserved.
 */
-static int osUnlock(sqlite3_file *pFd, int eLock){
-  if( !pFd->pMethods ){
-    return SQLITE_OK;
+SQLITE_PRIVATE void sqlite3PcacheCommit(PCache *pCache, int idJournal){
+  PgHdr *p;
+  pcacheEnterMutex();     /* Mutex is required to call pcacheFree() */
+  for(p=pCache->pDirty; p; p=p->pNext){
+    if( p->apSave[idJournal] ){
+      pcacheFree(p->apSave[idJournal]);
+      p->apSave[idJournal] = 0;
+    }
   }
-  return sqlite3OsUnlock(pFd, eLock);
+  pcacheExitMutex();
 }
 
 /*
-** This function determines whether or not the atomic-write optimization
-** can be used with this pager. The optimization can be used if:
-**
-**  (a) the value returned by OsDeviceCharacteristics() indicates that
-**      a database page may be written atomically, and
-**  (b) the value returned by OsSectorSize() is less than or equal
-**      to the page size.
-**
-** If the optimization cannot be used, 0 is returned. If it can be used,
-** then the value returned is the size of the journal file when it
-** contains rollback data for exactly one page.
+** Rollback a change previously preserved.
 */
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
-static int jrnlBufferSize(Pager *pPager){
-  int dc;           /* Device characteristics */
-  int nSector;      /* Sector size */
-  int szPage;        /* Page size */
-  sqlite3_file *fd = pPager->fd;
+SQLITE_PRIVATE void sqlite3PcacheRollback(PCache *pCache, int idJournal){
+  PgHdr *p;
+  int sz;
+  pcacheEnterMutex();     /* Mutex is required to call pcacheFree() */
+  sz = pCache->szPage;
+  for(p=pCache->pDirty; p; p=p->pNext){
+    if( p->apSave[idJournal] ){
+      memcpy(p->pData, p->apSave[idJournal], sz);
+      pcacheFree(p->apSave[idJournal]);
+      p->apSave[idJournal] = 0;
+    }
+  }
+  pcacheExitMutex();
+}
 
-  if( fd->pMethods ){
-    dc = sqlite3OsDeviceCharacteristics(fd);
-    nSector = sqlite3OsSectorSize(fd);
-    szPage = pPager->pageSize;
+/* 
+** Assert flags settings on all pages.  Debugging only.
+*/
+SQLITE_PRIVATE void sqlite3PcacheAssertFlags(PCache *pCache, int trueMask, int falseMask){
+  PgHdr *p;
+  for(p=pCache->pDirty; p; p=p->pNext){
+    assert( (p->flags&trueMask)==trueMask );
+    assert( (p->flags&falseMask)==0 );
+  }
+  for(p=pCache->pClean; p; p=p->pNext){
+    assert( (p->flags&trueMask)==trueMask );
+    assert( (p->flags&falseMask)==0 );
   }
+}
 
-  assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
-  assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
+/* 
+** Discard the contents of the cache.
+*/
+SQLITE_PRIVATE int sqlite3PcacheClear(PCache *pCache){
+  assert(pCache->nRef==0);
+  pcacheEnterMutex();
+  pcacheClear(pCache);
+  pcacheExitMutex();
+  return SQLITE_OK;
+}
 
-  if( !fd->pMethods || 
-       (dc & (SQLITE_IOCAP_ATOMIC|(szPage>>8)) && nSector<=szPage) ){
-    return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
+/*
+** Merge two lists of pages connected by pDirty and in pgno order.
+** Do not both fixing the pPrevDirty pointers.
+*/
+static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
+  PgHdr result, *pTail;
+  pTail = &result;
+  while( pA && pB ){
+    if( pA->pgno<pB->pgno ){
+      pTail->pDirty = pA;
+      pTail = pA;
+      pA = pA->pDirty;
+    }else{
+      pTail->pDirty = pB;
+      pTail = pB;
+      pB = pB->pDirty;
+    }
   }
-  return 0;
+  if( pA ){
+    pTail->pDirty = pA;
+  }else if( pB ){
+    pTail->pDirty = pB;
+  }else{
+    pTail->pDirty = 0;
+  }
+  return result.pDirty;
 }
-#endif
 
 /*
-** This function should be called when an error occurs within the pager
-** code. The first argument is a pointer to the pager structure, the
-** second the error-code about to be returned by a pager API function. 
-** The value returned is a copy of the second argument to this function. 
-**
-** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT, or SQLITE_FULL
-** the error becomes persistent. Until the persisten error is cleared,
-** subsequent API calls on this Pager will immediately return the same 
-** error code.
-**
-** A persistent error indicates that the contents of the pager-cache 
-** cannot be trusted. This state can be cleared by completely discarding 
-** the contents of the pager-cache. If a transaction was active when
-** the persistent error occured, then the rollback journal may need
-** to be replayed.
+** Sort the list of pages in accending order by pgno.  Pages are
+** connected by pDirty pointers.  The pPrevDirty pointers are
+** corrupted by this sort.
 */
-static void pager_unlock(Pager *pPager);
-static int pager_error(Pager *pPager, int rc){
-  int rc2 = rc & 0xff;
-  assert(
-       pPager->errCode==SQLITE_FULL ||
-       pPager->errCode==SQLITE_OK ||
-       (pPager->errCode & 0xff)==SQLITE_IOERR
-  );
-  if(
-    rc2==SQLITE_FULL ||
-    rc2==SQLITE_IOERR ||
-    rc2==SQLITE_CORRUPT
-  ){
-    pPager->errCode = rc;
-    if( pPager->state==PAGER_UNLOCK && pPager->nRef==0 ){
-      /* If the pager is already unlocked, call pager_unlock() now to
-      ** clear the error state and ensure that the pager-cache is 
-      ** completely empty.
+#define N_SORT_BUCKET_ALLOC 25
+#define N_SORT_BUCKET       25
+#ifdef SQLITE_TEST
+  int sqlite3_pager_n_sort_bucket = 0;
+  #undef N_SORT_BUCKET
+  #define N_SORT_BUCKET \
+   (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)
+#endif
+static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
+  PgHdr *a[N_SORT_BUCKET_ALLOC], *p;
+  int i;
+  memset(a, 0, sizeof(a));
+  while( pIn ){
+    p = pIn;
+    pIn = p->pDirty;
+    p->pDirty = 0;
+    for(i=0; i<N_SORT_BUCKET-1; i++){
+      if( a[i]==0 ){
+        a[i] = p;
+        break;
+      }else{
+        p = pcacheMergeDirtyList(a[i], p);
+        a[i] = 0;
+      }
+    }
+    if( i==N_SORT_BUCKET-1 ){
+      /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET) 
+      ** elements in the input list. This is possible, but impractical.
+      ** Testing this line is the point of global variable
+      ** sqlite3_pager_n_sort_bucket.
       */
-      pager_unlock(pPager);
+      a[i] = pcacheMergeDirtyList(a[i], p);
     }
   }
-  return rc;
+  p = a[0];
+  for(i=1; i<N_SORT_BUCKET; i++){
+    p = pcacheMergeDirtyList(p, a[i]);
+  }
+  return p;
 }
 
 /*
-** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
-** on the cache using a hash function.  This is used for testing
-** and debugging only.
-*/
-#ifdef SQLITE_CHECK_PAGES
-/*
-** Return a 32-bit hash of the page data for pPage.
+** Return a list of all dirty pages in the cache, sorted by page number.
 */
-static u32 pager_datahash(int nByte, unsigned char *pData){
-  u32 hash = 0;
-  int i;
-  for(i=0; i<nByte; i++){
-    hash = (hash*1039) + pData[i];
+SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
+  PgHdr *p;
+  for(p=pCache->pDirty; p; p=p->pNext){
+    p->pDirty = p->pNext;
   }
-  return hash;
-}
-static u32 pager_pagehash(PgHdr *pPage){
-  return pager_datahash(pPage->pPager->pageSize, 
-                        (unsigned char *)PGHDR_TO_DATA(pPage));
+  return pcacheSortDirtyList(pCache->pDirty);
 }
 
-/*
-** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
-** is defined, and NDEBUG is not defined, an assert() statement checks
-** that the page is either dirty or still matches the calculated page-hash.
+/* 
+** Return the total number of outstanding page references.
 */
-#define CHECK_PAGE(x) checkPage(x)
-static void checkPage(PgHdr *pPg){
-  Pager *pPager = pPg->pPager;
-  assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty || 
-      pPg->pageHash==pager_pagehash(pPg) );
+SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
+  return pCache->nRef;
 }
 
-#else
-#define pager_datahash(X,Y)  0
-#define pager_pagehash(X)  0
-#define CHECK_PAGE(x)
-#endif
+/* 
+** Return the total number of pages in the cache.
+*/
+SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
+  assert( pCache->nPage>=0 );
+  return pCache->nPage;
+}
 
+#ifdef SQLITE_CHECK_PAGES
 /*
-** When this is called the journal file for pager pPager must be open.
-** The master journal file name is read from the end of the file and 
-** written into memory supplied by the caller. 
-**
-** zMaster must point to a buffer of at least nMaster bytes allocated by
-** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
-** enough space to write the master journal name). If the master journal
-** name in the journal is longer than nMaster bytes (including a
-** nul-terminator), then this is handled as if no master journal name
-** were present in the journal.
-**
-** If no master journal file name is present zMaster[0] is set to 0 and
-** SQLITE_OK returned.
+** This function is used by the pager.c module to iterate through all 
+** pages in the cache. At present, this is only required if the
+** SQLITE_CHECK_PAGES macro (used for debugging) is specified.
 */
-static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, int nMaster){
-  int rc;
-  u32 len;
-  i64 szJ;
-  u32 cksum;
-  u32 u;                   /* Unsigned loop counter */
-  unsigned char aMagic[8]; /* A buffer to hold the magic header */
+SQLITE_PRIVATE void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *)){
+  PgHdr *p;
+  for(p=pCache->pClean; p; p=p->pNext){
+    xIter(p);
+  }
+  for(p=pCache->pDirty; p; p=p->pNext){
+    xIter(p);
+  }
+}
+#endif
 
-  zMaster[0] = '\0';
+/* 
+** Set flags on all pages in the page cache 
+*/
+SQLITE_PRIVATE void sqlite3PcacheSetFlags(PCache *pCache, int andMask, int orMask){
+  PgHdr *p;
 
-  rc = sqlite3OsFileSize(pJrnl, &szJ);
-  if( rc!=SQLITE_OK || szJ<16 ) return rc;
+  assert( (orMask&PGHDR_NEED_SYNC)==0 );
 
-  rc = read32bits(pJrnl, szJ-16, &len);
-  if( rc!=SQLITE_OK ) return rc;
+  /* Obtain the global mutex before modifying any PgHdr.flags variables 
+  ** or traversing the LRU list.
+  */ 
+  pcacheEnterMutex();
 
-  if( len>=nMaster ){
-    return SQLITE_OK;
+  for(p=pCache->pDirty; p; p=p->pNext){
+    p->flags = (p->flags&andMask)|orMask;
   }
-
-  rc = read32bits(pJrnl, szJ-12, &cksum);
-  if( rc!=SQLITE_OK ) return rc;
-
-  rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8);
-  if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc;
-
-  rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len);
-  if( rc!=SQLITE_OK ){
-    return rc;
+  for(p=pCache->pClean; p; p=p->pNext){
+    p->flags = (p->flags&andMask)|orMask;
   }
-  zMaster[len] = '\0';
 
-  /* See if the checksum matches the master journal name */
-  for(u=0; u<len; u++){
-    cksum -= zMaster[u];
-   }
-  if( cksum ){
-    /* If the checksum doesn't add up, then one or more of the disk sectors
-    ** containing the master journal filename is corrupted. This means
-    ** definitely roll back, so just return SQLITE_OK and report a (nul)
-    ** master-journal filename.
-    */
-    zMaster[0] = '\0';
+  if( 0==(andMask&PGHDR_NEED_SYNC) ){
+    pCache->pSynced = pCache->pDirtyTail;
+    assert( !pCache->pSynced || (pCache->pSynced->flags&PGHDR_NEED_SYNC)==0 );
   }
-   
-  return SQLITE_OK;
+
+  pcacheExitMutex();
 }
 
 /*
-** Seek the journal file descriptor to the next sector boundary where a
-** journal header may be read or written. Pager.journalOff is updated with
-** the new seek offset.
-**
-** i.e for a sector size of 512:
-**
-** Input Offset              Output Offset
-** ---------------------------------------
-** 0                         0
-** 512                       512
-** 100                       512
-** 2000                      2048
-** 
+** Set the suggested cache-size value.
 */
-static void seekJournalHdr(Pager *pPager){
-  i64 offset = 0;
-  i64 c = pPager->journalOff;
-  if( c ){
-    offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);
-  }
-  assert( offset%JOURNAL_HDR_SZ(pPager)==0 );
-  assert( offset>=c );
-  assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
-  pPager->journalOff = offset;
+SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){
+  return pCache->nMax;
 }
 
 /*
-** Write zeros over the header of the journal file.  This has the
-** effect of invalidating the journal file and committing the
-** transaction.
+** Set the suggested cache-size value.
 */
-static int zeroJournalHdr(Pager *pPager, int doTruncate){
-  int rc = SQLITE_OK;
-  static const char zeroHdr[28];
-
-  if( pPager->journalOff ){
-    i64 iLimit = pPager->journalSizeLimit;
-
-    IOTRACE(("JZEROHDR %p\n", pPager))
-    if( doTruncate || iLimit==0 ){
-      rc = sqlite3OsTruncate(pPager->jfd, 0);
-    }else{
-      rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
-    }
-    if( rc==SQLITE_OK && !pPager->noSync ){
-      rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->sync_flags);
-    }
-
-    /* At this point the transaction is committed but the write lock 
-    ** is still held on the file. If there is a size limit configured for 
-    ** the persistent journal and the journal file currently consumes more
-    ** space than that limit allows for, truncate it now. There is no need
-    ** to sync the file following this operation.
-    */
-    if( rc==SQLITE_OK && iLimit>0 ){
-      i64 sz;
-      rc = sqlite3OsFileSize(pPager->jfd, &sz);
-      if( rc==SQLITE_OK && sz>iLimit ){
-        rc = sqlite3OsTruncate(pPager->jfd, iLimit);
-      }
-    }
+SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
+  if( mxPage<10 ){
+    mxPage = 10;
   }
-  return rc;
+  if( pCache->bPurgeable ){
+    pcacheEnterMutex();
+    pcache.nMaxPage -= pCache->nMax;
+    pcache.nMaxPage += mxPage;
+    pcacheEnforceMaxPage();
+    pcacheExitMutex();
+  }
+  pCache->nMax = mxPage;
 }
 
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
 /*
-** The journal file must be open when this routine is called. A journal
-** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
-** current location.
+** This function is called to free superfluous dynamically allocated memory
+** held by the pager system. Memory in use by any SQLite pager allocated
+** by the current thread may be sqlite3_free()ed.
 **
-** The format for the journal header is as follows:
-** - 8 bytes: Magic identifying journal format.
-** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
-** - 4 bytes: Random number used for page hash.
-** - 4 bytes: Initial database page count.
-** - 4 bytes: Sector size used by the process that wrote this journal.
-** - 4 bytes: Database page size.
-** 
-** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
+** nReq is the number of bytes of memory required. Once this much has
+** been released, the function returns. The return value is the total number 
+** of bytes of memory released.
 */
-static int writeJournalHdr(Pager *pPager){
-  int rc = SQLITE_OK;
-  char *zHeader = pPager->pTmpSpace;
-  int nHeader = pPager->pageSize;
-  int nWrite;
-
-  if( nHeader>JOURNAL_HDR_SZ(pPager) ){
-    nHeader = JOURNAL_HDR_SZ(pPager);
-  }
-
-  if( pPager->stmtHdrOff==0 ){
-    pPager->stmtHdrOff = pPager->journalOff;
-  }
-
-  seekJournalHdr(pPager);
-  pPager->journalHdr = pPager->journalOff;
-
-  memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
-
-  /* 
-  ** Write the nRec Field - the number of page records that follow this
-  ** journal header. Normally, zero is written to this value at this time.
-  ** After the records are added to the journal (and the journal synced, 
-  ** if in full-sync mode), the zero is overwritten with the true number
-  ** of records (see syncJournal()).
-  **
-  ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
-  ** reading the journal this value tells SQLite to assume that the
-  ** rest of the journal file contains valid page records. This assumption
-  ** is dangerous, as if a failure occured whilst writing to the journal
-  ** file it may contain some garbage data. There are two scenarios
-  ** where this risk can be ignored:
-  **
-  **   * When the pager is in no-sync mode. Corruption can follow a
-  **     power failure in this case anyway.
-  **
-  **   * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
-  **     that garbage data is never appended to the journal file.
-  */
-  assert(pPager->fd->pMethods||pPager->noSync);
-  if( (pPager->noSync) 
-   || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) 
-  ){
-    put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
-  }else{
-    put32bits(&zHeader[sizeof(aJournalMagic)], 0);
-  }
-
-  /* The random check-hash initialiser */ 
-  sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
-  put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
-  /* The initial database size */
-  put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize);
-  /* The assumed sector size for this process */
-  put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
-  if( pPager->journalHdr==0 ){
-    /* The page size */
-    put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
+SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
+  int nFree = 0;
+  if( pcache.pStart==0 ){
+    PgHdr *p;
+    pcacheEnterMutex();
+    while( (nReq<0 || nFree<nReq) && (p=pcacheRecyclePage()) ){
+      nFree += pcachePageSize(p);
+      pcachePageFree(p);
+    }
+    pcacheExitMutex();
   }
+  return nFree;
+}
+#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
 
-  for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
-    IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
-    rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
-    pPager->journalOff += nHeader;
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE void sqlite3PcacheStats(
+  int *pnCurrent,
+  int *pnMax,
+  int *pnMin,
+  int *pnRecyclable
+){
+  PgHdr *p;
+  int nRecyclable = 0;
+  for(p=pcache.pLruHead; p; p=p->pNextLru){
+    nRecyclable++;
   }
 
-  return rc;
+  *pnCurrent = pcache.nCurrentPage;
+  *pnMax = pcache.nMaxPage;
+  *pnMin = pcache.nMinPage;
+  *pnRecyclable = nRecyclable;
 }
+#endif
+
 
+/************** End of pcache.c **********************************************/
+/************** Begin file pager.c *******************************************/
 /*
-** The journal file must be open when this is called. A journal header file
-** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal
-** file. See comments above function writeJournalHdr() for a description of
-** the journal header format.
+** 2001 September 15
 **
-** If the header is read successfully, *nRec is set to the number of
-** page records following this header and *dbSize is set to the size of the
-** database before the transaction began, in pages. Also, pPager->cksumInit
-** is set to the value read from the journal header. SQLITE_OK is returned
-** in this case.
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
 **
-** If the journal header file appears to be corrupted, SQLITE_DONE is
-** returned and *nRec and *dbSize are not set.  If JOURNAL_HDR_SZ bytes
-** cannot be read from the journal file an error code is returned.
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This is the implementation of the page cache subsystem or "pager".
+** 
+** The pager is used to access a database disk file.  It implements
+** atomic commit and rollback through the use of a journal file that
+** is separate from the database file.  The pager also implements file
+** locking to prevent two processes from writing the same database
+** file simultaneously, or one process from reading the database while
+** another is writing.
+**
+** @(#) $Id: pager.c,v 1.485 2008/08/28 02:26:07 drh Exp $
 */
-static int readJournalHdr(
-  Pager *pPager, 
-  i64 journalSize,
-  u32 *pNRec, 
-  u32 *pDbSize
-){
-  int rc;
-  unsigned char aMagic[8]; /* A buffer to hold the magic header */
-  i64 jrnlOff;
-  int iPageSize;
-
-  seekJournalHdr(pPager);
-  if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
-    return SQLITE_DONE;
-  }
-  jrnlOff = pPager->journalOff;
-
-  rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), jrnlOff);
-  if( rc ) return rc;
-  jrnlOff += sizeof(aMagic);
-
-  if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
-    return SQLITE_DONE;
-  }
-
-  rc = read32bits(pPager->jfd, jrnlOff, pNRec);
-  if( rc ) return rc;
-
-  rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit);
-  if( rc ) return rc;
-
-  rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize);
-  if( rc ) return rc;
-
-  rc = read32bits(pPager->jfd, jrnlOff+16, (u32 *)&iPageSize);
-  if( rc==SQLITE_OK 
-   && iPageSize>=512 
-   && iPageSize<=SQLITE_MAX_PAGE_SIZE 
-   && ((iPageSize-1)&iPageSize)==0 
-  ){
-    u16 pagesize = iPageSize;
-    rc = sqlite3PagerSetPagesize(pPager, &pagesize);
-  }
-  if( rc ) return rc;
-
-  /* Update the assumed sector-size to match the value used by 
-  ** the process that created this journal. If this journal was
-  ** created by a process other than this one, then this routine
-  ** is being called from within pager_playback(). The local value
-  ** of Pager.sectorSize is restored at the end of that routine.
-  */
-  rc = read32bits(pPager->jfd, jrnlOff+12, (u32 *)&pPager->sectorSize);
-  if( rc ) return rc;
+#ifndef SQLITE_OMIT_DISKIO
 
-  pPager->journalOff += JOURNAL_HDR_SZ(pPager);
-  return SQLITE_OK;
-}
+/*
+** Macros for troubleshooting.  Normally turned off
+*/
+#if 0
+#define sqlite3DebugPrintf printf
+#define PAGERTRACE1(X)       sqlite3DebugPrintf(X)
+#define PAGERTRACE2(X,Y)     sqlite3DebugPrintf(X,Y)
+#define PAGERTRACE3(X,Y,Z)   sqlite3DebugPrintf(X,Y,Z)
+#define PAGERTRACE4(X,Y,Z,W) sqlite3DebugPrintf(X,Y,Z,W)
+#define PAGERTRACE5(X,Y,Z,W,V) sqlite3DebugPrintf(X,Y,Z,W,V)
+#else
+#define PAGERTRACE1(X)
+#define PAGERTRACE2(X,Y)
+#define PAGERTRACE3(X,Y,Z)
+#define PAGERTRACE4(X,Y,Z,W)
+#define PAGERTRACE5(X,Y,Z,W,V)
+#endif
 
+/*
+** The following two macros are used within the PAGERTRACEX() macros above
+** to print out file-descriptors. 
+**
+** PAGERID() takes a pointer to a Pager struct as its argument. The
+** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
+** struct as its argument.
+*/
+#define PAGERID(p) ((int)(p->fd))
+#define FILEHANDLEID(fd) ((int)fd)
 
 /*
-** Write the supplied master journal name into the journal file for pager
-** pPager at the current location. The master journal name must be the last
-** thing written to a journal file. If the pager is in full-sync mode, the
-** journal file descriptor is advanced to the next sector boundary before
-** anything is written. The format is:
+** The page cache as a whole is always in one of the following
+** states:
 **
-** + 4 bytes: PAGER_MJ_PGNO.
-** + N bytes: length of master journal name.
-** + 4 bytes: N
-** + 4 bytes: Master journal name checksum.
-** + 8 bytes: aJournalMagic[].
+**   PAGER_UNLOCK        The page cache is not currently reading or 
+**                       writing the database file.  There is no
+**                       data held in memory.  This is the initial
+**                       state.
 **
-** The master journal page checksum is the sum of the bytes in the master
-** journal name.
+**   PAGER_SHARED        The page cache is reading the database.
+**                       Writing is not permitted.  There can be
+**                       multiple readers accessing the same database
+**                       file at the same time.
 **
-** If zMaster is a NULL pointer (occurs for a single database transaction), 
-** this call is a no-op.
+**   PAGER_RESERVED      This process has reserved the database for writing
+**                       but has not yet made any changes.  Only one process
+**                       at a time can reserve the database.  The original
+**                       database file has not been modified so other
+**                       processes may still be reading the on-disk
+**                       database file.
+**
+**   PAGER_EXCLUSIVE     The page cache is writing the database.
+**                       Access is exclusive.  No other processes or
+**                       threads can be reading or writing while one
+**                       process is writing.
+**
+**   PAGER_SYNCED        The pager moves to this state from PAGER_EXCLUSIVE
+**                       after all dirty pages have been written to the
+**                       database file and the file has been synced to
+**                       disk. All that remains to do is to remove or
+**                       truncate the journal file and the transaction 
+**                       will be committed.
+**
+** The page cache comes up in PAGER_UNLOCK.  The first time a
+** sqlite3PagerGet() occurs, the state transitions to PAGER_SHARED.
+** After all pages have been released using sqlite_page_unref(),
+** the state transitions back to PAGER_UNLOCK.  The first time
+** that sqlite3PagerWrite() is called, the state transitions to
+** PAGER_RESERVED.  (Note that sqlite3PagerWrite() can only be
+** called on an outstanding page which means that the pager must
+** be in PAGER_SHARED before it transitions to PAGER_RESERVED.)
+** PAGER_RESERVED means that there is an open rollback journal.
+** The transition to PAGER_EXCLUSIVE occurs before any changes
+** are made to the database file, though writes to the rollback
+** journal occurs with just PAGER_RESERVED.  After an sqlite3PagerRollback()
+** or sqlite3PagerCommitPhaseTwo(), the state can go back to PAGER_SHARED,
+** or it can stay at PAGER_EXCLUSIVE if we are in exclusive access mode.
 */
-static int writeMasterJournal(Pager *pPager, const char *zMaster){
-  int rc;
-  int len; 
-  int i; 
-  i64 jrnlOff;
-  i64 jrnlSize;
-  u32 cksum = 0;
-  char zBuf[sizeof(aJournalMagic)+2*4];
-
-  if( !zMaster || pPager->setMaster) return SQLITE_OK;
-  pPager->setMaster = 1;
-
-  len = strlen(zMaster);
-  for(i=0; i<len; i++){
-    cksum += zMaster[i];
-  }
-
-  /* If in full-sync mode, advance to the next disk sector before writing
-  ** the master journal name. This is in case the previous page written to
-  ** the journal has already been synced.
-  */
-  if( pPager->fullSync ){
-    seekJournalHdr(pPager);
-  }
-  jrnlOff = pPager->journalOff;
-  pPager->journalOff += (len+20);
-
-  rc = write32bits(pPager->jfd, jrnlOff, PAGER_MJ_PGNO(pPager));
-  if( rc!=SQLITE_OK ) return rc;
-  jrnlOff += 4;
-
-  rc = sqlite3OsWrite(pPager->jfd, zMaster, len, jrnlOff);
-  if( rc!=SQLITE_OK ) return rc;
-  jrnlOff += len;
-
-  put32bits(zBuf, len);
-  put32bits(&zBuf[4], cksum);
-  memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic));
-  rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic), jrnlOff);
-  jrnlOff += 8+sizeof(aJournalMagic);
-  pPager->needSync = !pPager->noSync;
-
-  /* If the pager is in peristent-journal mode, then the physical 
-  ** journal-file may extend past the end of the master-journal name
-  ** and 8 bytes of magic data just written to the file. This is 
-  ** dangerous because the code to rollback a hot-journal file
-  ** will not be able to find the master-journal name to determine 
-  ** whether or not the journal is hot. 
-  **
-  ** Easiest thing to do in this scenario is to truncate the journal 
-  ** file to the required size.
-  */ 
-  if( (rc==SQLITE_OK)
-   && (rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))==SQLITE_OK
-   && jrnlSize>jrnlOff
-  ){
-    rc = sqlite3OsTruncate(pPager->jfd, jrnlOff);
-  }
-  return rc;
-}
+#define PAGER_UNLOCK      0
+#define PAGER_SHARED      1   /* same as SHARED_LOCK */
+#define PAGER_RESERVED    2   /* same as RESERVED_LOCK */
+#define PAGER_EXCLUSIVE   4   /* same as EXCLUSIVE_LOCK */
+#define PAGER_SYNCED      5
 
 /*
-** Add or remove a page from the list of all pages that are in the
-** statement journal.
-**
-** The Pager keeps a separate list of pages that are currently in
-** the statement journal.  This helps the sqlite3PagerStmtCommit()
-** routine run MUCH faster for the common case where there are many
-** pages in memory but only a few are in the statement journal.
+** If the SQLITE_BUSY_RESERVED_LOCK macro is set to true at compile-time,
+** then failed attempts to get a reserved lock will invoke the busy callback.
+** This is off by default.  To see why, consider the following scenario:
+** 
+** Suppose thread A already has a shared lock and wants a reserved lock.
+** Thread B already has a reserved lock and wants an exclusive lock.  If
+** both threads are using their busy callbacks, it might be a long time
+** be for one of the threads give up and allows the other to proceed.
+** But if the thread trying to get the reserved lock gives up quickly
+** (if it never invokes its busy callback) then the contention will be
+** resolved quickly.
 */
-static void page_add_to_stmt_list(PgHdr *pPg){
-  Pager *pPager = pPg->pPager;
-  PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
-  assert( MEMDB );
-  if( !pHist->inStmt ){
-    assert( pHist->pPrevStmt==0 && pHist->pNextStmt==0 );
-    if( pPager->pStmt ){
-      PGHDR_TO_HIST(pPager->pStmt, pPager)->pPrevStmt = pPg;
-    }
-    pHist->pNextStmt = pPager->pStmt;
-    pPager->pStmt = pPg;
-    pHist->inStmt = 1;
-  }
-}
+#ifndef SQLITE_BUSY_RESERVED_LOCK
+# define SQLITE_BUSY_RESERVED_LOCK 0
+#endif
 
 /*
-** Find a page in the hash table given its page number.  Return
-** a pointer to the page or NULL if not found.
+** This macro rounds values up so that if the value is an address it
+** is guaranteed to be an address that is aligned to an 8-byte boundary.
 */
-static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
-  PgHdr *p;
-  if( pPager->aHash==0 ) return 0;
-  p = pPager->aHash[pgno & (pPager->nHash-1)];
-  while( p && p->pgno!=pgno ){
-    p = p->pNextHash;
-  }
-  return p;
-}
+#define FORCE_ALIGNMENT(X)   (((X)+7)&~7)
 
 /*
-** Clear the in-memory cache.  This routine
-** sets the state of the pager back to what it was when it was first
-** opened.  Any outstanding pages are invalidated and subsequent attempts
-** to access those pages will likely result in a coredump.
+** A macro used for invoking the codec if there is one
 */
-static void pager_reset(Pager *pPager){
-  PgHdr *pPg, *pNext;
-  if( pPager->errCode ) return;
-  for(pPg=pPager->pAll; pPg; pPg=pNext){
-    IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
-    PAGER_INCR(sqlite3_pager_pgfree_count);
-    pNext = pPg->pNextAll;
-    lruListRemove(pPg);
-    sqlite3PageFree(pPg->pData);
-    sqlite3_free(pPg);
-  }
-  assert(pPager->lru.pFirst==0);
-  assert(pPager->lru.pFirstSynced==0);
-  assert(pPager->lru.pLast==0);
-  pPager->pStmt = 0;
-  pPager->pAll = 0;
-  pPager->pDirty = 0;
-  pPager->nHash = 0;
-  sqlite3_free(pPager->aHash);
-  pPager->nPage = 0;
-  pPager->aHash = 0;
-  pPager->nRef = 0;
-}
+#ifdef SQLITE_HAS_CODEC
+# define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); }
+# define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D))
+#else
+# define CODEC1(P,D,N,X) /* NO-OP */
+# define CODEC2(P,D,N,X) ((char*)D)
+#endif
 
 /*
-** Unlock the database file. 
+** A open page cache is an instance of the following structure.
 **
-** If the pager is currently in error state, discard the contents of 
-** the cache and reset the Pager structure internal state. If there is
-** an open journal-file, then the next time a shared-lock is obtained
-** on the pager file (by this or any other process), it will be
-** treated as a hot-journal and rolled back.
+** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, or
+** or SQLITE_FULL. Once one of the first three errors occurs, it persists
+** and is returned as the result of every major pager API call.  The
+** SQLITE_FULL return code is slightly different. It persists only until the
+** next successful rollback is performed on the pager cache. Also,
+** SQLITE_FULL does not affect the sqlite3PagerGet() and sqlite3PagerLookup()
+** APIs, they may still be used successfully.
 */
-static void pager_unlock(Pager *pPager){
-  if( !pPager->exclusiveMode ){
-    if( !MEMDB ){
-      int rc = osUnlock(pPager->fd, NO_LOCK);
-      if( rc ) pPager->errCode = rc;
-      pPager->dbSize = -1;
-      IOTRACE(("UNLOCK %p\n", pPager))
-
-      /* Always close the journal file when dropping the database lock.
-      ** Otherwise, another connection with journal_mode=delete might
-      ** delete the file out from under us.
-      */
-      if( pPager->journalOpen ){
-        sqlite3OsClose(pPager->jfd);
-        pPager->journalOpen = 0;
-        sqlite3BitvecDestroy(pPager->pInJournal);
-        pPager->pInJournal = 0;
-      }
+struct Pager {
+  sqlite3_vfs *pVfs;          /* OS functions to use for IO */
+  u8 journalOpen;             /* True if journal file descriptors is valid */
+  u8 journalStarted;          /* True if header of journal is synced */
+  u8 useJournal;              /* Use a rollback journal on this file */
+  u8 noReadlock;              /* Do not bother to obtain readlocks */
+  u8 stmtOpen;                /* True if the statement subjournal is open */
+  u8 stmtInUse;               /* True we are in a statement subtransaction */
+  u8 stmtAutoopen;            /* Open stmt journal when main journal is opened*/
+  u8 noSync;                  /* Do not sync the journal if true */
+  u8 fullSync;                /* Do extra syncs of the journal for robustness */
+  u8 sync_flags;              /* One of SYNC_NORMAL or SYNC_FULL */
+  u8 state;                   /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */
+  u8 tempFile;                /* zFilename is a temporary file */
+  u8 readOnly;                /* True for a read-only database */
+  u8 needSync;                /* True if an fsync() is needed on the journal */
+  u8 dirtyCache;              /* True if cached pages have changed */
+  u8 alwaysRollback;          /* Disable DontRollback() for all pages */
+  u8 memDb;                   /* True to inhibit all file I/O */
+  u8 setMaster;               /* True if a m-j name has been written to jrnl */
+  u8 doNotSync;               /* Boolean. While true, do not spill the cache */
+  u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
+  u8 journalMode;             /* On of the PAGER_JOURNALMODE_* values */
+  u8 dbModified;              /* True if there are any changes to the Db */
+  u8 changeCountDone;         /* Set after incrementing the change-counter */
+  u32 vfsFlags;               /* Flags for sqlite3_vfs.xOpen() */
+  int errCode;                /* One of several kinds of errors */
+  int dbSize;                 /* Number of pages in the file */
+  int origDbSize;             /* dbSize before the current change */
+  int stmtSize;               /* Size of database (in pages) at stmt_begin() */
+  int nRec;                   /* Number of pages written to the journal */
+  u32 cksumInit;              /* Quasi-random value added to every checksum */
+  int stmtNRec;               /* Number of records in stmt subjournal */
+  int nExtra;                 /* Add this many bytes to each in-memory page */
+  int pageSize;               /* Number of bytes in a page */
+  int nPage;                  /* Total number of in-memory pages */
+  int mxPage;                 /* Maximum number of pages to hold in cache */
+  Pgno mxPgno;                /* Maximum allowed size of the database */
+  Bitvec *pInJournal;         /* One bit for each page in the database file */
+  Bitvec *pInStmt;            /* One bit for each page in the database */
+  Bitvec *pAlwaysRollback;    /* One bit for each page marked always-rollback */
+  char *zFilename;            /* Name of the database file */
+  char *zJournal;             /* Name of the journal file */
+  char *zDirectory;           /* Directory hold database and journal files */
+  sqlite3_file *fd, *jfd;     /* File descriptors for database and journal */
+  sqlite3_file *stfd;         /* File descriptor for the statement subjournal*/
+  BusyHandler *pBusyHandler;  /* Pointer to sqlite.busyHandler */
+  i64 journalOff;             /* Current byte offset in the journal file */
+  i64 journalHdr;             /* Byte offset to previous journal header */
+  i64 stmtHdrOff;             /* First journal header written this statement */
+  i64 stmtCksum;              /* cksumInit when statement was started */
+  i64 stmtJSize;              /* Size of journal at stmt_begin() */
+  int sectorSize;             /* Assumed sector size during rollback */
+#ifdef SQLITE_TEST
+  int nHit, nMiss;            /* Cache hits and missing */
+  int nRead, nWrite;          /* Database pages read/written */
+#endif
+  void (*xDestructor)(DbPage*,int); /* Call this routine when freeing pages */
+  void (*xReiniter)(DbPage*,int);   /* Call this routine when reloading pages */
+#ifdef SQLITE_HAS_CODEC
+  void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
+  void *pCodecArg;            /* First argument to xCodec() */
+#endif
+  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
+  char dbFileVers[16];        /* Changes whenever database file changes */
+  i64 journalSizeLimit;       /* Size limit for persistent journal files */
+  PCache *pPCache;            /* Pointer to page cache object */
+};
 
-      /* If Pager.errCode is set, the contents of the pager cache cannot be
-      ** trusted. Now that the pager file is unlocked, the contents of the
-      ** cache can be discarded and the error code safely cleared.
-      */
-      if( pPager->errCode ){
-        if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;
-        pager_reset(pPager);
-        if( pPager->stmtOpen ){
-          sqlite3OsClose(pPager->stfd);
-          sqlite3BitvecDestroy(pPager->pInStmt);
-          pPager->pInStmt = 0;
-        }
-        pPager->stmtOpen = 0;
-        pPager->stmtInUse = 0;
-        pPager->journalOff = 0;
-        pPager->journalStarted = 0;
-        pPager->stmtAutoopen = 0;
-        pPager->origDbSize = 0;
-      }
-    }
+/*
+** The following global variables hold counters used for
+** testing purposes only.  These variables do not exist in
+** a non-testing build.  These variables are not thread-safe.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_pager_readdb_count = 0;    /* Number of full pages read from DB */
+SQLITE_API int sqlite3_pager_writedb_count = 0;   /* Number of full pages written to DB */
+SQLITE_API int sqlite3_pager_writej_count = 0;    /* Number of pages written to journal */
+# define PAGER_INCR(v)  v++
+#else
+# define PAGER_INCR(v)
+#endif
 
-    if( !MEMDB || pPager->errCode==SQLITE_OK ){
-      pPager->state = PAGER_UNLOCK;
-      pPager->changeCountDone = 0;
-    }
+
+
+/*
+** Journal files begin with the following magic string.  The data
+** was obtained from /dev/random.  It is used only as a sanity check.
+**
+** Since version 2.8.0, the journal format contains additional sanity
+** checking information.  If the power fails while the journal is begin
+** written, semi-random garbage data might appear in the journal
+** file after power is restored.  If an attempt is then made
+** to roll the journal back, the database could be corrupted.  The additional
+** sanity checking data is an attempt to discover the garbage in the
+** journal and ignore it.
+**
+** The sanity checking information for the new journal format consists
+** of a 32-bit checksum on each page of data.  The checksum covers both
+** the page number and the pPager->pageSize bytes of data for the page.
+** This cksum is initialized to a 32-bit random value that appears in the
+** journal file right after the header.  The random initializer is important,
+** because garbage data that appears at the end of a journal is likely
+** data that was once in other files that have now been deleted.  If the
+** garbage data came from an obsolete journal file, the checksums might
+** be correct.  But by initializing the checksum to random value which
+** is different for every journal, we minimize that risk.
+*/
+static const unsigned char aJournalMagic[] = {
+  0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7,
+};
+
+/*
+** The size of the header and of each page in the journal is determined
+** by the following macros.
+*/
+#define JOURNAL_PG_SZ(pPager)  ((pPager->pageSize) + 8)
+
+/*
+** The journal header size for this pager. In the future, this could be
+** set to some value read from the disk controller. The important
+** characteristic is that it is the same size as a disk sector.
+*/
+#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
+
+/*
+** The macro MEMDB is true if we are dealing with an in-memory database.
+** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
+** the value of MEMDB will be a constant and the compiler will optimize
+** out code that would never execute.
+*/
+#ifdef SQLITE_OMIT_MEMORYDB
+# define MEMDB 0
+#else
+# define MEMDB pPager->memDb
+#endif
+
+/*
+** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
+** reserved for working around a windows/posix incompatibility). It is
+** used in the journal to signify that the remainder of the journal file 
+** is devoted to storing a master journal name - there are no more pages to
+** roll back. See comments for function writeMasterJournal() for details.
+*/
+/* #define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize)) */
+#define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1)
+
+/*
+** The maximum legal page number is (2^31 - 1).
+*/
+#define PAGER_MAX_PGNO 2147483647
+
+/*
+** Return true if page *pPg has already been written to the statement
+** journal (or statement snapshot has been created, if *pPg is part
+** of an in-memory database).
+*/
+static int pageInStatement(PgHdr *pPg){
+  Pager *pPager = pPg->pPager;
+  if( MEMDB ){
+    return pPg->apSave[1]!=0;
+  }else{
+    return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
   }
 }
 
 /*
-** Execute a rollback if a transaction is active and unlock the 
-** database file. If the pager has already entered the error state, 
-** do not attempt the rollback.
+** Read a 32-bit integer from the given file descriptor.  Store the integer
+** that is read in *pRes.  Return SQLITE_OK if everything worked, or an
+** error code is something goes wrong.
+**
+** All values are stored on disk as big-endian.
 */
-static void pagerUnlockAndRollback(Pager *p){
-  /* assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); */
-  if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){
-    sqlite3BeginBenignMalloc();
-    sqlite3PagerRollback(p);
-    sqlite3EndBenignMalloc();
+static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){
+  unsigned char ac[4];
+  int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
+  if( rc==SQLITE_OK ){
+    *pRes = sqlite3Get4byte(ac);
   }
-  pager_unlock(p);
-#if 0
-  assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) );
-  assert( p->errCode || !p->stmtOpen || p->exclusiveMode );
-#endif
+  return rc;
 }
 
 /*
-** This routine ends a transaction.  A transaction is ended by either
-** a COMMIT or a ROLLBACK.
-**
-** When this routine is called, the pager has the journal file open and
-** a RESERVED or EXCLUSIVE lock on the database.  This routine will release
-** the database lock and acquires a SHARED lock in its place if that is
-** the appropriate thing to do.  Release locks usually is appropriate,
-** unless we are in exclusive access mode or unless this is a 
-** COMMIT AND BEGIN or ROLLBACK AND BEGIN operation.
+** Write a 32-bit integer into a string buffer in big-endian byte order.
+*/
+#define put32bits(A,B)  sqlite3Put4byte((u8*)A,B)
+
+/*
+** Write a 32-bit integer into the given file descriptor.  Return SQLITE_OK
+** on success or an error code is something goes wrong.
+*/
+static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
+  char ac[4];
+  put32bits(ac, val);
+  return sqlite3OsWrite(fd, ac, 4, offset);
+}
+
+/*
+** If file pFd is open, call sqlite3OsUnlock() on it.
+*/
+static int osUnlock(sqlite3_file *pFd, int eLock){
+  if( !pFd->pMethods ){
+    return SQLITE_OK;
+  }
+  return sqlite3OsUnlock(pFd, eLock);
+}
+
+/*
+** This function determines whether or not the atomic-write optimization
+** can be used with this pager. The optimization can be used if:
 **
-** The journal file is either deleted or truncated.
+**  (a) the value returned by OsDeviceCharacteristics() indicates that
+**      a database page may be written atomically, and
+**  (b) the value returned by OsSectorSize() is less than or equal
+**      to the page size.
 **
-** TODO: Consider keeping the journal file open for temporary databases.
-** This might give a performance improvement on windows where opening
-** a file is an expensive operation.
+** If the optimization cannot be used, 0 is returned. If it can be used,
+** then the value returned is the size of the journal file when it
+** contains rollback data for exactly one page.
 */
-static int pager_end_transaction(Pager *pPager, int hasMaster){
-  PgHdr *pPg;
-  int rc = SQLITE_OK;
-  int rc2 = SQLITE_OK;
-  assert( !MEMDB );
-  if( pPager->state<PAGER_RESERVED ){
-    return SQLITE_OK;
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+static int jrnlBufferSize(Pager *pPager){
+  int dc;           /* Device characteristics */
+  int nSector;      /* Sector size */
+  int szPage;        /* Page size */
+  sqlite3_file *fd = pPager->fd;
+
+  if( fd->pMethods ){
+    dc = sqlite3OsDeviceCharacteristics(fd);
+    nSector = sqlite3OsSectorSize(fd);
+    szPage = pPager->pageSize;
   }
-  sqlite3PagerStmtCommit(pPager);
-  if( pPager->stmtOpen && !pPager->exclusiveMode ){
-    sqlite3OsClose(pPager->stfd);
-    pPager->stmtOpen = 0;
+
+  assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
+  assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
+
+  if( !fd->pMethods || 
+       (dc & (SQLITE_IOCAP_ATOMIC|(szPage>>8)) && nSector<=szPage) ){
+    return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
   }
-  if( pPager->journalOpen ){
-    if( pPager->exclusiveMode 
-     || pPager->journalMode==PAGER_JOURNALMODE_PERSIST
-    ){
-      rc = zeroJournalHdr(pPager, hasMaster);
-      pager_error(pPager, rc);
-      pPager->journalOff = 0;
-      pPager->journalStarted = 0;
-    }else{
-      sqlite3OsClose(pPager->jfd);
-      pPager->journalOpen = 0;
-      if( rc==SQLITE_OK && !pPager->tempFile ){
-        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
-      }
-    }
-    sqlite3BitvecDestroy(pPager->pInJournal);
-    pPager->pInJournal = 0;
-    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
-      pPg->inJournal = 0;
-      pPg->dirty = 0;
-      pPg->needSync = 0;
-      pPg->alwaysRollback = 0;
-#ifdef SQLITE_CHECK_PAGES
-      pPg->pageHash = pager_pagehash(pPg);
+  return 0;
+}
 #endif
+
+/*
+** This function should be called when an error occurs within the pager
+** code. The first argument is a pointer to the pager structure, the
+** second the error-code about to be returned by a pager API function. 
+** The value returned is a copy of the second argument to this function. 
+**
+** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT, or SQLITE_FULL
+** the error becomes persistent. Until the persisten error is cleared,
+** subsequent API calls on this Pager will immediately return the same 
+** error code.
+**
+** A persistent error indicates that the contents of the pager-cache 
+** cannot be trusted. This state can be cleared by completely discarding 
+** the contents of the pager-cache. If a transaction was active when
+** the persistent error occured, then the rollback journal may need
+** to be replayed.
+*/
+static void pager_unlock(Pager *pPager);
+static int pager_error(Pager *pPager, int rc){
+  int rc2 = rc & 0xff;
+  assert(
+       pPager->errCode==SQLITE_FULL ||
+       pPager->errCode==SQLITE_OK ||
+       (pPager->errCode & 0xff)==SQLITE_IOERR
+  );
+  if(
+    rc2==SQLITE_FULL ||
+    rc2==SQLITE_IOERR ||
+    rc2==SQLITE_CORRUPT
+  ){
+    pPager->errCode = rc;
+    if( pPager->state==PAGER_UNLOCK 
+     && sqlite3PcacheRefCount(pPager->pPCache)==0 
+    ){
+      /* If the pager is already unlocked, call pager_unlock() now to
+      ** clear the error state and ensure that the pager-cache is 
+      ** completely empty.
+      */
+      pager_unlock(pPager);
     }
-    pPager->pDirty = 0;
-    pPager->dirtyCache = 0;
-    pPager->nRec = 0;
-  }else{
-    assert( pPager->pInJournal==0 );
   }
+  return rc;
+}
 
-  if( !pPager->exclusiveMode ){
-    rc2 = osUnlock(pPager->fd, SHARED_LOCK);
-    pPager->state = PAGER_SHARED;
-  }else if( pPager->state==PAGER_SYNCED ){
-    pPager->state = PAGER_EXCLUSIVE;
+/*
+** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
+** on the cache using a hash function.  This is used for testing
+** and debugging only.
+*/
+#ifdef SQLITE_CHECK_PAGES
+/*
+** Return a 32-bit hash of the page data for pPage.
+*/
+static u32 pager_datahash(int nByte, unsigned char *pData){
+  u32 hash = 0;
+  int i;
+  for(i=0; i<nByte; i++){
+    hash = (hash*1039) + pData[i];
   }
-  pPager->origDbSize = 0;
-  pPager->setMaster = 0;
-  pPager->needSync = 0;
-  lruListSetFirstSynced(pPager);
-  pPager->dbSize = -1;
-  pPager->dbModified = 0;
-
-  return (rc==SQLITE_OK?rc2:rc);
+  return hash;
+}
+static u32 pager_pagehash(PgHdr *pPage){
+  return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
+}
+static u32 pager_set_pagehash(PgHdr *pPage){
+  pPage->pageHash = pager_pagehash(pPage);
 }
 
 /*
-** Compute and return a checksum for the page of data.
-**
-** This is not a real checksum.  It is really just the sum of the 
-** random initial value and the page number.  We experimented with
-** a checksum of the entire data, but that was found to be too slow.
-**
-** Note that the page number is stored at the beginning of data and
-** the checksum is stored at the end.  This is important.  If journal
-** corruption occurs due to a power failure, the most likely scenario
-** is that one end or the other of the record will be changed.  It is
-** much less likely that the two ends of the journal record will be
-** correct and the middle be corrupt.  Thus, this "checksum" scheme,
-** though fast and simple, catches the mostly likely kind of corruption.
-**
-** FIX ME:  Consider adding every 200th (or so) byte of the data to the
-** checksum.  That way if a single page spans 3 or more disk sectors and
-** only the middle sector is corrupt, we will still have a reasonable
-** chance of failing the checksum and thus detecting the problem.
+** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
+** is defined, and NDEBUG is not defined, an assert() statement checks
+** that the page is either dirty or still matches the calculated page-hash.
 */
-static u32 pager_cksum(Pager *pPager, const u8 *aData){
-  u32 cksum = pPager->cksumInit;
-  int i = pPager->pageSize-200;
-  while( i>0 ){
-    cksum += aData[i];
-    i -= 200;
-  }
-  return cksum;
+#define CHECK_PAGE(x) checkPage(x)
+static void checkPage(PgHdr *pPg){
+  Pager *pPager = pPg->pPager;
+  assert( !pPg->pageHash || pPager->errCode || MEMDB 
+      || (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
 }
 
-/* Forward declaration */
-static void makeClean(PgHdr*);
+#else
+#define pager_datahash(X,Y)  0
+#define pager_pagehash(X)  0
+#define CHECK_PAGE(x)
+#endif  /* SQLITE_CHECK_PAGES */
 
 /*
-** Read a single page from the journal file opened on file descriptor
-** jfd.  Playback this one page.
+** When this is called the journal file for pager pPager must be open.
+** The master journal file name is read from the end of the file and 
+** written into memory supplied by the caller. 
+**
+** zMaster must point to a buffer of at least nMaster bytes allocated by
+** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
+** enough space to write the master journal name). If the master journal
+** name in the journal is longer than nMaster bytes (including a
+** nul-terminator), then this is handled as if no master journal name
+** were present in the journal.
 **
-** If useCksum==0 it means this journal does not use checksums.  Checksums
-** are not used in statement journals because statement journals do not
-** need to survive power failures.
+** If no master journal file name is present zMaster[0] is set to 0 and
+** SQLITE_OK returned.
 */
-static int pager_playback_one_page(
-  Pager *pPager, 
-  sqlite3_file *jfd,
-  i64 offset,
-  int useCksum
-){
+static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, int nMaster){
   int rc;
-  PgHdr *pPg;                   /* An existing page in the cache */
-  Pgno pgno;                    /* The page number of a page in journal */
-  u32 cksum;                    /* Checksum used for sanity checking */
-  u8 *aData = (u8 *)pPager->pTmpSpace;   /* Temp storage for a page */
+  u32 len;
+  i64 szJ;
+  u32 cksum;
+  u32 u;                   /* Unsigned loop counter */
+  unsigned char aMagic[8]; /* A buffer to hold the magic header */
 
-  /* useCksum should be true for the main journal and false for
-  ** statement journals.  Verify that this is always the case
-  */
-  assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) );
-  assert( aData );
+  zMaster[0] = '\0';
 
-  rc = read32bits(jfd, offset, &pgno);
-  if( rc!=SQLITE_OK ) return rc;
-  rc = sqlite3OsRead(jfd, aData, pPager->pageSize, offset+4);
+  rc = sqlite3OsFileSize(pJrnl, &szJ);
+  if( rc!=SQLITE_OK || szJ<16 ) return rc;
+
+  rc = read32bits(pJrnl, szJ-16, &len);
   if( rc!=SQLITE_OK ) return rc;
-  pPager->journalOff += pPager->pageSize + 4;
 
-  /* Sanity checking on the page.  This is more important that I originally
-  ** thought.  If a power failure occurs while the journal is being written,
-  ** it could cause invalid data to be written into the journal.  We need to
-  ** detect this invalid data (with high probability) and ignore it.
-  */
-  if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
-    return SQLITE_DONE;
-  }
-  if( pgno>(unsigned)pPager->dbSize ){
+  if( len>=nMaster ){
     return SQLITE_OK;
   }
-  if( useCksum ){
-    rc = read32bits(jfd, offset+pPager->pageSize+4, &cksum);
-    if( rc ) return rc;
-    pPager->journalOff += 4;
-    if( pager_cksum(pPager, aData)!=cksum ){
-      return SQLITE_DONE;
-    }
+
+  rc = read32bits(pJrnl, szJ-12, &cksum);
+  if( rc!=SQLITE_OK ) return rc;
+
+  rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8);
+  if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc;
+
+  rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len);
+  if( rc!=SQLITE_OK ){
+    return rc;
   }
+  zMaster[len] = '\0';
 
-  assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE );
+  /* See if the checksum matches the master journal name */
+  for(u=0; u<len; u++){
+    cksum -= zMaster[u];
+   }
+  if( cksum ){
+    /* If the checksum doesn't add up, then one or more of the disk sectors
+    ** containing the master journal filename is corrupted. This means
+    ** definitely roll back, so just return SQLITE_OK and report a (nul)
+    ** master-journal filename.
+    */
+    zMaster[0] = '\0';
+  }
+   
+  return SQLITE_OK;
+}
 
-  /* If the pager is in RESERVED state, then there must be a copy of this
-  ** page in the pager cache. In this case just update the pager cache,
-  ** not the database file. The page is left marked dirty in this case.
-  **
-  ** An exception to the above rule: If the database is in no-sync mode
-  ** and a page is moved during an incremental vacuum then the page may
-  ** not be in the pager cache. Later: if a malloc() or IO error occurs
-  ** during a Movepage() call, then the page may not be in the cache
-  ** either. So the condition described in the above paragraph is not
-  ** assert()able.
-  **
-  ** If in EXCLUSIVE state, then we update the pager cache if it exists
-  ** and the main file. The page is then marked not dirty.
-  **
-  ** Ticket #1171:  The statement journal might contain page content that is
-  ** different from the page content at the start of the transaction.
-  ** This occurs when a page is changed prior to the start of a statement
-  ** then changed again within the statement.  When rolling back such a
-  ** statement we must not write to the original database unless we know
-  ** for certain that original page contents are synced into the main rollback
-  ** journal.  Otherwise, a power loss might leave modified data in the
-  ** database file without an entry in the rollback journal that can
-  ** restore the database to its original form.  Two conditions must be
-  ** met before writing to the database files. (1) the database must be
-  ** locked.  (2) we know that the original page content is fully synced
-  ** in the main journal either because the page is not in cache or else
-  ** the page is marked as needSync==0.
-  **
-  ** 2008-04-14:  When attempting to vacuum a corrupt database file, it
-  ** is possible to fail a statement on a database that does not yet exist.
-  ** Do not attempt to write if database file has never been opened.
-  */
-  pPg = pager_lookup(pPager, pgno);
-  PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n",
-               PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData));
-  if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0)
-        && pPager->fd->pMethods ){
-    i64 offset = (pgno-1)*(i64)pPager->pageSize;
-    rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, offset);
-    if( pPg ){
-      makeClean(pPg);
-    }
+/*
+** Seek the journal file descriptor to the next sector boundary where a
+** journal header may be read or written. Pager.journalOff is updated with
+** the new seek offset.
+**
+** i.e for a sector size of 512:
+**
+** Input Offset              Output Offset
+** ---------------------------------------
+** 0                         0
+** 512                       512
+** 100                       512
+** 2000                      2048
+** 
+*/
+static void seekJournalHdr(Pager *pPager){
+  i64 offset = 0;
+  i64 c = pPager->journalOff;
+  if( c ){
+    offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);
   }
-  if( pPg ){
-    /* No page should ever be explicitly rolled back that is in use, except
-    ** for page 1 which is held in use in order to keep the lock on the
-    ** database active. However such a page may be rolled back as a result
-    ** of an internal error resulting in an automatic call to
-    ** sqlite3PagerRollback().
-    */
-    void *pData;
-    /* assert( pPg->nRef==0 || pPg->pgno==1 ); */
-    pData = PGHDR_TO_DATA(pPg);
-    memcpy(pData, aData, pPager->pageSize);
-    if( pPager->xReiniter ){
-      pPager->xReiniter(pPg, pPager->pageSize);
+  assert( offset%JOURNAL_HDR_SZ(pPager)==0 );
+  assert( offset>=c );
+  assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
+  pPager->journalOff = offset;
+}
+
+/*
+** Write zeros over the header of the journal file.  This has the
+** effect of invalidating the journal file and committing the
+** transaction.
+*/
+static int zeroJournalHdr(Pager *pPager, int doTruncate){
+  int rc = SQLITE_OK;
+  static const char zeroHdr[28];
+
+  if( pPager->journalOff ){
+    i64 iLimit = pPager->journalSizeLimit;
+
+    IOTRACE(("JZEROHDR %p\n", pPager))
+    if( doTruncate || iLimit==0 ){
+      rc = sqlite3OsTruncate(pPager->jfd, 0);
+    }else{
+      rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
     }
-#ifdef SQLITE_CHECK_PAGES
-    pPg->pageHash = pager_pagehash(pPg);
-#endif
-    /* If this was page 1, then restore the value of Pager.dbFileVers.
-    ** Do this before any decoding. */
-    if( pgno==1 ){
-      memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
+    if( rc==SQLITE_OK && !pPager->noSync ){
+      rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->sync_flags);
     }
 
-    /* Decode the page just read from disk */
-    CODEC1(pPager, pData, pPg->pgno, 3);
+    /* At this point the transaction is committed but the write lock 
+    ** is still held on the file. If there is a size limit configured for 
+    ** the persistent journal and the journal file currently consumes more
+    ** space than that limit allows for, truncate it now. There is no need
+    ** to sync the file following this operation.
+    */
+    if( rc==SQLITE_OK && iLimit>0 ){
+      i64 sz;
+      rc = sqlite3OsFileSize(pPager->jfd, &sz);
+      if( rc==SQLITE_OK && sz>iLimit ){
+        rc = sqlite3OsTruncate(pPager->jfd, iLimit);
+      }
+    }
   }
   return rc;
 }
 
 /*
-** Parameter zMaster is the name of a master journal file. A single journal
-** file that referred to the master journal file has just been rolled back.
-** This routine checks if it is possible to delete the master journal file,
-** and does so if it is.
-**
-** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not 
-** available for use within this function.
-**
+** The journal file must be open when this routine is called. A journal
+** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
+** current location.
 **
-** The master journal file contains the names of all child journals.
-** To tell if a master journal can be deleted, check to each of the
-** children.  If all children are either missing or do not refer to
-** a different master journal, then this master journal can be deleted.
+** The format for the journal header is as follows:
+** - 8 bytes: Magic identifying journal format.
+** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
+** - 4 bytes: Random number used for page hash.
+** - 4 bytes: Initial database page count.
+** - 4 bytes: Sector size used by the process that wrote this journal.
+** - 4 bytes: Database page size.
+** 
+** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
 */
-static int pager_delmaster(Pager *pPager, const char *zMaster){
-  sqlite3_vfs *pVfs = pPager->pVfs;
-  int rc;
-  int master_open = 0;
-  sqlite3_file *pMaster;
-  sqlite3_file *pJournal;
-  char *zMasterJournal = 0; /* Contents of master journal file */
-  i64 nMasterJournal;       /* Size of master journal file */
+static int writeJournalHdr(Pager *pPager){
+  int rc = SQLITE_OK;
+  char *zHeader = pPager->pTmpSpace;
+  int nHeader = pPager->pageSize;
+  int nWrite;
 
-  /* Open the master journal file exclusively in case some other process
-  ** is running this routine also. Not that it makes too much difference.
-  */
-  pMaster = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile * 2);
-  pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
-  if( !pMaster ){
-    rc = SQLITE_NOMEM;
-  }else{
-    int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
-    rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
+  if( nHeader>JOURNAL_HDR_SZ(pPager) ){
+    nHeader = JOURNAL_HDR_SZ(pPager);
   }
-  if( rc!=SQLITE_OK ) goto delmaster_out;
-  master_open = 1;
-
-  rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
-  if( rc!=SQLITE_OK ) goto delmaster_out;
 
-  if( nMasterJournal>0 ){
-    char *zJournal;
-    char *zMasterPtr = 0;
-    int nMasterPtr = pPager->pVfs->mxPathname+1;
+  if( pPager->stmtHdrOff==0 ){
+    pPager->stmtHdrOff = pPager->journalOff;
+  }
 
-    /* Load the entire master journal file into space obtained from
-    ** sqlite3_malloc() and pointed to by zMasterJournal. 
-    */
-    zMasterJournal = (char *)sqlite3Malloc(nMasterJournal + nMasterPtr);
-    if( !zMasterJournal ){
-      rc = SQLITE_NOMEM;
-      goto delmaster_out;
-    }
-    zMasterPtr = &zMasterJournal[nMasterJournal];
-    rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0);
-    if( rc!=SQLITE_OK ) goto delmaster_out;
+  seekJournalHdr(pPager);
+  pPager->journalHdr = pPager->journalOff;
 
-    zJournal = zMasterJournal;
-    while( (zJournal-zMasterJournal)<nMasterJournal ){
-      int exists;
-      rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
-      if( rc!=SQLITE_OK ){
-        goto delmaster_out;
-      }
-      if( exists ){
-        /* One of the journals pointed to by the master journal exists.
-        ** Open it and check if it points at the master journal. If
-        ** so, return without deleting the master journal file.
-        */
-        int c;
-        int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
-        rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
-        if( rc!=SQLITE_OK ){
-          goto delmaster_out;
-        }
+  memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
 
-        rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
-        sqlite3OsClose(pJournal);
-        if( rc!=SQLITE_OK ){
-          goto delmaster_out;
-        }
+  /* 
+  ** Write the nRec Field - the number of page records that follow this
+  ** journal header. Normally, zero is written to this value at this time.
+  ** After the records are added to the journal (and the journal synced, 
+  ** if in full-sync mode), the zero is overwritten with the true number
+  ** of records (see syncJournal()).
+  **
+  ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
+  ** reading the journal this value tells SQLite to assume that the
+  ** rest of the journal file contains valid page records. This assumption
+  ** is dangerous, as if a failure occured whilst writing to the journal
+  ** file it may contain some garbage data. There are two scenarios
+  ** where this risk can be ignored:
+  **
+  **   * When the pager is in no-sync mode. Corruption can follow a
+  **     power failure in this case anyway.
+  **
+  **   * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
+  **     that garbage data is never appended to the journal file.
+  */
+  assert(pPager->fd->pMethods||pPager->noSync);
+  if( (pPager->noSync) 
+   || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) 
+  ){
+    put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
+  }else{
+    put32bits(&zHeader[sizeof(aJournalMagic)], 0);
+  }
 
-        c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
-        if( c ){
-          /* We have a match. Do not delete the master journal file. */
-          goto delmaster_out;
-        }
-      }
-      zJournal += (strlen(zJournal)+1);
-    }
+  /* The random check-hash initialiser */ 
+  sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
+  put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
+  /* The initial database size */
+  put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize);
+  /* The assumed sector size for this process */
+  put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
+  if( pPager->journalHdr==0 ){
+    /* The page size */
+    put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
   }
-  
-  rc = sqlite3OsDelete(pVfs, zMaster, 0);
 
-delmaster_out:
-  if( zMasterJournal ){
-    sqlite3_free(zMasterJournal);
-  }  
-  if( master_open ){
-    sqlite3OsClose(pMaster);
+  for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
+    IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
+    rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
+    pPager->journalOff += nHeader;
   }
-  sqlite3_free(pMaster);
+
   return rc;
 }
 
-
-static void pager_truncate_cache(Pager *pPager);
-
 /*
-** Truncate the main file of the given pager to the number of pages
-** indicated. Also truncate the cached representation of the file.
+** The journal file must be open when this is called. A journal header file
+** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal
+** file. See comments above function writeJournalHdr() for a description of
+** the journal header format.
 **
-** Might might be the case that the file on disk is smaller than nPage.
-** This can happen, for example, if we are in the middle of a transaction
-** which has extended the file size and the new pages are still all held
-** in cache, then an INSERT or UPDATE does a statement rollback.  Some
-** operating system implementations can get confused if you try to
-** truncate a file to some size that is larger than it currently is,
-** so detect this case and write a single zero byte to the end of the new
-** file instead.
+** If the header is read successfully, *nRec is set to the number of
+** page records following this header and *dbSize is set to the size of the
+** database before the transaction began, in pages. Also, pPager->cksumInit
+** is set to the value read from the journal header. SQLITE_OK is returned
+** in this case.
+**
+** If the journal header file appears to be corrupted, SQLITE_DONE is
+** returned and *nRec and *dbSize are not set.  If JOURNAL_HDR_SZ bytes
+** cannot be read from the journal file an error code is returned.
 */
-static int pager_truncate(Pager *pPager, int nPage){
-  int rc = SQLITE_OK;
-  if( pPager->state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){
-    i64 currentSize, newSize;
-    rc = sqlite3OsFileSize(pPager->fd, &currentSize);
-    newSize = pPager->pageSize*(i64)nPage;
-    if( rc==SQLITE_OK && currentSize!=newSize ){
-      if( currentSize>newSize ){
-        rc = sqlite3OsTruncate(pPager->fd, newSize);
-      }else{
-        rc = sqlite3OsWrite(pPager->fd, "", 1, newSize-1);
-      }
-    }
-  }
-  if( rc==SQLITE_OK ){
-    pPager->dbSize = nPage;
-    pager_truncate_cache(pPager);
+static int readJournalHdr(
+  Pager *pPager, 
+  i64 journalSize,
+  u32 *pNRec, 
+  u32 *pDbSize
+){
+  int rc;
+  unsigned char aMagic[8]; /* A buffer to hold the magic header */
+  i64 jrnlOff;
+  int iPageSize;
+
+  seekJournalHdr(pPager);
+  if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
+    return SQLITE_DONE;
   }
-  return rc;
-}
+  jrnlOff = pPager->journalOff;
 
-/*
-** Set the sectorSize for the given pager.
-**
-** The sector size is at least as big as the sector size reported
-** by sqlite3OsSectorSize().  The minimum sector size is 512.
-*/
-static void setSectorSize(Pager *pPager){
-  assert(pPager->fd->pMethods||pPager->tempFile);
-  if( !pPager->tempFile ){
-    /* Sector size doesn't matter for temporary files. Also, the file
-    ** may not have been opened yet, in whcih case the OsSectorSize()
-    ** call will segfault.
-    */
-    pPager->sectorSize = sqlite3OsSectorSize(pPager->fd);
+  rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), jrnlOff);
+  if( rc ) return rc;
+  jrnlOff += sizeof(aMagic);
+
+  if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
+    return SQLITE_DONE;
   }
-  if( pPager->sectorSize<512 ){
-    pPager->sectorSize = 512;
+
+  rc = read32bits(pPager->jfd, jrnlOff, pNRec);
+  if( rc ) return rc;
+
+  rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit);
+  if( rc ) return rc;
+
+  rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize);
+  if( rc ) return rc;
+
+  rc = read32bits(pPager->jfd, jrnlOff+16, (u32 *)&iPageSize);
+  if( rc==SQLITE_OK 
+   && iPageSize>=512 
+   && iPageSize<=SQLITE_MAX_PAGE_SIZE 
+   && ((iPageSize-1)&iPageSize)==0 
+  ){
+    u16 pagesize = iPageSize;
+    rc = sqlite3PagerSetPagesize(pPager, &pagesize);
   }
+  if( rc ) return rc;
+
+  /* Update the assumed sector-size to match the value used by 
+  ** the process that created this journal. If this journal was
+  ** created by a process other than this one, then this routine
+  ** is being called from within pager_playback(). The local value
+  ** of Pager.sectorSize is restored at the end of that routine.
+  */
+  rc = read32bits(pPager->jfd, jrnlOff+12, (u32 *)&pPager->sectorSize);
+  if( rc ) return rc;
+
+  pPager->journalOff += JOURNAL_HDR_SZ(pPager);
+  return SQLITE_OK;
 }
 
+
 /*
-** Playback the journal and thus restore the database file to
-** the state it was in before we started making changes.  
-**
-** The journal file format is as follows: 
-**
-**  (1)  8 byte prefix.  A copy of aJournalMagic[].
-**  (2)  4 byte big-endian integer which is the number of valid page records
-**       in the journal.  If this value is 0xffffffff, then compute the
-**       number of page records from the journal size.
-**  (3)  4 byte big-endian integer which is the initial value for the 
-**       sanity checksum.
-**  (4)  4 byte integer which is the number of pages to truncate the
-**       database to during a rollback.
-**  (5)  4 byte big-endian integer which is the sector size.  The header
-**       is this many bytes in size.
-**  (6)  4 byte big-endian integer which is the page case.
-**  (7)  4 byte integer which is the number of bytes in the master journal
-**       name.  The value may be zero (indicate that there is no master
-**       journal.)
-**  (8)  N bytes of the master journal name.  The name will be nul-terminated
-**       and might be shorter than the value read from (5).  If the first byte
-**       of the name is \000 then there is no master journal.  The master
-**       journal name is stored in UTF-8.
-**  (9)  Zero or more pages instances, each as follows:
-**        +  4 byte page number.
-**        +  pPager->pageSize bytes of data.
-**        +  4 byte checksum
-**
-** When we speak of the journal header, we mean the first 8 items above.
-** Each entry in the journal is an instance of the 9th item.
-**
-** Call the value from the second bullet "nRec".  nRec is the number of
-** valid page entries in the journal.  In most cases, you can compute the
-** value of nRec from the size of the journal file.  But if a power
-** failure occurred while the journal was being written, it could be the
-** case that the size of the journal file had already been increased but
-** the extra entries had not yet made it safely to disk.  In such a case,
-** the value of nRec computed from the file size would be too large.  For
-** that reason, we always use the nRec value in the header.
+** Write the supplied master journal name into the journal file for pager
+** pPager at the current location. The master journal name must be the last
+** thing written to a journal file. If the pager is in full-sync mode, the
+** journal file descriptor is advanced to the next sector boundary before
+** anything is written. The format is:
 **
-** If the nRec value is 0xffffffff it means that nRec should be computed
-** from the file size.  This value is used when the user selects the
-** no-sync option for the journal.  A power failure could lead to corruption
-** in this case.  But for things like temporary table (which will be
-** deleted when the power is restored) we don't care.  
+** + 4 bytes: PAGER_MJ_PGNO.
+** + N bytes: length of master journal name.
+** + 4 bytes: N
+** + 4 bytes: Master journal name checksum.
+** + 8 bytes: aJournalMagic[].
 **
-** If the file opened as the journal file is not a well-formed
-** journal file then all pages up to the first corrupted page are rolled
-** back (or no pages if the journal header is corrupted). The journal file
-** is then deleted and SQLITE_OK returned, just as if no corruption had
-** been encountered.
+** The master journal page checksum is the sum of the bytes in the master
+** journal name.
 **
-** If an I/O or malloc() error occurs, the journal-file is not deleted
-** and an error code is returned.
+** If zMaster is a NULL pointer (occurs for a single database transaction), 
+** this call is a no-op.
 */
-static int pager_playback(Pager *pPager, int isHot){
-  sqlite3_vfs *pVfs = pPager->pVfs;
-  i64 szJ;                 /* Size of the journal file in bytes */
-  u32 nRec;                /* Number of Records in the journal */
-  u32 u;                   /* Unsigned loop counter */
-  Pgno mxPg = 0;           /* Size of the original file in pages */
-  int rc;                  /* Result code of a subroutine */
-  int res = 1;             /* Value returned by sqlite3OsAccess() */
-  char *zMaster = 0;       /* Name of master journal file if any */
+static int writeMasterJournal(Pager *pPager, const char *zMaster){
+  int rc;
+  int len; 
+  int i; 
+  i64 jrnlOff;
+  i64 jrnlSize;
+  u32 cksum = 0;
+  char zBuf[sizeof(aJournalMagic)+2*4];
 
-  /* Figure out how many records are in the journal.  Abort early if
-  ** the journal is empty.
-  */
-  assert( pPager->journalOpen );
-  rc = sqlite3OsFileSize(pPager->jfd, &szJ);
-  if( rc!=SQLITE_OK || szJ==0 ){
-    goto end_playback;
+  if( !zMaster || pPager->setMaster) return SQLITE_OK;
+  pPager->setMaster = 1;
+
+  len = strlen(zMaster);
+  for(i=0; i<len; i++){
+    cksum += zMaster[i];
   }
 
-  /* Read the master journal name from the journal, if it is present.
-  ** If a master journal file name is specified, but the file is not
-  ** present on disk, then the journal is not hot and does not need to be
-  ** played back.
+  /* If in full-sync mode, advance to the next disk sector before writing
+  ** the master journal name. This is in case the previous page written to
+  ** the journal has already been synced.
   */
-  zMaster = pPager->pTmpSpace;
-  rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
-  if( rc==SQLITE_OK && zMaster[0] ){
-    rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
-  }
-  zMaster = 0;
-  if( rc!=SQLITE_OK || !res ){
-    goto end_playback;
+  if( pPager->fullSync ){
+    seekJournalHdr(pPager);
   }
-  pPager->journalOff = 0;
-
-  /* This loop terminates either when the readJournalHdr() call returns
-  ** SQLITE_DONE or an IO error occurs. */
-  while( 1 ){
+  jrnlOff = pPager->journalOff;
+  pPager->journalOff += (len+20);
 
-    /* Read the next journal header from the journal file.  If there are
-    ** not enough bytes left in the journal file for a complete header, or
-    ** it is corrupted, then a process must of failed while writing it.
-    ** This indicates nothing more needs to be rolled back.
-    */
-    rc = readJournalHdr(pPager, szJ, &nRec, &mxPg);
-    if( rc!=SQLITE_OK ){ 
-      if( rc==SQLITE_DONE ){
-        rc = SQLITE_OK;
-      }
-      goto end_playback;
-    }
+  rc = write32bits(pPager->jfd, jrnlOff, PAGER_MJ_PGNO(pPager));
+  if( rc!=SQLITE_OK ) return rc;
+  jrnlOff += 4;
 
-    /* If nRec is 0xffffffff, then this journal was created by a process
-    ** working in no-sync mode. This means that the rest of the journal
-    ** file consists of pages, there are no more journal headers. Compute
-    ** the value of nRec based on this assumption.
-    */
-    if( nRec==0xffffffff ){
-      assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
-      nRec = (szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager);
-    }
+  rc = sqlite3OsWrite(pPager->jfd, zMaster, len, jrnlOff);
+  if( rc!=SQLITE_OK ) return rc;
+  jrnlOff += len;
 
-    /* If nRec is 0 and this rollback is of a transaction created by this
-    ** process and if this is the final header in the journal, then it means
-    ** that this part of the journal was being filled but has not yet been
-    ** synced to disk.  Compute the number of pages based on the remaining
-    ** size of the file.
-    **
-    ** The third term of the test was added to fix ticket #2565.
-    */
-    if( nRec==0 && !isHot &&
-        pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
-      nRec = (szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager);
-    }
+  put32bits(zBuf, len);
+  put32bits(&zBuf[4], cksum);
+  memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic));
+  rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic), jrnlOff);
+  jrnlOff += 8+sizeof(aJournalMagic);
+  pPager->needSync = !pPager->noSync;
 
-    /* If this is the first header read from the journal, truncate the
-    ** database file back to its original size.
-    */
-    if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
-      rc = pager_truncate(pPager, mxPg);
-      if( rc!=SQLITE_OK ){
-        goto end_playback;
+  /* If the pager is in peristent-journal mode, then the physical 
+  ** journal-file may extend past the end of the master-journal name
+  ** and 8 bytes of magic data just written to the file. This is 
+  ** dangerous because the code to rollback a hot-journal file
+  ** will not be able to find the master-journal name to determine 
+  ** whether or not the journal is hot. 
+  **
+  ** Easiest thing to do in this scenario is to truncate the journal 
+  ** file to the required size.
+  */ 
+  if( (rc==SQLITE_OK)
+   && (rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))==SQLITE_OK
+   && jrnlSize>jrnlOff
+  ){
+    rc = sqlite3OsTruncate(pPager->jfd, jrnlOff);
+  }
+  return rc;
+}
+
+/*
+** Find a page in the hash table given its page number.  Return
+** a pointer to the page or NULL if not found.
+*/
+static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
+  PgHdr *p;
+  sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
+  return p;
+}
+
+/*
+** Clear the in-memory cache.  This routine
+** sets the state of the pager back to what it was when it was first
+** opened.  Any outstanding pages are invalidated and subsequent attempts
+** to access those pages will likely result in a coredump.
+*/
+static void pager_reset(Pager *pPager){
+  if( pPager->errCode ) return;
+  sqlite3PcacheClear(pPager->pPCache);
+}
+
+/*
+** Unlock the database file. 
+**
+** If the pager is currently in error state, discard the contents of 
+** the cache and reset the Pager structure internal state. If there is
+** an open journal-file, then the next time a shared-lock is obtained
+** on the pager file (by this or any other process), it will be
+** treated as a hot-journal and rolled back.
+*/
+static void pager_unlock(Pager *pPager){
+  if( !pPager->exclusiveMode ){
+    if( !MEMDB ){
+      int rc = osUnlock(pPager->fd, NO_LOCK);
+      if( rc ) pPager->errCode = rc;
+      pPager->dbSize = -1;
+      IOTRACE(("UNLOCK %p\n", pPager))
+
+      /* Always close the journal file when dropping the database lock.
+      ** Otherwise, another connection with journal_mode=delete might
+      ** delete the file out from under us.
+      */
+      if( pPager->journalOpen ){
+        sqlite3OsClose(pPager->jfd);
+        pPager->journalOpen = 0;
+        sqlite3BitvecDestroy(pPager->pInJournal);
+        pPager->pInJournal = 0;
+        sqlite3BitvecDestroy(pPager->pAlwaysRollback);
+        pPager->pAlwaysRollback = 0;
       }
-    }
 
-    /* Copy original pages out of the journal and back into the database file.
-    */
-    for(u=0; u<nRec; u++){
-      rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
-      if( rc!=SQLITE_OK ){
-        if( rc==SQLITE_DONE ){
-          rc = SQLITE_OK;
-          pPager->journalOff = szJ;
-          break;
-        }else{
-          goto end_playback;
+      /* If Pager.errCode is set, the contents of the pager cache cannot be
+      ** trusted. Now that the pager file is unlocked, the contents of the
+      ** cache can be discarded and the error code safely cleared.
+      */
+      if( pPager->errCode ){
+        if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;
+        pager_reset(pPager);
+        if( pPager->stmtOpen ){
+          sqlite3OsClose(pPager->stfd);
+          sqlite3BitvecDestroy(pPager->pInStmt);
+          pPager->pInStmt = 0;
         }
+        pPager->stmtOpen = 0;
+        pPager->stmtInUse = 0;
+        pPager->journalOff = 0;
+        pPager->journalStarted = 0;
+        pPager->stmtAutoopen = 0;
+        pPager->origDbSize = 0;
       }
     }
-  }
-  /*NOTREACHED*/
-  assert( 0 );
 
-end_playback:
-  if( rc==SQLITE_OK ){
-    zMaster = pPager->pTmpSpace;
-    rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
-  }
-  if( rc==SQLITE_OK ){
-    rc = pager_end_transaction(pPager, zMaster[0]!='\0');
-  }
-  if( rc==SQLITE_OK && zMaster[0] ){
-    /* If there was a master journal and this routine will return success,
-    ** see if it is possible to delete the master journal.
-    */
-    rc = pager_delmaster(pPager, zMaster);
+    if( !MEMDB || pPager->errCode==SQLITE_OK ){
+      pPager->state = PAGER_UNLOCK;
+      pPager->changeCountDone = 0;
+    }
   }
+}
 
-  /* The Pager.sectorSize variable may have been updated while rolling
-  ** back a journal created by a process with a different sector size
-  ** value. Reset it to the correct value for this process.
-  */
-  setSectorSize(pPager);
-  return rc;
+/*
+** Execute a rollback if a transaction is active and unlock the 
+** database file. If the pager has already entered the error state, 
+** do not attempt the rollback.
+*/
+static void pagerUnlockAndRollback(Pager *p){
+  if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){
+    sqlite3BeginBenignMalloc();
+    sqlite3PagerRollback(p);
+    sqlite3EndBenignMalloc();
+  }
+  pager_unlock(p);
 }
 
 /*
-** Playback the statement journal.
+** This routine ends a transaction.  A transaction is ended by either
+** a COMMIT or a ROLLBACK.
 **
-** This is similar to playing back the transaction journal but with
-** a few extra twists.
+** When this routine is called, the pager has the journal file open and
+** a RESERVED or EXCLUSIVE lock on the database.  This routine will release
+** the database lock and acquires a SHARED lock in its place if that is
+** the appropriate thing to do.  Release locks usually is appropriate,
+** unless we are in exclusive access mode or unless this is a 
+** COMMIT AND BEGIN or ROLLBACK AND BEGIN operation.
 **
-**    (1)  The number of pages in the database file at the start of
-**         the statement is stored in pPager->stmtSize, not in the
-**         journal file itself.
+** The journal file is either deleted or truncated.
 **
-**    (2)  In addition to playing back the statement journal, also
-**         playback all pages of the transaction journal beginning
-**         at offset pPager->stmtJSize.
+** TODO: Consider keeping the journal file open for temporary databases.
+** This might give a performance improvement on windows where opening
+** a file is an expensive operation.
 */
-static int pager_stmt_playback(Pager *pPager){
-  i64 szJ;                 /* Size of the full journal */
-  i64 hdrOff;
-  int nRec;                /* Number of Records */
-  int i;                   /* Loop counter */
-  int rc;
-
-  szJ = pPager->journalOff;
-
-  /* Set hdrOff to be the offset just after the end of the last journal
-  ** page written before the first journal-header for this statement
-  ** transaction was written, or the end of the file if no journal
-  ** header was written.
-  */
-  hdrOff = pPager->stmtHdrOff;
-  assert( pPager->fullSync || !hdrOff );
-  if( !hdrOff ){
-    hdrOff = szJ;
-  }
-  
-  /* Truncate the database back to its original size.
-  */
-  rc = pager_truncate(pPager, pPager->stmtSize);
-  assert( pPager->state>=PAGER_SHARED );
-
-  /* Figure out how many records are in the statement journal.
-  */
-  assert( pPager->stmtInUse && pPager->journalOpen );
-  nRec = pPager->stmtNRec;
-  
-  /* Copy original pages out of the statement journal and back into the
-  ** database file.  Note that the statement journal omits checksums from
-  ** each record since power-failure recovery is not important to statement
-  ** journals.
-  */
-  for(i=0; i<nRec; i++){
-    i64 offset = i*(4+pPager->pageSize);
-    rc = pager_playback_one_page(pPager, pPager->stfd, offset, 0);
-    assert( rc!=SQLITE_DONE );
-    if( rc!=SQLITE_OK ) goto end_stmt_playback;
+static int pager_end_transaction(Pager *pPager, int hasMaster){
+  int rc = SQLITE_OK;
+  int rc2 = SQLITE_OK;
+  assert( !MEMDB );
+  if( pPager->state<PAGER_RESERVED ){
+    return SQLITE_OK;
   }
-
-  /* Now roll some pages back from the transaction journal. Pager.stmtJSize
-  ** was the size of the journal file when this statement was started, so
-  ** everything after that needs to be rolled back, either into the
-  ** database, the memory cache, or both.
-  **
-  ** If it is not zero, then Pager.stmtHdrOff is the offset to the start
-  ** of the first journal header written during this statement transaction.
-  */
-  pPager->journalOff = pPager->stmtJSize;
-  pPager->cksumInit = pPager->stmtCksum;
-  while( pPager->journalOff < hdrOff ){
-    rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
-    assert( rc!=SQLITE_DONE );
-    if( rc!=SQLITE_OK ) goto end_stmt_playback;
+  sqlite3PagerStmtCommit(pPager);
+  if( pPager->stmtOpen && !pPager->exclusiveMode ){
+    sqlite3OsClose(pPager->stfd);
+    pPager->stmtOpen = 0;
   }
-
-  while( pPager->journalOff < szJ ){
-    u32 nJRec;         /* Number of Journal Records */
-    u32 dummy;
-    rc = readJournalHdr(pPager, szJ, &nJRec, &dummy);
-    if( rc!=SQLITE_OK ){
-      assert( rc!=SQLITE_DONE );
-      goto end_stmt_playback;
-    }
-    if( nJRec==0 ){
-      nJRec = (szJ - pPager->journalOff) / (pPager->pageSize+8);
-    }
-    for(i=nJRec-1; i>=0 && pPager->journalOff < szJ; i--){
-      rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
-      assert( rc!=SQLITE_DONE );
-      if( rc!=SQLITE_OK ) goto end_stmt_playback;
+  if( pPager->journalOpen ){
+    if( pPager->exclusiveMode 
+     || pPager->journalMode==PAGER_JOURNALMODE_PERSIST
+    ){
+      rc = zeroJournalHdr(pPager, hasMaster);
+      pager_error(pPager, rc);
+      pPager->journalOff = 0;
+      pPager->journalStarted = 0;
+    }else{
+      sqlite3OsClose(pPager->jfd);
+      pPager->journalOpen = 0;
+      if( rc==SQLITE_OK && !pPager->tempFile ){
+        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
+      }
     }
+    sqlite3BitvecDestroy(pPager->pInJournal);
+    pPager->pInJournal = 0;
+    sqlite3BitvecDestroy(pPager->pAlwaysRollback);
+    pPager->pAlwaysRollback = 0;
+    sqlite3PcacheCleanAll(pPager->pPCache);
+#ifdef SQLITE_CHECK_PAGES
+    sqlite3PcacheIterate(pPager->pPCache, pager_set_pagehash);
+#endif
+    sqlite3PcacheSetFlags(pPager->pPCache,
+       ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
+    );
+    pPager->dirtyCache = 0;
+    pPager->nRec = 0;
+  }else{
+    assert( pPager->pInJournal==0 );
   }
 
-  pPager->journalOff = szJ;
-  
-end_stmt_playback:
-  if( rc==SQLITE_OK) {
-    pPager->journalOff = szJ;
-    /* pager_reload_cache(pPager); */
+  if( !pPager->exclusiveMode ){
+    rc2 = osUnlock(pPager->fd, SHARED_LOCK);
+    pPager->state = PAGER_SHARED;
+  }else if( pPager->state==PAGER_SYNCED ){
+    pPager->state = PAGER_EXCLUSIVE;
   }
-  return rc;
-}
+  pPager->origDbSize = 0;
+  pPager->setMaster = 0;
+  pPager->needSync = 0;
+  /* lruListSetFirstSynced(pPager); */
+  pPager->dbSize = -1;
+  pPager->dbModified = 0;
 
-/*
-** Change the maximum number of in-memory pages that are allowed.
-*/
-SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
-  if( mxPage>10 ){
-    pPager->mxPage = mxPage;
-  }else{
-    pPager->mxPage = 10;
-  }
+  return (rc==SQLITE_OK?rc2:rc);
 }
 
 /*
-** Adjust the robustness of the database to damage due to OS crashes
-** or power failures by changing the number of syncs()s when writing
-** the rollback journal.  There are three levels:
-**
-**    OFF       sqlite3OsSync() is never called.  This is the default
-**              for temporary and transient files.
+** Compute and return a checksum for the page of data.
 **
-**    NORMAL    The journal is synced once before writes begin on the
-**              database.  This is normally adequate protection, but
-**              it is theoretically possible, though very unlikely,
-**              that an inopertune power failure could leave the journal
-**              in a state which would cause damage to the database
-**              when it is rolled back.
+** This is not a real checksum.  It is really just the sum of the 
+** random initial value and the page number.  We experimented with
+** a checksum of the entire data, but that was found to be too slow.
 **
-**    FULL      The journal is synced twice before writes begin on the
-**              database (with some additional information - the nRec field
-**              of the journal header - being written in between the two
-**              syncs).  If we assume that writing a
-**              single disk sector is atomic, then this mode provides
-**              assurance that the journal will not be corrupted to the
-**              point of causing damage to the database during rollback.
+** Note that the page number is stored at the beginning of data and
+** the checksum is stored at the end.  This is important.  If journal
+** corruption occurs due to a power failure, the most likely scenario
+** is that one end or the other of the record will be changed.  It is
+** much less likely that the two ends of the journal record will be
+** correct and the middle be corrupt.  Thus, this "checksum" scheme,
+** though fast and simple, catches the mostly likely kind of corruption.
 **
-** Numeric values associated with these states are OFF==1, NORMAL=2,
-** and FULL=3.
+** FIX ME:  Consider adding every 200th (or so) byte of the data to the
+** checksum.  That way if a single page spans 3 or more disk sectors and
+** only the middle sector is corrupt, we will still have a reasonable
+** chance of failing the checksum and thus detecting the problem.
 */
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int full_fsync){
-  pPager->noSync =  level==1 || pPager->tempFile;
-  pPager->fullSync = level==3 && !pPager->tempFile;
-  pPager->sync_flags = (full_fsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
-  if( pPager->noSync ) pPager->needSync = 0;
+static u32 pager_cksum(Pager *pPager, const u8 *aData){
+  u32 cksum = pPager->cksumInit;
+  int i = pPager->pageSize-200;
+  while( i>0 ){
+    cksum += aData[i];
+    i -= 200;
+  }
+  return cksum;
 }
-#endif
 
-/*
-** The following global variable is incremented whenever the library
-** attempts to open a temporary file.  This information is used for
-** testing and analysis only.  
-*/
-#ifdef SQLITE_TEST
-SQLITE_API int sqlite3_opentemp_count = 0;
-#endif
+/* Forward declaration */
+static void makeClean(PgHdr*);
 
 /*
-** Open a temporary file. 
+** Read a single page from the journal file opened on file descriptor
+** jfd.  Playback this one page.
 **
-** Write the file descriptor into *fd.  Return SQLITE_OK on success or some
-** other error code if we fail. The OS will automatically delete the temporary
-** file when it is closed.
+** The isMainJrnl flag is true if this is the main rollback journal and
+** false for the statement journal.  The main rollback journal uses
+** checksums - the statement journal does not.
 */
-static int sqlite3PagerOpentemp(
-  Pager *pPager,        /* The pager object */
-  sqlite3_file *pFile,  /* Write the file descriptor here */
-  int vfsFlags          /* Flags passed through to the VFS */
+static int pager_playback_one_page(
+  Pager *pPager,       /* The pager being played back */
+  sqlite3_file *jfd,   /* The file that is the journal being rolled back */
+  i64 offset,          /* Offset of the page within the journal */
+  int isMainJrnl       /* True for main rollback journal. False for Stmt jrnl */
 ){
   int rc;
+  PgHdr *pPg;                   /* An existing page in the cache */
+  Pgno pgno;                    /* The page number of a page in journal */
+  u32 cksum;                    /* Checksum used for sanity checking */
+  u8 *aData = (u8 *)pPager->pTmpSpace;   /* Temp storage for a page */
 
-#ifdef SQLITE_TEST
-  sqlite3_opentemp_count++;  /* Used for testing and analysis only */
+  /* isMainJrnl should be true for the main journal and false for
+  ** statement journals.  Verify that this is always the case
+  */
+  assert( jfd == (isMainJrnl ? pPager->jfd : pPager->stfd) );
+  assert( aData );
+
+  rc = read32bits(jfd, offset, &pgno);
+  if( rc!=SQLITE_OK ) return rc;
+  rc = sqlite3OsRead(jfd, aData, pPager->pageSize, offset+4);
+  if( rc!=SQLITE_OK ) return rc;
+  pPager->journalOff += pPager->pageSize + 4;
+
+  /* Sanity checking on the page.  This is more important that I originally
+  ** thought.  If a power failure occurs while the journal is being written,
+  ** it could cause invalid data to be written into the journal.  We need to
+  ** detect this invalid data (with high probability) and ignore it.
+  */
+  if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
+    return SQLITE_DONE;
+  }
+  if( pgno>(unsigned)pPager->dbSize ){
+    return SQLITE_OK;
+  }
+  if( isMainJrnl ){
+    rc = read32bits(jfd, offset+pPager->pageSize+4, &cksum);
+    if( rc ) return rc;
+    pPager->journalOff += 4;
+    if( pager_cksum(pPager, aData)!=cksum ){
+      return SQLITE_DONE;
+    }
+  }
+
+  assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE );
+
+  /* If the pager is in RESERVED state, then there must be a copy of this
+  ** page in the pager cache. In this case just update the pager cache,
+  ** not the database file. The page is left marked dirty in this case.
+  **
+  ** An exception to the above rule: If the database is in no-sync mode
+  ** and a page is moved during an incremental vacuum then the page may
+  ** not be in the pager cache. Later: if a malloc() or IO error occurs
+  ** during a Movepage() call, then the page may not be in the cache
+  ** either. So the condition described in the above paragraph is not
+  ** assert()able.
+  **
+  ** If in EXCLUSIVE state, then we update the pager cache if it exists
+  ** and the main file. The page is then marked not dirty.
+  **
+  ** Ticket #1171:  The statement journal might contain page content that is
+  ** different from the page content at the start of the transaction.
+  ** This occurs when a page is changed prior to the start of a statement
+  ** then changed again within the statement.  When rolling back such a
+  ** statement we must not write to the original database unless we know
+  ** for certain that original page contents are synced into the main rollback
+  ** journal.  Otherwise, a power loss might leave modified data in the
+  ** database file without an entry in the rollback journal that can
+  ** restore the database to its original form.  Two conditions must be
+  ** met before writing to the database files. (1) the database must be
+  ** locked.  (2) we know that the original page content is fully synced
+  ** in the main journal either because the page is not in cache or else
+  ** the page is marked as needSync==0.
+  **
+  ** 2008-04-14:  When attempting to vacuum a corrupt database file, it
+  ** is possible to fail a statement on a database that does not yet exist.
+  ** Do not attempt to write if database file has never been opened.
+  */
+  pPg = pager_lookup(pPager, pgno);
+  PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n",
+               PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData));
+  if( (pPager->state>=PAGER_EXCLUSIVE)
+   && (pPg==0 || 0==(pPg->flags&PGHDR_NEED_SYNC))
+   && (pPager->fd->pMethods)
+  ){
+    i64 ofst = (pgno-1)*(i64)pPager->pageSize;
+    rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, ofst);
+  }
+  if( pPg ){
+    /* No page should ever be explicitly rolled back that is in use, except
+    ** for page 1 which is held in use in order to keep the lock on the
+    ** database active. However such a page may be rolled back as a result
+    ** of an internal error resulting in an automatic call to
+    ** sqlite3PagerRollback().
+    */
+    void *pData;
+    pData = pPg->pData;
+    memcpy(pData, aData, pPager->pageSize);
+    if( pPager->xReiniter ){
+      pPager->xReiniter(pPg, pPager->pageSize);
+    }
+    if( isMainJrnl ) makeClean(pPg);
+#ifdef SQLITE_CHECK_PAGES
+    pPg->pageHash = pager_pagehash(pPg);
 #endif
+    /* If this was page 1, then restore the value of Pager.dbFileVers.
+    ** Do this before any decoding. */
+    if( pgno==1 ){
+      memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
+    }
 
-  vfsFlags |=  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
-            SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
-  rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
-  assert( rc!=SQLITE_OK || pFile->pMethods );
+    /* Decode the page just read from disk */
+    CODEC1(pPager, pData, pPg->pgno, 3);
+    sqlite3PcacheRelease(pPg);
+  }
   return rc;
 }
 
 /*
-** Create a new page cache and put a pointer to the page cache in *ppPager.
-** The file to be cached need not exist.  The file is not locked until
-** the first call to sqlite3PagerGet() and is only held open until the
-** last page is released using sqlite3PagerUnref().
+** Parameter zMaster is the name of a master journal file. A single journal
+** file that referred to the master journal file has just been rolled back.
+** This routine checks if it is possible to delete the master journal file,
+** and does so if it is.
 **
-** If zFilename is NULL then a randomly-named temporary file is created
-** and used as the file to be cached.  The file will be deleted
-** automatically when it is closed.
+** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not 
+** available for use within this function.
 **
-** If zFilename is ":memory:" then all information is held in cache.
-** It is never written to disk.  This can be used to implement an
-** in-memory database.
+**
+** The master journal file contains the names of all child journals.
+** To tell if a master journal can be deleted, check to each of the
+** children.  If all children are either missing or do not refer to
+** a different master journal, then this master journal can be deleted.
 */
-SQLITE_PRIVATE int sqlite3PagerOpen(
-  sqlite3_vfs *pVfs,       /* The virtual file system to use */
-  Pager **ppPager,         /* Return the Pager structure here */
-  const char *zFilename,   /* Name of the database file to open */
-  int nExtra,              /* Extra bytes append to each in-memory page */
-  int flags,               /* flags controlling this file */
-  int vfsFlags             /* flags passed through to sqlite3_vfs.xOpen() */
-){
-  u8 *pPtr;
-  Pager *pPager = 0;
-  int rc = SQLITE_OK;
-  int i;
-  int tempFile = 0;
-  int memDb = 0;
-  int readOnly = 0;
-  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
-  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
-  int journalFileSize = sqlite3JournalSize(pVfs);
-  int szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;
-  char *zPathname = 0;
-  int nPathname = 0;
-
-  /* The default return is a NULL pointer */
-  *ppPager = 0;
+static int pager_delmaster(Pager *pPager, const char *zMaster){
+  sqlite3_vfs *pVfs = pPager->pVfs;
+  int rc;
+  int master_open = 0;
+  sqlite3_file *pMaster;
+  sqlite3_file *pJournal;
+  char *zMasterJournal = 0; /* Contents of master journal file */
+  i64 nMasterJournal;       /* Size of master journal file */
 
-  /* Compute and store the full pathname in an allocated buffer pointed
-  ** to by zPathname, length nPathname. Or, if this is a temporary file,
-  ** leave both nPathname and zPathname set to 0.
+  /* Open the master journal file exclusively in case some other process
+  ** is running this routine also. Not that it makes too much difference.
   */
-  if( zFilename && zFilename[0] ){
-    nPathname = pVfs->mxPathname+1;
-    zPathname = sqlite3Malloc(nPathname*2);
-    if( zPathname==0 ){
-      return SQLITE_NOMEM;
-    }
-#ifndef SQLITE_OMIT_MEMORYDB
-    if( strcmp(zFilename,":memory:")==0 ){
-      memDb = 1;
-      zPathname[0] = 0;
-    }else
-#endif
-    {
-      rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
-    }
-    if( rc!=SQLITE_OK ){
-      sqlite3_free(zPathname);
-      return rc;
-    }
-    nPathname = strlen(zPathname);
+  pMaster = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile * 2);
+  pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
+  if( !pMaster ){
+    rc = SQLITE_NOMEM;
+  }else{
+    int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
+    rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
   }
+  if( rc!=SQLITE_OK ) goto delmaster_out;
+  master_open = 1;
 
-  /* Allocate memory for the pager structure */
-  pPager = sqlite3MallocZero(
-    sizeof(*pPager) +           /* Pager structure */
-    journalFileSize +           /* The journal file structure */ 
-    pVfs->szOsFile * 3 +        /* The main db and two journal files */ 
-    3*nPathname + 40            /* zFilename, zDirectory, zJournal */
-  );
-  if( !pPager ){
-    sqlite3_free(zPathname);
-    return SQLITE_NOMEM;
-  }
-  pPtr = (u8 *)&pPager[1];
-  pPager->vfsFlags = vfsFlags;
-  pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0];
-  pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1];
-  pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2];
-  pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize];
-  pPager->zDirectory = &pPager->zFilename[nPathname+1];
-  pPager->zJournal = &pPager->zDirectory[nPathname+1];
-  pPager->pVfs = pVfs;
-  if( zPathname ){
-    memcpy(pPager->zFilename, zPathname, nPathname+1);
-    sqlite3_free(zPathname);
-  }
+  rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
+  if( rc!=SQLITE_OK ) goto delmaster_out;
 
-  /* Open the pager file.
-  */
-  if( zFilename && zFilename[0] && !memDb ){
-    if( nPathname>(pVfs->mxPathname - sizeof("-journal")) ){
-      rc = SQLITE_CANTOPEN;
-    }else{
-      int fout = 0;
-      rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd,
-                         pPager->vfsFlags, &fout);
-      readOnly = (fout&SQLITE_OPEN_READONLY);
+  if( nMasterJournal>0 ){
+    char *zJournal;
+    char *zMasterPtr = 0;
+    int nMasterPtr = pPager->pVfs->mxPathname+1;
 
-      /* If the file was successfully opened for read/write access,
-      ** choose a default page size in case we have to create the
-      ** database file. The default page size is the maximum of:
-      **
-      **    + SQLITE_DEFAULT_PAGE_SIZE,
-      **    + The value returned by sqlite3OsSectorSize()
-      **    + The largest page size that can be written atomically.
-      */
-      if( rc==SQLITE_OK && !readOnly ){
-        int iSectorSize = sqlite3OsSectorSize(pPager->fd);
-        if( szPageDflt<iSectorSize ){
-          szPageDflt = iSectorSize;
+    /* Load the entire master journal file into space obtained from
+    ** sqlite3_malloc() and pointed to by zMasterJournal. 
+    */
+    zMasterJournal = (char *)sqlite3Malloc(nMasterJournal + nMasterPtr);
+    if( !zMasterJournal ){
+      rc = SQLITE_NOMEM;
+      goto delmaster_out;
+    }
+    zMasterPtr = &zMasterJournal[nMasterJournal];
+    rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0);
+    if( rc!=SQLITE_OK ) goto delmaster_out;
+
+    zJournal = zMasterJournal;
+    while( (zJournal-zMasterJournal)<nMasterJournal ){
+      int exists;
+      rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
+      if( rc!=SQLITE_OK ){
+        goto delmaster_out;
+      }
+      if( exists ){
+        /* One of the journals pointed to by the master journal exists.
+        ** Open it and check if it points at the master journal. If
+        ** so, return without deleting the master journal file.
+        */
+        int c;
+        int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
+        rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
+        if( rc!=SQLITE_OK ){
+          goto delmaster_out;
         }
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
-        {
-          int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
-          int ii;
-          assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
-          assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
-          assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
-          for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
-            if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ) szPageDflt = ii;
-          }
+
+        rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
+        sqlite3OsClose(pJournal);
+        if( rc!=SQLITE_OK ){
+          goto delmaster_out;
         }
-#endif
-        if( szPageDflt>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
-          szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
+
+        c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
+        if( c ){
+          /* We have a match. Do not delete the master journal file. */
+          goto delmaster_out;
         }
       }
+      zJournal += (strlen(zJournal)+1);
     }
-  }else if( !memDb ){
-    /* If a temporary file is requested, it is not opened immediately.
-    ** In this case we accept the default page size and delay actually
-    ** opening the file until the first call to OsWrite().
-    */ 
-    tempFile = 1;
-    pPager->state = PAGER_EXCLUSIVE;
-  }
-
-  if( pPager && rc==SQLITE_OK ){
-    pPager->pTmpSpace = sqlite3PageMalloc(szPageDflt);
-  }
-
-  /* If an error occured in either of the blocks above.
-  ** Free the Pager structure and close the file.
-  ** Since the pager is not allocated there is no need to set 
-  ** any Pager.errMask variables.
-  */
-  if( !pPager || !pPager->pTmpSpace ){
-    sqlite3OsClose(pPager->fd);
-    sqlite3_free(pPager);
-    return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
-  }
-
-  PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename);
-  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
-
-  /* Fill in Pager.zDirectory[] */
-  memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1);
-  for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){}
-  if( i>0 ) pPager->zDirectory[i-1] = 0;
-
-  /* Fill in Pager.zJournal[] */
-  if( zPathname ){
-    memcpy(pPager->zJournal, pPager->zFilename, nPathname);
-    memcpy(&pPager->zJournal[nPathname], "-journal", 9);
-  }else{
-    pPager->zJournal = 0;
   }
+  
+  rc = sqlite3OsDelete(pVfs, zMaster, 0);
 
-  /* pPager->journalOpen = 0; */
-  pPager->useJournal = useJournal && !memDb;
-  pPager->noReadlock = noReadlock && readOnly;
-  /* pPager->stmtOpen = 0; */
-  /* pPager->stmtInUse = 0; */
-  /* pPager->nRef = 0; */
-  pPager->dbSize = memDb-1;
-  pPager->pageSize = szPageDflt;
-  /* pPager->stmtSize = 0; */
-  /* pPager->stmtJSize = 0; */
-  /* pPager->nPage = 0; */
-  pPager->mxPage = 100;
-  pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
-  /* pPager->state = PAGER_UNLOCK; */
-  assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
-  /* pPager->errMask = 0; */
-  pPager->tempFile = tempFile;
-  assert( tempFile==PAGER_LOCKINGMODE_NORMAL 
-          || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
-  assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
-  pPager->exclusiveMode = tempFile; 
-  pPager->memDb = memDb;
-  pPager->readOnly = readOnly;
-  /* pPager->needSync = 0; */
-  pPager->noSync = pPager->tempFile || !useJournal;
-  pPager->fullSync = (pPager->noSync?0:1);
-  pPager->sync_flags = SQLITE_SYNC_NORMAL;
-  /* pPager->pFirst = 0; */
-  /* pPager->pFirstSynced = 0; */
-  /* pPager->pLast = 0; */
-  pPager->nExtra = FORCE_ALIGNMENT(nExtra);
-  pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
-  assert(pPager->fd->pMethods||memDb||tempFile);
-  if( !memDb ){
-    setSectorSize(pPager);
-  }
-  /* pPager->pBusyHandler = 0; */
-  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
-  *ppPager = pPager;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  pPager->iInUseMM = 0;
-  pPager->iInUseDB = 0;
-  if( !memDb ){
-#ifndef SQLITE_MUTEX_NOOP
-    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
-#endif
-    sqlite3_mutex_enter(mutex);
-    pPager->pNext = sqlite3PagerList;
-    if( sqlite3PagerList ){
-      assert( sqlite3PagerList->pPrev==0 );
-      sqlite3PagerList->pPrev = pPager;
-    }
-    pPager->pPrev = 0;
-    sqlite3PagerList = pPager;
-    sqlite3_mutex_leave(mutex);
+delmaster_out:
+  if( zMasterJournal ){
+    sqlite3_free(zMasterJournal);
+  }  
+  if( master_open ){
+    sqlite3OsClose(pMaster);
   }
-#endif
-  return SQLITE_OK;
-}
-
-/*
-** Set the busy handler function.
-*/
-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager *pPager, BusyHandler *pBusyHandler){
-  pPager->pBusyHandler = pBusyHandler;
+  sqlite3_free(pMaster);
+  return rc;
 }
 
-/*
-** Set the destructor for this pager.  If not NULL, the destructor is called
-** when the reference count on each page reaches zero.  The destructor can
-** be used to clean up information in the extra segment appended to each page.
-**
-** The destructor is not called as a result sqlite3PagerClose().  
-** Destructors are only called by sqlite3PagerUnref().
-*/
-SQLITE_PRIVATE void sqlite3PagerSetDestructor(Pager *pPager, void (*xDesc)(DbPage*,int)){
-  pPager->xDestructor = xDesc;
-}
 
-/*
-** Set the reinitializer for this pager.  If not NULL, the reinitializer
-** is called when the content of a page in cache is restored to its original
-** value as a result of a rollback.  The callback gives higher-level code
-** an opportunity to restore the EXTRA section to agree with the restored
-** page data.
-*/
-SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){
-  pPager->xReiniter = xReinit;
-}
+static void pager_truncate_cache(Pager *pPager);
 
 /*
-** Set the page size to *pPageSize. If the suggest new page size is
-** inappropriate, then an alternative page size is set to that
-** value before returning.
+** Truncate the main file of the given pager to the number of pages
+** indicated. Also truncate the cached representation of the file.
+**
+** Might might be the case that the file on disk is smaller than nPage.
+** This can happen, for example, if we are in the middle of a transaction
+** which has extended the file size and the new pages are still all held
+** in cache, then an INSERT or UPDATE does a statement rollback.  Some
+** operating system implementations can get confused if you try to
+** truncate a file to some size that is larger than it currently is,
+** so detect this case and write a single zero byte to the end of the new
+** file instead.
 */
-SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize){
+static int pager_truncate(Pager *pPager, int nPage){
   int rc = SQLITE_OK;
-  u16 pageSize = *pPageSize;
-  assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
-  if( pageSize && pageSize!=pPager->pageSize 
-   && !pPager->memDb && pPager->nRef==0 
-  ){
-    char *pNew = (char *)sqlite3PageMalloc(pageSize);
-    if( !pNew ){
-      rc = SQLITE_NOMEM;
-    }else{
-      pagerEnter(pPager);
-      pager_reset(pPager);
-      pPager->pageSize = pageSize;
-      setSectorSize(pPager);
-      sqlite3PageFree(pPager->pTmpSpace);
-      pPager->pTmpSpace = pNew;
-      pagerLeave(pPager);
+  if( pPager->state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){
+    i64 currentSize, newSize;
+    rc = sqlite3OsFileSize(pPager->fd, &currentSize);
+    newSize = pPager->pageSize*(i64)nPage;
+    if( rc==SQLITE_OK && currentSize!=newSize ){
+      if( currentSize>newSize ){
+        rc = sqlite3OsTruncate(pPager->fd, newSize);
+      }else{
+        rc = sqlite3OsWrite(pPager->fd, "", 1, newSize-1);
+      }
     }
   }
-  *pPageSize = pPager->pageSize;
+  if( rc==SQLITE_OK ){
+    pPager->dbSize = nPage;
+    pager_truncate_cache(pPager);
+  }
   return rc;
 }
 
 /*
-** Return a pointer to the "temporary page" buffer held internally
-** by the pager.  This is a buffer that is big enough to hold the
-** entire content of a database page.  This buffer is used internally
-** during rollback and will be overwritten whenever a rollback
-** occurs.  But other modules are free to use it too, as long as
-** no rollbacks are happening.
-*/
-SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){
-  return pPager->pTmpSpace;
-}
-
-/*
-** Attempt to set the maximum database page count if mxPage is positive. 
-** Make no changes if mxPage is zero or negative.  And never reduce the
-** maximum page count below the current size of the database.
+** Set the sectorSize for the given pager.
 **
-** Regardless of mxPage, return the current maximum page count.
+** The sector size is at least as big as the sector size reported
+** by sqlite3OsSectorSize().  The minimum sector size is 512.
 */
-SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
-  if( mxPage>0 ){
-    pPager->mxPgno = mxPage;
+static void setSectorSize(Pager *pPager){
+  assert(pPager->fd->pMethods||pPager->tempFile);
+  if( !pPager->tempFile ){
+    /* Sector size doesn't matter for temporary files. Also, the file
+    ** may not have been opened yet, in whcih case the OsSectorSize()
+    ** call will segfault.
+    */
+    pPager->sectorSize = sqlite3OsSectorSize(pPager->fd);
+  }
+  if( pPager->sectorSize<512 ){
+    pPager->sectorSize = 512;
   }
-  sqlite3PagerPagecount(pPager, 0);
-  return pPager->mxPgno;
 }
 
 /*
-** The following set of routines are used to disable the simulated
-** I/O error mechanism.  These routines are used to avoid simulated
-** errors in places where we do not care about errors.
+** Playback the journal and thus restore the database file to
+** the state it was in before we started making changes.  
 **
-** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops
-** and generate no code.
-*/
-#ifdef SQLITE_TEST
-SQLITE_API extern int sqlite3_io_error_pending;
-SQLITE_API extern int sqlite3_io_error_hit;
-static int saved_cnt;
-void disable_simulated_io_errors(void){
-  saved_cnt = sqlite3_io_error_pending;
-  sqlite3_io_error_pending = -1;
-}
-void enable_simulated_io_errors(void){
-  sqlite3_io_error_pending = saved_cnt;
-}
-#else
-# define disable_simulated_io_errors()
-# define enable_simulated_io_errors()
-#endif
-
-/*
-** Read the first N bytes from the beginning of the file into memory
-** that pDest points to. 
+** The journal file format is as follows: 
 **
-** No error checking is done. The rational for this is that this function 
-** may be called even if the file does not exist or contain a header. In 
-** these cases sqlite3OsRead() will return an error, to which the correct 
-** response is to zero the memory at pDest and continue.  A real IO error 
-** will presumably recur and be picked up later (Todo: Think about this).
+**  (1)  8 byte prefix.  A copy of aJournalMagic[].
+**  (2)  4 byte big-endian integer which is the number of valid page records
+**       in the journal.  If this value is 0xffffffff, then compute the
+**       number of page records from the journal size.
+**  (3)  4 byte big-endian integer which is the initial value for the 
+**       sanity checksum.
+**  (4)  4 byte integer which is the number of pages to truncate the
+**       database to during a rollback.
+**  (5)  4 byte big-endian integer which is the sector size.  The header
+**       is this many bytes in size.
+**  (6)  4 byte big-endian integer which is the page case.
+**  (7)  4 byte integer which is the number of bytes in the master journal
+**       name.  The value may be zero (indicate that there is no master
+**       journal.)
+**  (8)  N bytes of the master journal name.  The name will be nul-terminated
+**       and might be shorter than the value read from (5).  If the first byte
+**       of the name is \000 then there is no master journal.  The master
+**       journal name is stored in UTF-8.
+**  (9)  Zero or more pages instances, each as follows:
+**        +  4 byte page number.
+**        +  pPager->pageSize bytes of data.
+**        +  4 byte checksum
+**
+** When we speak of the journal header, we mean the first 8 items above.
+** Each entry in the journal is an instance of the 9th item.
+**
+** Call the value from the second bullet "nRec".  nRec is the number of
+** valid page entries in the journal.  In most cases, you can compute the
+** value of nRec from the size of the journal file.  But if a power
+** failure occurred while the journal was being written, it could be the
+** case that the size of the journal file had already been increased but
+** the extra entries had not yet made it safely to disk.  In such a case,
+** the value of nRec computed from the file size would be too large.  For
+** that reason, we always use the nRec value in the header.
+**
+** If the nRec value is 0xffffffff it means that nRec should be computed
+** from the file size.  This value is used when the user selects the
+** no-sync option for the journal.  A power failure could lead to corruption
+** in this case.  But for things like temporary table (which will be
+** deleted when the power is restored) we don't care.  
+**
+** If the file opened as the journal file is not a well-formed
+** journal file then all pages up to the first corrupted page are rolled
+** back (or no pages if the journal header is corrupted). The journal file
+** is then deleted and SQLITE_OK returned, just as if no corruption had
+** been encountered.
+**
+** If an I/O or malloc() error occurs, the journal-file is not deleted
+** and an error code is returned.
 */
-SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
-  int rc = SQLITE_OK;
-  memset(pDest, 0, N);
-  assert(MEMDB||pPager->fd->pMethods||pPager->tempFile);
-  if( pPager->fd->pMethods ){
-    IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
-    rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
-    if( rc==SQLITE_IOERR_SHORT_READ ){
-      rc = SQLITE_OK;
-    }
+static int pager_playback(Pager *pPager, int isHot){
+  sqlite3_vfs *pVfs = pPager->pVfs;
+  i64 szJ;                 /* Size of the journal file in bytes */
+  u32 nRec;                /* Number of Records in the journal */
+  u32 u;                   /* Unsigned loop counter */
+  Pgno mxPg = 0;           /* Size of the original file in pages */
+  int rc;                  /* Result code of a subroutine */
+  int res = 1;             /* Value returned by sqlite3OsAccess() */
+  char *zMaster = 0;       /* Name of master journal file if any */
+
+  /* Figure out how many records are in the journal.  Abort early if
+  ** the journal is empty.
+  */
+  assert( pPager->journalOpen );
+  rc = sqlite3OsFileSize(pPager->jfd, &szJ);
+  if( rc!=SQLITE_OK || szJ==0 ){
+    goto end_playback;
   }
-  return rc;
-}
 
-/*
-** Return the total number of pages in the disk file associated with
-** pPager. 
-**
-** If the PENDING_BYTE lies on the page directly after the end of the
-** file, then consider this page part of the file too. For example, if
-** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the
-** file is 4096 bytes, 5 is returned instead of 4.
-*/
-SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
-  i64 n = 0;
-  int rc;
-  assert( pPager!=0 );
-  if( pPager->errCode ){
-    return pPager->errCode;
+  /* Read the master journal name from the journal, if it is present.
+  ** If a master journal file name is specified, but the file is not
+  ** present on disk, then the journal is not hot and does not need to be
+  ** played back.
+  */
+  zMaster = pPager->pTmpSpace;
+  rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
+  if( rc==SQLITE_OK && zMaster[0] ){
+    rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
   }
-  if( pPager->dbSize>=0 ){
-    n = pPager->dbSize;
-  } else {
-    assert(pPager->fd->pMethods||pPager->tempFile);
-    if( (pPager->fd->pMethods)
-     && (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
-      pPager->nRef++;
-      pager_error(pPager, rc);
-      pPager->nRef--;
-      return rc;
-    }
-    if( n>0 && n<pPager->pageSize ){
-      n = 1;
-    }else{
-      n /= pPager->pageSize;
-    }
-    if( pPager->state!=PAGER_UNLOCK ){
-      pPager->dbSize = n;
-    }
-  }
-  if( n==(PENDING_BYTE/pPager->pageSize) ){
-    n++;
-  }
-  if( n>pPager->mxPgno ){
-    pPager->mxPgno = n;
-  }
-  if( pnPage ){
-    *pnPage = n;
+  zMaster = 0;
+  if( rc!=SQLITE_OK || !res ){
+    goto end_playback;
   }
-  return SQLITE_OK;
-}
+  pPager->journalOff = 0;
 
+  /* This loop terminates either when the readJournalHdr() call returns
+  ** SQLITE_DONE or an IO error occurs. */
+  while( 1 ){
 
-#ifndef SQLITE_OMIT_MEMORYDB
-/*
-** Clear a PgHistory block
-*/
-static void clearHistory(PgHistory *pHist){
-  sqlite3PageFree(pHist->pOrig);
-  sqlite3PageFree(pHist->pStmt);
-  pHist->pOrig = 0;
-  pHist->pStmt = 0;
-}
-#else
-#define clearHistory(x)
-#endif
+    /* Read the next journal header from the journal file.  If there are
+    ** not enough bytes left in the journal file for a complete header, or
+    ** it is corrupted, then a process must of failed while writing it.
+    ** This indicates nothing more needs to be rolled back.
+    */
+    rc = readJournalHdr(pPager, szJ, &nRec, &mxPg);
+    if( rc!=SQLITE_OK ){ 
+      if( rc==SQLITE_DONE ){
+        rc = SQLITE_OK;
+      }
+      goto end_playback;
+    }
 
-/*
-** Forward declaration
-*/
-static int syncJournal(Pager*);
+    /* If nRec is 0xffffffff, then this journal was created by a process
+    ** working in no-sync mode. This means that the rest of the journal
+    ** file consists of pages, there are no more journal headers. Compute
+    ** the value of nRec based on this assumption.
+    */
+    if( nRec==0xffffffff ){
+      assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
+      nRec = (szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager);
+    }
 
-/*
-** Unlink pPg from its hash chain. Also set the page number to 0 to indicate
-** that the page is not part of any hash chain. This is required because the
-** sqlite3PagerMovepage() routine can leave a page in the 
-** pNextFree/pPrevFree list that is not a part of any hash-chain.
-*/
-static void unlinkHashChain(Pager *pPager, PgHdr *pPg){
-  if( pPg->pgno==0 ){
-    assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
-    return;
+    /* If nRec is 0 and this rollback is of a transaction created by this
+    ** process and if this is the final header in the journal, then it means
+    ** that this part of the journal was being filled but has not yet been
+    ** synced to disk.  Compute the number of pages based on the remaining
+    ** size of the file.
+    **
+    ** The third term of the test was added to fix ticket #2565.
+    */
+    if( nRec==0 && !isHot &&
+        pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
+      nRec = (szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager);
+    }
+
+    /* If this is the first header read from the journal, truncate the
+    ** database file back to its original size.
+    */
+    if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
+      rc = pager_truncate(pPager, mxPg);
+      if( rc!=SQLITE_OK ){
+        goto end_playback;
+      }
+    }
+
+    /* Copy original pages out of the journal and back into the database file.
+    */
+    for(u=0; u<nRec; u++){
+      rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
+      if( rc!=SQLITE_OK ){
+        if( rc==SQLITE_DONE ){
+          rc = SQLITE_OK;
+          pPager->journalOff = szJ;
+          break;
+        }else{
+          goto end_playback;
+        }
+      }
+    }
   }
-  if( pPg->pNextHash ){
-    pPg->pNextHash->pPrevHash = pPg->pPrevHash;
+  /*NOTREACHED*/
+  assert( 0 );
+
+end_playback:
+  if( rc==SQLITE_OK ){
+    zMaster = pPager->pTmpSpace;
+    rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
   }
-  if( pPg->pPrevHash ){
-    assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg );
-    pPg->pPrevHash->pNextHash = pPg->pNextHash;
-  }else{
-    int h = pPg->pgno & (pPager->nHash-1);
-    pPager->aHash[h] = pPg->pNextHash;
+  if( rc==SQLITE_OK ){
+    rc = pager_end_transaction(pPager, zMaster[0]!='\0');
   }
-  if( MEMDB ){
-    clearHistory(PGHDR_TO_HIST(pPg, pPager));
+  if( rc==SQLITE_OK && zMaster[0] ){
+    /* If there was a master journal and this routine will return success,
+    ** see if it is possible to delete the master journal.
+    */
+    rc = pager_delmaster(pPager, zMaster);
   }
-  pPg->pgno = 0;
-  pPg->pNextHash = pPg->pPrevHash = 0;
-}
-
-/*
-** Unlink a page from the free list (the list of all pages where nRef==0)
-** and from its hash collision chain.
-*/
-static void unlinkPage(PgHdr *pPg){
-  Pager *pPager = pPg->pPager;
 
-  /* Unlink from free page list */
-  lruListRemove(pPg);
-
-  /* Unlink from the pgno hash table */
-  unlinkHashChain(pPager, pPg);
+  /* The Pager.sectorSize variable may have been updated while rolling
+  ** back a journal created by a process with a different sector size
+  ** value. Reset it to the correct value for this process.
+  */
+  setSectorSize(pPager);
+  return rc;
 }
 
 /*
-** This routine is used to truncate the cache when a database
-** is truncated.  Drop from the cache all pages whose pgno is
-** larger than pPager->dbSize and is unreferenced.
+** Playback the statement journal.
 **
-** Referenced pages larger than pPager->dbSize are zeroed.
+** This is similar to playing back the transaction journal but with
+** a few extra twists.
 **
-** Actually, at the point this routine is called, it would be
-** an error to have a referenced page.  But rather than delete
-** that page and guarantee a subsequent segfault, it seems better
-** to zero it and hope that we error out sanely.
-*/
-static void pager_truncate_cache(Pager *pPager){
-  PgHdr *pPg;
-  PgHdr **ppPg;
-  int dbSize = pPager->dbSize;
-
-  ppPg = &pPager->pAll;
-  while( (pPg = *ppPg)!=0 ){
-    if( pPg->pgno<=dbSize ){
-      ppPg = &pPg->pNextAll;
-    }else if( pPg->nRef>0 ){
-      memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
-      ppPg = &pPg->pNextAll;
-    }else{
-      *ppPg = pPg->pNextAll;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-      if( *ppPg ){
-        (*ppPg)->pPrevAll = pPg->pPrevAll;
-      }
-#endif
-      IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
-      PAGER_INCR(sqlite3_pager_pgfree_count);
-      unlinkPage(pPg);
-      makeClean(pPg);
-      sqlite3PageFree(pPg->pData);
-      sqlite3_free(pPg);
-      pPager->nPage--;
-    }
-  }
-}
-
-/*
-** Try to obtain a lock on a file.  Invoke the busy callback if the lock
-** is currently not available.  Repeat until the busy callback returns
-** false or until the lock succeeds.
+**    (1)  The number of pages in the database file at the start of
+**         the statement is stored in pPager->stmtSize, not in the
+**         journal file itself.
 **
-** Return SQLITE_OK on success and an error code if we cannot obtain
-** the lock.
+**    (2)  In addition to playing back the statement journal, also
+**         playback all pages of the transaction journal beginning
+**         at offset pPager->stmtJSize.
 */
-static int pager_wait_on_lock(Pager *pPager, int locktype){
+static int pager_stmt_playback(Pager *pPager){
+  i64 szJ;                 /* Size of the full journal */
+  i64 hdrOff;
+  int nRec;                /* Number of Records */
+  int i;                   /* Loop counter */
   int rc;
 
-  /* The OS lock values must be the same as the Pager lock values */
-  assert( PAGER_SHARED==SHARED_LOCK );
-  assert( PAGER_RESERVED==RESERVED_LOCK );
-  assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
-
-  /* If the file is currently unlocked then the size must be unknown */
-  assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB );
+  szJ = pPager->journalOff;
 
-  if( pPager->state>=locktype ){
-    rc = SQLITE_OK;
-  }else{
-    if( pPager->pBusyHandler ) pPager->pBusyHandler->nBusy = 0;
-    do {
-      rc = sqlite3OsLock(pPager->fd, locktype);
-    }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) );
-    if( rc==SQLITE_OK ){
-      pPager->state = locktype;
-      IOTRACE(("LOCK %p %d\n", pPager, locktype))
-    }
+  /* Set hdrOff to be the offset just after the end of the last journal
+  ** page written before the first journal-header for this statement
+  ** transaction was written, or the end of the file if no journal
+  ** header was written.
+  */
+  hdrOff = pPager->stmtHdrOff;
+  assert( pPager->fullSync || !hdrOff );
+  if( !hdrOff ){
+    hdrOff = szJ;
   }
-  return rc;
-}
+  
+  /* Truncate the database back to its original size.
+  */
+  rc = pager_truncate(pPager, pPager->stmtSize);
+  assert( pPager->state>=PAGER_SHARED );
 
-/*
-** Truncate the file to the number of pages specified.
-*/
-SQLITE_PRIVATE int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
-  int rc;
-  assert( pPager->state>=PAGER_SHARED || MEMDB );
-  sqlite3PagerPagecount(pPager, 0);
-  if( pPager->errCode ){
-    rc = pPager->errCode;
-    return rc;
-  }
-  if( nPage>=(unsigned)pPager->dbSize ){
-    return SQLITE_OK;
-  }
-  if( MEMDB ){
-    pPager->dbSize = nPage;
-    pager_truncate_cache(pPager);
-    return SQLITE_OK;
-  }
-  pagerEnter(pPager);
-  rc = syncJournal(pPager);
-  pagerLeave(pPager);
-  if( rc!=SQLITE_OK ){
-    return rc;
+  /* Figure out how many records are in the statement journal.
+  */
+  assert( pPager->stmtInUse && pPager->journalOpen );
+  nRec = pPager->stmtNRec;
+  
+  /* Copy original pages out of the statement journal and back into the
+  ** database file.  Note that the statement journal omits checksums from
+  ** each record since power-failure recovery is not important to statement
+  ** journals.
+  */
+  for(i=0; i<nRec; i++){
+    i64 offset = i*(4+pPager->pageSize);
+    rc = pager_playback_one_page(pPager, pPager->stfd, offset, 0);
+    assert( rc!=SQLITE_DONE );
+    if( rc!=SQLITE_OK ) goto end_stmt_playback;
   }
 
-  /* Get an exclusive lock on the database before truncating. */
-  pagerEnter(pPager);
-  rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
-  pagerLeave(pPager);
-  if( rc!=SQLITE_OK ){
-    return rc;
+  /* Now roll some pages back from the transaction journal. Pager.stmtJSize
+  ** was the size of the journal file when this statement was started, so
+  ** everything after that needs to be rolled back, either into the
+  ** database, the memory cache, or both.
+  **
+  ** If it is not zero, then Pager.stmtHdrOff is the offset to the start
+  ** of the first journal header written during this statement transaction.
+  */
+  pPager->journalOff = pPager->stmtJSize;
+  pPager->cksumInit = pPager->stmtCksum;
+  while( pPager->journalOff < hdrOff ){
+    rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
+    assert( rc!=SQLITE_DONE );
+    if( rc!=SQLITE_OK ) goto end_stmt_playback;
   }
 
-  rc = pager_truncate(pPager, nPage);
-  return rc;
-}
-
-/*
-** Shutdown the page cache.  Free all memory and close all files.
-**
-** If a transaction was in progress when this routine is called, that
-** transaction is rolled back.  All outstanding pages are invalidated
-** and their memory is freed.  Any attempt to use a page associated
-** with this page cache after this function returns will likely
-** result in a coredump.
-**
-** This function always succeeds. If a transaction is active an attempt
-** is made to roll it back. If an error occurs during the rollback 
-** a hot journal may be left in the filesystem but no error is returned
-** to the caller.
-*/
-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  if( !MEMDB ){
-#ifndef SQLITE_MUTEX_NOOP
-    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
-#endif
-    sqlite3_mutex_enter(mutex);
-    if( pPager->pPrev ){
-      pPager->pPrev->pNext = pPager->pNext;
-    }else{
-      sqlite3PagerList = pPager->pNext;
+  while( pPager->journalOff < szJ ){
+    u32 nJRec;         /* Number of Journal Records */
+    u32 dummy;
+    rc = readJournalHdr(pPager, szJ, &nJRec, &dummy);
+    if( rc!=SQLITE_OK ){
+      assert( rc!=SQLITE_DONE );
+      goto end_stmt_playback;
     }
-    if( pPager->pNext ){
-      pPager->pNext->pPrev = pPager->pPrev;
+    if( nJRec==0 ){
+      nJRec = (szJ - pPager->journalOff) / (pPager->pageSize+8);
+    }
+    for(i=nJRec-1; i>=0 && pPager->journalOff < szJ; i--){
+      rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
+      assert( rc!=SQLITE_DONE );
+      if( rc!=SQLITE_OK ) goto end_stmt_playback;
     }
-    sqlite3_mutex_leave(mutex);
   }
-#endif
 
-  disable_simulated_io_errors();
-  sqlite3BeginBenignMalloc();
-  pPager->errCode = 0;
-  pPager->exclusiveMode = 0;
-  pager_reset(pPager);
-  pagerUnlockAndRollback(pPager);
-  enable_simulated_io_errors();
-  sqlite3EndBenignMalloc();
-  PAGERTRACE2("CLOSE %d\n", PAGERID(pPager));
-  IOTRACE(("CLOSE %p\n", pPager))
-  if( pPager->journalOpen ){
-    sqlite3OsClose(pPager->jfd);
-  }
-  sqlite3BitvecDestroy(pPager->pInJournal);
-  if( pPager->stmtOpen ){
-    sqlite3OsClose(pPager->stfd);
+  pPager->journalOff = szJ;
+  
+end_stmt_playback:
+  if( rc==SQLITE_OK) {
+    pPager->journalOff = szJ;
+    /* pager_reload_cache(pPager); */
   }
-  sqlite3OsClose(pPager->fd);
-  /* Temp files are automatically deleted by the OS
-  ** if( pPager->tempFile ){
-  **   sqlite3OsDelete(pPager->zFilename);
-  ** }
-  */
-
-  sqlite3_free(pPager->aHash);
-  sqlite3PageFree(pPager->pTmpSpace);
-  sqlite3_free(pPager);
-  return SQLITE_OK;
+  return rc;
 }
 
-#if !defined(NDEBUG) || defined(SQLITE_TEST)
 /*
-** Return the page number for the given page data.
+** Change the maximum number of in-memory pages that are allowed.
 */
-SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *p){
-  return p->pgno;
+SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
+  sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
 }
-#endif
 
 /*
-** The page_ref() function increments the reference count for a page.
-** If the page is currently on the freelist (the reference count is zero) then
-** remove it from the freelist.
-**
-** For non-test systems, page_ref() is a macro that calls _page_ref()
-** online of the reference count is zero.  For test systems, page_ref()
-** is a real function so that we can set breakpoints and trace it.
-*/
-static void _page_ref(PgHdr *pPg){
-  if( pPg->nRef==0 ){
-    /* The page is currently on the freelist.  Remove it. */
-    lruListRemove(pPg);
-    pPg->pPager->nRef++;
-  }
-  pPg->nRef++;
+** Adjust the robustness of the database to damage due to OS crashes
+** or power failures by changing the number of syncs()s when writing
+** the rollback journal.  There are three levels:
+**
+**    OFF       sqlite3OsSync() is never called.  This is the default
+**              for temporary and transient files.
+**
+**    NORMAL    The journal is synced once before writes begin on the
+**              database.  This is normally adequate protection, but
+**              it is theoretically possible, though very unlikely,
+**              that an inopertune power failure could leave the journal
+**              in a state which would cause damage to the database
+**              when it is rolled back.
+**
+**    FULL      The journal is synced twice before writes begin on the
+**              database (with some additional information - the nRec field
+**              of the journal header - being written in between the two
+**              syncs).  If we assume that writing a
+**              single disk sector is atomic, then this mode provides
+**              assurance that the journal will not be corrupted to the
+**              point of causing damage to the database during rollback.
+**
+** Numeric values associated with these states are OFF==1, NORMAL=2,
+** and FULL=3.
+*/
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){
+  pPager->noSync =  level==1 || pPager->tempFile;
+  pPager->fullSync = level==3 && !pPager->tempFile;
+  pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
+  if( pPager->noSync ) pPager->needSync = 0;
 }
-#ifdef SQLITE_DEBUG
-  static void page_ref(PgHdr *pPg){
-    if( pPg->nRef==0 ){
-      _page_ref(pPg);
-    }else{
-      pPg->nRef++;
-    }
-  }
-#else
-# define page_ref(P)   ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++)
 #endif
 
 /*
-** Increment the reference count for a page.  The input pointer is
-** a reference to the page data.
+** The following global variable is incremented whenever the library
+** attempts to open a temporary file.  This information is used for
+** testing and analysis only.  
 */
-SQLITE_PRIVATE int sqlite3PagerRef(DbPage *pPg){
-  pagerEnter(pPg->pPager);
-  page_ref(pPg);
-  pagerLeave(pPg->pPager);
-  return SQLITE_OK;
-}
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_opentemp_count = 0;
+#endif
 
 /*
-** Sync the journal.  In other words, make sure all the pages that have
-** been written to the journal have actually reached the surface of the
-** disk.  It is not safe to modify the original database file until after
-** the journal has been synced.  If the original database is modified before
-** the journal is synced and a power failure occurs, the unsynced journal
-** data would be lost and we would be unable to completely rollback the
-** database changes.  Database corruption would occur.
-** 
-** This routine also updates the nRec field in the header of the journal.
-** (See comments on the pager_playback() routine for additional information.)
-** If the sync mode is FULL, two syncs will occur.  First the whole journal
-** is synced, then the nRec field is updated, then a second sync occurs.
-**
-** For temporary databases, we do not care if we are able to rollback
-** after a power failure, so no sync occurs.
-**
-** If the IOCAP_SEQUENTIAL flag is set for the persistent media on which
-** the database is stored, then OsSync() is never called on the journal
-** file. In this case all that is required is to update the nRec field in
-** the journal header.
+** Open a temporary file. 
 **
-** This routine clears the needSync field of every page current held in
-** memory.
+** Write the file descriptor into *fd.  Return SQLITE_OK on success or some
+** other error code if we fail. The OS will automatically delete the temporary
+** file when it is closed.
 */
-static int syncJournal(Pager *pPager){
-  PgHdr *pPg;
-  int rc = SQLITE_OK;
-
-  /* Sync the journal before modifying the main database
-  ** (assuming there is a journal and it needs to be synced.)
-  */
-  if( pPager->needSync ){
-    if( !pPager->tempFile ){
-      int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
-      assert( pPager->journalOpen );
-
-      if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
-        /* Write the nRec value into the journal file header. If in
-        ** full-synchronous mode, sync the journal first. This ensures that
-        ** all data has really hit the disk before nRec is updated to mark
-        ** it as a candidate for rollback.
-        **
-        ** This is not required if the persistent media supports the
-        ** SAFE_APPEND property. Because in this case it is not possible 
-        ** for garbage data to be appended to the file, the nRec field
-        ** is populated with 0xFFFFFFFF when the journal header is written
-        ** and never needs to be updated.
-        */
-        i64 jrnlOff;
-        if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
-          PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager));
-          IOTRACE(("JSYNC %p\n", pPager))
-          rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags);
-          if( rc!=0 ) return rc;
-        }
-
-        jrnlOff = pPager->journalHdr + sizeof(aJournalMagic);
-        IOTRACE(("JHDR %p %lld %d\n", pPager, jrnlOff, 4));
-        rc = write32bits(pPager->jfd, jrnlOff, pPager->nRec);
-        if( rc ) return rc;
-      }
-      if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
-        PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager));
-        IOTRACE(("JSYNC %p\n", pPager))
-        rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| 
-          (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
-        );
-        if( rc!=0 ) return rc;
-      }
-      pPager->journalStarted = 1;
-    }
-    pPager->needSync = 0;
-
-    /* Erase the needSync flag from every page.
-    */
-    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
-      pPg->needSync = 0;
-    }
-    lruListSetFirstSynced(pPager);
-  }
+static int sqlite3PagerOpentemp(
+  Pager *pPager,        /* The pager object */
+  sqlite3_file *pFile,  /* Write the file descriptor here */
+  int vfsFlags          /* Flags passed through to the VFS */
+){
+  int rc;
 
-#ifndef NDEBUG
-  /* If the Pager.needSync flag is clear then the PgHdr.needSync
-  ** flag must also be clear for all pages.  Verify that this
-  ** invariant is true.
-  */
-  else{
-    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
-      assert( pPg->needSync==0 );
-    }
-    assert( pPager->lru.pFirstSynced==pPager->lru.pFirst );
-  }
+#ifdef SQLITE_TEST
+  sqlite3_opentemp_count++;  /* Used for testing and analysis only */
 #endif
 
+  vfsFlags |=  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+            SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
+  rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
+  assert( rc!=SQLITE_OK || pFile->pMethods );
   return rc;
 }
 
-/*
-** Merge two lists of pages connected by pDirty and in pgno order.
-** Do not both fixing the pPrevDirty pointers.
-*/
-static PgHdr *merge_pagelist(PgHdr *pA, PgHdr *pB){
-  PgHdr result, *pTail;
-  pTail = &result;
-  while( pA && pB ){
-    if( pA->pgno<pB->pgno ){
-      pTail->pDirty = pA;
-      pTail = pA;
-      pA = pA->pDirty;
-    }else{
-      pTail->pDirty = pB;
-      pTail = pB;
-      pB = pB->pDirty;
-    }
-  }
-  if( pA ){
-    pTail->pDirty = pA;
-  }else if( pB ){
-    pTail->pDirty = pB;
-  }else{
-    pTail->pDirty = 0;
-  }
-  return result.pDirty;
-}
+static int pagerStress(void *,PgHdr *);
 
 /*
-** Sort the list of pages in accending order by pgno.  Pages are
-** connected by pDirty pointers.  The pPrevDirty pointers are
-** corrupted by this sort.
+** Create a new page cache and put a pointer to the page cache in *ppPager.
+** The file to be cached need not exist.  The file is not locked until
+** the first call to sqlite3PagerGet() and is only held open until the
+** last page is released using sqlite3PagerUnref().
+**
+** If zFilename is NULL then a randomly-named temporary file is created
+** and used as the file to be cached.  The file will be deleted
+** automatically when it is closed.
+**
+** If zFilename is ":memory:" then all information is held in cache.
+** It is never written to disk.  This can be used to implement an
+** in-memory database.
 */
-#define N_SORT_BUCKET_ALLOC 25
-#define N_SORT_BUCKET       25
-#ifdef SQLITE_TEST
-  int sqlite3_pager_n_sort_bucket = 0;
-  #undef N_SORT_BUCKET
-  #define N_SORT_BUCKET \
-   (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)
-#endif
-static PgHdr *sort_pagelist(PgHdr *pIn){
-  PgHdr *a[N_SORT_BUCKET_ALLOC], *p;
+SQLITE_PRIVATE int sqlite3PagerOpen(
+  sqlite3_vfs *pVfs,       /* The virtual file system to use */
+  Pager **ppPager,         /* Return the Pager structure here */
+  const char *zFilename,   /* Name of the database file to open */
+  void (*xDesc)(DbPage*),  /* Page destructor function */
+  int nExtra,              /* Extra bytes append to each in-memory page */
+  int flags,               /* flags controlling this file */
+  int vfsFlags             /* flags passed through to sqlite3_vfs.xOpen() */
+){
+  u8 *pPtr;
+  Pager *pPager = 0;
+  int rc = SQLITE_OK;
   int i;
-  memset(a, 0, sizeof(a));
-  while( pIn ){
-    p = pIn;
-    pIn = p->pDirty;
-    p->pDirty = 0;
-    for(i=0; i<N_SORT_BUCKET-1; i++){
-      if( a[i]==0 ){
-        a[i] = p;
-        break;
-      }else{
-        p = merge_pagelist(a[i], p);
-        a[i] = 0;
-      }
+  int tempFile = 0;
+  int memDb = 0;
+  int readOnly = 0;
+  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
+  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
+  int journalFileSize = sqlite3JournalSize(pVfs);
+  int pcacheSize = sqlite3PcacheSize();
+  int szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;
+  char *zPathname = 0;
+  int nPathname = 0;
+
+  /* The default return is a NULL pointer */
+  *ppPager = 0;
+
+  /* Compute and store the full pathname in an allocated buffer pointed
+  ** to by zPathname, length nPathname. Or, if this is a temporary file,
+  ** leave both nPathname and zPathname set to 0.
+  */
+  if( zFilename && zFilename[0] ){
+    nPathname = pVfs->mxPathname+1;
+    zPathname = sqlite3Malloc(nPathname*2);
+    if( zPathname==0 ){
+      return SQLITE_NOMEM;
     }
-    if( i==N_SORT_BUCKET-1 ){
-      /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET) 
-      ** elements in the input list. This is possible, but impractical.
-      ** Testing this line is the point of global variable
-      ** sqlite3_pager_n_sort_bucket.
-      */
-      a[i] = merge_pagelist(a[i], p);
+#ifndef SQLITE_OMIT_MEMORYDB
+    if( strcmp(zFilename,":memory:")==0 ){
+      memDb = 1;
+      zPathname[0] = 0;
+    }else
+#endif
+    {
+      rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
+    }
+    if( rc!=SQLITE_OK ){
+      sqlite3_free(zPathname);
+      return rc;
     }
+    nPathname = strlen(zPathname);
   }
-  p = a[0];
-  for(i=1; i<N_SORT_BUCKET; i++){
-    p = merge_pagelist(p, a[i]);
+
+  /* Allocate memory for the pager structure */
+  pPager = sqlite3MallocZero(
+    sizeof(*pPager) +           /* Pager structure */
+    pcacheSize      +           /* PCache object */
+    journalFileSize +           /* The journal file structure */ 
+    pVfs->szOsFile * 3 +        /* The main db and two journal files */ 
+    3*nPathname + 40            /* zFilename, zDirectory, zJournal */
+  );
+  if( !pPager ){
+    sqlite3_free(zPathname);
+    return SQLITE_NOMEM;
+  }
+  pPager->pPCache = (PCache *)&pPager[1];
+  pPtr = ((u8 *)&pPager[1]) + pcacheSize;
+  pPager->vfsFlags = vfsFlags;
+  pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0];
+  pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1];
+  pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2];
+  pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize];
+  pPager->zDirectory = &pPager->zFilename[nPathname+1];
+  pPager->zJournal = &pPager->zDirectory[nPathname+1];
+  pPager->pVfs = pVfs;
+  if( zPathname ){
+    memcpy(pPager->zFilename, zPathname, nPathname+1);
+    sqlite3_free(zPathname);
   }
-  return p;
-}
 
-/*
-** Given a list of pages (connected by the PgHdr.pDirty pointer) write
-** every one of those pages out to the database file and mark them all
-** as clean.
-*/
-static int pager_write_pagelist(PgHdr *pList){
-  Pager *pPager;
-  PgHdr *p;
-  int rc;
+  /* Open the pager file.
+  */
+  if( zFilename && zFilename[0] && !memDb ){
+    if( nPathname>(pVfs->mxPathname - sizeof("-journal")) ){
+      rc = SQLITE_CANTOPEN;
+    }else{
+      int fout = 0;
+      rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd,
+                         pPager->vfsFlags, &fout);
+      readOnly = (fout&SQLITE_OPEN_READONLY);
 
-  if( pList==0 ) return SQLITE_OK;
-  pPager = pList->pPager;
+      /* If the file was successfully opened for read/write access,
+      ** choose a default page size in case we have to create the
+      ** database file. The default page size is the maximum of:
+      **
+      **    + SQLITE_DEFAULT_PAGE_SIZE,
+      **    + The value returned by sqlite3OsSectorSize()
+      **    + The largest page size that can be written atomically.
+      */
+      if( rc==SQLITE_OK && !readOnly ){
+        int iSectorSize = sqlite3OsSectorSize(pPager->fd);
+        if( szPageDflt<iSectorSize ){
+          szPageDflt = iSectorSize;
+        }
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+        {
+          int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
+          int ii;
+          assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
+          assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
+          assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
+          for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
+            if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ) szPageDflt = ii;
+          }
+        }
+#endif
+        if( szPageDflt>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
+          szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
+        }
+      }
+    }
+  }else if( !memDb ){
+    /* If a temporary file is requested, it is not opened immediately.
+    ** In this case we accept the default page size and delay actually
+    ** opening the file until the first call to OsWrite().
+    */ 
+    tempFile = 1;
+    pPager->state = PAGER_EXCLUSIVE;
+  }
 
-  /* At this point there may be either a RESERVED or EXCLUSIVE lock on the
-  ** database file. If there is already an EXCLUSIVE lock, the following
-  ** calls to sqlite3OsLock() are no-ops.
-  **
-  ** Moving the lock from RESERVED to EXCLUSIVE actually involves going
-  ** through an intermediate state PENDING.   A PENDING lock prevents new
-  ** readers from attaching to the database but is unsufficient for us to
-  ** write.  The idea of a PENDING lock is to prevent new readers from
-  ** coming in while we wait for existing readers to clear.
-  **
-  ** While the pager is in the RESERVED state, the original database file
-  ** is unchanged and we can rollback without having to playback the
-  ** journal into the original database file.  Once we transition to
-  ** EXCLUSIVE, it means the database file has been changed and any rollback
-  ** will require a journal playback.
-  */
-  rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
-  if( rc!=SQLITE_OK ){
-    return rc;
+  if( pPager && rc==SQLITE_OK ){
+    pPager->pTmpSpace = sqlite3PageMalloc(szPageDflt);
   }
 
-  pList = sort_pagelist(pList);
-  for(p=pList; p; p=p->pDirty){
-    assert( p->dirty );
-    p->dirty = 0;
+  /* If an error occured in either of the blocks above.
+  ** Free the Pager structure and close the file.
+  ** Since the pager is not allocated there is no need to set 
+  ** any Pager.errMask variables.
+  */
+  if( !pPager || !pPager->pTmpSpace ){
+    sqlite3OsClose(pPager->fd);
+    sqlite3_free(pPager);
+    return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
   }
-  while( pList ){
+  nExtra = FORCE_ALIGNMENT(nExtra);
+  sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, xDesc, 
+                    !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
 
-    /* If the file has not yet been opened, open it now. */
-    if( !pPager->fd->pMethods ){
-      assert(pPager->tempFile);
-      rc = sqlite3PagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
-      if( rc ) return rc;
-    }
+  PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename);
+  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
 
-    /* If there are dirty pages in the page cache with page numbers greater
-    ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to
-    ** make the file smaller (presumably by auto-vacuum code). Do not write
-    ** any such pages to the file.
-    */
-    if( pList->pgno<=pPager->dbSize ){
-      i64 offset = (pList->pgno-1)*(i64)pPager->pageSize;
-      char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
-      PAGERTRACE4("STORE %d page %d hash(%08x)\n",
-                   PAGERID(pPager), pList->pgno, pager_pagehash(pList));
-      IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno));
-      rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
-      PAGER_INCR(sqlite3_pager_writedb_count);
-      PAGER_INCR(pPager->nWrite);
-      if( pList->pgno==1 ){
-        memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
-      }
-    }
-#ifndef NDEBUG
-    else{
-      PAGERTRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno);
-    }
-#endif
-    if( rc ) return rc;
-#ifdef SQLITE_CHECK_PAGES
-    pList->pageHash = pager_pagehash(pList);
-#endif
-    pList = pList->pDirty;
+  /* Fill in Pager.zDirectory[] */
+  memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1);
+  for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){}
+  if( i>0 ) pPager->zDirectory[i-1] = 0;
+
+  /* Fill in Pager.zJournal[] */
+  if( zPathname ){
+    memcpy(pPager->zJournal, pPager->zFilename, nPathname);
+    memcpy(&pPager->zJournal[nPathname], "-journal", 9);
+  }else{
+    pPager->zJournal = 0;
+  }
+
+  /* pPager->journalOpen = 0; */
+  pPager->useJournal = useJournal && !memDb;
+  pPager->noReadlock = noReadlock && readOnly;
+  /* pPager->stmtOpen = 0; */
+  /* pPager->stmtInUse = 0; */
+  /* pPager->nRef = 0; */
+  pPager->dbSize = memDb-1;
+  pPager->pageSize = szPageDflt;
+  /* pPager->stmtSize = 0; */
+  /* pPager->stmtJSize = 0; */
+  /* pPager->nPage = 0; */
+  pPager->mxPage = 100;
+  pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
+  /* pPager->state = PAGER_UNLOCK; */
+  assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
+  /* pPager->errMask = 0; */
+  pPager->tempFile = tempFile;
+  assert( tempFile==PAGER_LOCKINGMODE_NORMAL 
+          || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
+  assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
+  pPager->exclusiveMode = tempFile; 
+  pPager->memDb = memDb;
+  pPager->readOnly = readOnly;
+  /* pPager->needSync = 0; */
+  pPager->noSync = pPager->tempFile || !useJournal;
+  pPager->fullSync = (pPager->noSync?0:1);
+  pPager->sync_flags = SQLITE_SYNC_NORMAL;
+  /* pPager->pFirst = 0; */
+  /* pPager->pFirstSynced = 0; */
+  /* pPager->pLast = 0; */
+  pPager->nExtra = nExtra;
+  pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
+  assert(pPager->fd->pMethods||memDb||tempFile);
+  if( !memDb ){
+    setSectorSize(pPager);
   }
+  /* pPager->pBusyHandler = 0; */
+  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
+  *ppPager = pPager;
   return SQLITE_OK;
 }
 
 /*
-** Collect every dirty page into a dirty list and
-** return a pointer to the head of that list.  All pages are
-** collected even if they are still in use.
+** Set the busy handler function.
 */
-static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
-
-#ifndef NDEBUG
-  /* Verify the sanity of the dirty list when we are running
-  ** in debugging mode.  This is expensive, so do not
-  ** do this on a normal build. */
-  int n1 = 0;
-  int n2 = 0;
-  PgHdr *p;
-  for(p=pPager->pAll; p; p=p->pNextAll){ if( p->dirty ) n1++; }
-  for(p=pPager->pDirty; p; p=p->pDirty){ n2++; }
-  assert( n1==n2 );
-#endif
+SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager *pPager, BusyHandler *pBusyHandler){
+  pPager->pBusyHandler = pBusyHandler;
+}
 
-  return pPager->pDirty;
+/*
+** Set the reinitializer for this pager.  If not NULL, the reinitializer
+** is called when the content of a page in cache is restored to its original
+** value as a result of a rollback.  The callback gives higher-level code
+** an opportunity to restore the EXTRA section to agree with the restored
+** page data.
+*/
+SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){
+  pPager->xReiniter = xReinit;
 }
 
 /*
-** Return 1 if there is a hot journal on the given pager.
-** A hot journal is one that needs to be played back.
-**
-** If the current size of the database file is 0 but a journal file
-** exists, that is probably an old journal left over from a prior
-** database with the same name.  Just delete the journal.
-**
-** Return negative if unable to determine the status of the journal.
-**
-** This routine does not open the journal file to examine its
-** content.  Hence, the journal might contain the name of a master
-** journal file that has been deleted, and hence not be hot.  Or
-** the header of the journal might be zeroed out.  This routine
-** does not discover these cases of a non-hot journal - if the
-** journal file exists and is not empty this routine assumes it
-** is hot.  The pager_playback() routine will discover that the
-** journal file is not really hot and will no-op.
+** Set the page size to *pPageSize. If the suggest new page size is
+** inappropriate, then an alternative page size is set to that
+** value before returning.
 */
-static int hasHotJournal(Pager *pPager, int *pExists){
-  sqlite3_vfs *pVfs = pPager->pVfs;
+SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize){
   int rc = SQLITE_OK;
-  *pExists = 0;
-  if( pPager->useJournal && pPager->fd->pMethods ){
-    int exists;
-    int locked;
-
-    rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
-    if( rc==SQLITE_OK && exists ){
-      rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
-    }
-
-    if( rc==SQLITE_OK && exists && !locked ){
-      int nPage;
-      rc = sqlite3PagerPagecount(pPager, &nPage);
-      if( rc==SQLITE_OK ){
-        if( nPage==0 ){
-          sqlite3OsDelete(pVfs, pPager->zJournal, 0);
-        }else{
-          *pExists = 1;
-        }
-      }
+  u16 pageSize = *pPageSize;
+  assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
+  if( pageSize && pageSize!=pPager->pageSize 
+   && (pPager->memDb==0 || pPager->dbSize==0)
+   && sqlite3PcacheRefCount(pPager->pPCache)==0 
+  ){
+    char *pNew = (char *)sqlite3PageMalloc(pageSize);
+    if( !pNew ){
+      rc = SQLITE_NOMEM;
+    }else{
+      pager_reset(pPager);
+      pPager->pageSize = pageSize;
+      if( !pPager->memDb ) setSectorSize(pPager);
+      sqlite3PageFree(pPager->pTmpSpace);
+      pPager->pTmpSpace = pNew;
+      sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
     }
   }
-
+  *pPageSize = pPager->pageSize;
   return rc;
 }
 
 /*
-** Try to find a page in the cache that can be recycled. 
-**
-** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It 
-** does not set the pPager->errCode variable.
+** Return a pointer to the "temporary page" buffer held internally
+** by the pager.  This is a buffer that is big enough to hold the
+** entire content of a database page.  This buffer is used internally
+** during rollback and will be overwritten whenever a rollback
+** occurs.  But other modules are free to use it too, as long as
+** no rollbacks are happening.
 */
-static int pager_recycle(Pager *pPager, PgHdr **ppPg){
-  PgHdr *pPg;
-  *ppPg = 0;
-
-  /* It is illegal to call this function unless the pager object
-  ** pointed to by pPager has at least one free page (page with nRef==0).
-  */ 
-  assert(!MEMDB);
-  assert(pPager->lru.pFirst);
-
-  /* Find a page to recycle.  Try to locate a page that does not
-  ** require us to do an fsync() on the journal.
-  */
-  pPg = pPager->lru.pFirstSynced;
+SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){
+  return pPager->pTmpSpace;
+}
 
-  /* If we could not find a page that does not require an fsync()
-  ** on the journal file then fsync the journal file.  This is a
-  ** very slow operation, so we work hard to avoid it.  But sometimes
-  ** it can't be helped.
-  */
-  if( pPg==0 && pPager->lru.pFirst ){
-    if( !pPager->errCode ){
-      int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
-      int rc = syncJournal(pPager);
-      if( rc!=0 ){
-        return rc;
-      }
-      if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
-        /* If in full-sync mode, write a new journal header into the
-        ** journal file. This is done to avoid ever modifying a journal
-        ** header that is involved in the rollback of pages that have
-        ** already been written to the database (in case the header is
-        ** trashed when the nRec field is updated).
-        */
-        pPager->nRec = 0;
-        assert( pPager->journalOff > 0 );
-        assert( pPager->doNotSync==0 );
-        rc = writeJournalHdr(pPager);
-        if( rc!=0 ){
-          return rc;
-        }
-      }
-    }
-    pPg = pPager->lru.pFirst;
+/*
+** Attempt to set the maximum database page count if mxPage is positive. 
+** Make no changes if mxPage is zero or negative.  And never reduce the
+** maximum page count below the current size of the database.
+**
+** Regardless of mxPage, return the current maximum page count.
+*/
+SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
+  if( mxPage>0 ){
+    pPager->mxPgno = mxPage;
   }
+  sqlite3PagerPagecount(pPager, 0);
+  return pPager->mxPgno;
+}
 
-  assert( pPg->nRef==0 );
+/*
+** The following set of routines are used to disable the simulated
+** I/O error mechanism.  These routines are used to avoid simulated
+** errors in places where we do not care about errors.
+**
+** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops
+** and generate no code.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API extern int sqlite3_io_error_pending;
+SQLITE_API extern int sqlite3_io_error_hit;
+static int saved_cnt;
+void disable_simulated_io_errors(void){
+  saved_cnt = sqlite3_io_error_pending;
+  sqlite3_io_error_pending = -1;
+}
+void enable_simulated_io_errors(void){
+  sqlite3_io_error_pending = saved_cnt;
+}
+#else
+# define disable_simulated_io_errors()
+# define enable_simulated_io_errors()
+#endif
 
-  /* Write the page to the database file if it is dirty.
-  */
-  if( pPg->dirty && !pPager->errCode ){
-    int rc;
-    assert( pPg->needSync==0 );
-    makeClean(pPg);
-    pPg->dirty = 1;
-    pPg->pDirty = 0;
-    rc = pager_write_pagelist( pPg );
-    pPg->dirty = 0;
-    if( rc!=SQLITE_OK ){
-      return rc;
+/*
+** Read the first N bytes from the beginning of the file into memory
+** that pDest points to. 
+**
+** No error checking is done. The rational for this is that this function 
+** may be called even if the file does not exist or contain a header. In 
+** these cases sqlite3OsRead() will return an error, to which the correct 
+** response is to zero the memory at pDest and continue.  A real IO error 
+** will presumably recur and be picked up later (Todo: Think about this).
+*/
+SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
+  int rc = SQLITE_OK;
+  memset(pDest, 0, N);
+  assert(MEMDB||pPager->fd->pMethods||pPager->tempFile);
+  if( pPager->fd->pMethods ){
+    IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
+    rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
+    if( rc==SQLITE_IOERR_SHORT_READ ){
+      rc = SQLITE_OK;
     }
   }
-  assert( pPg->dirty==0 || pPager->errCode );
-
-  /* If the page we are recycling is marked as alwaysRollback, then
-  ** set the global alwaysRollback flag, thus disabling the
-  ** sqlite3PagerDontRollback() optimization for the rest of this transaction.
-  ** It is necessary to do this because the page marked alwaysRollback
-  ** might be reloaded at a later time but at that point we won't remember
-  ** that is was marked alwaysRollback.  This means that all pages must
-  ** be marked as alwaysRollback from here on out.
-  */
-  if( pPg->alwaysRollback ){
-    IOTRACE(("ALWAYS_ROLLBACK %p\n", pPager))
-    pPager->alwaysRollback = 1;
-  }
-
-  /* Unlink the old page from the free list and the hash table
-  */
-  unlinkPage(pPg);
-  assert( pPg->pgno==0 );
-
-  *ppPg = pPg;
-  return SQLITE_OK;
+  return rc;
 }
 
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
 /*
-** This function is called to free superfluous dynamically allocated memory
-** held by the pager system. Memory in use by any SQLite pager allocated
-** by the current thread may be sqlite3_free()ed.
+** Return the total number of pages in the disk file associated with
+** pPager. 
 **
-** nReq is the number of bytes of memory required. Once this much has
-** been released, the function returns. The return value is the total number 
-** of bytes of memory released.
+** If the PENDING_BYTE lies on the page directly after the end of the
+** file, then consider this page part of the file too. For example, if
+** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the
+** file is 4096 bytes, 5 is returned instead of 4.
 */
-SQLITE_PRIVATE int sqlite3PagerReleaseMemory(int nReq){
-  int nReleased = 0;          /* Bytes of memory released so far */
-  Pager *pPager;              /* For looping over pagers */
-  BusyHandler *savedBusy;     /* Saved copy of the busy handler */
-  int rc = SQLITE_OK;
-
-  /* Acquire the memory-management mutex
-  */
-#ifndef SQLITE_MUTEX_NOOP
-  sqlite3_mutex *mutex;       /* The MEM2 mutex */
-  mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
-#endif
-  sqlite3_mutex_enter(mutex);
-
-  /* Signal all database connections that memory management wants
-  ** to have access to the pagers.
-  */
-  for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
-     pPager->iInUseMM = 1;
+SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
+  i64 n = 0;
+  int rc;
+  assert( pPager!=0 );
+  if( pPager->errCode ){
+    rc = pPager->errCode;
+    return rc;
   }
-
-  while( rc==SQLITE_OK && (nReq<0 || nReleased<nReq) ){
-    PgHdr *pPg;
-    PgHdr *pRecycled;
- 
-    /* Try to find a page to recycle that does not require a sync(). If
-    ** this is not possible, find one that does require a sync().
-    */
-    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
-    pPg = sqlite3LruPageList.pFirstSynced;
-    while( pPg && (pPg->needSync || pPg->pPager->iInUseDB) ){
-      pPg = pPg->gfree.pNext;
+  if( pPager->dbSize>=0 ){
+    n = pPager->dbSize;
+  } else {
+    assert(pPager->fd->pMethods||pPager->tempFile);
+    if( (pPager->fd->pMethods)
+     && (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
+      pager_error(pPager, rc);
+      return rc;
     }
-    if( !pPg ){
-      pPg = sqlite3LruPageList.pFirst;
-      while( pPg && pPg->pPager->iInUseDB ){
-        pPg = pPg->gfree.pNext;
-      }
+    if( n>0 && n<pPager->pageSize ){
+      n = 1;
+    }else{
+      n /= pPager->pageSize;
     }
-    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
-
-    /* If pPg==0, then the block above has failed to find a page to
-    ** recycle. In this case return early - no further memory will
-    ** be released.
-    */
-    if( !pPg ) break;
-
-    pPager = pPg->pPager;
-    assert(!pPg->needSync || pPg==pPager->lru.pFirst);
-    assert(pPg->needSync || pPg==pPager->lru.pFirstSynced);
-  
-    savedBusy = pPager->pBusyHandler;
-    pPager->pBusyHandler = 0;
-    rc = pager_recycle(pPager, &pRecycled);
-    pPager->pBusyHandler = savedBusy;
-    assert(pRecycled==pPg || rc!=SQLITE_OK);
-    if( rc==SQLITE_OK ){
-      /* We've found a page to free. At this point the page has been 
-      ** removed from the page hash-table, free-list and synced-list 
-      ** (pFirstSynced). It is still in the all pages (pAll) list. 
-      ** Remove it from this list before freeing.
-      **
-      ** Todo: Check the Pager.pStmt list to make sure this is Ok. It 
-      ** probably is though.
-      */
-      PgHdr *pTmp;
-      assert( pPg );
-      if( pPg==pPager->pAll ){
-         assert(pPg->pPrevAll==0);
-         assert(pPg->pNextAll==0 || pPg->pNextAll->pPrevAll==pPg);
-         pPager->pAll = pPg->pNextAll;
-         if( pPager->pAll ){
-           pPager->pAll->pPrevAll = 0;
-         }
-      }else{
-         assert(pPg->pPrevAll);
-         assert(pPg->pPrevAll->pNextAll==pPg);
-         pTmp = pPg->pPrevAll;
-         pTmp->pNextAll = pPg->pNextAll;
-         if( pTmp->pNextAll ){
-           pTmp->pNextAll->pPrevAll = pTmp;
-         }
-      }
-      nReleased += (
-          sizeof(*pPg) + pPager->pageSize
-          + sizeof(u32) + pPager->nExtra
-          + MEMDB*sizeof(PgHistory) 
-      );
-      IOTRACE(("PGFREE %p %d *\n", pPager, pPg->pgno));
-      PAGER_INCR(sqlite3_pager_pgfree_count);
-      sqlite3PageFree(pPg->pData);
-      sqlite3_free(pPg);
-      pPager->nPage--;
-    }else{
-      /* An error occured whilst writing to the database file or 
-      ** journal in pager_recycle(). The error is not returned to the 
-      ** caller of this function. Instead, set the Pager.errCode variable.
-      ** The error will be returned to the user (or users, in the case 
-      ** of a shared pager cache) of the pager for which the error occured.
-      */
-      assert(
-          (rc&0xff)==SQLITE_IOERR ||
-          rc==SQLITE_FULL ||
-          rc==SQLITE_BUSY
-      );
-      assert( pPager->state>=PAGER_RESERVED );
-      pager_error(pPager, rc);
+    if( pPager->state!=PAGER_UNLOCK ){
+      pPager->dbSize = n;
     }
   }
-
-  /* Clear the memory management flags and release the mutex
-  */
-  for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
-     pPager->iInUseMM = 0;
+  if( n==(PENDING_BYTE/pPager->pageSize) ){
+    n++;
   }
-  sqlite3_mutex_leave(mutex);
-
-  /* Return the number of bytes released
-  */
-  return nReleased;
+  if( n>pPager->mxPgno ){
+    pPager->mxPgno = n;
+  }
+  if( pnPage ){
+    *pnPage = n;
+  }
+  return SQLITE_OK;
 }
-#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
 
 /*
-** Read the content of page pPg out of the database file.
+** Forward declaration
 */
-static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){
-  int rc;
-  i64 offset;
-  assert( MEMDB==0 );
-  assert(pPager->fd->pMethods||pPager->tempFile);
-  if( !pPager->fd->pMethods ){
-    return SQLITE_IOERR_SHORT_READ;
-  }
-  offset = (pgno-1)*(i64)pPager->pageSize;
-  rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize, offset);
-  PAGER_INCR(sqlite3_pager_readdb_count);
+static int syncJournal(Pager*);
+
+/*
+** This routine is used to truncate the cache when a database
+** is truncated.  Drop from the cache all pages whose pgno is
+** larger than pPager->dbSize and is unreferenced.
+**
+** Referenced pages larger than pPager->dbSize are zeroed.
+**
+** Actually, at the point this routine is called, it would be
+** an error to have a referenced page.  But rather than delete
+** that page and guarantee a subsequent segfault, it seems better
+** to zero it and hope that we error out sanely.
+*/
+static void pager_truncate_cache(Pager *pPager){
+  sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
+}
+
+/*
+** Try to obtain a lock on a file.  Invoke the busy callback if the lock
+** is currently not available.  Repeat until the busy callback returns
+** false or until the lock succeeds.
+**
+** Return SQLITE_OK on success and an error code if we cannot obtain
+** the lock.
+*/
+static int pager_wait_on_lock(Pager *pPager, int locktype){
+  int rc;
+
+  /* The OS lock values must be the same as the Pager lock values */
+  assert( PAGER_SHARED==SHARED_LOCK );
+  assert( PAGER_RESERVED==RESERVED_LOCK );
+  assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
+
+  /* If the file is currently unlocked then the size must be unknown */
+  assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB );
+
+  if( pPager->state>=locktype ){
+    rc = SQLITE_OK;
+  }else{
+    if( pPager->pBusyHandler ) pPager->pBusyHandler->nBusy = 0;
+    do {
+      rc = sqlite3OsLock(pPager->fd, locktype);
+    }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) );
+    if( rc==SQLITE_OK ){
+      pPager->state = locktype;
+      IOTRACE(("LOCK %p %d\n", pPager, locktype))
+    }
+  }
+  return rc;
+}
+
+/*
+** Truncate the file to the number of pages specified.
+*/
+SQLITE_PRIVATE int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
+  int rc = SQLITE_OK;
+  assert( pPager->state>=PAGER_SHARED || MEMDB );
+
+
+  sqlite3PagerPagecount(pPager, 0);
+  if( pPager->errCode ){
+    rc = pPager->errCode;
+  }else if( nPage<(unsigned)pPager->dbSize ){
+    if( MEMDB ){
+      pPager->dbSize = nPage;
+      pager_truncate_cache(pPager);
+    }else{
+      rc = syncJournal(pPager);
+      if( rc==SQLITE_OK ){
+        /* Get an exclusive lock on the database before truncating. */
+        rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+      }
+      if( rc==SQLITE_OK ){
+        rc = pager_truncate(pPager, nPage);
+      }
+    }
+  }
+
+  return rc;
+}
+
+/*
+** Shutdown the page cache.  Free all memory and close all files.
+**
+** If a transaction was in progress when this routine is called, that
+** transaction is rolled back.  All outstanding pages are invalidated
+** and their memory is freed.  Any attempt to use a page associated
+** with this page cache after this function returns will likely
+** result in a coredump.
+**
+** This function always succeeds. If a transaction is active an attempt
+** is made to roll it back. If an error occurs during the rollback 
+** a hot journal may be left in the filesystem but no error is returned
+** to the caller.
+*/
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
+
+  disable_simulated_io_errors();
+  sqlite3BeginBenignMalloc();
+  pPager->errCode = 0;
+  pPager->exclusiveMode = 0;
+  pager_reset(pPager);
+  pagerUnlockAndRollback(pPager);
+  enable_simulated_io_errors();
+  sqlite3EndBenignMalloc();
+  PAGERTRACE2("CLOSE %d\n", PAGERID(pPager));
+  IOTRACE(("CLOSE %p\n", pPager))
+  if( pPager->journalOpen ){
+    sqlite3OsClose(pPager->jfd);
+  }
+  sqlite3BitvecDestroy(pPager->pInJournal);
+  sqlite3BitvecDestroy(pPager->pAlwaysRollback);
+  if( pPager->stmtOpen ){
+    sqlite3OsClose(pPager->stfd);
+  }
+  sqlite3OsClose(pPager->fd);
+  /* Temp files are automatically deleted by the OS
+  ** if( pPager->tempFile ){
+  **   sqlite3OsDelete(pPager->zFilename);
+  ** }
+  */
+
+  sqlite3PageFree(pPager->pTmpSpace);
+  sqlite3PcacheClose(pPager->pPCache);
+  sqlite3_free(pPager);
+  return SQLITE_OK;
+}
+
+#if !defined(NDEBUG) || defined(SQLITE_TEST)
+/*
+** Return the page number for the given page data.
+*/
+SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *p){
+  return p->pgno;
+}
+#endif
+
+/*
+** Increment the reference count for a page.  The input pointer is
+** a reference to the page data.
+*/
+SQLITE_PRIVATE int sqlite3PagerRef(DbPage *pPg){
+  sqlite3PcacheRef(pPg);
+  return SQLITE_OK;
+}
+
+/*
+** Sync the journal.  In other words, make sure all the pages that have
+** been written to the journal have actually reached the surface of the
+** disk.  It is not safe to modify the original database file until after
+** the journal has been synced.  If the original database is modified before
+** the journal is synced and a power failure occurs, the unsynced journal
+** data would be lost and we would be unable to completely rollback the
+** database changes.  Database corruption would occur.
+** 
+** This routine also updates the nRec field in the header of the journal.
+** (See comments on the pager_playback() routine for additional information.)
+** If the sync mode is FULL, two syncs will occur.  First the whole journal
+** is synced, then the nRec field is updated, then a second sync occurs.
+**
+** For temporary databases, we do not care if we are able to rollback
+** after a power failure, so no sync occurs.
+**
+** If the IOCAP_SEQUENTIAL flag is set for the persistent media on which
+** the database is stored, then OsSync() is never called on the journal
+** file. In this case all that is required is to update the nRec field in
+** the journal header.
+**
+** This routine clears the needSync field of every page current held in
+** memory.
+*/
+static int syncJournal(Pager *pPager){
+  int rc = SQLITE_OK;
+
+  /* Sync the journal before modifying the main database
+  ** (assuming there is a journal and it needs to be synced.)
+  */
+  if( pPager->needSync ){
+    if( !pPager->tempFile ){
+      int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
+      assert( pPager->journalOpen );
+
+      if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
+        /* Write the nRec value into the journal file header. If in
+        ** full-synchronous mode, sync the journal first. This ensures that
+        ** all data has really hit the disk before nRec is updated to mark
+        ** it as a candidate for rollback.
+        **
+        ** This is not required if the persistent media supports the
+        ** SAFE_APPEND property. Because in this case it is not possible 
+        ** for garbage data to be appended to the file, the nRec field
+        ** is populated with 0xFFFFFFFF when the journal header is written
+        ** and never needs to be updated.
+        */
+        i64 jrnlOff;
+        if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
+          PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager));
+          IOTRACE(("JSYNC %p\n", pPager))
+          rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags);
+          if( rc!=0 ) return rc;
+        }
+
+        jrnlOff = pPager->journalHdr + sizeof(aJournalMagic);
+        IOTRACE(("JHDR %p %lld %d\n", pPager, jrnlOff, 4));
+        rc = write32bits(pPager->jfd, jrnlOff, pPager->nRec);
+        if( rc ) return rc;
+      }
+      if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
+        PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager));
+        IOTRACE(("JSYNC %p\n", pPager))
+        rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| 
+          (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
+        );
+        if( rc!=0 ) return rc;
+      }
+      pPager->journalStarted = 1;
+    }
+    pPager->needSync = 0;
+
+    /* Erase the needSync flag from every page.
+    */
+    sqlite3PcacheSetFlags(pPager->pPCache, ~PGHDR_NEED_SYNC, 0);
+    /* lruListSetFirstSynced(pPager); */
+  }
+
+#ifndef NDEBUG
+  /* If the Pager.needSync flag is clear then the PgHdr.needSync
+  ** flag must also be clear for all pages.  Verify that this
+  ** invariant is true.
+  */
+  else{
+    sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_NEED_SYNC);
+    /* assert( pPager->lru.pFirstSynced==pPager->lru.pFirst ); */
+  }
+#endif
+
+  return rc;
+}
+
+/*
+** Given a list of pages (connected by the PgHdr.pDirty pointer) write
+** every one of those pages out to the database file. No calls are made
+** to the page-cache to mark the pages as clean. It is the responsibility
+** of the caller to use PcacheCleanAll() or PcacheMakeClean() to mark
+** the pages as clean.
+*/
+static int pager_write_pagelist(PgHdr *pList){
+  Pager *pPager;
+  int rc;
+
+  if( pList==0 ) return SQLITE_OK;
+  pPager = pList->pPager;
+
+  /* At this point there may be either a RESERVED or EXCLUSIVE lock on the
+  ** database file. If there is already an EXCLUSIVE lock, the following
+  ** calls to sqlite3OsLock() are no-ops.
+  **
+  ** Moving the lock from RESERVED to EXCLUSIVE actually involves going
+  ** through an intermediate state PENDING.   A PENDING lock prevents new
+  ** readers from attaching to the database but is unsufficient for us to
+  ** write.  The idea of a PENDING lock is to prevent new readers from
+  ** coming in while we wait for existing readers to clear.
+  **
+  ** While the pager is in the RESERVED state, the original database file
+  ** is unchanged and we can rollback without having to playback the
+  ** journal into the original database file.  Once we transition to
+  ** EXCLUSIVE, it means the database file has been changed and any rollback
+  ** will require a journal playback.
+  */
+  rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+
+  while( pList ){
+
+    /* If the file has not yet been opened, open it now. */
+    if( !pPager->fd->pMethods ){
+      assert(pPager->tempFile);
+      rc = sqlite3PagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
+      if( rc ) return rc;
+    }
+
+    /* If there are dirty pages in the page cache with page numbers greater
+    ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to
+    ** make the file smaller (presumably by auto-vacuum code). Do not write
+    ** any such pages to the file.
+    */
+    if( pList->pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
+      i64 offset = (pList->pgno-1)*(i64)pPager->pageSize;
+      char *pData = CODEC2(pPager, pList->pData, pList->pgno, 6);
+      PAGERTRACE4("STORE %d page %d hash(%08x)\n",
+                   PAGERID(pPager), pList->pgno, pager_pagehash(pList));
+      IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno));
+      rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
+      PAGER_INCR(sqlite3_pager_writedb_count);
+      PAGER_INCR(pPager->nWrite);
+      if( pList->pgno==1 ){
+        memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
+      }
+    }
+#ifndef NDEBUG
+    else{
+      PAGERTRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno);
+    }
+#endif
+    if( rc ) return rc;
+#ifdef SQLITE_CHECK_PAGES
+    pList->pageHash = pager_pagehash(pList);
+#endif
+    /* makeClean(pList); */
+    pList = pList->pDirty;
+  }
+
+  /* sqlite3PcacheCleanAll(pPager->pPCache); */
+  return SQLITE_OK;
+}
+
+/*
+** This function is called by the pcache layer when it has reached some
+** soft memory limit. The argument is a pointer to a purgeable Pager 
+** object. This function attempts to make a single dirty page that has no
+** outstanding references (if one exists) clean so that it can be recycled 
+** by the pcache layer.
+*/
+static int pagerStress(void *p, PgHdr *pPg){
+  Pager *pPager = (Pager *)p;
+  int rc = SQLITE_OK;
+
+  if( pPager->doNotSync ){
+    return SQLITE_OK;
+  }
+
+  assert( pPg->flags&PGHDR_DIRTY );
+  if( pPager->errCode==SQLITE_OK ){
+    if( pPg->flags&PGHDR_NEED_SYNC ){
+      rc = syncJournal(pPager);
+      if( rc==SQLITE_OK && pPager->fullSync && 
+        !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
+      ){
+        pPager->nRec = 0;
+        rc = writeJournalHdr(pPager);
+      }
+    }
+    if( rc==SQLITE_OK ){
+      pPg->pDirty = 0;
+      rc = pager_write_pagelist(pPg);
+    }
+    if( rc!=SQLITE_OK ){
+      pager_error(pPager, rc);
+    }
+  }
+
+  if( rc==SQLITE_OK ){
+    sqlite3PcacheMakeClean(pPg);
+  }
+  return rc;
+}
+
+
+/*
+** Return 1 if there is a hot journal on the given pager.
+** A hot journal is one that needs to be played back.
+**
+** If the current size of the database file is 0 but a journal file
+** exists, that is probably an old journal left over from a prior
+** database with the same name.  Just delete the journal.
+**
+** Return negative if unable to determine the status of the journal.
+**
+** This routine does not open the journal file to examine its
+** content.  Hence, the journal might contain the name of a master
+** journal file that has been deleted, and hence not be hot.  Or
+** the header of the journal might be zeroed out.  This routine
+** does not discover these cases of a non-hot journal - if the
+** journal file exists and is not empty this routine assumes it
+** is hot.  The pager_playback() routine will discover that the
+** journal file is not really hot and will no-op.
+*/
+static int hasHotJournal(Pager *pPager, int *pExists){
+  sqlite3_vfs *pVfs = pPager->pVfs;
+  int rc = SQLITE_OK;
+  int exists;
+  int locked;
+  assert( pPager!=0 );
+  assert( pPager->useJournal );
+  assert( pPager->fd->pMethods );
+  *pExists = 0;
+  rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
+  if( rc==SQLITE_OK && exists ){
+    rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
+  }
+  if( rc==SQLITE_OK && exists && !locked ){
+    int nPage;
+    rc = sqlite3PagerPagecount(pPager, &nPage);
+    if( rc==SQLITE_OK ){
+     if( nPage==0 ){
+        sqlite3OsDelete(pVfs, pPager->zJournal, 0);
+      }else{
+        *pExists = 1;
+      }
+    }
+  }
+  return rc;
+}
+
+/*
+** Read the content of page pPg out of the database file.
+*/
+static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){
+  int rc;
+  i64 offset;
+  assert( MEMDB==0 );
+  assert(pPager->fd->pMethods||pPager->tempFile);
+  if( !pPager->fd->pMethods ){
+    return SQLITE_IOERR_SHORT_READ;
+  }
+  offset = (pgno-1)*(i64)pPager->pageSize;
+  rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, offset);
+  PAGER_INCR(sqlite3_pager_readdb_count);
   PAGER_INCR(pPager->nRead);
   IOTRACE(("PGIN %p %d\n", pPager, pgno));
   if( pgno==1 ){
-    memcpy(&pPager->dbFileVers, &((u8*)PGHDR_TO_DATA(pPg))[24],
+    memcpy(&pPager->dbFileVers, &((u8*)pPg->pData)[24],
                                               sizeof(pPager->dbFileVers));
   }
-  CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
+  CODEC1(pPager, pPg->pData, pPg->pgno, 3);
   PAGERTRACE4("FETCH %d page %d hash(%08x)\n",
                PAGERID(pPager), pPg->pgno, pager_pagehash(pPg));
   return rc;
@@ -29583,7 +30463,9 @@
   ** the error. Discard the contents of the pager-cache and treat any
   ** open journal file as a hot-journal.
   */
-  if( !MEMDB && pPager->exclusiveMode && pPager->nRef==0 && pPager->errCode ){
+  if( !MEMDB && pPager->exclusiveMode 
+   && sqlite3PcacheRefCount(pPager->pPCache)==0 && pPager->errCode 
+  ){
     if( pPager->journalOpen ){
       isErrorReset = 1;
     }
@@ -29603,7 +30485,7 @@
     sqlite3_vfs *pVfs = pPager->pVfs;
     if( !MEMDB ){
       int isHotJournal;
-      assert( pPager->nRef==0 );
+      assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
       if( !pPager->noReadlock ){
         rc = pager_wait_on_lock(pPager, SHARED_LOCK);
         if( rc!=SQLITE_OK ){
@@ -29697,7 +30579,7 @@
         );
       }
 
-      if( pPager->pAll ){
+      if( sqlite3PcachePagecount(pPager->pPCache)>0 ){
         /* The shared-lock has just been acquired on the database file
         ** and there are already pages in the cache (from a previous
         ** read or write transaction).  Check to see if the database
@@ -29752,104 +30634,6 @@
 }
 
 /*
-** Allocate a PgHdr object.   Either create a new one or reuse
-** an existing one that is not otherwise in use.
-**
-** A new PgHdr structure is created if any of the following are
-** true:
-**
-**     (1)  We have not exceeded our maximum allocated cache size
-**          as set by the "PRAGMA cache_size" command.
-**
-**     (2)  There are no unused PgHdr objects available at this time.
-**
-**     (3)  This is an in-memory database.
-**
-**     (4)  There are no PgHdr objects that do not require a journal
-**          file sync and a sync of the journal file is currently
-**          prohibited.
-**
-** Otherwise, reuse an existing PgHdr.  In other words, reuse an
-** existing PgHdr if all of the following are true:
-**
-**     (1)  We have reached or exceeded the maximum cache size
-**          allowed by "PRAGMA cache_size".
-**
-**     (2)  There is a PgHdr available with PgHdr->nRef==0
-**
-**     (3)  We are not in an in-memory database
-**
-**     (4)  Either there is an available PgHdr that does not need
-**          to be synced to disk or else disk syncing is currently
-**          allowed.
-*/
-static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
-  int rc = SQLITE_OK;
-  PgHdr *pPg;
-  int nByteHdr;
-
-  /* Create a new PgHdr if any of the four conditions defined 
-  ** above are met: */
-  if( pPager->nPage<pPager->mxPage
-   || pPager->lru.pFirst==0 
-   || MEMDB
-   || (pPager->lru.pFirstSynced==0 && pPager->doNotSync)
-  ){
-    void *pData;
-    if( pPager->nPage>=pPager->nHash ){
-      pager_resize_hash_table(pPager,
-         pPager->nHash<256 ? 256 : pPager->nHash*2);
-      if( pPager->nHash==0 ){
-        rc = SQLITE_NOMEM;
-        goto pager_allocate_out;
-      }
-    }
-    pagerLeave(pPager);
-    nByteHdr = sizeof(*pPg) + sizeof(u32) + pPager->nExtra
-              + MEMDB*sizeof(PgHistory);
-    pPg = sqlite3Malloc( nByteHdr );
-    if( pPg ){
-      pData = sqlite3PageMalloc( pPager->pageSize );
-      if( pData==0 ){
-        sqlite3_free(pPg);
-        pPg = 0;
-      }
-    }
-    pagerEnter(pPager);
-    if( pPg==0 ){
-      rc = SQLITE_NOMEM;
-      goto pager_allocate_out;
-    }
-    memset(pPg, 0, nByteHdr);
-    pPg->pData = pData;
-    pPg->pPager = pPager;
-    pPg->pNextAll = pPager->pAll;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-    if( pPg->pNextAll ){
-      pPg->pNextAll->pPrevAll = pPg;
-    }
-#endif
-    pPager->pAll = pPg;
-    pPager->nPage++;
-  }else{
-    /* Recycle an existing page with a zero ref-count. */
-    rc = pager_recycle(pPager, &pPg);
-    if( rc==SQLITE_BUSY ){
-      rc = SQLITE_IOERR_BLOCKED;
-    }
-    if( rc!=SQLITE_OK ){
-      goto pager_allocate_out;
-    }
-    assert( pPager->state>=SHARED_LOCK );
-    assert(pPg);
-  }
-  *ppPg = pPg;
-
-pager_allocate_out:
-  return rc;
-}
-
-/*
 ** Make sure we have the content for a page.  If the page was
 ** previously acquired with noContent==1, then the content was
 ** just initialized to zeros instead of being read from disk.
@@ -29857,10 +30641,10 @@
 ** have it.  Read it in if we do not have it already.
 */
 static int pager_get_content(PgHdr *pPg){
-  if( pPg->needRead ){
+  if( pPg->flags&PGHDR_NEED_READ ){
     int rc = readDbPage(pPg->pPager, pPg, pPg->pgno);
     if( rc==SQLITE_OK ){
-      pPg->needRead = 0;
+      pPg->flags &= ~PGHDR_NEED_READ;
     }else{
       return rc;
     }
@@ -29869,6 +30653,30 @@
 }
 
 /*
+** If the reference count has reached zero, and the pager is not in the
+** middle of a write transaction or opened in exclusive mode, unlock it.
+*/ 
+static void pagerUnlockIfUnused(Pager *pPager){
+  if( (sqlite3PcacheRefCount(pPager->pPCache)==0)
+    && (!pPager->exclusiveMode || pPager->journalOff>0) 
+  ){
+    pagerUnlockAndRollback(pPager);
+  }
+}
+
+/*
+** Drop a page from the cache using sqlite3PcacheDrop().
+**
+** If this means there are now no pages with references to them, a rollback
+** occurs and the lock on the database is removed.
+*/
+static void pagerDropPage(DbPage *pPg){
+  Pager *pPager = pPg->pPager;
+  sqlite3PcacheDrop(pPg);
+  pagerUnlockIfUnused(pPager);
+}
+
+/*
 ** Acquire a page.
 **
 ** A read lock on the disk file is obtained when the first page is acquired. 
@@ -29906,10 +30714,13 @@
   DbPage **ppPage,    /* Write a pointer to the page here */
   int noContent       /* Do not bother reading content from disk if true */
 ){
-  PgHdr *pPg;
+  PgHdr *pPg = 0;
   int rc;
 
-  assert( pPager->state==PAGER_UNLOCK || pPager->nRef>0 || pgno==1 );
+  assert( pPager->state==PAGER_UNLOCK 
+       || sqlite3PcacheRefCount(pPager->pPCache)>0 
+       || pgno==1 
+  );
 
   /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
   ** number greater than this, or zero, is requested.
@@ -29933,84 +30744,66 @@
   }
   assert( pPager->state!=PAGER_UNLOCK );
 
-  pPg = pager_lookup(pPager, pgno);
-  if( pPg==0 ){
-    /* The requested page is not in the page cache. */
+  rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, &pPg);
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+  if( pPg->pPager==0 ){
+    /* The pager cache has created a new page. Its content needs to 
+    ** be initialized.
+    */
     int nMax;
-    int h;
     PAGER_INCR(pPager->nMiss);
-    rc = pagerAllocatePage(pPager, &pPg);
-    if( rc!=SQLITE_OK ){
-      return rc;
+    pPg->pPager = pPager;
+    if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
+      pPg->flags |= PGHDR_IN_JOURNAL;
     }
+    memset(pPg->pExtra, 0, pPager->nExtra);
 
-    pPg->pgno = pgno;
-    assert( !MEMDB || pgno>pPager->stmtSize );
-    pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno);
-    pPg->needSync = 0;
-
-    makeClean(pPg);
-    pPg->nRef = 1;
-
-    pPager->nRef++;
-    if( pPager->nExtra>0 ){
-      memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
-    }
     rc = sqlite3PagerPagecount(pPager, &nMax);
     if( rc!=SQLITE_OK ){
       sqlite3PagerUnref(pPg);
       return rc;
     }
 
-    /* Populate the page with data, either by reading from the database
-    ** file, or by setting the entire page to zero.
-    */
-    if( nMax<(int)pgno || MEMDB || (noContent && !pPager->alwaysRollback) ){
+    if( nMax<(int)pgno || MEMDB || noContent ){
       if( pgno>pPager->mxPgno ){
         sqlite3PagerUnref(pPg);
         return SQLITE_FULL;
       }
-      memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
-      pPg->needRead = noContent && !pPager->alwaysRollback;
+      memset(pPg->pData, 0, pPager->pageSize);
+      if( noContent ){
+        pPg->flags |= PGHDR_NEED_READ;
+      }
       IOTRACE(("ZERO %p %d\n", pPager, pgno));
     }else{
       rc = readDbPage(pPager, pPg, pgno);
       if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
-        pPg->pgno = 0;
-        sqlite3PagerUnref(pPg);
+        /* sqlite3PagerUnref(pPg); */
+        pagerDropPage(pPg);
         return rc;
       }
-      pPg->needRead = 0;
-    }
-
-    /* Link the page into the page hash table */
-    h = pgno & (pPager->nHash-1);
-    assert( pgno!=0 );
-    pPg->pNextHash = pPager->aHash[h];
-    pPager->aHash[h] = pPg;
-    if( pPg->pNextHash ){
-      assert( pPg->pNextHash->pPrevHash==0 );
-      pPg->pNextHash->pPrevHash = pPg;
     }
-
 #ifdef SQLITE_CHECK_PAGES
     pPg->pageHash = pager_pagehash(pPg);
 #endif
   }else{
     /* The requested page is in the page cache. */
-    assert(pPager->nRef>0 || pgno==1);
+    assert(sqlite3PcacheRefCount(pPager->pPCache)>0 || pgno==1);
     PAGER_INCR(pPager->nHit);
     if( !noContent ){
       rc = pager_get_content(pPg);
       if( rc ){
+        sqlite3PagerUnref(pPg);
         return rc;
       }
     }
-    page_ref(pPg);
   }
+
   *ppPage = pPg;
   return SQLITE_OK;
 }
+
 SQLITE_PRIVATE int sqlite3PagerAcquire(
   Pager *pPager,      /* The pager open on the database file */
   Pgno pgno,          /* Page number to fetch */
@@ -30018,9 +30811,7 @@
   int noContent       /* Do not bother reading content from disk if true */
 ){
   int rc;
-  pagerEnter(pPager);
   rc = pagerAcquire(pPager, pgno, ppPage, noContent);
-  pagerLeave(pPager);
   return rc;
 }
 
@@ -30038,19 +30829,15 @@
 */
 SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
   PgHdr *pPg = 0;
-
   assert( pPager!=0 );
   assert( pgno!=0 );
 
-  pagerEnter(pPager);
-  if( pPager->state==PAGER_UNLOCK ){
-    assert( !pPager->pAll || pPager->exclusiveMode );
-  }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
-    /* Do nothing */
-  }else if( (pPg = pager_lookup(pPager, pgno))!=0 ){
-    page_ref(pPg);
+  if( (pPager->state!=PAGER_UNLOCK)
+   && (pPager->errCode==SQLITE_OK || pPager->errCode==SQLITE_FULL)
+  ){
+    sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
   }
-  pagerLeave(pPager);
+
   return pPg;
 }
 
@@ -30063,39 +30850,11 @@
 ** removed.
 */
 SQLITE_PRIVATE int sqlite3PagerUnref(DbPage *pPg){
-  Pager *pPager;
-
-  if( pPg==0 ) return SQLITE_OK;
-  pPager = pPg->pPager;
-
-  /* Decrement the reference count for this page
-  */
-  assert( pPg->nRef>0 );
-  pagerEnter(pPg->pPager);
-  pPg->nRef--;
-
-  CHECK_PAGE(pPg);
-
-  /* When the number of references to a page reach 0, call the
-  ** destructor and add the page to the freelist.
-  */
-  if( pPg->nRef==0 ){
-
-    lruListAdd(pPg);
-    if( pPager->xDestructor ){
-      pPager->xDestructor(pPg, pPager->pageSize);
-    }
-  
-    /* When all pages reach the freelist, drop the read lock from
-    ** the database file.
-    */
-    pPager->nRef--;
-    assert( pPager->nRef>=0 );
-    if( pPager->nRef==0 && (!pPager->exclusiveMode || pPager->journalOff>0) ){
-      pagerUnlockAndRollback(pPager);
-    }
+  if( pPg ){
+    Pager *pPager = pPg->pPager;
+    sqlite3PcacheRelease(pPg);
+    pagerUnlockIfUnused(pPager);
   }
-  pagerLeave(pPager);
   return SQLITE_OK;
 }
 
@@ -30116,9 +30875,7 @@
   assert( pPager->useJournal );
   assert( pPager->pInJournal==0 );
   sqlite3PagerPagecount(pPager, 0);
-  pagerLeave(pPager);
   pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
-  pagerEnter(pPager);
   if( pPager->pInJournal==0 ){
     rc = SQLITE_NOMEM;
     goto failed_to_open_journal;
@@ -30151,7 +30908,6 @@
   pPager->journalOpen = 1;
   pPager->journalStarted = 0;
   pPager->needSync = 0;
-  pPager->alwaysRollback = 0;
   pPager->nRec = 0;
   if( pPager->errCode ){
     rc = pPager->errCode;
@@ -30208,11 +30964,11 @@
 SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
   Pager *pPager = pPg->pPager;
   int rc = SQLITE_OK;
-  pagerEnter(pPager);
   assert( pPg->nRef>0 );
   assert( pPager->state!=PAGER_UNLOCK );
   if( pPager->state==PAGER_SHARED ){
     assert( pPager->pInJournal==0 );
+    sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
     if( MEMDB ){
       pPager->state = PAGER_EXCLUSIVE;
       pPager->origDbSize = pPager->dbSize;
@@ -30225,7 +30981,6 @@
         }
       }
       if( rc!=SQLITE_OK ){
-        pagerLeave(pPager);
         return rc;
       }
       pPager->dirtyCache = 0;
@@ -30246,9 +31001,7 @@
     assert( pPager->origDbSize==0 );
     assert( pPager->pInJournal==0 );
     sqlite3PagerPagecount(pPager, 0);
-    pagerLeave(pPager);
     pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize );
-    pagerEnter(pPager);
     if( !pPager->pInJournal ){
       rc = SQLITE_NOMEM;
     }else{
@@ -30257,7 +31010,6 @@
     }
   }
   assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK );
-  pagerLeave(pPager);
   return rc;
 }
 
@@ -30266,16 +31018,7 @@
 ** page list.
 */
 static void makeDirty(PgHdr *pPg){
-  if( pPg->dirty==0 ){
-    Pager *pPager = pPg->pPager;
-    pPg->dirty = 1;
-    pPg->pDirty = pPager->pDirty;
-    if( pPager->pDirty ){
-      pPager->pDirty->pPrevDirty = pPg;
-    }
-    pPg->pPrevDirty = 0;
-    pPager->pDirty = pPg;
-  }
+  sqlite3PcacheMakeDirty(pPg);
 }
 
 /*
@@ -30283,20 +31026,7 @@
 ** dirty page list.
 */
 static void makeClean(PgHdr *pPg){
-  if( pPg->dirty ){
-    pPg->dirty = 0;
-    if( pPg->pDirty ){
-      assert( pPg->pDirty->pPrevDirty==pPg );
-      pPg->pDirty->pPrevDirty = pPg->pPrevDirty;
-    }
-    if( pPg->pPrevDirty ){
-      assert( pPg->pPrevDirty->pDirty==pPg );
-      pPg->pPrevDirty->pDirty = pPg->pDirty;
-    }else{
-      assert( pPg->pPager->pDirty==pPg );
-      pPg->pPager->pDirty = pPg->pDirty;
-    }
-  }
+  sqlite3PcacheMakeClean(pPg);
 }
 
 
@@ -30318,7 +31048,7 @@
 ** reset.
 */
 static int pager_write(PgHdr *pPg){
-  void *pData = PGHDR_TO_DATA(pPg);
+  void *pData = pPg->pData;
   Pager *pPager = pPg->pPager;
   int rc = SQLITE_OK;
 
@@ -30352,7 +31082,9 @@
   ** to the journal then we can return right away.
   */
   makeDirty(pPg);
-  if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){
+  if( (pPg->flags&PGHDR_IN_JOURNAL)
+   && (pageInStatement(pPg) || pPager->stmtInUse==0) 
+  ){
     pPager->dirtyCache = 1;
     pPager->dbModified = 1;
   }else{
@@ -30382,17 +31114,14 @@
     ** EXCLUSIVE lock on the main database file.  Write the current page to
     ** the transaction journal if it is not there already.
     */
-    if( !pPg->inJournal && (pPager->journalOpen || MEMDB) ){
+    if( !(pPg->flags&PGHDR_IN_JOURNAL) && (pPager->journalOpen || MEMDB) ){
       if( (int)pPg->pgno <= pPager->origDbSize ){
         if( MEMDB ){
-          PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
           PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
-          assert( pHist->pOrig==0 );
-          pHist->pOrig = sqlite3PageMalloc( pPager->pageSize );
-          if( !pHist->pOrig ){
-            return SQLITE_NOMEM;
+          rc = sqlite3PcachePreserve(pPg, 0);
+          if( rc!=SQLITE_OK ){
+            return rc;
           }
-          memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
         }else{
           u32 cksum;
           char *pData2;
@@ -30417,7 +31146,8 @@
                    pPager->journalOff, pPager->pageSize));
           PAGER_INCR(sqlite3_pager_writej_count);
           PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n",
-               PAGERID(pPager), pPg->pgno, pPg->needSync, pager_pagehash(pPg));
+               PAGERID(pPager), pPg->pgno, 
+               ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg));
 
           /* An error has occured writing to the journal file. The 
           ** transaction will be rolled back by the layer above.
@@ -30429,20 +31159,25 @@
           pPager->nRec++;
           assert( pPager->pInJournal!=0 );
           sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
-          pPg->needSync = !pPager->noSync;
+          if( !pPager->noSync ){
+            pPg->flags |= PGHDR_NEED_SYNC;
+          }
           if( pPager->stmtInUse ){
             sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
           }
         }
       }else{
-        pPg->needSync = !pPager->journalStarted && !pPager->noSync;
+        if( !pPager->journalStarted && !pPager->noSync ){
+          pPg->flags |= PGHDR_NEED_SYNC;
+        }
         PAGERTRACE4("APPEND %d page %d needSync=%d\n",
-                PAGERID(pPager), pPg->pgno, pPg->needSync);
+                PAGERID(pPager), pPg->pgno,
+               ((pPg->flags&PGHDR_NEED_SYNC)?1:0));
       }
-      if( pPg->needSync ){
+      if( pPg->flags&PGHDR_NEED_SYNC ){
         pPager->needSync = 1;
       }
-      pPg->inJournal = 1;
+      pPg->flags |= PGHDR_IN_JOURNAL;
     }
   
     /* If the statement journal is open and the page is not in it,
@@ -30454,16 +31189,14 @@
      && !pageInStatement(pPg) 
      && (int)pPg->pgno<=pPager->stmtSize 
     ){
-      assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
+      assert( (pPg->flags&PGHDR_IN_JOURNAL) 
+                 || (int)pPg->pgno>pPager->origDbSize );
       if( MEMDB ){
-        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
-        assert( pHist->pStmt==0 );
-        pHist->pStmt = sqlite3PageMalloc( pPager->pageSize );
-        if( pHist->pStmt ){
-          memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
+        rc = sqlite3PcachePreserve(pPg, 1);
+        if( rc!=SQLITE_OK ){
+          return rc;
         }
         PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
-        page_add_to_stmt_list(pPg);
       }else{
         i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
         char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
@@ -30511,7 +31244,6 @@
   Pager *pPager = pPg->pPager;
   Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
 
-  pagerEnter(pPager);
   if( !MEMDB && nPagePerSector>1 ){
     Pgno nPageCount;          /* Total number of pages in database file */
     Pgno pg1;                 /* First page of the sector pPg is located on. */
@@ -30551,16 +31283,17 @@
           rc = sqlite3PagerGet(pPager, pg, &pPage);
           if( rc==SQLITE_OK ){
             rc = pager_write(pPage);
-            if( pPage->needSync ){
+            if( pPage->flags&PGHDR_NEED_SYNC ){
               needSync = 1;
             }
             sqlite3PagerUnref(pPage);
           }
         }
       }else if( (pPage = pager_lookup(pPager, pg))!=0 ){
-        if( pPage->needSync ){
+        if( pPage->flags&PGHDR_NEED_SYNC ){
           needSync = 1;
         }
+        sqlite3PagerUnref(pPage);
       }
     }
 
@@ -30573,7 +31306,8 @@
     if( needSync ){
       for(ii=0; ii<nPage && needSync; ii++){
         PgHdr *pPage = pager_lookup(pPager, pg1+ii);
-        if( pPage ) pPage->needSync = 1;
+        if( pPage ) pPage->flags |= PGHDR_NEED_SYNC;
+        sqlite3PagerUnref(pPage);
       }
       assert(pPager->needSync);
     }
@@ -30583,7 +31317,6 @@
   }else{
     rc = pager_write(pDbPage);
   }
-  pagerLeave(pPager);
   return rc;
 }
 
@@ -30594,7 +31327,7 @@
 */
 #ifndef NDEBUG
 SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
-  return pPg->dirty;
+  return pPg->flags&PGHDR_DIRTY;
 }
 #endif
 
@@ -30622,14 +31355,24 @@
 ** page contains critical data, we still need to be sure it gets
 ** rolled back in spite of the sqlite3PagerDontRollback() call.
 */
-SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage *pDbPage){
+SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage *pDbPage){
   PgHdr *pPg = pDbPage;
   Pager *pPager = pPg->pPager;
+  int rc;
+
+  if( MEMDB || pPg->pgno>pPager->origDbSize ){
+    return SQLITE_OK;
+  }
+  if( pPager->pAlwaysRollback==0 ){
+    assert( pPager->pInJournal );
+    pPager->pAlwaysRollback = sqlite3BitvecCreate(pPager->origDbSize);
+    if( !pPager->pAlwaysRollback ){
+      return SQLITE_NOMEM;
+    }
+  }
+  rc = sqlite3BitvecSet(pPager->pAlwaysRollback, pPg->pgno);
 
-  if( MEMDB ) return;
-  pagerEnter(pPager);
-  pPg->alwaysRollback = 1;
-  if( pPg->dirty && !pPager->stmtInUse ){
+  if( rc==SQLITE_OK && (pPg->flags&PGHDR_DIRTY) && !pPager->stmtInUse ){
     assert( pPager->state>=PAGER_SHARED );
     if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
       /* If this pages is the last page in the file and the file has grown
@@ -30643,13 +31386,13 @@
     }else{
       PAGERTRACE3("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager));
       IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
-      makeClean(pPg);
+      pPg->flags |= PGHDR_DONT_WRITE;
 #ifdef SQLITE_CHECK_PAGES
       pPg->pageHash = pager_pagehash(pPg);
 #endif
     }
   }
-  pagerLeave(pPager);
+  return rc;
 }
 
 /*
@@ -30666,21 +31409,22 @@
 SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){
   Pager *pPager = pPg->pPager;
 
-  pagerEnter(pPager);
   assert( pPager->state>=PAGER_RESERVED );
 
   /* If the journal file is not open, or DontWrite() has been called on
   ** this page (DontWrite() sets the alwaysRollback flag), then this
   ** function is a no-op.
   */
-  if( pPager->journalOpen==0 || pPg->alwaysRollback || pPager->alwaysRollback ){
-    pagerLeave(pPager);
+  if( pPager->journalOpen==0 
+   || sqlite3BitvecTest(pPager->pAlwaysRollback, pPg->pgno)
+   || pPg->pgno>pPager->origDbSize
+  ){
     return;
   }
   assert( !MEMDB );    /* For a memdb, pPager->journalOpen is always 0 */
 
 #ifdef SQLITE_SECURE_DELETE
-  if( pPg->inJournal || (int)pPg->pgno > pPager->origDbSize ){
+  if( (pPg->flags & PGHDR_IN_JOURNAL)!=0 || (int)pPg->pgno>pPager->origDbSize ){
     return;
   }
 #endif
@@ -30699,15 +31443,14 @@
 
   assert( pPager->pInJournal!=0 );
   sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
-  pPg->inJournal = 1;
-  pPg->needRead = 0;
+  pPg->flags |= PGHDR_IN_JOURNAL;
+  pPg->flags &= ~PGHDR_NEED_READ;
   if( pPager->stmtInUse ){
     assert( pPager->stmtSize >= pPager->origDbSize );
     sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
   }
   PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
   IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno))
-  pagerLeave(pPager);
 }
 
 
@@ -30739,11 +31482,11 @@
     /* Increment the value just read and write it back to byte 24. */
     change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
     change_counter++;
-    put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter);
+    put32bits(((char*)pPgHdr->pData)+24, change_counter);
 
 #ifdef SQLITE_ENABLE_ATOMIC_WRITE
     if( isDirect && pPager->fd->pMethods ){
-      const void *zBuf = PGHDR_TO_DATA(pPgHdr);
+      const void *zBuf = pPgHdr->pData;
       rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
     }
 #endif
@@ -30760,9 +31503,11 @@
 */
 SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
   int rc;
-  pagerEnter(pPager);
-  rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
-  pagerLeave(pPager);
+  if( MEMDB ){
+    rc = SQLITE_OK;
+  }else{
+    rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
+  }
   return rc;
 }
 
@@ -30811,7 +31556,6 @@
 
   PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", 
       pPager->zFilename, zMaster, nTrunc);
-  pagerEnter(pPager);
 
   /* If this is an in-memory db, or no pages have been written to, or this
   ** function has already been called, it is a no-op.
@@ -30831,12 +31575,13 @@
     ** If the optimization can be used, then the journal file will never
     ** be created for this transaction.
     */
+    pPg = sqlite3PcacheDirtyList(pPager->pPCache);
     int useAtomicWrite = (
         !zMaster && 
         pPager->journalOpen &&
         pPager->journalOff==jrnlBufferSize(pPager) && 
         nTrunc==0 && 
-        (0==pPager->pDirty || 0==pPager->pDirty->pDirty)
+        (pPg==0 || pPg->pDirty==0)
     );
     assert( pPager->journalOpen || pPager->journalMode==PAGER_JOURNALMODE_OFF );
     if( useAtomicWrite ){
@@ -30905,7 +31650,7 @@
 #endif
 
     /* Write all dirty pages to the database file */
-    pPg = pager_get_all_dirty_pages(pPager);
+    pPg = sqlite3PcacheDirtyList(pPager->pPCache);
     rc = pager_write_pagelist(pPg);
     if( rc!=SQLITE_OK ){
       assert( rc!=SQLITE_IOERR_BLOCKED );
@@ -30918,7 +31663,7 @@
       */
       goto sync_exit;
     }
-    pPager->pDirty = 0;
+    sqlite3PcacheCleanAll(pPager->pPCache);
 
     /* Sync the database file. */
     if( !pPager->noSync && !noSync ){
@@ -30940,7 +31685,6 @@
      */
     rc = SQLITE_BUSY;
   }
-  pagerLeave(pPager);
   return rc;
 }
 
@@ -30953,8 +31697,7 @@
 ** is returned.
 */
 SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
-  int rc;
-  PgHdr *pPg;
+  int rc = SQLITE_OK;
 
   if( pPager->errCode ){
     return pPager->errCode;
@@ -30968,38 +31711,19 @@
     assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
     return SQLITE_OK;
   }
-  pagerEnter(pPager);
   PAGERTRACE2("COMMIT %d\n", PAGERID(pPager));
   if( MEMDB ){
-    pPg = pager_get_all_dirty_pages(pPager);
-    while( pPg ){
-      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
-      clearHistory(pHist);
-      pPg->dirty = 0;
-      pPg->inJournal = 0;
-      pHist->inStmt = 0;
-      pPg->needSync = 0;
-      pHist->pPrevStmt = pHist->pNextStmt = 0;
-      pPg = pPg->pDirty;
-    }
-    pPager->pDirty = 0;
-#ifndef NDEBUG
-    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
-      PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
-      assert( !pPg->alwaysRollback );
-      assert( !pHist->pOrig );
-      assert( !pHist->pStmt );
-    }
-#endif
-    pPager->pStmt = 0;
+    sqlite3PcacheCommit(pPager->pPCache, 0);
+    sqlite3PcacheCleanAll(pPager->pPCache);
+    sqlite3PcacheSetFlags(pPager->pPCache, 
+       ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
+    );
     pPager->state = PAGER_SHARED;
-    pagerLeave(pPager);
-    return SQLITE_OK;
+  }else{
+    assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
+    rc = pager_end_transaction(pPager, pPager->setMaster);
+    rc = pager_error(pPager, rc);
   }
-  assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
-  rc = pager_end_transaction(pPager, pPager->setMaster);
-  rc = pager_error(pPager, rc);
-  pagerLeave(pPager);
   return rc;
 }
 
@@ -31016,77 +31740,46 @@
 ** SQLITE_OK is returned.
 */
 SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
-  int rc;
+  int rc = SQLITE_OK;
   PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
   if( MEMDB ){
-    PgHdr *p;
-    for(p=pPager->pAll; p; p=p->pNextAll){
-      PgHistory *pHist;
-      assert( !p->alwaysRollback );
-      if( !p->dirty ){
-        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
-        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
-        continue;
-      }
-
-      pHist = PGHDR_TO_HIST(p, pPager);
-      if( pHist->pOrig ){
-        memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize);
-        PAGERTRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager));
-      }else{
-        PAGERTRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager));
-      }
-      clearHistory(pHist);
-      p->dirty = 0;
-      p->inJournal = 0;
-      pHist->inStmt = 0;
-      pHist->pPrevStmt = pHist->pNextStmt = 0;
-      if( pPager->xReiniter ){
-        pPager->xReiniter(p, pPager->pageSize);
-      }
-    }
-    pPager->pDirty = 0;
-    pPager->pStmt = 0;
+    sqlite3PcacheRollback(pPager->pPCache, 1);
+    sqlite3PcacheRollback(pPager->pPCache, 0);
+    sqlite3PcacheCleanAll(pPager->pPCache);
+    sqlite3PcacheSetFlags(pPager->pPCache, 
+       ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
+    );
     pPager->dbSize = pPager->origDbSize;
     pager_truncate_cache(pPager);
     pPager->stmtInUse = 0;
     pPager->state = PAGER_SHARED;
-    return SQLITE_OK;
-  }
-
-  pagerEnter(pPager);
-  if( !pPager->dirtyCache || !pPager->journalOpen ){
+  }else if( !pPager->dirtyCache || !pPager->journalOpen ){
     rc = pager_end_transaction(pPager, pPager->setMaster);
-    pagerLeave(pPager);
-    return rc;
-  }
-
-  if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
+  }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
     if( pPager->state>=PAGER_EXCLUSIVE ){
       pager_playback(pPager, 0);
     }
-    pagerLeave(pPager);
-    return pPager->errCode;
-  }
-  if( pPager->state==PAGER_RESERVED ){
-    int rc2;
-    rc = pager_playback(pPager, 0);
-    rc2 = pager_end_transaction(pPager, pPager->setMaster);
-    if( rc==SQLITE_OK ){
-      rc = rc2;
-    }
+    rc = pPager->errCode;
   }else{
-    rc = pager_playback(pPager, 0);
-  }
-  /* pager_reset(pPager); */
-  pPager->dbSize = -1;
+    if( pPager->state==PAGER_RESERVED ){
+      int rc2;
+      rc = pager_playback(pPager, 0);
+      rc2 = pager_end_transaction(pPager, pPager->setMaster);
+      if( rc==SQLITE_OK ){
+        rc = rc2;
+      }
+    }else{
+      rc = pager_playback(pPager, 0);
+    }
 
-  /* If an error occurs during a ROLLBACK, we can no longer trust the pager
-  ** cache. So call pager_error() on the way out to make any error 
-  ** persistent.
-  */
-  rc = pager_error(pPager, rc);
-  pagerLeave(pPager);
+    pPager->dbSize = -1;
+
+    /* If an error occurs during a ROLLBACK, we can no longer trust the pager
+    ** cache. So call pager_error() on the way out to make any error 
+    ** persistent.
+    */
+    rc = pager_error(pPager, rc);
+  }
   return rc;
 }
 
@@ -31102,7 +31795,7 @@
 ** Return the number of references to the pager.
 */
 SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
-  return pPager->nRef;
+  return sqlite3PcacheRefCount(pPager->pPCache);
 }
 
 #ifdef SQLITE_TEST
@@ -31111,9 +31804,9 @@
 */
 SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
   static int a[11];
-  a[0] = pPager->nRef;
-  a[1] = pPager->nPage;
-  a[2] = pPager->mxPage;
+  a[0] = sqlite3PcacheRefCount(pPager->pPCache);
+  a[1] = sqlite3PcachePagecount(pPager->pPCache);
+  a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
   a[3] = pPager->dbSize;
   a[4] = pPager->state;
   a[5] = pPager->errCode;
@@ -31152,10 +31845,8 @@
     return SQLITE_OK;
   }
   assert( pPager->journalOpen );
-  pagerLeave(pPager);
   assert( pPager->pInStmt==0 );
   pPager->pInStmt = sqlite3BitvecCreate(pPager->dbSize);
-  pagerEnter(pPager);
   if( pPager->pInStmt==0 ){
     /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */
     return SQLITE_NOMEM;
@@ -31184,9 +31875,7 @@
 }
 SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager *pPager){
   int rc;
-  pagerEnter(pPager);
   rc = pagerStmtBegin(pPager);
-  pagerLeave(pPager);
   return rc;
 }
 
@@ -31194,31 +31883,19 @@
 ** Commit a statement.
 */
 SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager *pPager){
-  pagerEnter(pPager);
   if( pPager->stmtInUse ){
-    PgHdr *pPg, *pNext;
     PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
     if( !MEMDB ){
       /* sqlite3OsTruncate(pPager->stfd, 0); */
       sqlite3BitvecDestroy(pPager->pInStmt);
       pPager->pInStmt = 0;
     }else{
-      for(pPg=pPager->pStmt; pPg; pPg=pNext){
-        PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
-        pNext = pHist->pNextStmt;
-        assert( pHist->inStmt );
-        pHist->inStmt = 0;
-        pHist->pPrevStmt = pHist->pNextStmt = 0;
-        sqlite3PageFree(pHist->pStmt);
-        pHist->pStmt = 0;
-      }
+      sqlite3PcacheCommit(pPager->pPCache, 1);
     }
     pPager->stmtNRec = 0;
     pPager->stmtInUse = 0;
-    pPager->pStmt = 0;
   }
   pPager->stmtAutoopen = 0;
-  pagerLeave(pPager);
   return SQLITE_OK;
 }
 
@@ -31227,20 +31904,10 @@
 */
 SQLITE_PRIVATE int sqlite3PagerStmtRollback(Pager *pPager){
   int rc;
-  pagerEnter(pPager);
   if( pPager->stmtInUse ){
     PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
     if( MEMDB ){
-      PgHdr *pPg;
-      PgHistory *pHist;
-      for(pPg=pPager->pStmt; pPg; pPg=pHist->pNextStmt){
-        pHist = PGHDR_TO_HIST(pPg, pPager);
-        if( pHist->pStmt ){
-          memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize);
-          sqlite3PageFree(pHist->pStmt);
-          pHist->pStmt = 0;
-        }
-      }
+      sqlite3PcacheRollback(pPager->pPCache, 1);
       pPager->dbSize = pPager->stmtSize;
       pager_truncate_cache(pPager);
       rc = SQLITE_OK;
@@ -31252,7 +31919,6 @@
     rc = SQLITE_OK;
   }
   pPager->stmtAutoopen = 0;
-  pagerLeave(pPager);
   return rc;
 }
 
@@ -31340,14 +32006,12 @@
 */
 SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
   PgHdr *pPgOld;  /* The page being overwritten. */
-  int h;
   Pgno needSyncPgno = 0;
 
-  pagerEnter(pPager);
   assert( pPg->nRef>0 );
 
   PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", 
-      PAGERID(pPager), pPg->pgno, pPg->needSync, pgno);
+      PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno);
   IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))
 
   pager_get_content(pPg);
@@ -31359,44 +32023,33 @@
   ** the journal needs to be sync()ed before database page pPg->pgno 
   ** can be written to. The caller has already promised not to write to it.
   */
-  if( pPg->needSync && !isCommit ){
+  if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
     needSyncPgno = pPg->pgno;
-    assert( pPg->inJournal || (int)pgno>pPager->origDbSize );
-    assert( pPg->dirty );
+    assert( (pPg->flags&PGHDR_IN_JOURNAL) || (int)pgno>pPager->origDbSize );
+    assert( pPg->flags&PGHDR_DIRTY );
     assert( pPager->needSync );
   }
 
-  /* Unlink pPg from its hash-chain */
-  unlinkHashChain(pPager, pPg);
-
   /* If the cache contains a page with page-number pgno, remove it
   ** from its hash chain. Also, if the PgHdr.needSync was set for 
   ** page pgno before the 'move' operation, it needs to be retained 
   ** for the page moved there.
   */
-  pPg->needSync = 0;
+  pPg->flags &= ~(PGHDR_NEED_SYNC|PGHDR_IN_JOURNAL);
   pPgOld = pager_lookup(pPager, pgno);
+  assert( !pPgOld || pPgOld->nRef==1 );
   if( pPgOld ){
-    assert( pPgOld->nRef==0 );
-    unlinkHashChain(pPager, pPgOld);
-    makeClean(pPgOld);
-    pPg->needSync = pPgOld->needSync;
-  }else{
-    pPg->needSync = 0;
+    pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
+  }
+  if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
+    pPg->flags |= PGHDR_IN_JOURNAL;
   }
-  pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno);
 
-  /* Change the page number for pPg and insert it into the new hash-chain. */
-  assert( pgno!=0 );
-  pPg->pgno = pgno;
-  h = pgno & (pPager->nHash-1);
-  if( pPager->aHash[h] ){
-    assert( pPager->aHash[h]->pPrevHash==0 );
-    pPager->aHash[h]->pPrevHash = pPg;
-  }
-  pPg->pNextHash = pPager->aHash[h];
-  pPager->aHash[h] = pPg;
-  pPg->pPrevHash = 0;
+  sqlite3PcacheMove(pPg, pgno);
+  if( pPgOld ){
+    sqlite3PcacheMove(pPgOld, 0);
+    sqlite3PcacheRelease(pPgOld);
+  }
 
   makeDirty(pPg);
   pPager->dirtyCache = 1;
@@ -31428,17 +32081,15 @@
       if( pPager->pInJournal && (int)needSyncPgno<=pPager->origDbSize ){
         sqlite3BitvecClear(pPager->pInJournal, needSyncPgno);
       }
-      pagerLeave(pPager);
       return rc;
     }
     pPager->needSync = 1;
-    pPgHdr->needSync = 1;
-    pPgHdr->inJournal = 1;
+    pPgHdr->flags |= PGHDR_NEED_SYNC;
+    pPgHdr->flags |= PGHDR_IN_JOURNAL;
     makeDirty(pPgHdr);
     sqlite3PagerUnref(pPgHdr);
   }
 
-  pagerLeave(pPager);
   return SQLITE_OK;
 }
 #endif
@@ -31447,7 +32098,8 @@
 ** Return a pointer to the data for the specified page.
 */
 SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
-  return PGHDR_TO_DATA(pPg);
+  assert( pPg->nRef>0 );
+  return pPg->pData;
 }
 
 /*
@@ -31456,7 +32108,7 @@
 */
 SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
   Pager *pPager = pPg->pPager;
-  return (pPager?PGHDR_TO_EXTRA(pPg, pPager):0);
+  return (pPager?pPg->pExtra:0);
 }
 
 /*
@@ -32475,7 +33127,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.495 2008/08/02 17:36:46 danielk1977 Exp $
+** $Id: btree.c,v 1.504 2008/08/27 15:16:34 danielk1977 Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** See the header comment on "btreeInt.h" for additional information.
@@ -32840,7 +33492,7 @@
     return pCur->skip;
   }
   pCur->eState = CURSOR_INVALID;
-  rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip);
+  rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip);
   if( rc==SQLITE_OK ){
     sqlite3_free(pCur->pKey);
     pCur->pKey = 0;
@@ -33160,7 +33812,7 @@
   int size;                  /* Size of a cell */
   int usableSize;            /* Number of usable bytes on a page */
   int cellOffset;            /* Offset to the cell pointer array */
-  int brk;                   /* Offset to the cell content area */
+  int cbrk;                  /* Offset to the cell content area */
   int nCell;                 /* Number of cells on the page */
   unsigned char *data;       /* The page data */
   unsigned char *temp;       /* Temp area for cell content */
@@ -33177,26 +33829,26 @@
   nCell = pPage->nCell;
   assert( nCell==get2byte(&data[hdr+3]) );
   usableSize = pPage->pBt->usableSize;
-  brk = get2byte(&data[hdr+5]);
-  memcpy(&temp[brk], &data[brk], usableSize - brk);
-  brk = usableSize;
+  cbrk = get2byte(&data[hdr+5]);
+  memcpy(&temp[cbrk], &data[cbrk], usableSize - cbrk);
+  cbrk = usableSize;
   for(i=0; i<nCell; i++){
     u8 *pAddr;     /* The i-th cell pointer */
     pAddr = &data[cellOffset + i*2];
     pc = get2byte(pAddr);
     assert( pc<pPage->pBt->usableSize );
     size = cellSizePtr(pPage, &temp[pc]);
-    brk -= size;
-    memcpy(&data[brk], &temp[pc], size);
-    put2byte(pAddr, brk);
+    cbrk -= size;
+    memcpy(&data[cbrk], &temp[pc], size);
+    put2byte(pAddr, cbrk);
   }
-  assert( brk>=cellOffset+2*nCell );
-  put2byte(&data[hdr+5], brk);
+  assert( cbrk>=cellOffset+2*nCell );
+  put2byte(&data[hdr+5], cbrk);
   data[hdr+1] = 0;
   data[hdr+2] = 0;
   data[hdr+7] = 0;
   addr = cellOffset+2*nCell;
-  memset(&data[addr], 0, brk-addr);
+  memset(&data[addr], 0, cbrk-addr);
 }
 
 /*
@@ -33597,18 +34249,19 @@
 ** reaches zero.  We need to unref the pParent pointer when that
 ** happens.
 */
-static void pageDestructor(DbPage *pData, int pageSize){
+static void pageDestructor(DbPage *pData){
   MemPage *pPage;
-  assert( (pageSize & 7)==0 );
   pPage = (MemPage *)sqlite3PagerGetExtra(pData);
-  assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
-  if( pPage->pParent ){
-    MemPage *pParent = pPage->pParent;
-    assert( pParent->pBt==pPage->pBt );
-    pPage->pParent = 0;
-    releasePage(pParent);
+  if( pPage ){
+    assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
+    if( pPage->pParent ){
+      MemPage *pParent = pPage->pParent;
+      assert( pParent->pBt==pPage->pBt );
+      pPage->pParent = 0;
+      releasePage(pParent);
+    }
+    pPage->isInit = 0;
   }
-  pPage->isInit = 0;
 }
 
 /*
@@ -33752,7 +34405,7 @@
     }
     pBt->busyHdr.xFunc = sqlite3BtreeInvokeBusyHandler;
     pBt->busyHdr.pArg = pBt;
-    rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
+    rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, pageDestructor,
                           EXTRA_SIZE, flags, vfsFlags);
     if( rc==SQLITE_OK ){
       rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
@@ -33763,7 +34416,6 @@
     sqlite3PagerSetBusyhandler(pBt->pPager, &pBt->busyHdr);
     p->pBt = pBt;
   
-    sqlite3PagerSetDestructor(pBt->pPager, pageDestructor);
     sqlite3PagerSetReiniter(pBt->pPager, pageReinit);
     pBt->pCursor = 0;
     pBt->pPage1 = 0;
@@ -35953,6 +36605,7 @@
   assert( !sqlite3BtreeIsRootPage(pPage) );
   pParent = pPage->pParent;
   assert( pParent!=0 );
+  assert( pPage->pDbPage->nRef>0 );
   idxParent = pPage->idxParent;
   sqlite3PagerRef(pParent->pDbPage);
   releasePage(pPage);
@@ -36113,12 +36766,11 @@
 }
 
 /* Move the cursor so that it points to an entry near the key 
-** specified by pKey/nKey/pUnKey. Return a success code.
+** specified by pIdxKey or intKey.   Return a success code.
 **
-** For INTKEY tables, only the nKey parameter is used.  pKey 
-** and pUnKey must be NULL.  For index tables, either pUnKey
-** must point to a key that has already been unpacked, or else
-** pKey/nKey describes a blob containing the key.
+** For INTKEY tables, the intKey parameter is used.  pIdxKey 
+** must be NULL.  For index tables, pIdxKey is used and intKey
+** is ignored.
 **
 ** If an exact match is not found, then the cursor is always
 ** left pointing at a leaf page which would hold the entry if it
@@ -36140,16 +36792,14 @@
 **                  is larger than pKey.
 **
 */
-SQLITE_PRIVATE int sqlite3BtreeMoveto(
-  BtCursor *pCur,        /* The cursor to be moved */
-  const void *pKey,      /* The key content for indices.  Not used by tables */
-  UnpackedRecord *pUnKey,/* Unpacked version of pKey */
-  i64 nKey,              /* Size of pKey.  Or the key for tables */
-  int biasRight,         /* If true, bias the search to the high end */
-  int *pRes              /* Search result flag */
+SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
+  BtCursor *pCur,          /* The cursor to be moved */
+  UnpackedRecord *pIdxKey, /* Unpacked index key */
+  i64 intKey,              /* The table key */
+  int biasRight,           /* If true, bias the search to the high end */
+  int *pRes                /* Write search results here */
 ){
   int rc;
-  char aSpace[200];
 
   assert( cursorHoldsMutex(pCur) );
   assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
@@ -36157,11 +36807,11 @@
   /* If the cursor is already positioned at the point we are trying
   ** to move to, then just return without doing any work */
   if( pCur->eState==CURSOR_VALID && pCur->validNKey && pCur->pPage->intKey ){
-    if( pCur->info.nKey==nKey ){
+    if( pCur->info.nKey==intKey ){
       *pRes = 0;
       return SQLITE_OK;
     }
-    if( pCur->atLast && pCur->info.nKey<nKey ){
+    if( pCur->atLast && pCur->info.nKey<intKey ){
       *pRes = -1;
       return SQLITE_OK;
     }
@@ -36179,24 +36829,7 @@
     assert( pCur->pPage->nCell==0 );
     return SQLITE_OK;
   }
-  if( pCur->pPage->intKey ){
-    /* We are given an SQL table to search.  The key is the integer
-    ** rowid contained in nKey.  pKey and pUnKey should both be NULL */
-    assert( pUnKey==0 );
-    assert( pKey==0 );
-  }else if( pUnKey==0 ){
-    /* We are to search an SQL index using a key encoded as a blob.
-    ** The blob is found at pKey and is nKey bytes in length.  Unpack
-    ** this key so that we can use it. */
-    assert( pKey!=0 );
-    pUnKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
-                                   aSpace, sizeof(aSpace));
-    if( pUnKey==0 ) return SQLITE_NOMEM;
-  }else{
-    /* We are to search an SQL index using a key that is already unpacked
-    ** and handed to us in pUnKey. */
-    assert( pKey==0 );
-  }
+  assert( pCur->pPage->intKey || pIdxKey );
   for(;;){
     int lwr, upr;
     Pgno chldPg;
@@ -36204,7 +36837,7 @@
     int c = -1;  /* pRes return if table is empty must be -1 */
     lwr = 0;
     upr = pPage->nCell-1;
-    if( !pPage->intKey && pUnKey==0 ){
+    if( !pPage->intKey && pIdxKey==0 ){
       rc = SQLITE_CORRUPT_BKPT;
       goto moveto_finish;
     }
@@ -36226,12 +36859,12 @@
           pCell += getVarint32(pCell, dummy);
         }
         getVarint(pCell, (u64*)&nCellKey);
-        if( nCellKey==nKey ){
+        if( nCellKey==intKey ){
           c = 0;
-        }else if( nCellKey<nKey ){
+        }else if( nCellKey<intKey ){
           c = -1;
         }else{
-          assert( nCellKey>nKey );
+          assert( nCellKey>intKey );
           c = +1;
         }
       }else{
@@ -36239,7 +36872,7 @@
         pCellKey = (void *)fetchPayload(pCur, &available, 0);
         nCellKey = pCur->info.nKey;
         if( available>=nCellKey ){
-          c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
+          c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
         }else{
           pCellKey = sqlite3Malloc( nCellKey );
           if( pCellKey==0 ){
@@ -36247,7 +36880,7 @@
             goto moveto_finish;
           }
           rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
-          c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
+          c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
           sqlite3_free(pCellKey);
           if( rc ) goto moveto_finish;
         }
@@ -36297,10 +36930,35 @@
     if( rc ) goto moveto_finish;
   }
 moveto_finish:
+  return rc;
+}
+
+/*
+** In this version of BtreeMoveto, pKey is a packed index record
+** such as is generated by the OP_MakeRecord opcode.  Unpack the
+** record and then call BtreeMovetoUnpacked() to do the work.
+*/
+SQLITE_PRIVATE int sqlite3BtreeMoveto(
+  BtCursor *pCur,     /* Cursor open on the btree to be searched */
+  const void *pKey,   /* Packed key if the btree is an index */
+  i64 nKey,           /* Integer key for tables.  Size of pKey for indices */
+  int bias,           /* Bias search to the high end */
+  int *pRes           /* Write search results here */
+){
+  int rc;                    /* Status code */
+  UnpackedRecord *pIdxKey;   /* Unpacked index key */
+  UnpackedRecord aSpace[16]; /* Temp space for pIdxKey - to avoid a malloc */
+
   if( pKey ){
-    /* If we created our own unpacked key at the top of this
-    ** procedure, then destroy that key before returning. */
-    sqlite3VdbeDeleteUnpackedRecord(pUnKey);
+    pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
+                                      aSpace, sizeof(aSpace));
+    if( pIdxKey==0 ) return SQLITE_NOMEM;
+  }else{
+    pIdxKey = 0;
+  }
+  rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
+  if( pKey ){
+    sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
   }
   return rc;
 }
@@ -36806,7 +37464,7 @@
         put4byte(&pTrunk->aData[4], k+1);
         put4byte(&pTrunk->aData[8+k*4], pPage->pgno);
 #ifndef SQLITE_SECURE_DELETE
-        sqlite3PagerDontWrite(pPage->pDbPage);
+        rc = sqlite3PagerDontWrite(pPage->pDbPage);
 #endif
       }
       TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
@@ -38113,7 +38771,7 @@
   u8 *data;           /* Content of the parent page */
   u8 *cdata;          /* Content of the child page */
   int hdr;            /* Offset to page header in parent */
-  int brk;            /* Offset to content of first cell in parent */
+  int cbrk;           /* Offset to content of first cell in parent */
 
   assert( pPage->pParent==0 );
   assert( pPage->nOverflow>0 );
@@ -38125,10 +38783,10 @@
   usableSize = pBt->usableSize;
   data = pPage->aData;
   hdr = pPage->hdrOffset;
-  brk = get2byte(&data[hdr+5]);
+  cbrk = get2byte(&data[hdr+5]);
   cdata = pChild->aData;
   memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr);
-  memcpy(&cdata[brk], &data[brk], usableSize-brk);
+  memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk);
   if( pChild->isInit ) return SQLITE_CORRUPT;
   rc = sqlite3BtreeInitPage(pChild, pPage);
   if( rc ) goto balancedeeper_out;
@@ -38301,7 +38959,7 @@
   clearCursorPosition(pCur);
   if( 
     SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
-    SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc))
+    SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
   ){
     return rc;
   }
@@ -39217,8 +39875,11 @@
     cellStart = hdr + 12 - 4*pPage->leaf;
     for(i=0; i<nCell; i++){
       int pc = get2byte(&data[cellStart+i*2]);
-      u16 size = cellSizePtr(pPage, &data[pc]);
+      u16 size = 1024;
       int j;
+      if( pc<=usableSize ){
+        size = cellSizePtr(pPage, &data[pc]);
+      }
       if( (pc+size-1)>=usableSize || pc<0 ){
         checkAppendMsg(pCheck, 0, 
             "Corruption detected in cell %d on page %d",i,iPage,0);
@@ -39495,7 +40156,7 @@
           ** page is still on the rollback journal, though.  And that is the 
           ** whole point of this block: to put pages on the rollback journal. 
           */
-          sqlite3PagerDontWrite(pDbPage);
+          rc = sqlite3PagerDontWrite(pDbPage);
         }
         sqlite3PagerUnref(pDbPage);
       }
@@ -39604,7 +40265,7 @@
           rc = sqlite3PagerGet(pBtFrom->pPager, iFrom, &pFromPage);
           if( rc==SQLITE_OK ){
             char *zFrom = sqlite3PagerGetData(pFromPage);
-  	  rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff);
+            rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff);
             sqlite3PagerUnref(pFromPage);
           }
         }
@@ -39940,7 +40601,7 @@
 ** only within the VDBE.  Interface routines refer to a Mem using the
 ** name sqlite_value
 **
-** $Id: vdbemem.c,v 1.121 2008/08/01 20:10:09 drh Exp $
+** $Id: vdbemem.c,v 1.122 2008/08/22 14:41:01 drh Exp $
 */
 
 /*
@@ -40162,12 +40823,11 @@
     sqlite3_context ctx;
     assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
     assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+    memset(&ctx, 0, sizeof(ctx));
     ctx.s.flags = MEM_Null;
     ctx.s.db = pMem->db;
-    ctx.s.zMalloc = 0;
     ctx.pMem = pMem;
     ctx.pFunc = pFunc;
-    ctx.isError = 0;
     pFunc->xFinalize(&ctx);
     assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel );
     sqlite3DbFree(pMem->db, pMem->zMalloc);
@@ -40983,7 +41643,7 @@
 ** to version 2.8.7, all this code was combined into the vdbe.c source file.
 ** But that file was getting too big so this subroutines were split out.
 **
-** $Id: vdbeaux.c,v 1.405 2008/08/02 03:50:39 drh Exp $
+** $Id: vdbeaux.c,v 1.409 2008/08/20 22:06:48 drh Exp $
 */
 
 
@@ -42816,9 +43476,8 @@
     extern int sqlite3_search_count;
 #endif
     assert( p->isTable );
-    rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res);
+    rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
     if( rc ) return rc;
-    *p->pIncrKey = 0;
     p->lastRowid = keyToInt(p->movetoTarget);
     p->rowidIsValid = res==0;
     if( res<0 ){
@@ -43165,7 +43824,7 @@
   KeyInfo *pKeyInfo,     /* Information about the record format */
   int nKey,              /* Size of the binary record */
   const void *pKey,      /* The binary record */
-  void *pSpace,          /* Space available to hold resulting object */
+  UnpackedRecord *pSpace,/* Space available to hold resulting object */
   int szSpace            /* Size of pSpace[] in bytes */
 ){
   const unsigned char *aKey = (const unsigned char *)pKey;
@@ -43181,14 +43840,13 @@
   if( nByte>szSpace ){
     p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
     if( p==0 ) return 0;
-    p->needFree = 1;
+    p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
   }else{
     p = pSpace;
-    p->needFree = 0;
+    p->flags = UNPACKED_NEED_DESTROY;
   }
   p->pKeyInfo = pKeyInfo;
   p->nField = pKeyInfo->nField + 1;
-  p->needDestroy = 1;
   p->aMem = pMem = &((Mem*)p)[1];
   idx = getVarint32(aKey, szHdr);
   d = szHdr;
@@ -43206,6 +43864,7 @@
     pMem++;
     u++;
   }
+  assert( u<=pKeyInfo->nField + 1 );
   p->nField = u;
   return (void*)p;
 }
@@ -43215,7 +43874,7 @@
 */
 SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
   if( p ){
-    if( p->needDestroy ){
+    if( p->flags & UNPACKED_NEED_DESTROY ){
       int i;
       Mem *pMem;
       for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
@@ -43224,7 +43883,7 @@
         }
       }
     }
-    if( p->needFree ){
+    if( p->flags & UNPACKED_NEED_FREE ){
       sqlite3DbFree(p->pKeyInfo->db, p);
     }
   }
@@ -43233,25 +43892,32 @@
 /*
 ** This function compares the two table rows or index records
 ** specified by {nKey1, pKey1} and pPKey2.  It returns a negative, zero
-** or positive integer if {nKey1, pKey1} is less than, equal to or 
-** greater than pPKey2.  The {nKey1, pKey1} key must be a blob
+** or positive integer if key1 is less than, equal to or 
+** greater than key2.  The {nKey1, pKey1} key must be a blob
 ** created by th OP_MakeRecord opcode of the VDBE.  The pPKey2
 ** key must be a parsed key such as obtained from
 ** sqlite3VdbeParseRecord.
 **
 ** Key1 and Key2 do not have to contain the same number of fields.
-** But if the lengths differ, Key2 must be the shorter of the two.
-**
-** Historical note: In earlier versions of this routine both Key1
-** and Key2 were blobs obtained from OP_MakeRecord.  But we found
-** that in typical use the same Key2 would be submitted multiple times
-** in a row.  So an optimization was added to parse the Key2 key
-** separately and submit the parsed version.  In this way, we avoid
-** parsing the same Key2 multiple times in a row.
+** The key with fewer fields is usually compares less than the 
+** longer key.  However if the UNPACKED_INCRKEY flags in pPKey2 is set
+** and the common prefixes are equal, then key1 is less than key2.
+** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
+** equal, then the keys are considered to be equal and
+** the parts beyond the common prefix are ignored.
+**
+** If the UNPACKED_IGNORE_ROWID flag is set, then the last byte of
+** the header of pKey1 is ignored.  It is assumed that pKey1 is
+** an index key, and thus ends with a rowid value.  The last byte
+** of the header will therefore be the serial type of the rowid:
+** one of 1, 2, 3, 4, 5, 6, 8, or 9 - the integer serial types.
+** The serial type of the final rowid will always be a single byte.
+** By ignoring this last byte of the header, we force the comparison
+** to ignore the rowid at the end of key1.
 */
 SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
-  int nKey1, const void *pKey1, 
-  UnpackedRecord *pPKey2
+  int nKey1, const void *pKey1, /* Left key */
+  UnpackedRecord *pPKey2        /* Right key */
 ){
   u32 d1;            /* Offset into aKey[] of next data element */
   u32 idx1;          /* Offset into aKey[] of next header element */
@@ -43271,6 +43937,9 @@
   
   idx1 = getVarint32(aKey1, szHdr1);
   d1 = szHdr1;
+  if( pPKey2->flags & UNPACKED_IGNORE_ROWID ){
+    szHdr1--;
+  }
   nField = pKeyInfo->nField;
   while( idx1<szHdr1 && i<pPKey2->nField ){
     u32 serial_type1;
@@ -43294,17 +43963,21 @@
   }
   if( mem1.zMalloc ) sqlite3VdbeMemRelease(&mem1);
 
-  /* One of the keys ran out of fields, but all the fields up to that point
-  ** were equal. If the incrKey flag is true, then the second key is
-  ** treated as larger.
-  */
   if( rc==0 ){
-    if( pKeyInfo->incrKey ){
+    /* rc==0 here means that one of the keys ran out of fields and
+    ** all the fields up to that point were equal. If the UNPACKED_INCRKEY
+    ** flag is set, then break the tie by treating key2 as larger.
+    ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
+    ** are considered to be equal.  Otherwise, the longer key is the 
+    ** larger.  As it happens, the pPKey2 will always be the longer
+    ** if there is a difference.
+    */
+    if( pPKey2->flags & UNPACKED_INCRKEY ){
       rc = -1;
-    }else if( !pKeyInfo->prefixIsEqual ){
-      if( d1<nKey1 ){
-        rc = 1;
-      }
+    }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
+      /* Leave rc==0 */
+    }else if( idx1<szHdr1 ){
+      rc = 1;
     }
   }else if( pKeyInfo->aSortOrder && i<pKeyInfo->nField
                && pKeyInfo->aSortOrder[i] ){
@@ -43313,26 +43986,7 @@
 
   return rc;
 }
-
-/*
-** The argument is an index entry composed using the OP_MakeRecord opcode.
-** The last entry in this record should be an integer (specifically
-** an integer rowid).  This routine returns the number of bytes in
-** that integer.
-*/
-SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8 *aKey, int nKey, int *pRowidLen){
-  u32 szHdr;        /* Size of the header */
-  u32 typeRowid;    /* Serial type of the rowid */
-
-  (void)getVarint32(aKey, szHdr);
-  if( szHdr>nKey ){
-    return SQLITE_CORRUPT_BKPT;
-  }
-  (void)getVarint32(&aKey[szHdr-1], typeRowid);
-  *pRowidLen = sqlite3VdbeSerialTypeLen(typeRowid);
-  return SQLITE_OK;
-}
-  
+ 
 
 /*
 ** pCur points at an index entry created using the OP_MakeRecord opcode.
@@ -43375,21 +44029,21 @@
 **
 ** pKey is either created without a rowid or is truncated so that it
 ** omits the rowid at the end.  The rowid at the end of the index entry
-** is ignored as well.
+** is ignored as well.  Hence, this routine only compares the prefixes 
+** of the keys prior to the final rowid, not the entire key.
+**
+** pUnpacked may be an unpacked version of pKey,nKey.  If pUnpacked is
+** supplied it is used in place of pKey,nKey.
 */
 SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
   Cursor *pC,                 /* The cursor to compare against */
-  UnpackedRecord *pUnpacked,
-  int nKey, const u8 *pKey,   /* The key to compare */
+  UnpackedRecord *pUnpacked,  /* Unpacked version of pKey and nKey */
   int *res                    /* Write the comparison result here */
 ){
   i64 nCellKey = 0;
   int rc;
   BtCursor *pCur = pC->pCursor;
-  int lenRowid;
   Mem m;
-  UnpackedRecord *pRec;
-  char zSpace[200];
 
   sqlite3BtreeKeySize(pCur, &nCellKey);
   if( nCellKey<=0 ){
@@ -43399,24 +44053,12 @@
   m.db = 0;
   m.flags = 0;
   m.zMalloc = 0;
-  if( (rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m))
-   || (rc = sqlite3VdbeIdxRowidLen((u8*)m.z, m.n, &lenRowid))
-  ){
+  rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m);
+  if( rc ){
     return rc;
   }
-  if( !pUnpacked ){
-    pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey,
-                                zSpace, sizeof(zSpace));
-  }else{
-    pRec = pUnpacked;
-  }
-  if( pRec==0 ){
-    return SQLITE_NOMEM;
-  }
-  *res = sqlite3VdbeRecordCompare(m.n-lenRowid, m.z, pRec);
-  if( !pUnpacked ){
-    sqlite3VdbeDeleteUnpackedRecord(pRec);
-  }
+  assert( pUnpacked->flags & UNPACKED_IGNORE_ROWID );
+  *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
   sqlite3VdbeMemRelease(&m);
   return SQLITE_OK;
 }
@@ -43480,10 +44122,10 @@
 ** This file contains code use to implement APIs that are part of the
 ** VDBE.
 **
-** $Id: vdbeapi.c,v 1.138 2008/08/02 03:50:39 drh Exp $
+** $Id: vdbeapi.c,v 1.140 2008/08/21 12:19:44 danielk1977 Exp $
 */
 
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
 /*
 ** The following structure contains pointers to the end points of a
 ** doubly-linked list of all compiled SQL statements that may be holding
@@ -43898,7 +44540,9 @@
 
   /* Assert that malloc() has not failed */
   db = p->db;
-  assert( !db->mallocFailed );
+  if( db->mallocFailed ){
+    return SQLITE_NOMEM;
+  }
 
   if( p->pc<=0 && p->expired ){
     if( p->rc==SQLITE_OK ){
@@ -44786,7 +45430,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.772 2008/08/02 15:10:09 danielk1977 Exp $
+** $Id: vdbe.c,v 1.777 2008/08/21 19:28:30 drh Exp $
 */
 
 /*
@@ -45386,6 +46030,8 @@
 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
   int nProgressOps = 0;      /* Opcodes executed since progress callback. */
 #endif
+  UnpackedRecord aTempRec[16]; /* Space to hold a transient UnpackedRecord */
+
 
   assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
   assert( db->magic==SQLITE_MAGIC_BUSY );
@@ -47536,11 +48182,9 @@
   rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor);
   if( pOp->p4type==P4_KEYINFO ){
     pCur->pKeyInfo = pOp->p4.pKeyInfo;
-    pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
     pCur->pKeyInfo->enc = ENC(p->db);
   }else{
     pCur->pKeyInfo = 0;
-    pCur->pIncrKey = &pCur->bogusIncrKey;
   }
   switch( rc ){
     case SQLITE_BUSY: {
@@ -47640,13 +48284,11 @@
                                 (KeyInfo*)pOp->p4.z, pCx->pCursor);
         pCx->pKeyInfo = pOp->p4.pKeyInfo;
         pCx->pKeyInfo->enc = ENC(p->db);
-        pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
       }
       pCx->isTable = 0;
     }else{
       rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
       pCx->isTable = 1;
-      pCx->pIncrKey = &pCx->bogusIncrKey;
     }
   }
   pCx->isIndex = !pCx->isTable;
@@ -47682,7 +48324,6 @@
   pCx->nullRow = 1;
   pCx->pseudoTable = 1;
   pCx->ephemPseudoTable = pOp->p2;
-  pCx->pIncrKey = &pCx->bogusIncrKey;
   pCx->isTable = 1;
   pCx->isIndex = 0;
   break;
@@ -47774,7 +48415,6 @@
     int res, oc;
     oc = pOp->opcode;
     pC->nullRow = 0;
-    *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
     if( pC->isTable ){
       i64 iKey = sqlite3VdbeIntValue(pIn3);
       if( pOp->p2==0 ){
@@ -47784,7 +48424,7 @@
         pC->deferredMoveto = 1;
         break;
       }
-      rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res);
+      rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
@@ -47797,10 +48437,13 @@
       assert( nField>0 );
       r.pKeyInfo = pC->pKeyInfo;
       r.nField = nField;
-      r.needFree = 0;
-      r.needDestroy = 0;
+      if( oc==OP_MoveGt || oc==OP_MoveLe ){
+        r.flags = UNPACKED_INCRKEY;
+      }else{
+        r.flags = 0;
+      }
       r.aMem = &p->aMem[pOp->p3];
-      rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res);
+      rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
@@ -47808,7 +48451,6 @@
     }
     pC->deferredMoveto = 0;
     pC->cacheStatus = CACHE_STALE;
-    *pC->pIncrKey = 0;
 #ifdef SQLITE_TEST
     sqlite3_search_count++;
 #endif
@@ -47866,7 +48508,7 @@
 ** in the record in register P3, where N is the total number of values in
 ** the P3 record (the P3 record is a prefix of the P1 record). 
 **
-** See also: NotFound, MoveTo, IsUnique, NotExists
+** See also: NotFound, IsUnique, NotExists
 */
 /* Opcode: NotFound P1 P2 P3 * *
 **
@@ -47875,7 +48517,7 @@
 ** to P2.  If an entry does existing, fall through.  The cursor is left
 ** pointing to the entry that matches.
 **
-** See also: Found, MoveTo, NotExists, IsUnique
+** See also: Found, NotExists, IsUnique
 */
 case OP_NotFound:       /* jump, in3 */
 case OP_Found: {        /* jump, in3 */
@@ -47886,13 +48528,20 @@
   assert( p->apCsr[i]!=0 );
   if( (pC = p->apCsr[i])->pCursor!=0 ){
     int res;
+    UnpackedRecord *pIdxKey;
+
     assert( pC->isTable==0 );
     assert( pIn3->flags & MEM_Blob );
+    pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z,
+                                      aTempRec, sizeof(aTempRec));
+    if( pIdxKey==0 ){
+      goto no_mem;
+    }
     if( pOp->opcode==OP_Found ){
-      pC->pKeyInfo->prefixIsEqual = 1;
+      pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
     }
-    rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
-    pC->pKeyInfo->prefixIsEqual = 0;
+    rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
+    sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
     if( rc!=SQLITE_OK ){
       break;
     }
@@ -47912,7 +48561,7 @@
 **
 ** The P3 register contains an integer record number.  Call this
 ** record number R.  The P4 register contains an index key created
-** using MakeIdxRec.  Call it K.
+** using MakeRecord.  Call it K.
 **
 ** P1 is an index.  So it has no data and its key consists of a
 ** record generated by OP_MakeRecord where the last field is the 
@@ -47948,45 +48597,39 @@
   pCrsr = pCx->pCursor;
   if( pCrsr!=0 ){
     int res;
-    i64 v;         /* The record number on the P1 entry that matches K */
-    char *zKey;    /* The value of K */
-    int nKey;      /* Number of bytes in K */
-    int len;       /* Number of bytes in K without the rowid at the end */
-    int szRowid;   /* Size of the rowid column at the end of zKey */
+    i64 v;                     /* The record number that matches K */
+    UnpackedRecord *pIdxKey;   /* Unpacked version of P4 */
 
     /* Make sure K is a string and make zKey point to K
     */
     assert( pK->flags & MEM_Blob );
-    zKey = pK->z;
-    nKey = pK->n;
-
-    /* sqlite3VdbeIdxRowidLen() only returns other than SQLITE_OK when the
-    ** record passed as an argument corrupt. Since the record in this case
-    ** has just been created by an OP_MakeRecord instruction, and not loaded
-    ** from the database file, it is not possible for it to be corrupt.
-    ** Therefore, assert(rc==SQLITE_OK).
-    */
-    rc = sqlite3VdbeIdxRowidLen((u8*)zKey, nKey, &szRowid);
-    assert(rc==SQLITE_OK);
-    len = nKey-szRowid;
+    pIdxKey = sqlite3VdbeRecordUnpack(pCx->pKeyInfo, pK->n, pK->z,
+                                      aTempRec, sizeof(aTempRec));
+    if( pIdxKey==0 ){
+      goto no_mem;
+    }
+    pIdxKey->flags |= UNPACKED_IGNORE_ROWID;
 
-    /* Search for an entry in P1 where all but the last four bytes match K.
+    /* Search for an entry in P1 where all but the last rowid match K
     ** If there is no such entry, jump immediately to P2.
     */
     assert( pCx->deferredMoveto==0 );
     pCx->cacheStatus = CACHE_STALE;
-    rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res);
+    rc = sqlite3BtreeMovetoUnpacked(pCrsr, pIdxKey, 0, 0, &res);
     if( rc!=SQLITE_OK ){
+      sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
       goto abort_due_to_error;
     }
     if( res<0 ){
       rc = sqlite3BtreeNext(pCrsr, &res);
       if( res ){
         pc = pOp->p2 - 1;
+        sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
         break;
       }
     }
-    rc = sqlite3VdbeIdxKeyCompare(pCx, 0, len, (u8*)zKey, &res); 
+    rc = sqlite3VdbeIdxKeyCompare(pCx, pIdxKey, &res); 
+    sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
     if( rc!=SQLITE_OK ) goto abort_due_to_error;
     if( res>0 ){
       pc = pOp->p2 - 1;
@@ -48029,7 +48672,7 @@
 ** NotFound assumes key is a blob constructed from MakeRecord and
 ** P1 is an index.
 **
-** See also: Found, MoveTo, NotFound, IsUnique
+** See also: Found, NotFound, IsUnique
 */
 case OP_NotExists: {        /* jump, in3 */
   int i = pOp->p1;
@@ -48043,7 +48686,7 @@
     assert( pIn3->flags & MEM_Int );
     assert( p->apCsr[i]->isTable );
     iKey = intToKey(pIn3->u.i);
-    rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res);
+    rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0,&res);
     pC->lastRowid = pIn3->u.i;
     pC->rowidIsValid = res==0;
     pC->nullRow = 0;
@@ -48220,7 +48863,7 @@
         }
         if( v==0 ) continue;
         x = intToKey(v);
-        rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res);
+        rx = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)x, 0, &res);
         cnt++;
       }while( cnt<100 && rx==SQLITE_OK && res==0 );
       db->priorNewRowid = v;
@@ -48716,10 +49359,9 @@
     UnpackedRecord r;
     r.pKeyInfo = pC->pKeyInfo;
     r.nField = pOp->p3;
-    r.needFree = 0;
-    r.needDestroy = 0;
+    r.flags = 0;
     r.aMem = &p->aMem[pOp->p2];
-    rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res);
+    rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
     if( rc==SQLITE_OK && res==0 ){
       rc = sqlite3BtreeDelete(pCrsr);
     }
@@ -48802,12 +49444,13 @@
     assert( pOp->p4type==P4_INT32 );
     r.pKeyInfo = pC->pKeyInfo;
     r.nField = pOp->p4.i;
-    r.needFree = 0;
-    r.needDestroy = 0;
+    if( pOp->p5 ){
+      r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
+    }else{
+      r.flags = UNPACKED_IGNORE_ROWID;
+    }
     r.aMem = &p->aMem[pOp->p3];
-    *pC->pIncrKey = pOp->p5;
-    rc = sqlite3VdbeIdxKeyCompare(pC, &r, 0, 0, &res);
-    *pC->pIncrKey = 0;
+    rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
     if( pOp->opcode==OP_IdxLT ){
       res = -res;
     }else{
@@ -48970,9 +49613,10 @@
   (void)sqlite3SafetyOff(db);
   assert( db->init.busy==0 );
   db->init.busy = 1;
+  initData.rc = SQLITE_OK;
   assert( !db->mallocFailed );
   rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
-  if( rc==SQLITE_ABORT ) rc = initData.rc;
+  if( rc==SQLITE_OK ) rc = initData.rc;
   sqlite3DbFree(db, zSql);
   db->init.busy = 0;
   (void)sqlite3SafetyOn(db);
@@ -50265,280 +50909,1563 @@
       v->rc = rc;
     }
   }
-  rc = sqlite3ApiExit(db, rc);
-  sqlite3_mutex_leave(db->mutex);
-  return rc;
-}
-
-/*
-** Read data from a blob handle.
-*/
-SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
-  return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData);
-}
-
-/*
-** Write data to a blob handle.
-*/
-SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
-  return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);
+  rc = sqlite3ApiExit(db, rc);
+  sqlite3_mutex_leave(db->mutex);
+  return rc;
+}
+
+/*
+** Read data from a blob handle.
+*/
+SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
+  return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData);
+}
+
+/*
+** Write data to a blob handle.
+*/
+SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
+  return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);
+}
+
+/*
+** Query a blob handle for the size of the data.
+**
+** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
+** so no mutex is required for access.
+*/
+SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){
+  Incrblob *p = (Incrblob *)pBlob;
+  return p->nByte;
+}
+
+#endif /* #ifndef SQLITE_OMIT_INCRBLOB */
+
+/************** End of vdbeblob.c ********************************************/
+/************** Begin file journal.c *****************************************/
+/*
+** 2007 August 22
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** @(#) $Id: journal.c,v 1.8 2008/05/01 18:01:47 drh Exp $
+*/
+
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+
+/*
+** This file implements a special kind of sqlite3_file object used
+** by SQLite to create journal files if the atomic-write optimization
+** is enabled.
+**
+** The distinctive characteristic of this sqlite3_file is that the
+** actual on disk file is created lazily. When the file is created,
+** the caller specifies a buffer size for an in-memory buffer to
+** be used to service read() and write() requests. The actual file
+** on disk is not created or populated until either:
+**
+**   1) The in-memory representation grows too large for the allocated 
+**      buffer, or
+**   2) The xSync() method is called.
+*/
+
+
+
+/*
+** A JournalFile object is a subclass of sqlite3_file used by
+** as an open file handle for journal files.
+*/
+struct JournalFile {
+  sqlite3_io_methods *pMethod;    /* I/O methods on journal files */
+  int nBuf;                       /* Size of zBuf[] in bytes */
+  char *zBuf;                     /* Space to buffer journal writes */
+  int iSize;                      /* Amount of zBuf[] currently used */
+  int flags;                      /* xOpen flags */
+  sqlite3_vfs *pVfs;              /* The "real" underlying VFS */
+  sqlite3_file *pReal;            /* The "real" underlying file descriptor */
+  const char *zJournal;           /* Name of the journal file */
+};
+typedef struct JournalFile JournalFile;
+
+/*
+** If it does not already exists, create and populate the on-disk file 
+** for JournalFile p.
+*/
+static int createFile(JournalFile *p){
+  int rc = SQLITE_OK;
+  if( !p->pReal ){
+    sqlite3_file *pReal = (sqlite3_file *)&p[1];
+    rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0);
+    if( rc==SQLITE_OK ){
+      p->pReal = pReal;
+      if( p->iSize>0 ){
+        assert(p->iSize<=p->nBuf);
+        rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
+      }
+    }
+  }
+  return rc;
+}
+
+/*
+** Close the file.
+*/
+static int jrnlClose(sqlite3_file *pJfd){
+  JournalFile *p = (JournalFile *)pJfd;
+  if( p->pReal ){
+    sqlite3OsClose(p->pReal);
+  }
+  sqlite3_free(p->zBuf);
+  return SQLITE_OK;
+}
+
+/*
+** Read data from the file.
+*/
+static int jrnlRead(
+  sqlite3_file *pJfd,    /* The journal file from which to read */
+  void *zBuf,            /* Put the results here */
+  int iAmt,              /* Number of bytes to read */
+  sqlite_int64 iOfst     /* Begin reading at this offset */
+){
+  int rc = SQLITE_OK;
+  JournalFile *p = (JournalFile *)pJfd;
+  if( p->pReal ){
+    rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
+  }else{
+    assert( iAmt+iOfst<=p->iSize );
+    memcpy(zBuf, &p->zBuf[iOfst], iAmt);
+  }
+  return rc;
+}
+
+/*
+** Write data to the file.
+*/
+static int jrnlWrite(
+  sqlite3_file *pJfd,    /* The journal file into which to write */
+  const void *zBuf,      /* Take data to be written from here */
+  int iAmt,              /* Number of bytes to write */
+  sqlite_int64 iOfst     /* Begin writing at this offset into the file */
+){
+  int rc = SQLITE_OK;
+  JournalFile *p = (JournalFile *)pJfd;
+  if( !p->pReal && (iOfst+iAmt)>p->nBuf ){
+    rc = createFile(p);
+  }
+  if( rc==SQLITE_OK ){
+    if( p->pReal ){
+      rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
+    }else{
+      memcpy(&p->zBuf[iOfst], zBuf, iAmt);
+      if( p->iSize<(iOfst+iAmt) ){
+        p->iSize = (iOfst+iAmt);
+      }
+    }
+  }
+  return rc;
+}
+
+/*
+** Truncate the file.
+*/
+static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
+  int rc = SQLITE_OK;
+  JournalFile *p = (JournalFile *)pJfd;
+  if( p->pReal ){
+    rc = sqlite3OsTruncate(p->pReal, size);
+  }else if( size<p->iSize ){
+    p->iSize = size;
+  }
+  return rc;
+}
+
+/*
+** Sync the file.
+*/
+static int jrnlSync(sqlite3_file *pJfd, int flags){
+  int rc;
+  JournalFile *p = (JournalFile *)pJfd;
+  if( p->pReal ){
+    rc = sqlite3OsSync(p->pReal, flags);
+  }else{
+    rc = SQLITE_OK;
+  }
+  return rc;
+}
+
+/*
+** Query the size of the file in bytes.
+*/
+static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
+  int rc = SQLITE_OK;
+  JournalFile *p = (JournalFile *)pJfd;
+  if( p->pReal ){
+    rc = sqlite3OsFileSize(p->pReal, pSize);
+  }else{
+    *pSize = (sqlite_int64) p->iSize;
+  }
+  return rc;
+}
+
+/*
+** Table of methods for JournalFile sqlite3_file object.
+*/
+static struct sqlite3_io_methods JournalFileMethods = {
+  1,             /* iVersion */
+  jrnlClose,     /* xClose */
+  jrnlRead,      /* xRead */
+  jrnlWrite,     /* xWrite */
+  jrnlTruncate,  /* xTruncate */
+  jrnlSync,      /* xSync */
+  jrnlFileSize,  /* xFileSize */
+  0,             /* xLock */
+  0,             /* xUnlock */
+  0,             /* xCheckReservedLock */
+  0,             /* xFileControl */
+  0,             /* xSectorSize */
+  0              /* xDeviceCharacteristics */
+};
+
+/* 
+** Open a journal file.
+*/
+SQLITE_PRIVATE int sqlite3JournalOpen(
+  sqlite3_vfs *pVfs,         /* The VFS to use for actual file I/O */
+  const char *zName,         /* Name of the journal file */
+  sqlite3_file *pJfd,        /* Preallocated, blank file handle */
+  int flags,                 /* Opening flags */
+  int nBuf                   /* Bytes buffered before opening the file */
+){
+  JournalFile *p = (JournalFile *)pJfd;
+  memset(p, 0, sqlite3JournalSize(pVfs));
+  if( nBuf>0 ){
+    p->zBuf = sqlite3MallocZero(nBuf);
+    if( !p->zBuf ){
+      return SQLITE_NOMEM;
+    }
+  }else{
+    return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0);
+  }
+  p->pMethod = &JournalFileMethods;
+  p->nBuf = nBuf;
+  p->flags = flags;
+  p->zJournal = zName;
+  p->pVfs = pVfs;
+  return SQLITE_OK;
+}
+
+/*
+** If the argument p points to a JournalFile structure, and the underlying
+** file has not yet been created, create it now.
+*/
+SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){
+  if( p->pMethods!=&JournalFileMethods ){
+    return SQLITE_OK;
+  }
+  return createFile((JournalFile *)p);
+}
+
+/* 
+** Return the number of bytes required to store a JournalFile that uses vfs
+** pVfs to create the underlying on-disk files.
+*/
+SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
+  return (pVfs->szOsFile+sizeof(JournalFile));
+}
+#endif
+
+/************** End of journal.c *********************************************/
+/************** Begin file walker.c ******************************************/
+/*
+** 2008 August 16
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains routines used for walking the parser tree for
+** an SQL statement.
+**
+** $Id: walker.c,v 1.1 2008/08/20 16:35:10 drh Exp $
+*/
+
+
+/*
+** Walk an expression tree.  Invoke the callback once for each node
+** of the expression, while decending.  (In other words, the callback
+** is invoked before visiting children.)
+**
+** The return value from the callback should be one of the WRC_*
+** constants to specify how to proceed with the walk.
+**
+**    WRC_Continue      Continue descending down the tree.
+**
+**    WRC_Prune         Do not descend into child nodes.  But allow
+**                      the walk to continue with sibling nodes.
+**
+**    WRC_Abort         Do no more callbacks.  Unwind the stack and
+**                      return the top-level walk call.
+**
+** The return value from this routine is WRC_Abort to abandon the tree walk
+** and WRC_Continue to continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
+  int rc;
+  if( pExpr==0 ) return WRC_Continue;
+  rc = pWalker->xExprCallback(pWalker, pExpr);
+  if( rc==WRC_Continue ){
+    if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
+    if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
+    if( sqlite3WalkExprList(pWalker, pExpr->pList) ) return WRC_Abort;
+    if( sqlite3WalkSelect(pWalker, pExpr->pSelect) ){
+      return WRC_Abort;
+    }
+  }
+  return rc & WRC_Abort;
+}
+
+/*
+** Call sqlite3WalkExpr() for every expression in list p or until
+** an abort request is seen.
+*/
+SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
+  int i, rc = WRC_Continue;
+  struct ExprList_item *pItem;
+  if( p ){
+    for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
+      if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
+    }
+  }
+  return rc & WRC_Continue;
+}
+
+/*
+** Walk all expressions associated with SELECT statement p.  Do
+** not invoke the SELECT callback on p, but do (of course) invoke
+** any expr callbacks and SELECT callbacks that come from subqueries.
+** Return WRC_Abort or WRC_Continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
+  if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
+  if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
+  if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
+  if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
+  if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
+  if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
+  if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
+  return WRC_Continue;
+}
+
+/*
+** Walk the parse trees associated with all subqueries in the
+** FROM clause of SELECT statement p.  Do not invoke the select
+** callback on p, but do invoke it on each FROM clause subquery
+** and on any subqueries further down in the tree.  Return 
+** WRC_Abort or WRC_Continue;
+*/
+SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
+  SrcList *pSrc;
+  int i;
+  struct SrcList_item *pItem;
+
+  pSrc = p->pSrc;
+  if( pSrc ){
+    for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
+      if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+        return WRC_Abort;
+      }
+    }
+  }
+  return WRC_Continue;
+} 
+
+/*
+** Call sqlite3WalkExpr() for every expression in Select statement p.
+** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
+** on the compound select chain, p->pPrior.
+**
+** Return WRC_Continue under normal conditions.  Return WRC_Abort if
+** there is an abort request.
+**
+** If the Walker does not have an xSelectCallback() then this routine
+** is a no-op returning WRC_Continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
+  int rc;
+  if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
+  rc = WRC_Continue;
+  while( p  ){
+    rc = pWalker->xSelectCallback(pWalker, p);
+    if( rc ) break;
+    if( sqlite3WalkSelectExpr(pWalker, p) ) return WRC_Abort;
+    if( sqlite3WalkSelectFrom(pWalker, p) ) return WRC_Abort;
+    p = p->pPrior;
+  }
+  return rc & WRC_Abort;
+}
+
+/************** End of walker.c **********************************************/
+/************** Begin file resolve.c *****************************************/
+/*
+** 2008 August 18
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains routines used for walking the parser tree and
+** resolve all identifiers by associating them with a particular
+** table and column.
+**
+** $Id: resolve.c,v 1.5 2008/08/29 02:14:03 drh Exp $
+*/
+
+/*
+** Turn the pExpr expression into an alias for the iCol-th column of the
+** result set in pEList.
+**
+** If the result set column is a simple column reference, then this routine
+** makes an exact copy.  But for any other kind of expression, this
+** routine make a copy of the result set column as the argument to the
+** TK_AS operator.  The TK_AS operator causes the expression to be
+** evaluated just once and then reused for each alias.
+**
+** The reason for suppressing the TK_AS term when the expression is a simple
+** column reference is so that the column reference will be recognized as
+** usable by indices within the WHERE clause processing logic. 
+**
+** Hack:  The TK_AS operator is inhibited if zType[0]=='G'.  This means
+** that in a GROUP BY clause, the expression is evaluated twice.  Hence:
+**
+**     SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
+**
+** Is equivalent to:
+**
+**     SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
+**
+** The result of random()%5 in the GROUP BY clause is probably different
+** from the result in the result-set.  We might fix this someday.  Or
+** then again, we might not...
+*/
+static void resolveAlias(
+  Parse *pParse,         /* Parsing context */
+  ExprList *pEList,      /* A result set */
+  int iCol,              /* A column in the result set.  0..pEList->nExpr-1 */
+  Expr *pExpr,           /* Transform this into an alias to the result set */
+  const char *zType      /* "GROUP" or "ORDER" or "" */
+){
+  Expr *pOrig;           /* The iCol-th column of the result set */
+  Expr *pDup;            /* Copy of pOrig */
+  sqlite3 *db;           /* The database connection */
+
+  assert( iCol>=0 && iCol<pEList->nExpr );
+  pOrig = pEList->a[iCol].pExpr;
+  assert( pOrig!=0 );
+  assert( pOrig->flags & EP_Resolved );
+  db = pParse->db;
+  pDup = sqlite3ExprDup(db, pOrig);
+  if( pDup==0 ) return;
+  if( pDup->op!=TK_COLUMN && zType[0]!='G' ){
+    pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
+    if( pDup==0 ) return;
+    if( pEList->a[iCol].iAlias==0 ){
+      pEList->a[iCol].iAlias = ++pParse->nAlias;
+    }
+    pDup->iTable = pEList->a[iCol].iAlias;
+  }
+  if( pExpr->flags & EP_ExpCollate ){
+    pDup->pColl = pExpr->pColl;
+    pDup->flags |= EP_ExpCollate;
+  }
+  if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z);
+  if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z);
+  memcpy(pExpr, pDup, sizeof(*pExpr));
+  sqlite3DbFree(db, pDup);
+}
+
+/*
+** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
+** that name in the set of source tables in pSrcList and make the pExpr 
+** expression node refer back to that source column.  The following changes
+** are made to pExpr:
+**
+**    pExpr->iDb           Set the index in db->aDb[] of the database X
+**                         (even if X is implied).
+**    pExpr->iTable        Set to the cursor number for the table obtained
+**                         from pSrcList.
+**    pExpr->pTab          Points to the Table structure of X.Y (even if
+**                         X and/or Y are implied.)
+**    pExpr->iColumn       Set to the column number within the table.
+**    pExpr->op            Set to TK_COLUMN.
+**    pExpr->pLeft         Any expression this points to is deleted
+**    pExpr->pRight        Any expression this points to is deleted.
+**
+** The 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. */
+  NameContext *pNC,    /* The name context used to resolve the name */
+  Expr *pExpr          /* Make this EXPR node point to the selected column */
+){
+  char *zDb = 0;       /* Name of the database.  The "X" in X.Y.Z */
+  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 */
+  sqlite3 *db = pParse->db;         /* The database connection */
+  struct SrcList_item *pItem;       /* Use for looping over pSrcList items */
+  struct SrcList_item *pMatch = 0;  /* The matching pSrcList item */
+  NameContext *pTopNC = pNC;        /* First namecontext in the list */
+  Schema *pSchema = 0;              /* Schema of the expression */
+
+  assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
+
+  /* Dequote and zero-terminate the names */
+  zDb = sqlite3NameFromToken(db, pDbToken);
+  zTab = sqlite3NameFromToken(db, pTableToken);
+  zCol = sqlite3NameFromToken(db, pColumnToken);
+  if( db->mallocFailed ){
+    goto lookupname_end;
+  }
+
+  /* Initialize the node to no-match */
+  pExpr->iTable = -1;
+  pExpr->pTab = 0;
+
+  /* Start at the inner-most context and move outward until a match is found */
+  while( pNC && cnt==0 ){
+    ExprList *pEList;
+    SrcList *pSrcList = pNC->pSrcList;
+
+    if( pSrcList ){
+      for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
+        Table *pTab;
+        int iDb;
+        Column *pCol;
+  
+        pTab = pItem->pTab;
+        assert( pTab!=0 && pTab->zName!=0 );
+        iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+        assert( pTab->nCol>0 );
+        if( zTab ){
+          if( pItem->zAlias ){
+            char *zTabName = pItem->zAlias;
+            if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+          }else{
+            char *zTabName = pTab->zName;
+            if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+            if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
+              continue;
+            }
+          }
+        }
+        if( 0==(cntTab++) ){
+          pExpr->iTable = pItem->iCursor;
+          pExpr->pTab = pTab;
+          pSchema = pTab->pSchema;
+          pMatch = pItem;
+        }
+        for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
+          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+            IdList *pUsing;
+            cnt++;
+            pExpr->iTable = pItem->iCursor;
+            pExpr->pTab = pTab;
+            pMatch = pItem;
+            pSchema = pTab->pSchema;
+            /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
+            pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+            if( i<pSrcList->nSrc-1 ){
+              if( pItem[1].jointype & JT_NATURAL ){
+                /* If this match occurred in the left table of a natural join,
+                ** then skip the right table to avoid a duplicate match */
+                pItem++;
+                i++;
+              }else if( (pUsing = pItem[1].pUsing)!=0 ){
+                /* If this match occurs on a column that is in the USING clause
+                ** of a join, skip the search of the right table of the join
+                ** to avoid a duplicate match there. */
+                int k;
+                for(k=0; k<pUsing->nId; k++){
+                  if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
+                    pItem++;
+                    i++;
+                    break;
+                  }
+                }
+              }
+            }
+            break;
+          }
+        }
+      }
+    }
+
+#ifndef SQLITE_OMIT_TRIGGER
+    /* If we have not already resolved the name, then maybe 
+    ** it is a new.* or old.* trigger argument reference
+    */
+    if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
+      TriggerStack *pTriggerStack = pParse->trigStack;
+      Table *pTab = 0;
+      u32 *piColMask;
+      if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
+        pExpr->iTable = pTriggerStack->newIdx;
+        assert( pTriggerStack->pTab );
+        pTab = pTriggerStack->pTab;
+        piColMask = &(pTriggerStack->newColMask);
+      }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
+        pExpr->iTable = pTriggerStack->oldIdx;
+        assert( pTriggerStack->pTab );
+        pTab = pTriggerStack->pTab;
+        piColMask = &(pTriggerStack->oldColMask);
+      }
+
+      if( pTab ){ 
+        int iCol;
+        Column *pCol = pTab->aCol;
+
+        pSchema = pTab->pSchema;
+        cntTab++;
+        for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) {
+          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+            cnt++;
+            pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
+            pExpr->pTab = pTab;
+            if( iCol>=0 ){
+              testcase( iCol==31 );
+              testcase( iCol==32 );
+              *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
+            }
+            break;
+          }
+        }
+      }
+    }
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
+
+    /*
+    ** Perhaps the name is a reference to the ROWID
+    */
+    if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
+      cnt = 1;
+      pExpr->iColumn = -1;
+      pExpr->affinity = SQLITE_AFF_INTEGER;
+    }
+
+    /*
+    ** 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 = pNC->pEList)!=0 && zTab==0 ){
+      for(j=0; j<pEList->nExpr; j++){
+        char *zAs = pEList->a[j].zName;
+        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+          Expr *pOrig;
+          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+          assert( pExpr->pList==0 );
+          assert( pExpr->pSelect==0 );
+          pOrig = pEList->a[j].pExpr;
+          if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
+            sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
+            sqlite3DbFree(db, zCol);
+            return 2;
+          }
+          resolveAlias(pParse, pEList, j, pExpr, "");
+          cnt = 1;
+          pMatch = 0;
+          assert( zTab==0 && zDb==0 );
+          goto lookupname_end_2;
+        }
+      } 
+    }
+
+    /* Advance to the next name context.  The loop will exit when either
+    ** we have a match (cnt>0) or when we run out of name contexts.
+    */
+    if( cnt==0 ){
+      pNC = pNC->pNext;
+    }
+  }
+
+  /*
+  ** If X and Y are NULL (in other words if only the column name Z is
+  ** supplied) and the value of Z is enclosed in double-quotes, then
+  ** Z is a string literal if it doesn't match any column names.  In that
+  ** case, we need to return right away and not make any changes to
+  ** pExpr.
+  **
+  ** Because no reference was made to outer contexts, the pNC->nRef
+  ** fields are not changed in any context.
+  */
+  if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
+    sqlite3DbFree(db, zCol);
+    pExpr->op = TK_STRING;
+    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 ){
+    const char *zErr;
+    zErr = cnt==0 ? "no such column" : "ambiguous column name";
+    if( zDb ){
+      sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
+    }else if( zTab ){
+      sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
+    }else{
+      sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
+    }
+    pTopNC->nErr++;
+  }
+
+  /* If a column from a table in pSrcList is referenced, then record
+  ** this fact in the pSrcList.a[].colUsed bitmask.  Column 0 causes
+  ** bit 0 to be set.  Column 1 sets bit 1.  And so forth.  If the
+  ** column number is greater than the number of bits in the bitmask
+  ** then set the high-order bit of the bitmask.
+  */
+  if( pExpr->iColumn>=0 && pMatch!=0 ){
+    int n = pExpr->iColumn;
+    testcase( n==sizeof(Bitmask)*8-1 );
+    if( n>=sizeof(Bitmask)*8 ){
+      n = sizeof(Bitmask)*8-1;
+    }
+    assert( pMatch->iCursor==pExpr->iTable );
+    pMatch->colUsed |= ((Bitmask)1)<<n;
+  }
+
+lookupname_end:
+  /* Clean up and return
+  */
+  sqlite3DbFree(db, zDb);
+  sqlite3DbFree(db, zTab);
+  sqlite3ExprDelete(db, pExpr->pLeft);
+  pExpr->pLeft = 0;
+  sqlite3ExprDelete(db, pExpr->pRight);
+  pExpr->pRight = 0;
+  pExpr->op = TK_COLUMN;
+lookupname_end_2:
+  sqlite3DbFree(db, zCol);
+  if( cnt==1 ){
+    assert( pNC!=0 );
+    sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
+    /* Increment the nRef value on all name contexts from TopNC up to
+    ** the point where the name matched. */
+    for(;;){
+      assert( pTopNC!=0 );
+      pTopNC->nRef++;
+      if( pTopNC==pNC ) break;
+      pTopNC = pTopNC->pNext;
+    }
+    return 0;
+  } else {
+    return 1;
+  }
+}
+
+/*
+** This routine is callback for sqlite3WalkExpr().
+**
+** Resolve symbolic names into TK_COLUMN operators for the current
+** node in the expression tree.  Return 0 to continue the search down
+** the tree or 2 to abort the tree walk.
+**
+** This routine also does error checking and name resolution for
+** function names.  The operator for aggregate functions is changed
+** to TK_AGG_FUNCTION.
+*/
+static int resolveExprStep(Walker *pWalker, Expr *pExpr){
+  NameContext *pNC;
+  Parse *pParse;
+
+  pNC = pWalker->u.pNC;
+  assert( pNC!=0 );
+  pParse = pNC->pParse;
+  assert( pParse==pWalker->pParse );
+
+  if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;
+  ExprSetProperty(pExpr, EP_Resolved);
+#ifndef NDEBUG
+  if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
+    SrcList *pSrcList = pNC->pSrcList;
+    int i;
+    for(i=0; i<pNC->pSrcList->nSrc; i++){
+      assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
+    }
+  }
+#endif
+  switch( pExpr->op ){
+    /* A lone identifier is the name of a column.
+    */
+    case TK_ID: {
+      lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
+      return WRC_Prune;
+    }
+  
+    /* 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;
+
+      /* if( pSrcList==0 ) break; */
+      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;
+      }
+      lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
+      return WRC_Prune;
+    }
+
+    /* Resolve function names
+    */
+    case TK_CONST_FUNC:
+    case TK_FUNCTION: {
+      ExprList *pList = pExpr->pList;    /* The argument list */
+      int n = pList ? pList->nExpr : 0;  /* Number of arguments */
+      int no_such_func = 0;       /* True if no such function exists */
+      int wrong_num_args = 0;     /* True if wrong number of arguments */
+      int is_agg = 0;             /* True if is an aggregate function */
+      int auth;                   /* Authorization to use the function */
+      int nId;                    /* Number of characters in function name */
+      const char *zId;            /* The function name. */
+      FuncDef *pDef;              /* Information about the function */
+      int enc = ENC(pParse->db);  /* The database encoding */
+
+      zId = (char*)pExpr->token.z;
+      nId = pExpr->token.n;
+      pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
+      if( pDef==0 ){
+        pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
+        if( pDef==0 ){
+          no_such_func = 1;
+        }else{
+          wrong_num_args = 1;
+        }
+      }else{
+        is_agg = pDef->xFunc==0;
+      }
+#ifndef SQLITE_OMIT_AUTHORIZATION
+      if( pDef ){
+        auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
+        if( auth!=SQLITE_OK ){
+          if( auth==SQLITE_DENY ){
+            sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
+                                    pDef->zName);
+            pNC->nErr++;
+          }
+          pExpr->op = TK_NULL;
+          return WRC_Prune;
+        }
+      }
+#endif
+      if( is_agg && !pNC->allowAgg ){
+        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
+        pNC->nErr++;
+        is_agg = 0;
+      }else if( no_such_func ){
+        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+        pNC->nErr++;
+      }else if( wrong_num_args ){
+        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
+             nId, zId);
+        pNC->nErr++;
+      }
+      if( is_agg ){
+        pExpr->op = TK_AGG_FUNCTION;
+        pNC->hasAgg = 1;
+      }
+      if( is_agg ) pNC->allowAgg = 0;
+      sqlite3WalkExprList(pWalker, pList);
+      if( is_agg ) pNC->allowAgg = 1;
+      /* FIX ME:  Compute pExpr->affinity based on the expected return
+      ** type of the function 
+      */
+      return WRC_Prune;
+    }
+#ifndef SQLITE_OMIT_SUBQUERY
+    case TK_SELECT:
+    case TK_EXISTS:
+#endif
+    case TK_IN: {
+      if( pExpr->pSelect ){
+        int nRef = pNC->nRef;
+#ifndef SQLITE_OMIT_CHECK
+        if( pNC->isCheck ){
+          sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
+        }
+#endif
+        sqlite3WalkSelect(pWalker, pExpr->pSelect);
+        assert( pNC->nRef>=nRef );
+        if( nRef!=pNC->nRef ){
+          ExprSetProperty(pExpr, EP_VarSelect);
+        }
+      }
+      break;
+    }
+#ifndef SQLITE_OMIT_CHECK
+    case TK_VARIABLE: {
+      if( pNC->isCheck ){
+        sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
+      }
+      break;
+    }
+#endif
+  }
+  return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
 }
 
 /*
-** Query a blob handle for the size of the data.
+** pEList is a list of expressions which are really the result set of the
+** a SELECT statement.  pE is a term in an ORDER BY or GROUP BY clause.
+** This routine checks to see if pE is a simple identifier which corresponds
+** to the AS-name of one of the terms of the expression list.  If it is,
+** this routine return an integer between 1 and N where N is the number of
+** elements in pEList, corresponding to the matching entry.  If there is
+** no match, or if pE is not a simple identifier, then this routine
+** return 0.
 **
-** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
-** so no mutex is required for access.
+** pEList has been resolved.  pE has not.
 */
-SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){
-  Incrblob *p = (Incrblob *)pBlob;
-  return p->nByte;
-}
+static int resolveAsName(
+  Parse *pParse,     /* Parsing context for error messages */
+  ExprList *pEList,  /* List of expressions to scan */
+  Expr *pE           /* Expression we are trying to match */
+){
+  int i;             /* Loop counter */
 
-#endif /* #ifndef SQLITE_OMIT_INCRBLOB */
+  if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){
+    sqlite3 *db = pParse->db;
+    char *zCol = sqlite3NameFromToken(db, &pE->token);
+    if( zCol==0 ){
+      return -1;
+    }
+    for(i=0; i<pEList->nExpr; i++){
+      char *zAs = pEList->a[i].zName;
+      if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+        sqlite3DbFree(db, zCol);
+        return i+1;
+      }
+    }
+    sqlite3DbFree(db, zCol);
+  }
+  return 0;
+}
 
-/************** End of vdbeblob.c ********************************************/
-/************** Begin file journal.c *****************************************/
 /*
-** 2007 August 22
-**
-** The author disclaims copyright to this source code.  In place of
-** a legal notice, here is a blessing:
-**
-**    May you do good and not evil.
-**    May you find forgiveness for yourself and forgive others.
-**    May you share freely, never taking more than you give.
-**
-*************************************************************************
+** pE is a pointer to an expression which is a single term in the
+** ORDER BY of a compound SELECT.  The expression has not been
+** name resolved.
 **
-** @(#) $Id: journal.c,v 1.8 2008/05/01 18:01:47 drh Exp $
-*/
-
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
-
-/*
-** This file implements a special kind of sqlite3_file object used
-** by SQLite to create journal files if the atomic-write optimization
-** is enabled.
+** At the point this routine is called, we already know that the
+** ORDER BY term is not an integer index into the result set.  That
+** case is handled by the calling routine.
 **
-** The distinctive characteristic of this sqlite3_file is that the
-** actual on disk file is created lazily. When the file is created,
-** the caller specifies a buffer size for an in-memory buffer to
-** be used to service read() and write() requests. The actual file
-** on disk is not created or populated until either:
+** Attempt to match pE against result set columns in the left-most
+** SELECT statement.  Return the index i of the matching column,
+** as an indication to the caller that it should sort by the i-th column.
+** The left-most column is 1.  In other words, the value returned is the
+** same integer value that would be used in the SQL statement to indicate
+** the column.
 **
-**   1) The in-memory representation grows too large for the allocated 
-**      buffer, or
-**   2) The xSync() method is called.
+** If there is no match, return 0.  Return -1 if an error occurs.
 */
+static int resolveOrderByTermToExprList(
+  Parse *pParse,     /* Parsing context for error messages */
+  Select *pSelect,   /* The SELECT statement with the ORDER BY clause */
+  Expr *pE           /* The specific ORDER BY term */
+){
+  int i;             /* Loop counter */
+  ExprList *pEList;  /* The columns of the result set */
+  NameContext nc;    /* Name context for resolving pE */
 
+  assert( sqlite3ExprIsInteger(pE, &i)==0 );
+  pEList = pSelect->pEList;
 
+  /* Resolve all names in the ORDER BY term expression
+  */
+  memset(&nc, 0, sizeof(nc));
+  nc.pParse = pParse;
+  nc.pSrcList = pSelect->pSrc;
+  nc.pEList = pEList;
+  nc.allowAgg = 1;
+  nc.nErr = 0;
+  if( sqlite3ResolveExprNames(&nc, pE) ){
+    sqlite3ErrorClear(pParse);
+    return 0;
+  }
 
-/*
-** A JournalFile object is a subclass of sqlite3_file used by
-** as an open file handle for journal files.
-*/
-struct JournalFile {
-  sqlite3_io_methods *pMethod;    /* I/O methods on journal files */
-  int nBuf;                       /* Size of zBuf[] in bytes */
-  char *zBuf;                     /* Space to buffer journal writes */
-  int iSize;                      /* Amount of zBuf[] currently used */
-  int flags;                      /* xOpen flags */
-  sqlite3_vfs *pVfs;              /* The "real" underlying VFS */
-  sqlite3_file *pReal;            /* The "real" underlying file descriptor */
-  const char *zJournal;           /* Name of the journal file */
-};
-typedef struct JournalFile JournalFile;
-
-/*
-** If it does not already exists, create and populate the on-disk file 
-** for JournalFile p.
-*/
-static int createFile(JournalFile *p){
-  int rc = SQLITE_OK;
-  if( !p->pReal ){
-    sqlite3_file *pReal = (sqlite3_file *)&p[1];
-    rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0);
-    if( rc==SQLITE_OK ){
-      p->pReal = pReal;
-      if( p->iSize>0 ){
-        assert(p->iSize<=p->nBuf);
-        rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
-      }
+  /* Try to match the ORDER BY expression against an expression
+  ** in the result set.  Return an 1-based index of the matching
+  ** result-set entry.
+  */
+  for(i=0; i<pEList->nExpr; i++){
+    if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
+      return i+1;
     }
   }
-  return rc;
+
+  /* If no match, return 0. */
+  return 0;
 }
 
 /*
-** Close the file.
+** Generate an ORDER BY or GROUP BY term out-of-range error.
 */
-static int jrnlClose(sqlite3_file *pJfd){
-  JournalFile *p = (JournalFile *)pJfd;
-  if( p->pReal ){
-    sqlite3OsClose(p->pReal);
-  }
-  sqlite3_free(p->zBuf);
-  return SQLITE_OK;
+static void resolveOutOfRangeError(
+  Parse *pParse,         /* The error context into which to write the error */
+  const char *zType,     /* "ORDER" or "GROUP" */
+  int i,                 /* The index (1-based) of the term out of range */
+  int mx                 /* Largest permissible value of i */
+){
+  sqlite3ErrorMsg(pParse, 
+    "%r %s BY term out of range - should be "
+    "between 1 and %d", i, zType, mx);
 }
 
 /*
-** Read data from the file.
+** Analyze the ORDER BY clause in a compound SELECT statement.   Modify
+** each term of the ORDER BY clause is a constant integer between 1
+** and N where N is the number of columns in the compound SELECT.
+**
+** ORDER BY terms that are already an integer between 1 and N are
+** unmodified.  ORDER BY terms that are integers outside the range of
+** 1 through N generate an error.  ORDER BY terms that are expressions
+** are matched against result set expressions of compound SELECT
+** beginning with the left-most SELECT and working toward the right.
+** At the first match, the ORDER BY expression is transformed into
+** the integer column number.
+**
+** Return the number of errors seen.
 */
-static int jrnlRead(
-  sqlite3_file *pJfd,    /* The journal file from which to read */
-  void *zBuf,            /* Put the results here */
-  int iAmt,              /* Number of bytes to read */
-  sqlite_int64 iOfst     /* Begin reading at this offset */
+static int resolveCompoundOrderBy(
+  Parse *pParse,        /* Parsing context.  Leave error messages here */
+  Select *pSelect       /* The SELECT statement containing the ORDER BY */
 ){
-  int rc = SQLITE_OK;
-  JournalFile *p = (JournalFile *)pJfd;
-  if( p->pReal ){
-    rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
-  }else{
-    assert( iAmt+iOfst<=p->iSize );
-    memcpy(zBuf, &p->zBuf[iOfst], iAmt);
+  int i;
+  ExprList *pOrderBy;
+  ExprList *pEList;
+  sqlite3 *db;
+  int moreToDo = 1;
+
+  pOrderBy = pSelect->pOrderBy;
+  if( pOrderBy==0 ) return 0;
+  db = pParse->db;
+#if SQLITE_MAX_COLUMN
+  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+    sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
+    return 1;
   }
-  return rc;
+#endif
+  for(i=0; i<pOrderBy->nExpr; i++){
+    pOrderBy->a[i].done = 0;
+  }
+  pSelect->pNext = 0;
+  while( pSelect->pPrior ){
+    pSelect->pPrior->pNext = pSelect;
+    pSelect = pSelect->pPrior;
+  }
+  while( pSelect && moreToDo ){
+    struct ExprList_item *pItem;
+    moreToDo = 0;
+    pEList = pSelect->pEList;
+    assert( pEList!=0 );
+    for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+      int iCol = -1;
+      Expr *pE, *pDup;
+      if( pItem->done ) continue;
+      pE = pItem->pExpr;
+      if( sqlite3ExprIsInteger(pE, &iCol) ){
+        if( iCol<0 || iCol>pEList->nExpr ){
+          resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
+          return 1;
+        }
+      }else{
+        iCol = resolveAsName(pParse, pEList, pE);
+        if( iCol==0 ){
+          pDup = sqlite3ExprDup(db, pE);
+          if( !db->mallocFailed ){
+            assert(pDup);
+            iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
+          }
+          sqlite3ExprDelete(db, pDup);
+        }
+        if( iCol<0 ){
+          return 1;
+        }
+      }
+      if( iCol>0 ){
+        CollSeq *pColl = pE->pColl;
+        int flags = pE->flags & EP_ExpCollate;
+        sqlite3ExprDelete(db, pE);
+        pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0, 0, 0);
+        if( pE==0 ) return 1;
+        pE->pColl = pColl;
+        pE->flags |= EP_IntValue | flags;
+        pE->iTable = iCol;
+        pItem->iCol = iCol;
+        pItem->done = 1;
+      }else{
+        moreToDo = 1;
+      }
+    }
+    pSelect = pSelect->pNext;
+  }
+  for(i=0; i<pOrderBy->nExpr; i++){
+    if( pOrderBy->a[i].done==0 ){
+      sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
+            "column in the result set", i+1);
+      return 1;
+    }
+  }
+  return 0;
 }
 
 /*
-** Write data to the file.
+** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
+** the SELECT statement pSelect.  If any term is reference to a
+** result set expression (as determined by the ExprList.a.iCol field)
+** then convert that term into a copy of the corresponding result set
+** column.
+**
+** If any errors are detected, add an error message to pParse and
+** return non-zero.  Return zero if no errors are seen.
 */
-static int jrnlWrite(
-  sqlite3_file *pJfd,    /* The journal file into which to write */
-  const void *zBuf,      /* Take data to be written from here */
-  int iAmt,              /* Number of bytes to write */
-  sqlite_int64 iOfst     /* Begin writing at this offset into the file */
+SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
+  Parse *pParse,        /* Parsing context.  Leave error messages here */
+  Select *pSelect,      /* The SELECT statement containing the clause */
+  ExprList *pOrderBy,   /* The ORDER BY or GROUP BY clause to be processed */
+  const char *zType     /* "ORDER" or "GROUP" */
 ){
-  int rc = SQLITE_OK;
-  JournalFile *p = (JournalFile *)pJfd;
-  if( !p->pReal && (iOfst+iAmt)>p->nBuf ){
-    rc = createFile(p);
+  int i;
+  sqlite3 *db = pParse->db;
+  ExprList *pEList;
+  struct ExprList_item *pItem;
+
+  if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
+#if SQLITE_MAX_COLUMN
+  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+    sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
+    return 1;
   }
-  if( rc==SQLITE_OK ){
-    if( p->pReal ){
-      rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
-    }else{
-      memcpy(&p->zBuf[iOfst], zBuf, iAmt);
-      if( p->iSize<(iOfst+iAmt) ){
-        p->iSize = (iOfst+iAmt);
+#endif
+  pEList = pSelect->pEList;
+  assert( pEList!=0 );  /* sqlite3SelectNew() guarantees this */
+  for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+    if( pItem->iCol ){
+      if( pItem->iCol>pEList->nExpr ){
+        resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
+        return 1;
       }
+      resolveAlias(pParse, pEList, pItem->iCol-1, pItem->pExpr, zType);
     }
   }
-  return rc;
+  return 0;
 }
 
 /*
-** Truncate the file.
-*/
-static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
-  int rc = SQLITE_OK;
-  JournalFile *p = (JournalFile *)pJfd;
-  if( p->pReal ){
-    rc = sqlite3OsTruncate(p->pReal, size);
-  }else if( size<p->iSize ){
-    p->iSize = size;
+** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
+** The Name context of the SELECT statement is pNC.  zType is either
+** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
+**
+** This routine resolves each term of the clause into an expression.
+** If the order-by term is an integer I between 1 and N (where N is the
+** number of columns in the result set of the SELECT) then the expression
+** in the resolution is a copy of the I-th result-set expression.  If
+** the order-by term is an identify that corresponds to the AS-name of
+** a result-set expression, then the term resolves to a copy of the
+** result-set expression.  Otherwise, the expression is resolved in
+** the usual way - using sqlite3ResolveExprNames().
+**
+** This routine returns the number of errors.  If errors occur, then
+** an appropriate error message might be left in pParse.  (OOM errors
+** excepted.)
+*/
+static int resolveOrderGroupBy(
+  NameContext *pNC,     /* The name context of the SELECT statement */
+  Select *pSelect,      /* The SELECT statement holding pOrderBy */
+  ExprList *pOrderBy,   /* An ORDER BY or GROUP BY clause to resolve */
+  const char *zType     /* Either "ORDER" or "GROUP", as appropriate */
+){
+  int i;                         /* Loop counter */
+  int iCol;                      /* Column number */
+  struct ExprList_item *pItem;   /* A term of the ORDER BY clause */
+  Parse *pParse;                 /* Parsing context */
+  int nResult;                   /* Number of terms in the result set */
+
+  if( pOrderBy==0 ) return 0;
+  nResult = pSelect->pEList->nExpr;
+  pParse = pNC->pParse;
+  for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+    Expr *pE = pItem->pExpr;
+    iCol = resolveAsName(pParse, pSelect->pEList, pE);
+    if( iCol<0 ){
+      return 1;  /* OOM error */
+    }
+    if( iCol>0 ){
+      /* If an AS-name match is found, mark this ORDER BY column as being
+      ** a copy of the iCol-th result-set column.  The subsequent call to
+      ** sqlite3ResolveOrderGroupBy() will convert the expression to a
+      ** copy of the iCol-th result-set expression. */
+      pItem->iCol = iCol;
+      continue;
+    }
+    if( sqlite3ExprIsInteger(pE, &iCol) ){
+      /* The ORDER BY term is an integer constant.  Again, set the column
+      ** number so that sqlite3ResolveOrderGroupBy() will convert the
+      ** order-by term to a copy of the result-set expression */
+      if( iCol<1 ){
+        resolveOutOfRangeError(pParse, zType, i+1, nResult);
+        return 1;
+      }
+      pItem->iCol = iCol;
+      continue;
+    }
+
+    /* Otherwise, treat the ORDER BY term as an ordinary expression */
+    pItem->iCol = 0;
+    if( sqlite3ResolveExprNames(pNC, pE) ){
+      return 1;
+    }
   }
-  return rc;
+  return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
 }
 
 /*
-** Sync the file.
+** Resolve names in the SELECT statement p and all of its descendents.
 */
-static int jrnlSync(sqlite3_file *pJfd, int flags){
-  int rc;
-  JournalFile *p = (JournalFile *)pJfd;
-  if( p->pReal ){
-    rc = sqlite3OsSync(p->pReal, flags);
-  }else{
-    rc = SQLITE_OK;
+static int resolveSelectStep(Walker *pWalker, Select *p){
+  NameContext *pOuterNC;  /* Context that contains this SELECT */
+  NameContext sNC;        /* Name context of this SELECT */
+  int isCompound;         /* True if p is a compound select */
+  int nCompound;          /* Number of compound terms processed so far */
+  Parse *pParse;          /* Parsing context */
+  ExprList *pEList;       /* Result set expression list */
+  int i;                  /* Loop counter */
+  ExprList *pGroupBy;     /* The GROUP BY clause */
+  Select *pLeftmost;      /* Left-most of SELECT of a compound */
+  sqlite3 *db;            /* Database connection */
+  
+
+  assert( p!=0 );
+  if( p->selFlags & SF_Resolved ){
+    return WRC_Prune;
   }
-  return rc;
-}
+  pOuterNC = pWalker->u.pNC;
+  pParse = pWalker->pParse;
+  db = pParse->db;
 
-/*
-** Query the size of the file in bytes.
-*/
-static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
-  int rc = SQLITE_OK;
-  JournalFile *p = (JournalFile *)pJfd;
-  if( p->pReal ){
-    rc = sqlite3OsFileSize(p->pReal, pSize);
-  }else{
-    *pSize = (sqlite_int64) p->iSize;
+  /* Normally sqlite3SelectExpand() will be called first and will have
+  ** already expanded this SELECT.  However, if this is a subquery within
+  ** an expression, sqlite3ResolveExprNames() will be called without a
+  ** prior call to sqlite3SelectExpand().  When that happens, let
+  ** sqlite3SelectPrep() do all of the processing for this SELECT.
+  ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and
+  ** this routine in the correct order.
+  */
+  if( (p->selFlags & SF_Expanded)==0 ){
+    sqlite3SelectPrep(pParse, p, pOuterNC);
+    return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
+  }
+
+  isCompound = p->pPrior!=0;
+  nCompound = 0;
+  pLeftmost = p;
+  while( p ){
+    assert( (p->selFlags & SF_Expanded)!=0 );
+    assert( (p->selFlags & SF_Resolved)==0 );
+    p->selFlags |= SF_Resolved;
+
+    /* Resolve the expressions in the LIMIT and OFFSET clauses. These
+    ** are not allowed to refer to any names, so pass an empty NameContext.
+    */
+    memset(&sNC, 0, sizeof(sNC));
+    sNC.pParse = pParse;
+    if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
+        sqlite3ResolveExprNames(&sNC, p->pOffset) ){
+      return WRC_Abort;
+    }
+  
+    /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
+    ** resolve the result-set expression list.
+    */
+    sNC.allowAgg = 1;
+    sNC.pSrcList = p->pSrc;
+    sNC.pNext = pOuterNC;
+  
+    /* Resolve names in the result set. */
+    pEList = p->pEList;
+    assert( pEList!=0 );
+    for(i=0; i<pEList->nExpr; i++){
+      Expr *pX = pEList->a[i].pExpr;
+      if( sqlite3ResolveExprNames(&sNC, pX) ){
+        return WRC_Abort;
+      }
+    }
+  
+    /* Recursively resolve names in all subqueries
+    */
+    for(i=0; i<p->pSrc->nSrc; i++){
+      struct SrcList_item *pItem = &p->pSrc->a[i];
+      if( pItem->pSelect ){
+        const char *zSavedContext = pParse->zAuthContext;
+        if( pItem->zName ) pParse->zAuthContext = pItem->zName;
+        sqlite3ResolveSelectNames(pParse, pItem->pSelect, &sNC);
+        pParse->zAuthContext = zSavedContext;
+        if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
+      }
+    }
+  
+    /* If there are no aggregate functions in the result-set, and no GROUP BY 
+    ** expression, do not allow aggregates in any of the other expressions.
+    */
+    assert( (p->selFlags & SF_Aggregate)==0 );
+    pGroupBy = p->pGroupBy;
+    if( pGroupBy || sNC.hasAgg ){
+      p->selFlags |= SF_Aggregate;
+    }else{
+      sNC.allowAgg = 0;
+    }
+  
+    /* If a HAVING clause is present, then there must be a GROUP BY clause.
+    */
+    if( p->pHaving && !pGroupBy ){
+      sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
+      return WRC_Abort;
+    }
+  
+    /* Add the expression list to the name-context before parsing the
+    ** other expressions in the SELECT statement. This is so that
+    ** expressions in the WHERE clause (etc.) can refer to expressions by
+    ** aliases in the result set.
+    **
+    ** Minor point: If this is the case, then the expression will be
+    ** re-evaluated for each reference to it.
+    */
+    sNC.pEList = p->pEList;
+    if( sqlite3ResolveExprNames(&sNC, p->pWhere) ||
+       sqlite3ResolveExprNames(&sNC, p->pHaving)
+    ){
+      return WRC_Abort;
+    }
+
+    /* The ORDER BY and GROUP BY clauses may not refer to terms in
+    ** outer queries 
+    */
+    sNC.pNext = 0;
+    sNC.allowAgg = 1;
+
+    /* Process the ORDER BY clause for singleton SELECT statements.
+    ** The ORDER BY clause for compounds SELECT statements is handled
+    ** below, after all of the result-sets for all of the elements of
+    ** the compound have been resolved.
+    */
+    if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){
+      return WRC_Abort;
+    }
+    if( db->mallocFailed ){
+      return WRC_Abort;
+    }
+  
+    /* Resolve the GROUP BY clause.  At the same time, make sure 
+    ** the GROUP BY clause does not contain aggregate functions.
+    */
+    if( pGroupBy ){
+      struct ExprList_item *pItem;
+    
+      if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
+        return WRC_Abort;
+      }
+      for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
+        if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
+          sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
+              "the GROUP BY clause");
+          return WRC_Abort;
+        }
+      }
+    }
+
+    /* Advance to the next term of the compound
+    */
+    p = p->pPrior;
+    nCompound++;
   }
-  return rc;
+
+  /* Resolve the ORDER BY on a compound SELECT after all terms of
+  ** the compound have been resolved.
+  */
+  if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){
+    return WRC_Abort;
+  }
+
+  return WRC_Prune;
 }
 
 /*
-** Table of methods for JournalFile sqlite3_file object.
-*/
-static struct sqlite3_io_methods JournalFileMethods = {
-  1,             /* iVersion */
-  jrnlClose,     /* xClose */
-  jrnlRead,      /* xRead */
-  jrnlWrite,     /* xWrite */
-  jrnlTruncate,  /* xTruncate */
-  jrnlSync,      /* xSync */
-  jrnlFileSize,  /* xFileSize */
-  0,             /* xLock */
-  0,             /* xUnlock */
-  0,             /* xCheckReservedLock */
-  0,             /* xFileControl */
-  0,             /* xSectorSize */
-  0              /* xDeviceCharacteristics */
-};
-
-/* 
-** Open a journal file.
+** This routine walks an expression tree and resolves references to
+** table columns and result-set columns.  At the same time, do error
+** checking on function usage and set a flag if any aggregate functions
+** are seen.
+**
+** To resolve table columns references we look for nodes (or subtrees) of the 
+** form X.Y.Z or Y.Z or just Z where
+**
+**      X:   The name of a database.  Ex:  "main" or "temp" or
+**           the symbolic name assigned to an ATTACH-ed database.
+**
+**      Y:   The name of a table in a FROM clause.  Or in a trigger
+**           one of the special names "old" or "new".
+**
+**      Z:   The name of a column in table Y.
+**
+** The node at the root of the subtree is modified as follows:
+**
+**    Expr.op        Changed to TK_COLUMN
+**    Expr.pTab      Points to the Table object for X.Y
+**    Expr.iColumn   The column index in X.Y.  -1 for the rowid.
+**    Expr.iTable    The VDBE cursor number for X.Y
+**
+**
+** To resolve result-set references, look for expression nodes of the
+** form Z (with no X and Y prefix) where the Z matches the right-hand
+** size of an AS clause in the result-set of a SELECT.  The Z expression
+** is replaced by a copy of the left-hand side of the result-set expression.
+** Table-name and function resolution occurs on the substituted expression
+** tree.  For example, in:
+**
+**      SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;
+**
+** The "x" term of the order by is replaced by "a+b" to render:
+**
+**      SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
+**
+** Function calls are checked to make sure that the function is 
+** defined and that the correct number of arguments are specified.
+** If the function is an aggregate function, then the pNC->hasAgg is
+** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
+** If an expression contains aggregate functions then the EP_Agg
+** property on the expression is set.
+**
+** An error message is left in pParse if anything is amiss.  The number
+** if errors is returned.
 */
-SQLITE_PRIVATE int sqlite3JournalOpen(
-  sqlite3_vfs *pVfs,         /* The VFS to use for actual file I/O */
-  const char *zName,         /* Name of the journal file */
-  sqlite3_file *pJfd,        /* Preallocated, blank file handle */
-  int flags,                 /* Opening flags */
-  int nBuf                   /* Bytes buffered before opening the file */
+SQLITE_PRIVATE int sqlite3ResolveExprNames( 
+  NameContext *pNC,       /* Namespace to resolve expressions in. */
+  Expr *pExpr             /* The expression to be analyzed. */
 ){
-  JournalFile *p = (JournalFile *)pJfd;
-  memset(p, 0, sqlite3JournalSize(pVfs));
-  if( nBuf>0 ){
-    p->zBuf = sqlite3MallocZero(nBuf);
-    if( !p->zBuf ){
-      return SQLITE_NOMEM;
+  int savedHasAgg;
+  Walker w;
+
+  if( pExpr==0 ) return 0;
+#if SQLITE_MAX_EXPR_DEPTH>0
+  {
+    Parse *pParse = pNC->pParse;
+    if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
+      return 1;
     }
-  }else{
-    return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0);
+    pParse->nHeight += pExpr->nHeight;
   }
-  p->pMethod = &JournalFileMethods;
-  p->nBuf = nBuf;
-  p->flags = flags;
-  p->zJournal = zName;
-  p->pVfs = pVfs;
-  return SQLITE_OK;
+#endif
+  savedHasAgg = pNC->hasAgg;
+  pNC->hasAgg = 0;
+  w.xExprCallback = resolveExprStep;
+  w.xSelectCallback = resolveSelectStep;
+  w.pParse = pNC->pParse;
+  w.u.pNC = pNC;
+  sqlite3WalkExpr(&w, pExpr);
+#if SQLITE_MAX_EXPR_DEPTH>0
+  pNC->pParse->nHeight -= pExpr->nHeight;
+#endif
+  if( pNC->nErr>0 ){
+    ExprSetProperty(pExpr, EP_Error);
+  }
+  if( pNC->hasAgg ){
+    ExprSetProperty(pExpr, EP_Agg);
+  }else if( savedHasAgg ){
+    pNC->hasAgg = 1;
+  }
+  return ExprHasProperty(pExpr, EP_Error);
 }
 
+
 /*
-** If the argument p points to a JournalFile structure, and the underlying
-** file has not yet been created, create it now.
+** Resolve all names in all expressions of a SELECT and in all
+** decendents of the SELECT, including compounds off of p->pPrior,
+** subqueries in expressions, and subqueries used as FROM clause
+** terms.
+**
+** See sqlite3ResolveExprNames() for a description of the kinds of
+** transformations that occur.
+**
+** All SELECT statements should have been expanded using
+** sqlite3SelectExpand() prior to invoking this routine.
 */
-SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){
-  if( p->pMethods!=&JournalFileMethods ){
-    return SQLITE_OK;
-  }
-  return createFile((JournalFile *)p);
-}
+SQLITE_PRIVATE void sqlite3ResolveSelectNames(
+  Parse *pParse,         /* The parser context */
+  Select *p,             /* The SELECT statement being coded. */
+  NameContext *pOuterNC  /* Name context for parent SELECT statement */
+){
+  Walker w;
 
-/* 
-** Return the number of bytes required to store a JournalFile that uses vfs
-** pVfs to create the underlying on-disk files.
-*/
-SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
-  return (pVfs->szOsFile+sizeof(JournalFile));
+  assert( p!=0 );
+  w.xExprCallback = resolveExprStep;
+  w.xSelectCallback = resolveSelectStep;
+  w.pParse = pParse;
+  w.u.pNC = pOuterNC;
+  sqlite3WalkSelect(&w, p);
 }
-#endif
 
-/************** End of journal.c *********************************************/
+/************** End of resolve.c *********************************************/
 /************** Begin file expr.c ********************************************/
 /*
 ** 2001 September 15
@@ -50554,7 +52481,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.387 2008/07/28 19:34:53 drh Exp $
+** $Id: expr.c,v 1.392 2008/08/29 02:14:03 drh Exp $
 */
 
 /*
@@ -50583,6 +52510,14 @@
     return sqlite3AffinityType(&pExpr->token);
   }
 #endif
+  if( (op==TK_COLUMN || op==TK_REGISTER) && pExpr->pTab!=0 ){
+    /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally
+    ** a TK_COLUMN but was previously evaluated and cached in a register */
+    int j = pExpr->iColumn;
+    if( j<0 ) return SQLITE_AFF_INTEGER;
+    assert( pExpr->pTab && j<pExpr->pTab->nCol );
+    return pExpr->pTab->aCol[j].affinity;
+  }
   return pExpr->affinity;
 }
 
@@ -50593,11 +52528,11 @@
 ** flag.  An explicit collating sequence will override implicit
 ** collating sequences.
 */
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){
+SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pCollName){
   char *zColl = 0;            /* Dequoted name of collation sequence */
   CollSeq *pColl;
   sqlite3 *db = pParse->db;
-  zColl = sqlite3NameFromToken(db, pName);
+  zColl = sqlite3NameFromToken(db, pCollName);
   if( pExpr && zColl ){
     pColl = sqlite3LocateCollSeq(pParse, zColl, -1);
     if( pColl ){
@@ -50615,13 +52550,29 @@
 */
 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
   CollSeq *pColl = 0;
-  if( pExpr ){
+  Expr *p = pExpr;
+  while( p ){
     int op;
-    pColl = pExpr->pColl;
-    op = pExpr->op;
-    if( (op==TK_CAST || op==TK_UPLUS) && !pColl ){
-      return sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+    pColl = p->pColl;
+    if( pColl ) break;
+    op = p->op;
+    if( (op==TK_COLUMN || op==TK_REGISTER) && p->pTab!=0 ){
+      /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
+      ** a TK_COLUMN but was previously evaluated and cached in a register */
+      const char *zColl;
+      int j = p->iColumn;
+      if( j>=0 ){
+        sqlite3 *db = pParse->db;
+        zColl = p->pTab->aCol[j].zColl;
+        pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0);
+        pExpr->pColl = pColl;
+      }
+      break;
     }
+    if( op!=TK_CAST && op!=TK_UPLUS ){
+      break;
+    }
+    p = p->pLeft;
   }
   if( sqlite3CheckCollSeq(pParse, pColl) ){ 
     pColl = 0;
@@ -50800,7 +52751,7 @@
 ** expression depth allowed. If it is not, leave an error message in
 ** pParse.
 */
-static int checkExprHeight(Parse *pParse, int nHeight){
+SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){
   int rc = SQLITE_OK;
   int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];
   if( nHeight>mxHeight ){
@@ -50872,7 +52823,7 @@
 */
 SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p){
   exprSetHeight(p);
-  checkExprHeight(pParse, p->nHeight);
+  sqlite3ExprCheckHeight(pParse, p->nHeight);
 }
 
 /*
@@ -50885,7 +52836,6 @@
   return nHeight;
 }
 #else
-  #define checkExprHeight(x,y)
   #define exprSetHeight(y)
 #endif /* SQLITE_MAX_EXPR_DEPTH>0 */
 
@@ -50953,7 +52903,7 @@
 ){
   Expr *p = sqlite3Expr(pParse->db, op, pLeft, pRight, pToken);
   if( p ){
-    checkExprHeight(pParse, p->nHeight);
+    sqlite3ExprCheckHeight(pParse, p->nHeight);
   }
   return p;
 }
@@ -51146,7 +53096,6 @@
   sqlite3Dequote((char*)p->token.z);
 }
 
-
 /*
 ** The following group of routines make deep copies of expressions,
 ** expression lists, ID lists, and select statements.  The copies can
@@ -51217,8 +53166,9 @@
             || db->mallocFailed );
     pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
     pItem->sortOrder = pOldItem->sortOrder;
-    pItem->isAgg = pOldItem->isAgg;
     pItem->done = 0;
+    pItem->iCol = pOldItem->iCol;
+    pItem->iAlias = pOldItem->iAlias;
   }
   return pNew;
 }
@@ -51286,7 +53236,6 @@
   if( p==0 ) return 0;
   pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
   if( pNew==0 ) return 0;
-  pNew->isDistinct = p->isDistinct;
   pNew->pEList = sqlite3ExprListDup(db, p->pEList);
   pNew->pSrc = sqlite3SrcListDup(db, p->pSrc);
   pNew->pWhere = sqlite3ExprDup(db, p->pWhere);
@@ -51299,10 +53248,7 @@
   pNew->pOffset = sqlite3ExprDup(db, p->pOffset);
   pNew->iLimit = 0;
   pNew->iOffset = 0;
-  pNew->isResolved = p->isResolved;
-  pNew->isAgg = p->isAgg;
-  pNew->usesEphm = 0;
-  pNew->disallowOrderBy = 0;
+  pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
   pNew->pRightmost = 0;
   pNew->addrOpenEphm[0] = -1;
   pNew->addrOpenEphm[1] = -1;
@@ -51351,6 +53297,7 @@
     memset(pItem, 0, sizeof(*pItem));
     pItem->zName = sqlite3NameFromToken(db, pName);
     pItem->pExpr = pExpr;
+    pItem->iAlias = 0;
   }
   return pList;
 
@@ -51379,109 +53326,50 @@
 }
 
 /*
-** Delete an entire expression list.
-*/
-SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
-  int i;
-  struct ExprList_item *pItem;
-  if( pList==0 ) return;
-  assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
-  assert( pList->nExpr<=pList->nAlloc );
-  for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
-    sqlite3ExprDelete(db, pItem->pExpr);
-    sqlite3DbFree(db, pItem->zName);
-  }
-  sqlite3DbFree(db, pList->a);
-  sqlite3DbFree(db, pList);
-}
-
-/*
-** Walk an expression tree.  Call xFunc for each node visited.  xFunc
-** is called on the node before xFunc is called on the nodes children.
-**
-** The return value from xFunc determines whether the tree walk continues.
-** 0 means continue walking the tree.  1 means do not walk children
-** of the current node but continue with siblings.  2 means abandon
-** the tree walk completely.
-**
-** The return value from this routine is 1 to abandon the tree walk
-** and 0 to continue.
-**
-** NOTICE:  This routine does *not* descend into subqueries.
-*/
-static int walkExprList(ExprList *, int (*)(void *, Expr*), void *);
-static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
-  int rc;
-  if( pExpr==0 ) return 0;
-  rc = (*xFunc)(pArg, pExpr);
-  if( rc==0 ){
-    if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1;
-    if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1;
-    if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1;
-  }
-  return rc>1;
-}
-
-/*
-** Call walkExprTree() for every expression in list p.
-*/
-static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){
-  int i;
-  struct ExprList_item *pItem;
-  if( !p ) return 0;
-  for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
-    if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1;
-  }
-  return 0;
-}
-
-/*
-** Call walkExprTree() for every expression in Select p, not including
-** expressions that are part of sub-selects in any FROM clause or the LIMIT
-** or OFFSET expressions..
-*/
-static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){
-  walkExprList(p->pEList, xFunc, pArg);
-  walkExprTree(p->pWhere, xFunc, pArg);
-  walkExprList(p->pGroupBy, xFunc, pArg);
-  walkExprTree(p->pHaving, xFunc, pArg);
-  walkExprList(p->pOrderBy, xFunc, pArg);
-  if( p->pPrior ){
-    walkSelectExpr(p->pPrior, xFunc, pArg);
+** Delete an entire expression list.
+*/
+SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
+  int i;
+  struct ExprList_item *pItem;
+  if( pList==0 ) return;
+  assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
+  assert( pList->nExpr<=pList->nAlloc );
+  for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
+    sqlite3ExprDelete(db, pItem->pExpr);
+    sqlite3DbFree(db, pItem->zName);
   }
-  return 0;
+  sqlite3DbFree(db, pList->a);
+  sqlite3DbFree(db, pList);
 }
 
-
 /*
-** This routine is designed as an xFunc for walkExprTree().
+** These routines are Walker callbacks.  Walker.u.pi is a pointer
+** to an integer.  These routines are checking an expression to see
+** if it is a constant.  Set *Walker.u.pi to 0 if the expression is
+** not constant.
+**
+** These callback routines are used to implement the following:
+**
+**     sqlite3ExprIsConstant()
+**     sqlite3ExprIsConstantNotJoin()
+**     sqlite3ExprIsConstantOrFunction()
 **
-** pArg is really a pointer to an integer.  If we can tell by looking
-** at pExpr that the expression that contains pExpr is not a constant
-** expression, then set *pArg to 0 and return 2 to abandon the tree walk.
-** If pExpr does does not disqualify the expression from being a constant
-** then do nothing.
-**
-** After walking the whole tree, if no nodes are found that disqualify
-** the expression as constant, then we assume the whole expression
-** is constant.  See sqlite3ExprIsConstant() for additional information.
 */
-static int exprNodeIsConstant(void *pArg, Expr *pExpr){
-  int *pN = (int*)pArg;
+static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
 
-  /* If *pArg is 3 then any term of the expression that comes from
+  /* If pWalker->u.i is 3 then any term of the expression that comes from
   ** the ON or USING clauses of a join disqualifies the expression
   ** from being considered constant. */
-  if( (*pN)==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
-    *pN = 0;
-    return 2;
+  if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
+    pWalker->u.i = 0;
+    return WRC_Abort;
   }
 
   switch( pExpr->op ){
     /* Consider functions to be constant if all their arguments are constant
-    ** and *pArg==2 */
+    ** and pWalker->u.i==2 */
     case TK_FUNCTION:
-      if( (*pN)==2 ) return 0;
+      if( pWalker->u.i==2 ) return 0;
       /* Fall through */
     case TK_ID:
     case TK_COLUMN:
@@ -51499,17 +53387,24 @@
       testcase( pExpr->op==TK_DOT );
       testcase( pExpr->op==TK_AGG_FUNCTION );
       testcase( pExpr->op==TK_AGG_COLUMN );
-      *pN = 0;
-      return 2;
-    case TK_IN:
-      if( pExpr->pSelect ){
-        *pN = 0;
-        return 2;
-      }
+      pWalker->u.i = 0;
+      return WRC_Abort;
     default:
-      return 0;
+      return WRC_Continue;
   }
 }
+static int selectNodeIsConstant(Walker *pWalker, Select *pSelect){
+  pWalker->u.i = 0;
+  return WRC_Abort;
+}
+static int exprIsConst(Expr *p, int initFlag){
+  Walker w;
+  w.u.i = initFlag;
+  w.xExprCallback = exprNodeIsConstant;
+  w.xSelectCallback = selectNodeIsConstant;
+  sqlite3WalkExpr(&w, p);
+  return w.u.i;
+}
 
 /*
 ** Walk an expression tree.  Return 1 if the expression is constant
@@ -51520,9 +53415,7 @@
 ** a constant.
 */
 SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
-  int isConst = 1;
-  walkExprTree(p, exprNodeIsConstant, &isConst);
-  return isConst;
+  return exprIsConst(p, 1);
 }
 
 /*
@@ -51532,9 +53425,7 @@
 ** an ON or USING clause.
 */
 SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
-  int isConst = 3;
-  walkExprTree(p, exprNodeIsConstant, &isConst);
-  return isConst!=0;
+  return exprIsConst(p, 3);
 }
 
 /*
@@ -51547,9 +53438,7 @@
 ** a constant.
 */
 SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p){
-  int isConst = 2;
-  walkExprTree(p, exprNodeIsConstant, &isConst);
-  return isConst!=0;
+  return exprIsConst(p, 2);
 }
 
 /*
@@ -51601,554 +53490,6 @@
   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->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. */
-  NameContext *pNC,    /* The name context used to resolve the name */
-  Expr *pExpr          /* Make this EXPR node point to the selected column */
-){
-  char *zDb = 0;       /* Name of the database.  The "X" in X.Y.Z */
-  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 */
-  sqlite3 *db = pParse->db;  /* The database */
-  struct SrcList_item *pItem;       /* Use for looping over pSrcList items */
-  struct SrcList_item *pMatch = 0;  /* The matching pSrcList item */
-  NameContext *pTopNC = pNC;        /* First namecontext in the list */
-  Schema *pSchema = 0;              /* Schema of the expression */
-
-  assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
-  zDb = sqlite3NameFromToken(db, pDbToken);
-  zTab = sqlite3NameFromToken(db, pTableToken);
-  zCol = sqlite3NameFromToken(db, pColumnToken);
-  if( db->mallocFailed ){
-    goto lookupname_end;
-  }
-
-  pExpr->iTable = -1;
-  while( pNC && cnt==0 ){
-    ExprList *pEList;
-    SrcList *pSrcList = pNC->pSrcList;
-
-    if( pSrcList ){
-      for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
-        Table *pTab;
-        int iDb;
-        Column *pCol;
-  
-        pTab = pItem->pTab;
-        assert( pTab!=0 );
-        iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
-        assert( pTab->nCol>0 );
-        if( zTab ){
-          if( pItem->zAlias ){
-            char *zTabName = pItem->zAlias;
-            if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
-          }else{
-            char *zTabName = pTab->zName;
-            if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
-            if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
-              continue;
-            }
-          }
-        }
-        if( 0==(cntTab++) ){
-          pExpr->iTable = pItem->iCursor;
-          pSchema = pTab->pSchema;
-          pMatch = pItem;
-        }
-        for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
-          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
-            const char *zColl = pTab->aCol[j].zColl;
-            IdList *pUsing;
-            cnt++;
-            pExpr->iTable = pItem->iCursor;
-            pMatch = pItem;
-            pSchema = pTab->pSchema;
-            /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
-            pExpr->iColumn = j==pTab->iPKey ? -1 : j;
-            pExpr->affinity = pTab->aCol[j].affinity;
-            if( (pExpr->flags & EP_ExpCollate)==0 ){
-              pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
-            }
-            if( i<pSrcList->nSrc-1 ){
-              if( pItem[1].jointype & JT_NATURAL ){
-                /* If this match occurred in the left table of a natural join,
-                ** then skip the right table to avoid a duplicate match */
-                pItem++;
-                i++;
-              }else if( (pUsing = pItem[1].pUsing)!=0 ){
-                /* If this match occurs on a column that is in the USING clause
-                ** of a join, skip the search of the right table of the join
-                ** to avoid a duplicate match there. */
-                int k;
-                for(k=0; k<pUsing->nId; k++){
-                  if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
-                    pItem++;
-                    i++;
-                    break;
-                  }
-                }
-              }
-            }
-            break;
-          }
-        }
-      }
-    }
-
-#ifndef SQLITE_OMIT_TRIGGER
-    /* If we have not already resolved the name, then maybe 
-    ** it is a new.* or old.* trigger argument reference
-    */
-    if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
-      TriggerStack *pTriggerStack = pParse->trigStack;
-      Table *pTab = 0;
-      u32 *piColMask;
-      if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
-        pExpr->iTable = pTriggerStack->newIdx;
-        assert( pTriggerStack->pTab );
-        pTab = pTriggerStack->pTab;
-        piColMask = &(pTriggerStack->newColMask);
-      }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
-        pExpr->iTable = pTriggerStack->oldIdx;
-        assert( pTriggerStack->pTab );
-        pTab = pTriggerStack->pTab;
-        piColMask = &(pTriggerStack->oldColMask);
-      }
-
-      if( pTab ){ 
-        int iCol;
-        Column *pCol = pTab->aCol;
-
-        pSchema = pTab->pSchema;
-        cntTab++;
-        for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) {
-          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
-            const char *zColl = pTab->aCol[iCol].zColl;
-            cnt++;
-            pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
-            pExpr->affinity = pTab->aCol[iCol].affinity;
-            if( (pExpr->flags & EP_ExpCollate)==0 ){
-              pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
-            }
-            pExpr->pTab = pTab;
-            if( iCol>=0 ){
-              testcase( iCol==31 );
-              testcase( iCol==32 );
-              *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
-            }
-            break;
-          }
-        }
-      }
-    }
-#endif /* !defined(SQLITE_OMIT_TRIGGER) */
-
-    /*
-    ** Perhaps the name is a reference to the ROWID
-    */
-    if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
-      cnt = 1;
-      pExpr->iColumn = -1;
-      pExpr->affinity = SQLITE_AFF_INTEGER;
-    }
-
-    /*
-    ** 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 = pNC->pEList)!=0 && zTab==0 ){
-      for(j=0; j<pEList->nExpr; j++){
-        char *zAs = pEList->a[j].zName;
-        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
-          Expr *pDup, *pOrig;
-          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
-          assert( pExpr->pList==0 );
-          assert( pExpr->pSelect==0 );
-          pOrig = pEList->a[j].pExpr;
-          if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
-            sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
-            sqlite3DbFree(db, zCol);
-            return 2;
-          }
-          pDup = sqlite3ExprDup(db, pOrig);
-          if( pExpr->flags & EP_ExpCollate ){
-            pDup->pColl = pExpr->pColl;
-            pDup->flags |= EP_ExpCollate;
-          }
-          if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z);
-          if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z);
-          memcpy(pExpr, pDup, sizeof(*pExpr));
-          sqlite3DbFree(db, pDup);
-          cnt = 1;
-          pMatch = 0;
-          assert( zTab==0 && zDb==0 );
-          goto lookupname_end_2;
-        }
-      } 
-    }
-
-    /* Advance to the next name context.  The loop will exit when either
-    ** we have a match (cnt>0) or when we run out of name contexts.
-    */
-    if( cnt==0 ){
-      pNC = pNC->pNext;
-    }
-  }
-
-  /*
-  ** If X and Y are NULL (in other words if only the column name Z is
-  ** supplied) and the value of Z is enclosed in double-quotes, then
-  ** Z is a string literal if it doesn't match any column names.  In that
-  ** case, we need to return right away and not make any changes to
-  ** pExpr.
-  **
-  ** Because no reference was made to outer contexts, the pNC->nRef
-  ** fields are not changed in any context.
-  */
-  if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
-    sqlite3DbFree(db, 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 ){
-    const char *zErr;
-    zErr = cnt==0 ? "no such column" : "ambiguous column name";
-    if( zDb ){
-      sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
-    }else if( zTab ){
-      sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
-    }else{
-      sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
-    }
-    pTopNC->nErr++;
-  }
-
-  /* If a column from a table in pSrcList is referenced, then record
-  ** this fact in the pSrcList.a[].colUsed bitmask.  Column 0 causes
-  ** bit 0 to be set.  Column 1 sets bit 1.  And so forth.  If the
-  ** column number is greater than the number of bits in the bitmask
-  ** then set the high-order bit of the bitmask.
-  */
-  if( pExpr->iColumn>=0 && pMatch!=0 ){
-    int n = pExpr->iColumn;
-    testcase( n==sizeof(Bitmask)*8-1 );
-    if( n>=sizeof(Bitmask)*8 ){
-      n = sizeof(Bitmask)*8-1;
-    }
-    assert( pMatch->iCursor==pExpr->iTable );
-    pMatch->colUsed |= ((Bitmask)1)<<n;
-  }
-
-lookupname_end:
-  /* Clean up and return
-  */
-  sqlite3DbFree(db, zDb);
-  sqlite3DbFree(db, zTab);
-  sqlite3ExprDelete(db, pExpr->pLeft);
-  pExpr->pLeft = 0;
-  sqlite3ExprDelete(db, pExpr->pRight);
-  pExpr->pRight = 0;
-  pExpr->op = TK_COLUMN;
-lookupname_end_2:
-  sqlite3DbFree(db, zCol);
-  if( cnt==1 ){
-    assert( pNC!=0 );
-    sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
-    if( pMatch && !pMatch->pSelect ){
-      pExpr->pTab = pMatch->pTab;
-    }
-    /* Increment the nRef value on all name contexts from TopNC up to
-    ** the point where the name matched. */
-    for(;;){
-      assert( pTopNC!=0 );
-      pTopNC->nRef++;
-      if( pTopNC==pNC ) break;
-      pTopNC = pTopNC->pNext;
-    }
-    return 0;
-  } else {
-    return 1;
-  }
-}
-
-/*
-** This routine is designed as an xFunc for walkExprTree().
-**
-** Resolve symbolic names into TK_COLUMN operators for the current
-** node in the expression tree.  Return 0 to continue the search down
-** the tree or 2 to abort the tree walk.
-**
-** This routine also does error checking and name resolution for
-** function names.  The operator for aggregate functions is changed
-** to TK_AGG_FUNCTION.
-*/
-static int nameResolverStep(void *pArg, Expr *pExpr){
-  NameContext *pNC = (NameContext*)pArg;
-  Parse *pParse;
-
-  if( pExpr==0 ) return 1;
-  assert( pNC!=0 );
-  pParse = pNC->pParse;
-
-  if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1;
-  ExprSetProperty(pExpr, EP_Resolved);
-#ifndef NDEBUG
-  if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
-    SrcList *pSrcList = pNC->pSrcList;
-    int i;
-    for(i=0; i<pNC->pSrcList->nSrc; i++){
-      assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
-    }
-  }
-#endif
-  switch( pExpr->op ){
-    /* Double-quoted strings (ex: "abc") are used as identifiers if
-    ** possible.  Otherwise they remain as strings.  Single-quoted
-    ** 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 column.
-    */
-    case TK_ID: {
-      lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
-      return 1;
-    }
-  
-    /* 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;
-
-      /* if( pSrcList==0 ) break; */
-      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;
-      }
-      lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
-      return 1;
-    }
-
-    /* Resolve function names
-    */
-    case TK_CONST_FUNC:
-    case TK_FUNCTION: {
-      ExprList *pList = pExpr->pList;    /* The argument list */
-      int n = pList ? pList->nExpr : 0;  /* Number of arguments */
-      int no_such_func = 0;       /* True if no such function exists */
-      int wrong_num_args = 0;     /* True if wrong number of arguments */
-      int is_agg = 0;             /* True if is an aggregate function */
-      int i;
-      int auth;                   /* Authorization to use the function */
-      int nId;                    /* Number of characters in function name */
-      const char *zId;            /* The function name. */
-      FuncDef *pDef;              /* Information about the function */
-      int enc = ENC(pParse->db);  /* The database encoding */
-
-      zId = (char*)pExpr->token.z;
-      nId = pExpr->token.n;
-      pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
-      if( pDef==0 ){
-        pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
-        if( pDef==0 ){
-          no_such_func = 1;
-        }else{
-          wrong_num_args = 1;
-        }
-      }else{
-        is_agg = pDef->xFunc==0;
-      }
-#ifndef SQLITE_OMIT_AUTHORIZATION
-      if( pDef ){
-        auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
-        if( auth!=SQLITE_OK ){
-          if( auth==SQLITE_DENY ){
-            sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
-                                    pDef->zName);
-            pNC->nErr++;
-          }
-          pExpr->op = TK_NULL;
-          return 1;
-        }
-      }
-#endif
-      if( is_agg && !pNC->allowAgg ){
-        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
-        pNC->nErr++;
-        is_agg = 0;
-      }else if( no_such_func ){
-        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
-        pNC->nErr++;
-      }else if( wrong_num_args ){
-        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
-             nId, zId);
-        pNC->nErr++;
-      }
-      if( is_agg ){
-        pExpr->op = TK_AGG_FUNCTION;
-        pNC->hasAgg = 1;
-      }
-      if( is_agg ) pNC->allowAgg = 0;
-      for(i=0; pNC->nErr==0 && i<n; i++){
-        walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC);
-      }
-      if( is_agg ) pNC->allowAgg = 1;
-      /* FIX ME:  Compute pExpr->affinity based on the expected return
-      ** type of the function 
-      */
-      return is_agg;
-    }
-#ifndef SQLITE_OMIT_SUBQUERY
-    case TK_SELECT:
-    case TK_EXISTS:
-#endif
-    case TK_IN: {
-      if( pExpr->pSelect ){
-        int nRef = pNC->nRef;
-#ifndef SQLITE_OMIT_CHECK
-        if( pNC->isCheck ){
-          sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
-        }
-#endif
-        sqlite3SelectResolve(pParse, pExpr->pSelect, pNC);
-        assert( pNC->nRef>=nRef );
-        if( nRef!=pNC->nRef ){
-          ExprSetProperty(pExpr, EP_VarSelect);
-        }
-      }
-      break;
-    }
-#ifndef SQLITE_OMIT_CHECK
-    case TK_VARIABLE: {
-      if( pNC->isCheck ){
-        sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
-      }
-      break;
-    }
-#endif
-  }
-  return 0;
-}
-
-/*
-** This routine walks an expression tree and resolves references to
-** table columns.  Nodes of the form ID.ID or ID resolve into an
-** index to the table in the table list and a column offset.  The 
-** Expr.opcode for such nodes is changed to TK_COLUMN.  The Expr.iTable
-** value is changed to the index of the referenced table in pTabList
-** plus the "base" value.  The base value will ultimately become the
-** VDBE cursor number for a cursor that is pointing into the referenced
-** table.  The Expr.iColumn value is changed to the index of the column 
-** of the referenced table.  The Expr.iColumn value for the special
-** ROWID column is -1.  Any INTEGER PRIMARY KEY column is tried as an
-** alias for ROWID.
-**
-** Also resolve function names and check the functions for proper
-** usage.  Make sure all function names are recognized and all functions
-** have the correct number of arguments.  Leave an error message
-** in pParse->zErrMsg if anything is amiss.  Return the number of errors.
-**
-** If the expression contains aggregate functions then set the EP_Agg
-** property on the expression.
-*/
-SQLITE_PRIVATE int sqlite3ExprResolveNames( 
-  NameContext *pNC,       /* Namespace to resolve expressions in. */
-  Expr *pExpr             /* The expression to be analyzed. */
-){
-  int savedHasAgg;
-
-  if( pExpr==0 ) return 0;
-#if SQLITE_MAX_EXPR_DEPTH>0
-  {
-    if( checkExprHeight(pNC->pParse, pExpr->nHeight + pNC->pParse->nHeight) ){
-      return 1;
-    }
-    pNC->pParse->nHeight += pExpr->nHeight;
-  }
-#endif
-  savedHasAgg = pNC->hasAgg;
-  pNC->hasAgg = 0;
-  walkExprTree(pExpr, nameResolverStep, pNC);
-#if SQLITE_MAX_EXPR_DEPTH>0
-  pNC->pParse->nHeight -= pExpr->nHeight;
-#endif
-  if( pNC->nErr>0 ){
-    ExprSetProperty(pExpr, EP_Error);
-  }
-  if( pNC->hasAgg ){
-    ExprSetProperty(pExpr, EP_Agg);
-  }else if( savedHasAgg ){
-    pNC->hasAgg = 1;
-  }
-  return ExprHasProperty(pExpr, EP_Error);
-}
-
-/*
-** A pointer instance of this structure is used to pass information
-** through walkExprTree into codeSubqueryStep().
-*/
-typedef struct QueryCoder QueryCoder;
-struct QueryCoder {
-  Parse *pParse;       /* The parsing context */
-  NameContext *pNC;    /* Namespace of first enclosing query */
-};
-
 #ifdef SQLITE_TEST
   int sqlite3_enable_in_opt = 1;
 #else
@@ -52173,8 +53514,9 @@
   if( !sqlite3_enable_in_opt ) return 0; /* IN optimization must be enabled */
   if( p==0 ) return 0;                   /* right-hand side of IN is SELECT */
   if( p->pPrior ) return 0;              /* Not a compound SELECT */
-  if( p->isDistinct ) return 0;          /* No DISTINCT keyword */
-  if( p->isAgg ) return 0;               /* Contains no aggregate functions */
+  if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
+      return 0; /* No DISTINCT keyword and no aggregate functions */
+  }
   if( p->pGroupBy ) return 0;            /* Has no GROUP BY clause */
   if( p->pLimit ) return 0;              /* Has no LIMIT clause */
   if( p->pOffset ) return 0;
@@ -52429,7 +53771,7 @@
         sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
         dest.affinity = (int)affinity;
         assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
-        if( sqlite3Select(pParse, pExpr->pSelect, &dest, 0, 0, 0) ){
+        if( sqlite3Select(pParse, pExpr->pSelect, &dest) ){
           return;
         }
         pEList = pExpr->pSelect->pEList;
@@ -52453,7 +53795,7 @@
         if( !affinity ){
           affinity = SQLITE_AFF_NONE;
         }
-        keyInfo.aColl[0] = pExpr->pLeft->pColl;
+        keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
 
         /* Loop through each expression in <exprlist>. */
         r1 = sqlite3GetTempReg(pParse);
@@ -52510,7 +53852,7 @@
       }
       sqlite3ExprDelete(pParse->db, pSel->pLimit);
       pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one);
-      if( sqlite3Select(pParse, pSel, &dest, 0, 0, 0) ){
+      if( sqlite3Select(pParse, pSel, &dest) ){
         return;
       }
       pExpr->iColumn = dest.iParm;
@@ -52792,11 +54134,46 @@
 }
 
 /*
+** Generate code to store the value of the iAlias-th alias in register
+** target.  The first time this is called, pExpr is evaluated to compute
+** the value of the alias.  The value is stored in an auxiliary register
+** and the number of that register is returned.  On subsequent calls,
+** the register number is returned without generating any code.
+**
+** Note that in order for this to work, code must be generated in the
+** same order that it is executed.
+**
+** Aliases are numbered starting with 1.  So iAlias is in the range
+** of 1 to pParse->nAlias inclusive.  
+**
+** pParse->aAlias[iAlias-1] records the register number where the value
+** of the iAlias-th alias is stored.  If zero, that means that the
+** alias has not yet been computed.
+*/
+static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr){
+  sqlite3 *db = pParse->db;
+  int iReg;
+  if( pParse->aAlias==0 ){
+    pParse->aAlias = sqlite3DbMallocZero(db, 
+                                 sizeof(pParse->aAlias[0])*pParse->nAlias );
+    if( db->mallocFailed ) return 0;
+  }
+  assert( iAlias>0 && iAlias<=pParse->nAlias );
+  iReg = pParse->aAlias[iAlias-1];
+  if( iReg==0 ){
+    iReg = ++pParse->nMem;
+    sqlite3ExprCode(pParse, pExpr, iReg);
+    pParse->aAlias[iAlias-1] = iReg;
+  }
+  return iReg;
+}
+
+/*
 ** Generate code into the current Vdbe to evaluate the given
 ** expression.  Attempt to store the results in register "target".
 ** Return the register where results are stored.
 **
-** With this routine, there is no guaranteed that results will
+** With this routine, there is no guarantee that results will
 ** be stored in target.  The result might be stored in some other
 ** register if it is convenient to do so.  The calling function
 ** must check the return code and move the results to the desired
@@ -52809,8 +54186,10 @@
   int regFree1 = 0;         /* If non-zero free this temporary register */
   int regFree2 = 0;         /* If non-zero free this temporary register */
   int r1, r2, r3, r4;       /* Various register numbers */
+  sqlite3 *db;
 
-  assert( v!=0 || pParse->db->mallocFailed );
+  db = pParse->db;
+  assert( v!=0 || db->mallocFailed );
   assert( target>0 && target<=pParse->nMem );
   if( v==0 ) return 0;
 
@@ -52856,7 +54235,7 @@
       break;
     }
     case TK_STRING: {
-      sqlite3DequoteExpr(pParse->db, pExpr);
+      sqlite3DequoteExpr(db, pExpr);
       sqlite3VdbeAddOp4(v,OP_String8, 0, target, 0,
                         (char*)pExpr->token.z, pExpr->token.n);
       break;
@@ -52892,6 +54271,10 @@
       inReg = pExpr->iTable;
       break;
     }
+    case TK_AS: {
+      inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft);
+      break;
+    }
 #ifndef SQLITE_OMIT_CAST
     case TK_CAST: {
       /* Expressions of the form:   CAST(pLeft AS token) */
@@ -53048,7 +54431,6 @@
       const char *zId;
       int constMask = 0;
       int i;
-      sqlite3 *db = pParse->db;
       u8 enc = ENC(db);
       CollSeq *pColl = 0;
 
@@ -53056,7 +54438,7 @@
       testcase( op==TK_FUNCTION );
       zId = (char*)pExpr->token.z;
       nId = pExpr->token.n;
-      pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
+      pDef = sqlite3FindFunction(db, zId, nId, nExpr, enc, 0);
       assert( pDef!=0 );
       if( pList ){
         nExpr = pList->nExpr;
@@ -53093,7 +54475,7 @@
         }
       }
       if( pDef->needCollSeq ){
-        if( !pColl ) pColl = pParse->db->pDfltColl; 
+        if( !pColl ) pColl = db->pDfltColl; 
         sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
       }
       sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
@@ -53292,7 +54674,6 @@
         cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, &regFree1);
         testcase( regFree1==0 );
         cacheX.op = TK_REGISTER;
-        cacheX.iColumn = 0;
         opCompare.op = TK_EQ;
         opCompare.pLeft = &cacheX;
         pTest = &opCompare;
@@ -53334,7 +54715,7 @@
          assert( pExpr->iColumn==OE_Rollback ||
                  pExpr->iColumn == OE_Abort ||
                  pExpr->iColumn == OE_Fail );
-         sqlite3DequoteExpr(pParse->db, pExpr);
+         sqlite3DequoteExpr(db, pExpr);
          sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, 0,
                         (char*)pExpr->token.z, pExpr->token.n);
       } else {
@@ -53412,7 +54793,6 @@
     iMem = ++pParse->nMem;
     sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
     pExpr->iTable = iMem;
-    pExpr->iColumn = pExpr->op;
     pExpr->op = TK_REGISTER;
   }
   return inReg;
@@ -53483,8 +54863,8 @@
 ** into a register and convert the expression into a TK_REGISTER
 ** expression.
 */
-static int evalConstExpr(void *pArg, Expr *pExpr){
-  Parse *pParse = (Parse*)pArg;
+static int evalConstExpr(Walker *pWalker, Expr *pExpr){
+  Parse *pParse = pWalker->pParse;
   switch( pExpr->op ){
     case TK_REGISTER: {
       return 1;
@@ -53512,12 +54892,11 @@
     int r2;
     r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
     if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1);
-    pExpr->iColumn = pExpr->op;
     pExpr->op = TK_REGISTER;
     pExpr->iTable = r2;
-    return 1;
+    return WRC_Prune;
   }
-  return 0;
+  return WRC_Continue;
 }
 
 /*
@@ -53526,7 +54905,11 @@
 ** are TK_REGISTER opcodes that refer to the precomputed values.
 */
 SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
-   walkExprTree(pExpr, evalConstExpr, pParse);
+  Walker w;
+  w.xExprCallback = evalConstExpr;
+  w.xSelectCallback = 0;
+  w.pParse = pParse;
+  sqlite3WalkExpr(&w, pExpr);
 }
 
 
@@ -53544,14 +54927,17 @@
 ){
   struct ExprList_item *pItem;
   int i, n;
-  assert( pList!=0 || pParse->db->mallocFailed );
-  if( pList==0 ){
-    return 0;
-  }
+  assert( pList!=0 );
   assert( target>0 );
   n = pList->nExpr;
   for(pItem=pList->a, i=0; i<n; i++, pItem++){
-    sqlite3ExprCode(pParse, pItem->pExpr, target+i);
+    if( pItem->iAlias ){
+      int iReg = codeAlias(pParse, pItem->iAlias, pItem->pExpr);
+      Vdbe *v = sqlite3GetVdbe(pParse);
+      sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i);
+    }else{
+      sqlite3ExprCode(pParse, pItem->pExpr, target+i);
+    }
     if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n);
   }
   return n;
@@ -53926,15 +55312,13 @@
 }    
 
 /*
-** This is an xFunc for walkExprTree() used to implement 
-** sqlite3ExprAnalyzeAggregates().  See sqlite3ExprAnalyzeAggregates
+** This is the xExprCallback for a tree walker.  It is used to
+** implement sqlite3ExprAnalyzeAggregates().  See sqlite3ExprAnalyzeAggregates
 ** for additional information.
-**
-** This routine analyzes the aggregate function at pExpr.
 */
-static int analyzeAggregate(void *pArg, Expr *pExpr){
+static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
   int i;
-  NameContext *pNC = (NameContext *)pArg;
+  NameContext *pNC = pWalker->u.pNC;
   Parse *pParse = pNC->pParse;
   SrcList *pSrcList = pNC->pSrcList;
   AggInfo *pAggInfo = pNC->pAggInfo;
@@ -53942,6 +55326,8 @@
   switch( pExpr->op ){
     case TK_AGG_COLUMN:
     case TK_COLUMN: {
+      testcase( pExpr->op==TK_AGG_COLUMN );
+      testcase( pExpr->op==TK_COLUMN );
       /* Check to see if the column is in one of the tables in the FROM
       ** clause of the aggregate query */
       if( pSrcList ){
@@ -54003,7 +55389,7 @@
           } /* endif pExpr->iTable==pItem->iCursor */
         } /* end loop over pSrcList */
       }
-      return 1;
+      return WRC_Prune;
     }
     case TK_AGG_FUNCTION: {
       /* The pNC->nDepth==0 test causes aggregate functions in subqueries
@@ -54041,21 +55427,22 @@
         */
         pExpr->iAgg = i;
         pExpr->pAggInfo = pAggInfo;
-        return 1;
+        return WRC_Prune;
       }
     }
   }
-
-  /* Recursively walk subqueries looking for TK_COLUMN nodes that need
-  ** to be changed to TK_AGG_COLUMN.  But increment nDepth so that
-  ** TK_AGG_FUNCTION nodes in subqueries will be unchanged.
-  */
-  if( pExpr->pSelect ){
+  return WRC_Continue;
+}
+static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
+  NameContext *pNC = pWalker->u.pNC;
+  if( pNC->nDepth==0 ){
     pNC->nDepth++;
-    walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC);
+    sqlite3WalkSelect(pWalker, pSelect);
     pNC->nDepth--;
+    return WRC_Prune;
+  }else{
+    return WRC_Continue;
   }
-  return 0;
 }
 
 /*
@@ -54064,10 +55451,14 @@
 ** Make additional entries to the pParse->aAgg[] array as necessary.
 **
 ** This routine should only be called after the expression has been
-** analyzed by sqlite3ExprResolveNames().
+** analyzed by sqlite3ResolveExprNames().
 */
 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
-  walkExprTree(pExpr, analyzeAggregate, pNC);
+  Walker w;
+  w.xExprCallback = analyzeAggregate;
+  w.xSelectCallback = analyzeAggregatesInSelect;
+  w.u.pNC = pNC;
+  sqlite3WalkExpr(&w, pExpr);
 }
 
 /*
@@ -54141,7 +55532,7 @@
 ** This file contains C code routines that used to generate VDBE code
 ** that implements the ALTER TABLE command.
 **
-** $Id: alter.c,v 1.47 2008/07/28 19:34:53 drh Exp $
+** $Id: alter.c,v 1.48 2008/08/08 14:19:41 drh Exp $
 */
 
 /*
@@ -54201,7 +55592,7 @@
       do {
         zCsr += len;
         len = sqlite3GetToken(zCsr, &token);
-      } while( token==TK_SPACE || token==TK_COMMENT );
+      } while( token==TK_SPACE );
       assert( len>0 );
     } while( token!=TK_LP && token!=TK_USING );
 
@@ -55189,7 +56580,7 @@
 *************************************************************************
 ** This file contains code used to implement the ATTACH and DETACH commands.
 **
-** $Id: attach.c,v 1.77 2008/07/28 19:34:53 drh Exp $
+** $Id: attach.c,v 1.78 2008/08/20 16:35:10 drh Exp $
 */
 
 #ifndef SQLITE_OMIT_ATTACH
@@ -55216,7 +56607,7 @@
   int rc = SQLITE_OK;
   if( pExpr ){
     if( pExpr->op!=TK_ID ){
-      rc = sqlite3ExprResolveNames(pName, pExpr);
+      rc = sqlite3ResolveExprNames(pName, pExpr);
       if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
         sqlite3ErrorMsg(pName->pParse, "invalid name: \"%T\"", &pExpr->span);
         return SQLITE_ERROR;
@@ -55962,7 +57353,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.493 2008/08/04 04:39:49 danielk1977 Exp $
+** $Id: build.c,v 1.496 2008/08/20 16:35:10 drh Exp $
 */
 
 /*
@@ -57078,12 +58469,12 @@
   char *zType = 0;
   int iCol = -1, i;
   if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
-  if( pTab->hasPrimKey ){
+  if( pTab->tabFlags & TF_HasPrimaryKey ){
     sqlite3ErrorMsg(pParse, 
       "table \"%s\" has more than one primary key", pTab->zName);
     goto primary_key_exit;
   }
-  pTab->hasPrimKey = 1;
+  pTab->tabFlags |= TF_HasPrimaryKey;
   if( pList==0 ){
     iCol = pTab->nCol - 1;
     pTab->aCol[iCol].isPrimKey = 1;
@@ -57107,7 +58498,8 @@
         && sortOrder==SQLITE_SO_ASC ){
     pTab->iPKey = iCol;
     pTab->keyConf = onError;
-    pTab->autoInc = autoInc;
+    assert( autoInc==0 || autoInc==1 );
+    pTab->tabFlags |= autoInc*TF_Autoincrement;
   }else if( autoInc ){
 #ifndef SQLITE_OMIT_AUTOINCREMENT
     sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
@@ -57394,7 +58786,7 @@
     sNC.pParse = pParse;
     sNC.pSrcList = &sSrc;
     sNC.isCheck = 1;
-    if( sqlite3ExprResolveNames(&sNC, p->pCheck) ){
+    if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){
       return;
     }
   }
@@ -57467,10 +58859,10 @@
       sqlite3VdbeChangeP5(v, 1);
       pParse->nTab = 2;
       sqlite3SelectDestInit(&dest, SRT_Table, 1);
-      sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
+      sqlite3Select(pParse, pSelect, &dest);
       sqlite3VdbeAddOp1(v, OP_Close, 1);
       if( pParse->nErr==0 ){
-        pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
+        pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
         if( pSelTab==0 ) return;
         assert( p->aCol==0 );
         p->nCol = pSelTab->nCol;
@@ -57516,7 +58908,7 @@
     /* Check to see if we need to create an sqlite_sequence table for
     ** keeping track of autoincrement keys.
     */
-    if( p->autoInc ){
+    if( p->tabFlags & TF_Autoincrement ){
       Db *pDb = &db->aDb[iDb];
       if( pDb->pSchema->pSeqTab==0 ){
         sqlite3NestedParse(pParse,
@@ -57712,10 +59104,10 @@
 #ifndef SQLITE_OMIT_AUTHORIZATION
     xAuth = db->xAuth;
     db->xAuth = 0;
-    pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
+    pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
     db->xAuth = xAuth;
 #else
-    pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
+    pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
 #endif
     pParse->nTab = n;
     if( pSelTab ){
@@ -57949,7 +59341,7 @@
     }
   }
 #endif
-  if( pTab->readOnly || pTab==db->aDb[iDb].pSchema->pSeqTab ){
+  if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
     sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
     goto exit_drop_table;
   }
@@ -58004,7 +59396,7 @@
     ** at the btree level, in case the sqlite_sequence table needs to
     ** move as a result of the drop (can happen in auto-vacuum mode).
     */
-    if( pTab->autoInc ){
+    if( pTab->tabFlags & TF_Autoincrement ){
       sqlite3NestedParse(pParse,
         "DELETE FROM %s.sqlite_sequence WHERE name=%Q",
         pDb->zName, pTab->zName
@@ -58074,6 +59466,7 @@
   ExprList *pToCol,    /* Columns in the other table */
   int flags            /* Conflict resolution algorithms. */
 ){
+  sqlite3 *db = pParse->db;
 #ifndef SQLITE_OMIT_FOREIGN_KEY
   FKey *pFKey = 0;
   Table *p = pParse->pNewTable;
@@ -58081,10 +59474,8 @@
   int i;
   int nCol;
   char *z;
-  sqlite3 *db;
 
   assert( pTo!=0 );
-  db = pParse->db;
   if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end;
   if( pFromCol==0 ){
     int iCol = p->nCol-1;
@@ -58350,7 +59741,7 @@
   pDb = &db->aDb[iDb];
 
   if( pTab==0 || pParse->nErr ) goto exit_create_index;
-  if( pTab->readOnly ){
+  if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
     sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
     goto exit_create_index;
   }
@@ -58442,9 +59833,10 @@
   ** specified collation sequence names.
   */
   for(i=0; i<pList->nExpr; i++){
-    Expr *pExpr = pList->a[i].pExpr;
-    if( pExpr ){
-      nExtra += (1 + strlen(pExpr->pColl->zName));
+    Expr *pExpr;
+    CollSeq *pColl;
+    if( (pExpr = pList->a[i].pExpr)!=0 && (pColl = pExpr->pColl)!=0 ){
+      nExtra += (1 + strlen(pColl->zName));
     }
   }
 
@@ -58511,7 +59903,7 @@
     ** break backwards compatibility - it needs to be a warning.
     */
     pIndex->aiColumn[i] = j;
-    if( pListItem->pExpr ){
+    if( pListItem->pExpr && pListItem->pExpr->pColl ){
       assert( pListItem->pExpr->pColl );
       zColl = zExtra;
       sqlite3_snprintf(nExtra, zExtra, "%s", pListItem->pExpr->pColl->zName);
@@ -59450,7 +60842,7 @@
 ** This file contains functions used to access the internal hash tables
 ** of user defined functions and collation sequences.
 **
-** $Id: callback.c,v 1.26 2008/07/28 19:34:53 drh Exp $
+** $Id: callback.c,v 1.29 2008/08/21 20:21:35 drh Exp $
 */
 
 
@@ -59658,6 +61050,87 @@
   return pColl;
 }
 
+/* During the search for the best function definition, this procedure
+** is called to test how well the function passed as the first argument
+** matches the request for a function with nArg arguments in a system
+** that uses encoding enc. The value returned indicates how well the
+** request is matched. A higher value indicates a better match.
+**
+** The returned value is always between 1 and 6, as follows:
+**
+** 1: A variable arguments function that prefers UTF-8 when a UTF-16
+**    encoding is requested, or vice versa.
+** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
+**    requested, or vice versa.
+** 3: A variable arguments function using the same text encoding.
+** 4: A function with the exact number of arguments requested that
+**    prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
+** 5: A function with the exact number of arguments requested that
+**    prefers UTF-16LE when UTF-16BE is requested, or vice versa.
+** 6: An exact match.
+**
+*/
+static int matchQuality(FuncDef *p, int nArg, u8 enc){
+  int match = 0;
+  if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
+    match = 1;
+    if( p->nArg==nArg || nArg==-1 ){
+      match = 4;
+    }
+    if( enc==p->iPrefEnc ){
+      match += 2;
+    }
+    else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
+             (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
+      match += 1;
+    }
+  }
+  return match;
+}
+
+/*
+** Search a FuncDefHash for a function with the given name.  Return
+** a pointer to the matching FuncDef if found, or 0 if there is no match.
+*/
+static FuncDef *functionSearch(
+  FuncDefHash *pHash,  /* Hash table to search */
+  int h,               /* Hash of the name */
+  const char *zFunc,   /* Name of function */
+  int nFunc            /* Number of bytes in zFunc */
+){
+  FuncDef *p;
+  for(p=pHash->a[h]; p; p=p->pHash){
+    if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){
+      return p;
+    }
+  }
+  return 0;
+}
+
+/*
+** Insert a new FuncDef into a FuncDefHash hash table.
+*/
+SQLITE_PRIVATE void sqlite3FuncDefInsert(
+  FuncDefHash *pHash,  /* The hash table into which to insert */
+  FuncDef *pDef        /* The function definition to insert */
+){
+  FuncDef *pOther;
+  int nName = strlen(pDef->zName);
+  u8 c1 = (u8)pDef->zName[0];
+  int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a);
+  pOther = functionSearch(pHash, h, pDef->zName, nName);
+  if( pOther ){
+    pDef->pNext = pOther->pNext;
+    pOther->pNext = pDef;
+  }else{
+    pDef->pNext = 0;
+    pDef->pHash = pHash->a[h];
+    pHash->a[h] = pDef;
+  }
+}
+  
+  
+
 /*
 ** Locate a user function given a name, a number of arguments and a flag
 ** indicating whether the function prefers UTF-16 over UTF-8.  Return a
@@ -59687,51 +61160,39 @@
   int createFlag     /* Create new entry if true and does not otherwise exist */
 ){
   FuncDef *p;         /* Iterator variable */
-  FuncDef *pFirst;    /* First function with this name */
   FuncDef *pBest = 0; /* Best match found so far */
-  int bestmatch = 0;  
+  int bestScore = 0;  /* Score of best match */
+  int h;              /* Hash value */
 
 
   assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
   if( nArg<-1 ) nArg = -1;
+  h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
 
-  pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName);
-  for(p=pFirst; p; p=p->pNext){
-    /* During the search for the best function definition, bestmatch is set
-    ** as follows to indicate the quality of the match with the definition
-    ** pointed to by pBest:
-    **
-    ** 0: pBest is NULL. No match has been found.
-    ** 1: A variable arguments function that prefers UTF-8 when a UTF-16
-    **    encoding is requested, or vice versa.
-    ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
-    **    requested, or vice versa.
-    ** 3: A variable arguments function using the same text encoding.
-    ** 4: A function with the exact number of arguments requested that
-    **    prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
-    ** 5: A function with the exact number of arguments requested that
-    **    prefers UTF-16LE when UTF-16BE is requested, or vice versa.
-    ** 6: An exact match.
-    **
-    ** A larger value of 'matchqual' indicates a more desirable match.
-    */
-    if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
-      int match = 1;          /* Quality of this match */
-      if( p->nArg==nArg || nArg==-1 ){
-        match = 4;
-      }
-      if( enc==p->iPrefEnc ){
-        match += 2;
-      }
-      else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
-               (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
-        match += 1;
-      }
 
-      if( match>bestmatch ){
+  p = functionSearch(&db->aFunc, h, zName, nName);
+  while( p ){
+    int score = matchQuality(p, nArg, enc);
+    if( score>bestScore ){
+      pBest = p;
+      bestScore = score;
+    }
+    p = p->pNext;
+  }
+
+  /* If the createFlag parameter is false and no match was found amongst
+  ** the custom functions stored in sqlite3.aFunc, try to find a built-in
+  ** function to use.
+  */ 
+  if( !createFlag && !pBest ){
+    p = functionSearch(&sqlite3GlobalFunctions, h, zName, nName);
+    while( p ){
+      int score = matchQuality(p, nArg, enc);
+      if( score>bestScore ){
         pBest = p;
-        bestmatch = match;
+        bestScore = score;
       }
+      p = p->pNext;
     }
   }
 
@@ -59739,18 +61200,14 @@
   ** exact match for the name, number of arguments and encoding, then add a
   ** new entry to the hash table and return it.
   */
-  if( createFlag && bestmatch<6 && 
-      (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName))!=0 ){
+  if( createFlag && bestScore<6 && 
+      (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
+    pBest->zName = (char *)&pBest[1];
     pBest->nArg = nArg;
-    pBest->pNext = pFirst;
     pBest->iPrefEnc = enc;
     memcpy(pBest->zName, zName, nName);
     pBest->zName[nName] = 0;
-    if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
-      db->mallocFailed = 1;
-      sqlite3DbFree(db, pBest);
-      return 0;
-    }
+    sqlite3FuncDefInsert(&db->aFunc, pBest);
   }
 
   if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
@@ -59831,7 +61288,7 @@
 ** This file contains C code routines that are called by the parser
 ** in order to generate code for DELETE FROM statements.
 **
-** $Id: delete.c,v 1.171 2008/07/28 19:34:53 drh Exp $
+** $Id: delete.c,v 1.174 2008/08/29 02:14:03 drh Exp $
 */
 
 /*
@@ -59860,7 +61317,8 @@
 ** writable return 0;
 */
 SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
-  if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
+  if( ((pTab->tabFlags & TF_Readonly)!=0
+        && (pParse->db->flags & SQLITE_WriteSchema)==0
         && pParse->nested==0) 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
       || (pTab->pMod && pTab->pMod->pModule->xUpdate==0)
@@ -59907,7 +61365,7 @@
 */
 SQLITE_PRIVATE void sqlite3MaterializeView(
   Parse *pParse,       /* Parsing context */
-  Select *pView,       /* View definition */
+  Table *pView,        /* View definition */
   Expr *pWhere,        /* Optional WHERE clause to be added */
   int iCur             /* Cursor number for ephemerial table */
 ){
@@ -59915,16 +61373,19 @@
   Select *pDup;
   sqlite3 *db = pParse->db;
 
-  pDup = sqlite3SelectDup(db, pView);
+  pDup = sqlite3SelectDup(db, pView->pSelect);
   if( pWhere ){
     SrcList *pFrom;
+    Token viewName;
     
     pWhere = sqlite3ExprDup(db, pWhere);
-    pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, 0, pDup, 0, 0);
+    viewName.z = (u8*)pView->zName;
+    viewName.n = (unsigned int)strlen((const char*)viewName.z);
+    pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0);
     pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
   }
   sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
-  sqlite3Select(pParse, pDup, &dest, 0, 0, 0);
+  sqlite3Select(pParse, pDup, &dest);
   sqlite3SelectDelete(db, pDup);
 }
 #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
@@ -60064,7 +61525,7 @@
   ** a ephemeral table.
   */
   if( isView ){
-    sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur);
+    sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
   }
 
   /* Resolve the column names in the WHERE clause.
@@ -60072,7 +61533,7 @@
   memset(&sNC, 0, sizeof(sNC));
   sNC.pParse = pParse;
   sNC.pSrcList = pTabList;
-  if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+  if( sqlite3ResolveExprNames(&sNC, pWhere) ){
     goto delete_from_cleanup;
   }
 
@@ -60381,10 +61842,9 @@
 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
 ** All other code has file scope.
 **
-** $Id: func.c,v 1.196 2008/07/28 19:34:53 drh Exp $
+** $Id: func.c,v 1.199 2008/08/21 20:21:35 drh Exp $
 */
 
-
 /*
 ** Return the collating function associated with a function.
 */
@@ -61574,108 +63034,12 @@
 ** external linkage.
 */
 SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
-  static const struct {
-     char *zName;
-     signed char nArg;
-     u8 argType;           /* 1: 0, 2: 1, 3: 2,...  N:  N-1. */
-     u8 eTextRep;          /* 1: UTF-16.  0: UTF-8 */
-     u8 needCollSeq;
-     void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
-  } aFuncs[] = {
-    { "min",               -1, 0, SQLITE_UTF8,    1, minmaxFunc },
-    { "min",                0, 0, SQLITE_UTF8,    1, 0          },
-    { "max",               -1, 1, SQLITE_UTF8,    1, minmaxFunc },
-    { "max",                0, 1, SQLITE_UTF8,    1, 0          },
-    { "typeof",             1, 0, SQLITE_UTF8,    0, typeofFunc },
-    { "length",             1, 0, SQLITE_UTF8,    0, lengthFunc },
-    { "substr",             2, 0, SQLITE_UTF8,    0, substrFunc },
-    { "substr",             3, 0, SQLITE_UTF8,    0, substrFunc },
-    { "abs",                1, 0, SQLITE_UTF8,    0, absFunc    },
-    { "round",              1, 0, SQLITE_UTF8,    0, roundFunc  },
-    { "round",              2, 0, SQLITE_UTF8,    0, roundFunc  },
-    { "upper",              1, 0, SQLITE_UTF8,    0, upperFunc  },
-    { "lower",              1, 0, SQLITE_UTF8,    0, lowerFunc  },
-    { "coalesce",          -1, 0, SQLITE_UTF8,    0, ifnullFunc },
-    { "coalesce",           0, 0, SQLITE_UTF8,    0, 0          },
-    { "coalesce",           1, 0, SQLITE_UTF8,    0, 0          },
-    { "hex",                1, 0, SQLITE_UTF8,    0, hexFunc    },
-    { "ifnull",             2, 0, SQLITE_UTF8,    1, ifnullFunc },
-    { "random",            -1, 0, SQLITE_UTF8,    0, randomFunc },
-    { "randomblob",         1, 0, SQLITE_UTF8,    0, randomBlob },
-    { "nullif",             2, 0, SQLITE_UTF8,    1, nullifFunc },
-    { "sqlite_version",     0, 0, SQLITE_UTF8,    0, versionFunc},
-    { "quote",              1, 0, SQLITE_UTF8,    0, quoteFunc  },
-    { "last_insert_rowid",  0, 0, SQLITE_UTF8, 0, last_insert_rowid },
-    { "changes",            0, 0, SQLITE_UTF8, 0, changes           },
-    { "total_changes",      0, 0, SQLITE_UTF8, 0, total_changes     },
-    { "replace",            3, 0, SQLITE_UTF8,    0, replaceFunc       },
-    { "ltrim",              1, 1, SQLITE_UTF8,    0, trimFunc          },
-    { "ltrim",              2, 1, SQLITE_UTF8,    0, trimFunc          },
-    { "rtrim",              1, 2, SQLITE_UTF8,    0, trimFunc          },
-    { "rtrim",              2, 2, SQLITE_UTF8,    0, trimFunc          },
-    { "trim",               1, 3, SQLITE_UTF8,    0, trimFunc          },
-    { "trim",               2, 3, SQLITE_UTF8,    0, trimFunc          },
-    { "zeroblob",           1, 0, SQLITE_UTF8,    0, zeroblobFunc      },
-#ifdef SQLITE_SOUNDEX
-    { "soundex",            1, 0, SQLITE_UTF8,    0, soundexFunc},
-#endif
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-    { "load_extension",     1, 0, SQLITE_UTF8, 0, loadExt },
-    { "load_extension",     2, 0, SQLITE_UTF8, 0, loadExt },
-#endif
-  };
-  static const struct {
-    char *zName;
-    signed char nArg;
-    u8 argType;
-    u8 needCollSeq;
-    void (*xStep)(sqlite3_context*,int,sqlite3_value**);
-    void (*xFinalize)(sqlite3_context*);
-  } aAggs[] = {
-    { "min",    1, 0, 1, minmaxStep,   minMaxFinalize },
-    { "max",    1, 1, 1, minmaxStep,   minMaxFinalize },
-    { "sum",    1, 0, 0, sumStep,      sumFinalize    },
-    { "total",  1, 0, 0, sumStep,      totalFinalize    },
-    { "avg",    1, 0, 0, sumStep,      avgFinalize    },
-    { "count",  0, 0, 0, countStep,    countFinalize  },
-    { "count",  1, 0, 0, countStep,    countFinalize  },
-    { "group_concat", -1, 0, 0, groupConcatStep, groupConcatFinalize },
-  };
-  int i;
-
-  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
-    void *pArg;
-    u8 argType = aFuncs[i].argType;
-    pArg = SQLITE_INT_TO_PTR(argType);
-    sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
-        aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
-    if( aFuncs[i].needCollSeq ){
-      FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName, 
-          strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0);
-      if( pFunc && aFuncs[i].needCollSeq ){
-        pFunc->needCollSeq = 1;
-      }
-    }
-  }
 #ifndef SQLITE_OMIT_ALTERTABLE
   sqlite3AlterFunctions(db);
 #endif
 #ifndef SQLITE_OMIT_PARSER
   sqlite3AttachFunctions(db);
 #endif
-  for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
-    void *pArg = SQLITE_INT_TO_PTR(aAggs[i].argType);
-    sqlite3CreateFunc(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8, 
-        pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
-    if( aAggs[i].needCollSeq ){
-      FuncDef *pFunc = sqlite3FindFunction( db, aAggs[i].zName,
-          strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0);
-      if( pFunc && aAggs[i].needCollSeq ){
-        pFunc->needCollSeq = 1;
-      }
-    }
-  }
-  sqlite3RegisterDateTimeFunctions(db);
   if( !db->mallocFailed ){
     int rc = sqlite3_overload_function(db, "MATCH", 2);
     assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
@@ -61686,11 +63050,6 @@
 #ifdef SQLITE_SSE
   (void)sqlite3SseFunctions(db);
 #endif
-#ifdef SQLITE_CASE_SENSITIVE_LIKE
-  sqlite3RegisterLikeFunctions(db, 1);
-#else
-  sqlite3RegisterLikeFunctions(db, 0);
-#endif
 }
 
 /*
@@ -61758,6 +63117,90 @@
   return 1;
 }
 
+/*
+** The following array holds FuncDef structures for all of the functions
+** defined in this file.
+**
+** The array cannot be constant since changes are made to the
+** FuncDef.pHash elements at start-time.  The elements of this array
+** are read-only after initialization is complete.
+*/
+static FuncDef aBuiltinFunc[] = {
+  FUNCTION(ltrim,              1, 1, 0, trimFunc         ),
+  FUNCTION(ltrim,              2, 1, 0, trimFunc         ),
+  FUNCTION(rtrim,              1, 2, 0, trimFunc         ),
+  FUNCTION(rtrim,              2, 2, 0, trimFunc         ),
+  FUNCTION(trim,               1, 3, 0, trimFunc         ),
+  FUNCTION(trim,               2, 3, 0, trimFunc         ),
+  FUNCTION(min,               -1, 0, 1, minmaxFunc       ),
+  FUNCTION(min,                0, 0, 1, 0                ),
+  AGGREGATE(min,               1, 0, 1, minmaxStep,      minMaxFinalize ),
+  FUNCTION(max,               -1, 1, 1, minmaxFunc       ),
+  FUNCTION(max,                0, 1, 1, 0                ),
+  AGGREGATE(max,               1, 1, 1, minmaxStep,      minMaxFinalize ),
+  FUNCTION(typeof,             1, 0, 0, typeofFunc       ),
+  FUNCTION(length,             1, 0, 0, lengthFunc       ),
+  FUNCTION(substr,             2, 0, 0, substrFunc       ),
+  FUNCTION(substr,             3, 0, 0, substrFunc       ),
+  FUNCTION(abs,                1, 0, 0, absFunc          ),
+  FUNCTION(round,              1, 0, 0, roundFunc        ),
+  FUNCTION(round,              2, 0, 0, roundFunc        ),
+  FUNCTION(upper,              1, 0, 0, upperFunc        ),
+  FUNCTION(lower,              1, 0, 0, lowerFunc        ),
+  FUNCTION(coalesce,           1, 0, 0, 0                ),
+  FUNCTION(coalesce,          -1, 0, 0, ifnullFunc       ),
+  FUNCTION(coalesce,           0, 0, 0, 0                ),
+  FUNCTION(hex,                1, 0, 0, hexFunc          ),
+  FUNCTION(ifnull,             2, 0, 1, ifnullFunc       ),
+  FUNCTION(random,            -1, 0, 0, randomFunc       ),
+  FUNCTION(randomblob,         1, 0, 0, randomBlob       ),
+  FUNCTION(nullif,             2, 0, 1, nullifFunc       ),
+  FUNCTION(sqlite_version,     0, 0, 0, versionFunc      ),
+  FUNCTION(quote,              1, 0, 0, quoteFunc        ),
+  FUNCTION(last_insert_rowid,  0, 0, 0, last_insert_rowid),
+  FUNCTION(changes,            0, 0, 0, changes          ),
+  FUNCTION(total_changes,      0, 0, 0, total_changes    ),
+  FUNCTION(replace,            3, 0, 0, replaceFunc      ),
+  FUNCTION(zeroblob,           1, 0, 0, zeroblobFunc     ),
+#ifdef SQLITE_SOUNDEX
+  FUNCTION(soundex,            1, 0, 0, soundexFunc      ),
+#endif
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+  FUNCTION(load_extension,     1, 0, 0, loadExt          ),
+  FUNCTION(load_extension,     2, 0, 0, loadExt          ),
+#endif
+  AGGREGATE(sum,               1, 0, 0, sumStep,         sumFinalize    ),
+  AGGREGATE(total,             1, 0, 0, sumStep,         totalFinalize    ),
+  AGGREGATE(avg,               1, 0, 0, sumStep,         avgFinalize    ),
+  AGGREGATE(count,             0, 0, 0, countStep,       countFinalize  ),
+  AGGREGATE(count,             1, 0, 0, countStep,       countFinalize  ),
+  AGGREGATE(group_concat,     -1, 0, 0, groupConcatStep, groupConcatFinalize),
+
+  LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+#ifdef SQLITE_CASE_SENSITIVE_LIKE
+  LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+  LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+#else
+  LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
+  LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
+#endif
+};
+
+/*
+** All all of the FuncDef structures in the aBuiltinFunc[] array above
+** to the global function hash table.  This occurs at start-time (as
+** a consequence of calling sqlite3_initialize()).
+**
+** After this routine runs
+*/
+SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
+  int i;
+  for(i=0; i<ArraySize(aBuiltinFunc); i++){
+    sqlite3FuncDefInsert(&sqlite3GlobalFunctions, &aBuiltinFunc[i]);
+  }
+  sqlite3RegisterDateTimeFunctions();
+}
+
 /************** End of func.c ************************************************/
 /************** Begin file insert.c ******************************************/
 /*
@@ -61774,7 +63217,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.248 2008/07/28 19:34:53 drh Exp $
+** $Id: insert.c,v 1.249 2008/08/20 16:35:10 drh Exp $
 */
 
 /*
@@ -61926,7 +63369,7 @@
   Table *pTab         /* The table we are writing to */
 ){
   int memId = 0;      /* Register holding maximum rowid */
-  if( pTab->autoInc ){
+  if( pTab->tabFlags & TF_Autoincrement ){
     Vdbe *v = pParse->pVdbe;
     Db *pDb = &pParse->db->aDb[iDb];
     int iCur = pParse->nTab;
@@ -61977,7 +63420,7 @@
   Table *pTab,       /* Table we are inserting into */
   int memId          /* Memory cell holding the maximum rowid */
 ){
-  if( pTab->autoInc ){
+  if( pTab->tabFlags & TF_Autoincrement ){
     int iCur = pParse->nTab;
     Vdbe *v = pParse->pVdbe;
     Db *pDb = &pParse->db->aDb[iDb];
@@ -62293,7 +63736,7 @@
     VdbeComment((v, "Jump over SELECT coroutine"));
 
     /* Resolve the expressions in the SELECT statement and execute it. */
-    rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
+    rc = sqlite3Select(pParse, pSelect, &dest);
     if( rc || pParse->nErr || db->mallocFailed ){
       goto insert_cleanup;
     }
@@ -62363,7 +63806,7 @@
     assert( useTempTable==0 );
     nColumn = pList ? pList->nExpr : 0;
     for(i=0; i<nColumn; i++){
-      if( sqlite3ExprResolveNames(&sNC, pList->a[i].pExpr) ){
+      if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
         goto insert_cleanup;
       }
     }
@@ -63296,7 +64739,7 @@
     return 0;   /* tab1 must not have triggers */
   }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  if( pDest->isVirtual ){
+  if( pDest->tabFlags & TF_Virtual ){
     return 0;   /* tab1 must not be a virtual table */
   }
 #endif
@@ -63331,7 +64774,7 @@
   if( pSelect->pPrior ){
     return 0;   /* SELECT may not be a compound query */
   }
-  if( pSelect->isDistinct ){
+  if( pSelect->selFlags & SF_Distinct ){
     return 0;   /* SELECT may not be DISTINCT */
   }
   pEList = pSelect->pEList;
@@ -63357,7 +64800,7 @@
     return 0;   /* tab1 and tab2 may not be the same table */
   }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  if( pSrc->isVirtual ){
+  if( pSrc->tabFlags & TF_Virtual ){
     return 0;   /* tab2 must not be a virtual table */
   }
 #endif
@@ -63448,7 +64891,7 @@
     addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
   }else{
     addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
-    assert( pDest->autoInc==0 );
+    assert( (pDest->tabFlags & TF_Autoincrement)==0 );
   }
   sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
   sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
@@ -64604,7 +66047,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.183 2008/07/28 19:34:53 drh Exp $
+** $Id: pragma.c,v 1.184 2008/08/20 16:34:24 danielk1977 Exp $
 */
 
 /* Ignore this whole file if pragmas are disabled
@@ -64866,7 +66309,7 @@
     zRight = sqlite3NameFromToken(db, pValue);
   }
 
-  zDb = ((iDb>0)?pDb->zName:0);
+  zDb = ((pId2 && pId2->n>0)?pDb->zName:0);
   if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
     goto pragma_out;
   }
@@ -65978,7 +67421,7 @@
 ** interface, and routines that contribute to loading the database schema
 ** from disk.
 **
-** $Id: prepare.c,v 1.91 2008/08/02 03:50:39 drh Exp $
+** $Id: prepare.c,v 1.93 2008/08/20 16:35:10 drh Exp $
 */
 
 /*
@@ -65990,7 +67433,8 @@
   const char *zObj,    /* Object being parsed at the point of error */
   const char *zExtra   /* Error information */
 ){
-  if( !pData->db->mallocFailed ){
+  sqlite3 *db = pData->db;
+  if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){
     if( zObj==0 ) zObj = "?";
     sqlite3SetString(pData->pzErrMsg, pData->db,
        "malformed database schema (%s)", zObj);
@@ -66020,7 +67464,6 @@
   int iDb = pData->iDb;
 
   assert( sqlite3_mutex_held(db->mutex) );
-  pData->rc = SQLITE_OK;
   DbClearProperty(db, iDb, DB_Empty);
   if( db->mallocFailed ){
     corruptSchema(pData, argv[0], 0);
@@ -66060,7 +67503,6 @@
         corruptSchema(pData, argv[0], zErr);
       }
       sqlite3DbFree(db, zErr);
-      return 1;
     }
   }else if( argv[0]==0 ){
     corruptSchema(pData, 0, 0);
@@ -66156,17 +67598,18 @@
   azArg[3] = 0;
   initData.db = db;
   initData.iDb = iDb;
+  initData.rc = SQLITE_OK;
   initData.pzErrMsg = pzErrMsg;
   (void)sqlite3SafetyOff(db);
-  rc = sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
+  sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
   (void)sqlite3SafetyOn(db);
-  if( rc ){
+  if( initData.rc ){
     rc = initData.rc;
     goto error_out;
   }
   pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
   if( pTab ){
-    pTab->readOnly = 1;
+    pTab->tabFlags |= TF_Readonly;
   }
 
   /* Create a cursor to hold the database open
@@ -66301,7 +67744,7 @@
       db->xAuth = xAuth;
     }
 #endif
-    if( rc==SQLITE_ABORT ) rc = initData.rc;
+    if( rc==SQLITE_OK ) rc = initData.rc;
     (void)sqlite3SafetyOn(db);
     sqlite3DbFree(db, zSql);
 #ifndef SQLITE_OMIT_ANALYZE
@@ -66791,7 +68234,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.463 2008/08/04 03:51:24 danielk1977 Exp $
+** $Id: select.c,v 1.471 2008/08/26 12:56:14 drh Exp $
 */
 
 
@@ -66857,7 +68300,7 @@
   pNew->pGroupBy = pGroupBy;
   pNew->pHaving = pHaving;
   pNew->pOrderBy = pOrderBy;
-  pNew->isDistinct = isDistinct;
+  pNew->selFlags = isDistinct ? SF_Distinct : 0;
   pNew->op = TK_SELECT;
   assert( pOffset==0 || pLimit!=0 );
   pNew->pLimit = pLimit;
@@ -66865,8 +68308,9 @@
   pNew->addrOpenEphm[0] = -1;
   pNew->addrOpenEphm[1] = -1;
   pNew->addrOpenEphm[2] = -1;
-  if( pNew==&standin) {
+  if( db->mallocFailed ) {
     clearSelect(db, pNew);
+    if( pNew!=&standin ) sqlite3DbFree(db, pNew);
     pNew = 0;
   }
   return pNew;
@@ -67351,7 +68795,7 @@
     /* If the destination is an EXISTS(...) expression, the actual
     ** values returned by the SELECT are not required.
     */
-    sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Callback);
+    sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
   }
   nColumn = nResultCol;
 
@@ -67468,7 +68912,7 @@
     ** popping the data from the stack.
     */
     case SRT_Coroutine:
-    case SRT_Callback: {
+    case SRT_Output: {
       if( pOrderBy ){
         int r1 = sqlite3GetTempReg(pParse);
         sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
@@ -67575,10 +69019,10 @@
   int regRowid;
 
   iTab = pOrderBy->iECursor;
-  if( eDest==SRT_Callback || eDest==SRT_Coroutine ){
+  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
     pseudoTab = pParse->nTab++;
     sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn);
-    sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Callback);
+    sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Output);
   }
   addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk);
   codeOffset(v, p, cont);
@@ -67608,7 +69052,7 @@
       break;
     }
 #endif
-    case SRT_Callback:
+    case SRT_Output:
     case SRT_Coroutine: {
       int i;
       sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid);
@@ -67617,7 +69061,7 @@
         assert( regRow!=pDest->iMem+i );
         sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i);
       }
-      if( eDest==SRT_Callback ){
+      if( eDest==SRT_Output ){
         sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
         sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn);
       }else{
@@ -67642,7 +69086,7 @@
   sqlite3VdbeResolveLabel(v, cont);
   sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
   sqlite3VdbeResolveLabel(v, brk);
-  if( eDest==SRT_Callback || eDest==SRT_Coroutine ){
+  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
     sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
   }
 
@@ -67906,58 +69350,36 @@
 #endif /* SQLITE_OMIT_COMPOUND_SELECT */
 
 /*
-** Forward declaration
-*/
-static int prepSelectStmt(Parse*, Select*);
-
-/*
-** Given a SELECT statement, generate a Table structure that describes
-** the result set of that SELECT.
+** Given a an expression list (which is really the list of expressions
+** that form the result set of a SELECT statement) compute appropriate
+** column names for a table that would hold the expression list.
+**
+** All column names will be unique.
+**
+** Only the column names are computed.  Column.zType, Column.zColl,
+** and other fields of Column are zeroed.
+**
+** Return SQLITE_OK on success.  If a memory allocation error occurs,
+** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM.
 */
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
-  Table *pTab;
-  int i, j, rc;
-  ExprList *pEList;
-  Column *aCol, *pCol;
+static int selectColumnsFromExprList(
+  Parse *pParse,          /* Parsing context */
+  ExprList *pEList,       /* Expr list from which to derive column names */
+  int *pnCol,             /* Write the number of columns here */
+  Column **paCol          /* Write the new column list here */
+){
   sqlite3 *db = pParse->db;
-  int savedFlags;
+  int i, j, cnt;
+  Column *aCol, *pCol;
+  int nCol;
+  Expr *p;
+  char *zName;
+  int nName;
 
-  savedFlags = db->flags;
-  db->flags &= ~SQLITE_FullColNames;
-  db->flags |= SQLITE_ShortColNames;
-  rc = sqlite3SelectResolve(pParse, pSelect, 0);
-  if( rc==SQLITE_OK ){
-    while( pSelect->pPrior ) pSelect = pSelect->pPrior;
-    rc = prepSelectStmt(pParse, pSelect);
-    if( rc==SQLITE_OK ){
-      rc = sqlite3SelectResolve(pParse, pSelect, 0);
-    }
-  }
-  db->flags = savedFlags;
-  if( rc ){
-    return 0;
-  }
-  pTab = sqlite3DbMallocZero(db, sizeof(Table) );
-  if( pTab==0 ){
-    return 0;
-  }
-  pTab->db = db;
-  pTab->nRef = 1;
-  pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0;
-  pEList = pSelect->pEList;
-  pTab->nCol = pEList->nExpr;
-  assert( pTab->nCol>0 );
-  pTab->aCol = aCol = sqlite3DbMallocZero(db, sizeof(pTab->aCol[0])*pTab->nCol);
-  testcase( aCol==0 );
-  for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
-    Expr *p;
-    char *zType;
-    char *zName;
-    int nName;
-    CollSeq *pColl;
-    int cnt;
-    NameContext sNC;
-    
+  *pnCol = nCol = pEList->nExpr;
+  aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
+  if( aCol==0 ) return SQLITE_NOMEM;
+  for(i=0, pCol=aCol; i<nCol; i++, pCol++){
     /* Get an appropriate name for the column
     */
     p = pEList->a[i].pExpr;
@@ -67965,14 +69387,20 @@
     if( (zName = pEList->a[i].zName)!=0 ){
       /* If the column contains an "AS <name>" phrase, use <name> as the name */
       zName = sqlite3DbStrDup(db, zName);
-    }else if( p->op==TK_COLUMN && p->pTab ){
-      /* For columns use the column name name */
-      int iCol = p->iColumn;
-      if( iCol<0 ) iCol = p->pTab->iPKey;
-      zName = sqlite3MPrintf(db, "%s", p->pTab->aCol[iCol].zName);
     }else{
-      /* Use the original text of the column expression as its name */
-      zName = sqlite3MPrintf(db, "%T", &p->span);
+      Expr *pCol = p;
+      Table *pTab;
+      while( pCol->op==TK_DOT ) pCol = pCol->pRight;
+      if( pCol->op==TK_COLUMN && (pTab = pCol->pTab)!=0 ){
+        /* For columns use the column name name */
+        int iCol = pCol->iColumn;
+        if( iCol<0 ) iCol = pTab->iPKey;
+        zName = sqlite3MPrintf(db, "%s",
+                 iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
+      }else{
+        /* Use the original text of the column expression as its name */
+        zName = sqlite3MPrintf(db, "%T", &pCol->span);
+      }
     }
     if( db->mallocFailed ){
       sqlite3DbFree(db, zName);
@@ -67989,525 +69417,101 @@
         char *zNewName;
         zName[nName] = 0;
         zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
-        sqlite3DbFree(db, zName);
-        zName = zNewName;
-        j = -1;
-        if( zName==0 ) break;
-      }
-    }
-    pCol->zName = zName;
-
-    /* Get the typename, type affinity, and collating sequence for the
-    ** column.
-    */
-    memset(&sNC, 0, sizeof(sNC));
-    sNC.pSrcList = pSelect->pSrc;
-    zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
-    pCol->zType = zType;
-    pCol->affinity = sqlite3ExprAffinity(p);
-    pColl = sqlite3ExprCollSeq(pParse, p);
-    if( pColl ){
-      pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
-    }
-  }
-  pTab->iPKey = -1;
-  if( db->mallocFailed ){
-    sqlite3DeleteTable(pTab);
-    return 0;
-  }
-  return pTab;
-}
-
-/*
-** Prepare a SELECT statement for processing by doing the following
-** things:
-**
-**    (1)  Make sure VDBE cursor numbers have been assigned to every
-**         element of the FROM clause.
-**
-**    (2)  Fill in the pTabList->a[].pTab fields in the SrcList that 
-**         defines FROM clause.  When views appear in the FROM clause,
-**         fill pTabList->a[].pSelect with a copy of the SELECT statement
-**         that implements the view.  A copy is made of the view's SELECT
-**         statement so that we can freely modify or delete that statement
-**         without worrying about messing up the presistent representation
-**         of the view.
-**
-**    (3)  Add terms to the WHERE clause to accomodate the NATURAL keyword
-**         on joins and the ON and USING clause of joins.
-**
-**    (4)  Scan the list of columns in the result set (pEList) looking
-**         for instances of the "*" operator or the TABLE.* operator.
-**         If found, expand each "*" to be every column in every table
-**         and TABLE.* to be every column in TABLE.
-**
-** Return 0 on success.  If there are problems, leave an error message
-** in pParse and return non-zero.
-*/
-static int prepSelectStmt(Parse *pParse, Select *p){
-  int i, j, k, rc;
-  SrcList *pTabList;
-  ExprList *pEList;
-  struct SrcList_item *pFrom;
-  sqlite3 *db = pParse->db;
-
-  if( p==0 || p->pSrc==0 || db->mallocFailed ){
-    return 1;
-  }
-  pTabList = p->pSrc;
-  pEList = p->pEList;
-
-  /* Make sure cursor numbers have been assigned to all entries in
-  ** the FROM clause of the SELECT statement.
-  */
-  sqlite3SrcListAssignCursors(pParse, p->pSrc);
-
-  /* Look up every table named in the FROM clause of the select.  If
-  ** an entry of the FROM clause is a subquery instead of a table or view,
-  ** then create a transient table structure to describe the subquery.
-  */
-  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
-    Table *pTab;
-    if( pFrom->pTab!=0 ){
-      /* This statement has already been prepared.  There is no need
-      ** to go further. */
-      assert( i==0 );
-      return 0;
-    }
-    if( pFrom->zName==0 ){
-#ifndef SQLITE_OMIT_SUBQUERY
-      /* A sub-query in the FROM clause of a SELECT */
-      assert( pFrom->pSelect!=0 );
-      if( pFrom->zAlias==0 ){
-        pFrom->zAlias =
-          sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pFrom->pSelect);
-      }
-      assert( pFrom->pTab==0 );
-      pFrom->pTab = pTab = 
-        sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
-      if( pTab==0 ){
-        return 1;
-      }
-      /* The isEphem flag indicates that the Table structure has been
-      ** dynamically allocated and may be freed at any time.  In other words,
-      ** pTab is not pointing to a persistent table structure that defines
-      ** part of the schema. */
-      pTab->isEphem = 1;
-#endif
-    }else{
-      /* An ordinary table or view name in the FROM clause */
-      assert( pFrom->pTab==0 );
-      pFrom->pTab = pTab = 
-        sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
-      if( pTab==0 ){
-        return 1;
-      }
-      pTab->nRef++;
-#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
-      if( pTab->pSelect || IsVirtual(pTab) ){
-        /* We reach here if the named table is a really a view */
-        if( sqlite3ViewGetColumnNames(pParse, pTab) ){
-          return 1;
-        }
-        /* If pFrom->pSelect!=0 it means we are dealing with a
-        ** view within a view.  The SELECT structure has already been
-        ** copied by the outer view so we can skip the copy step here
-        ** in the inner view.
-        */
-        if( pFrom->pSelect==0 ){
-          pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
-        }
-      }
-#endif
-    }
-  }
-
-  /* Process NATURAL keywords, and ON and USING clauses of joins.
-  */
-  if( sqliteProcessJoin(pParse, p) ) return 1;
-
-  /* For every "*" that occurs in the column list, insert the names of
-  ** all columns in all tables.  And for every TABLE.* insert the names
-  ** of all columns in TABLE.  The parser inserted a special expression
-  ** with the TK_ALL operator for each "*" that it found in the column list.
-  ** The following code just has to locate the TK_ALL expressions and expand
-  ** each one to the list of all columns in all tables.
-  **
-  ** The first loop just checks to see if there are any "*" operators
-  ** that need expanding.
-  */
-  for(k=0; k<pEList->nExpr; k++){
-    Expr *pE = pEList->a[k].pExpr;
-    if( pE->op==TK_ALL ) break;
-    if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
-         && pE->pLeft && pE->pLeft->op==TK_ID ) break;
-  }
-  rc = 0;
-  if( k<pEList->nExpr ){
-    /*
-    ** If we get here it means the result set contains one or more "*"
-    ** operators that need to be expanded.  Loop through each expression
-    ** in the result set and expand them one by one.
-    */
-    struct ExprList_item *a = pEList->a;
-    ExprList *pNew = 0;
-    int flags = pParse->db->flags;
-    int longNames = (flags & SQLITE_FullColNames)!=0
-                      && (flags & SQLITE_ShortColNames)==0;
-
-    for(k=0; k<pEList->nExpr; k++){
-      Expr *pE = a[k].pExpr;
-      if( pE->op!=TK_ALL &&
-           (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
-        /* This particular expression does not need to be expanded.
-        */
-        pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
-        if( pNew ){
-          pNew->a[pNew->nExpr-1].zName = a[k].zName;
-        }else{
-          rc = 1;
-        }
-        a[k].pExpr = 0;
-        a[k].zName = 0;
-      }else{
-        /* This expression is a "*" or a "TABLE.*" and needs to be
-        ** expanded. */
-        int tableSeen = 0;      /* Set to 1 when TABLE matches */
-        char *zTName;            /* text of name of TABLE */
-        if( pE->op==TK_DOT && pE->pLeft ){
-          zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
-        }else{
-          zTName = 0;
-        }
-        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
-          Table *pTab = pFrom->pTab;
-          char *zTabName = pFrom->zAlias;
-          if( zTabName==0 || zTabName[0]==0 ){ 
-            zTabName = pTab->zName;
-          }
-          assert( zTabName );
-          if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
-            continue;
-          }
-          tableSeen = 1;
-          for(j=0; j<pTab->nCol; j++){
-            Expr *pExpr, *pRight;
-            char *zName = pTab->aCol[j].zName;
-
-            /* If a column is marked as 'hidden' (currently only possible
-            ** for virtual tables), do not include it in the expanded
-            ** result-set list.
-            */
-            if( IsHiddenColumn(&pTab->aCol[j]) ){
-              assert(IsVirtual(pTab));
-              continue;
-            }
-
-            if( i>0 ){
-              struct SrcList_item *pLeft = &pTabList->a[i-1];
-              if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
-                        columnIndex(pLeft->pTab, zName)>=0 ){
-                /* In a NATURAL join, omit the join columns from the 
-                ** table on the right */
-                continue;
-              }
-              if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
-                /* In a join with a USING clause, omit columns in the
-                ** using clause from the table on the right. */
-                continue;
-              }
-            }
-            pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
-            if( pRight==0 ) break;
-            setQuotedToken(pParse, &pRight->token, zName);
-            if( longNames || pTabList->nSrc>1 ){
-              Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
-              pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
-              if( pExpr==0 ) break;
-              setQuotedToken(pParse, &pLeft->token, zTabName);
-#if 1
-              setToken(&pExpr->span, 
-                  sqlite3MPrintf(db, "%s.%s", zTabName, zName));
-              pExpr->span.dyn = 1;
-#else
-              pExpr->span = pRight->token;
-              pExpr->span.dyn = 0;
-#endif
-              pExpr->token.z = 0;
-              pExpr->token.n = 0;
-              pExpr->token.dyn = 0;
-            }else{
-              pExpr = pRight;
-              pExpr->span = pExpr->token;
-              pExpr->span.dyn = 0;
-            }
-            if( longNames ){
-              pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
-            }else{
-              pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
-            }
-          }
-        }
-        if( !tableSeen ){
-          if( zTName ){
-            sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
-          }else{
-            sqlite3ErrorMsg(pParse, "no tables specified");
-          }
-          rc = 1;
-        }
-        sqlite3DbFree(db, zTName);
-      }
-    }
-    sqlite3ExprListDelete(db, pEList);
-    p->pEList = pNew;
-  }
-#if SQLITE_MAX_COLUMN
-  if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
-    sqlite3ErrorMsg(pParse, "too many columns in result set");
-    rc = SQLITE_ERROR;
-  }
-#endif
-  if( db->mallocFailed ){
-    rc = SQLITE_NOMEM;
-  }
-  return rc;
-}
-
-/*
-** pE is a pointer to an expression which is a single term in
-** ORDER BY or GROUP BY clause.
-**
-** At the point this routine is called, we already know that the
-** ORDER BY term is not an integer index into the result set.  That
-** casee is handled by the calling routine.
-**
-** If pE is a well-formed expression and the SELECT statement
-** is not compound, then return 0.  This indicates to the
-** caller that it should sort by the value of the ORDER BY
-** expression.
-**
-** If the SELECT is compound, then attempt to match pE against
-** result set columns in the left-most SELECT statement.  Return
-** the index i of the matching column, as an indication to the 
-** caller that it should sort by the i-th column.  If there is
-** no match, return -1 and leave an error message in pParse.
-*/
-static int matchOrderByTermToExprList(
-  Parse *pParse,     /* Parsing context for error messages */
-  Select *pSelect,   /* The SELECT statement with the ORDER BY clause */
-  Expr *pE,          /* The specific ORDER BY term */
-  int idx,           /* When ORDER BY term is this */
-  int isCompound,    /* True if this is a compound SELECT */
-  u8 *pHasAgg        /* True if expression contains aggregate functions */
-){
-  int i;             /* Loop counter */
-  ExprList *pEList;  /* The columns of the result set */
-  NameContext nc;    /* Name context for resolving pE */
-
-  assert( sqlite3ExprIsInteger(pE, &i)==0 );
-  pEList = pSelect->pEList;
-
-  /* If the term is a simple identifier that try to match that identifier
-  ** against a column name in the result set.
-  */
-  if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){
-    sqlite3 *db = pParse->db;
-    char *zCol = sqlite3NameFromToken(db, &pE->token);
-    if( zCol==0 ){
-      return -1;
-    }
-    for(i=0; i<pEList->nExpr; i++){
-      char *zAs = pEList->a[i].zName;
-      if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
-        sqlite3DbFree(db, zCol);
-        return i+1;
-      }
-    }
-    sqlite3DbFree(db, zCol);
-  }
-
-  /* Resolve all names in the ORDER BY term expression
-  */
-  memset(&nc, 0, sizeof(nc));
-  nc.pParse = pParse;
-  nc.pSrcList = pSelect->pSrc;
-  nc.pEList = pEList;
-  nc.allowAgg = 1;
-  nc.nErr = 0;
-  if( sqlite3ExprResolveNames(&nc, pE) ){
-    if( isCompound ){
-      sqlite3ErrorClear(pParse);
-      return 0;
-    }else{
-      return -1;
-    }
-  }
-  if( nc.hasAgg && pHasAgg ){
-    *pHasAgg = 1;
-  }
-
-  /* For a compound SELECT, we need to try to match the ORDER BY
-  ** expression against an expression in the result set
-  */
-  if( isCompound ){
-    for(i=0; i<pEList->nExpr; i++){
-      if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
-        return i+1;
-      }
-    }
-  }
-  return 0;
-}
-
-
-/*
-** Analyze and ORDER BY or GROUP BY clause in a simple SELECT statement.
-** Return the number of errors seen.
-**
-** Every term of the ORDER BY or GROUP BY clause needs to be an
-** expression.  If any expression is an integer constant, then
-** that expression is replaced by the corresponding 
-** expression from the result set.
-*/
-static int processOrderGroupBy(
-  Parse *pParse,        /* Parsing context.  Leave error messages here */
-  Select *pSelect,      /* The SELECT statement containing the clause */
-  ExprList *pOrderBy,   /* The ORDER BY or GROUP BY clause to be processed */
-  int isOrder,          /* 1 for ORDER BY.  0 for GROUP BY */
-  u8 *pHasAgg           /* Set to TRUE if any term contains an aggregate */
-){
-  int i;
-  sqlite3 *db = pParse->db;
-  ExprList *pEList;
-
-  if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
-#if SQLITE_MAX_COLUMN
-  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
-    const char *zType = isOrder ? "ORDER" : "GROUP";
-    sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
-    return 1;
-  }
-#endif
-  pEList = pSelect->pEList;
-  if( pEList==0 ){
-    return 0;
-  }
-  for(i=0; i<pOrderBy->nExpr; i++){
-    int iCol;
-    Expr *pE = pOrderBy->a[i].pExpr;
-    if( sqlite3ExprIsInteger(pE, &iCol) ){
-      if( iCol<=0 || iCol>pEList->nExpr ){
-        const char *zType = isOrder ? "ORDER" : "GROUP";
-        sqlite3ErrorMsg(pParse, 
-           "%r %s BY term out of range - should be "
-           "between 1 and %d", i+1, zType, pEList->nExpr);
-        return 1;
-      }
-    }else{
-      iCol = matchOrderByTermToExprList(pParse, pSelect, pE, i+1, 0, pHasAgg);
-      if( iCol<0 ){
-        return 1;
+        sqlite3DbFree(db, zName);
+        zName = zNewName;
+        j = -1;
+        if( zName==0 ) break;
       }
     }
-    if( iCol>0 ){
-      CollSeq *pColl = pE->pColl;
-      int flags = pE->flags & EP_ExpCollate;
-      sqlite3ExprDelete(db, pE);
-      pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr);
-      pOrderBy->a[i].pExpr = pE;
-      if( pE && pColl && flags ){
-        pE->pColl = pColl;
-        pE->flags |= flags;
-      }
+    pCol->zName = zName;
+  }
+  if( db->mallocFailed ){
+    int j;
+    for(j=0; j<i; j++){
+      sqlite3DbFree(db, aCol[j].zName);
     }
+    sqlite3DbFree(db, aCol);
+    *paCol = 0;
+    *pnCol = 0;
+    return SQLITE_NOMEM;
   }
-  return 0;
+  return SQLITE_OK;
 }
 
 /*
-** Analyze and ORDER BY or GROUP BY clause in a SELECT statement.  Return
-** the number of errors seen.
-**
-** If iTable>0 then make the N-th term of the ORDER BY clause refer to
-** the N-th column of table iTable.
-**
-** If iTable==0 then transform each term of the ORDER BY clause to refer
-** to a column of the result set by number.
-*/
-static int processCompoundOrderBy(
-  Parse *pParse,        /* Parsing context.  Leave error messages here */
-  Select *pSelect       /* The SELECT statement containing the ORDER BY */
+** Add type and collation information to a column list based on
+** a SELECT statement.
+** 
+** The column list presumably came from selectColumnNamesFromExprList().
+** The column list has only names, not types or collations.  This
+** routine goes through and adds the types and collations.
+**
+** This routine requires that all indentifiers in the SELECT
+** statement be resolved.
+*/
+static void selectAddColumnTypeAndCollation(
+  Parse *pParse,        /* Parsing contexts */
+  int nCol,             /* Number of columns */
+  Column *aCol,         /* List of columns */
+  Select *pSelect       /* SELECT used to determine types and collations */
 ){
+  sqlite3 *db = pParse->db;
+  NameContext sNC;
+  Column *pCol;
+  CollSeq *pColl;
   int i;
-  ExprList *pOrderBy;
-  ExprList *pEList;
-  sqlite3 *db;
-  int moreToDo = 1;
+  Expr *p;
+  struct ExprList_item *a;
 
-  pOrderBy = pSelect->pOrderBy;
-  if( pOrderBy==0 ) return 0;
-  db = pParse->db;
-#if SQLITE_MAX_COLUMN
-  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
-    sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
-    return 1;
-  }
-#endif
-  for(i=0; i<pOrderBy->nExpr; i++){
-    pOrderBy->a[i].done = 0;
-  }
-  while( pSelect->pPrior ){
-    pSelect = pSelect->pPrior;
-  }
-  while( pSelect && moreToDo ){
-    moreToDo = 0;
-    pEList = pSelect->pEList;
-    if( pEList==0 ){
-      return 1;
-    }
-    for(i=0; i<pOrderBy->nExpr; i++){
-      int iCol = -1;
-      Expr *pE, *pDup;
-      if( pOrderBy->a[i].done ) continue;
-      pE = pOrderBy->a[i].pExpr;
-      if( sqlite3ExprIsInteger(pE, &iCol) ){
-        if( iCol<0 || iCol>pEList->nExpr ){
-          sqlite3ErrorMsg(pParse, 
-             "%r ORDER BY term out of range - should be "
-             "between 1 and %d", i+1, pEList->nExpr);
-          return 1;
-        }
-      }else{
-        pDup = sqlite3ExprDup(db, pE);
-        if( !db->mallocFailed ){
-          assert(pDup);
-          iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0);
-        }
-        sqlite3ExprDelete(db, pDup);
-        if( iCol<0 ){
-          return 1;
-        }
-      }
-      if( iCol>0 ){
-        pE->op = TK_INTEGER;
-        pE->flags |= EP_IntValue;
-        pE->iTable = iCol;
-        pOrderBy->a[i].done = 1;
-      }else{
-        moreToDo = 1;
-      }
+  assert( pSelect!=0 );
+  assert( (pSelect->selFlags & SF_Resolved)!=0 );
+  assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
+  if( db->mallocFailed ) return;
+  memset(&sNC, 0, sizeof(sNC));
+  sNC.pSrcList = pSelect->pSrc;
+  a = pSelect->pEList->a;
+  for(i=0, pCol=aCol; i<nCol; i++, pCol++){
+    p = a[i].pExpr;
+    pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
+    pCol->affinity = sqlite3ExprAffinity(p);
+    pColl = sqlite3ExprCollSeq(pParse, p);
+    if( pColl ){
+      pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
     }
-    pSelect = pSelect->pNext;
   }
-  for(i=0; i<pOrderBy->nExpr; i++){
-    if( pOrderBy->a[i].done==0 ){
-      sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
-            "column in the result set", i+1);
-      return 1;
-    }
+}
+
+/*
+** Given a SELECT statement, generate a Table structure that describes
+** the result set of that SELECT.
+*/
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
+  Table *pTab;
+  sqlite3 *db = pParse->db;
+  int savedFlags;
+
+  savedFlags = db->flags;
+  db->flags &= ~SQLITE_FullColNames;
+  db->flags |= SQLITE_ShortColNames;
+  sqlite3SelectPrep(pParse, pSelect, 0);
+  if( pParse->nErr ) return 0;
+  while( pSelect->pPrior ) pSelect = pSelect->pPrior;
+  db->flags = savedFlags;
+  pTab = sqlite3DbMallocZero(db, sizeof(Table) );
+  if( pTab==0 ){
+    return 0;
   }
-  return 0;
+  pTab->db = db;
+  pTab->nRef = 1;
+  pTab->zName = 0;
+  selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
+  selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
+  pTab->iPKey = -1;
+  if( db->mallocFailed ){
+    sqlite3DeleteTable(pTab);
+    return 0;
+  }
+  return pTab;
 }
 
 /*
@@ -68674,6 +69678,7 @@
   pPrior = p->pPrior;
   assert( pPrior->pRightmost!=pPrior );
   assert( pPrior->pRightmost==p->pRightmost );
+  dest = *pDest;
   if( pPrior->pOrderBy ){
     sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
       selectOpName(p->op));
@@ -68692,7 +69697,6 @@
 
   /* Create the destination temporary table if necessary
   */
-  dest = *pDest;
   if( dest.eDest==SRT_EphemTab ){
     assert( p->pEList );
     sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr);
@@ -68724,7 +69728,7 @@
       assert( !pPrior->pLimit );
       pPrior->pLimit = p->pLimit;
       pPrior->pOffset = p->pOffset;
-      rc = sqlite3Select(pParse, pPrior, &dest, 0, 0, 0);
+      rc = sqlite3Select(pParse, pPrior, &dest);
       p->pLimit = 0;
       p->pOffset = 0;
       if( rc ){
@@ -68737,7 +69741,7 @@
         addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit);
         VdbeComment((v, "Jump ahead if LIMIT reached"));
       }
-      rc = sqlite3Select(pParse, p, &dest, 0, 0, 0);
+      rc = sqlite3Select(pParse, p, &dest);
       pDelete = p->pPrior;
       p->pPrior = pPrior;
       if( rc ){
@@ -68772,7 +69776,7 @@
         addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
         assert( p->addrOpenEphm[0] == -1 );
         p->addrOpenEphm[0] = addr;
-        p->pRightmost->usesEphm = 1;
+        p->pRightmost->selFlags |= SF_UsesEphemeral;
         assert( p->pEList );
       }
 
@@ -68780,7 +69784,7 @@
       */
       assert( !pPrior->pOrderBy );
       sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
-      rc = sqlite3Select(pParse, pPrior, &uniondest, 0, 0, 0);
+      rc = sqlite3Select(pParse, pPrior, &uniondest);
       if( rc ){
         goto multi_select_end;
       }
@@ -68794,13 +69798,12 @@
         op = SRT_Union;
       }
       p->pPrior = 0;
-      p->disallowOrderBy = 0;
       pLimit = p->pLimit;
       p->pLimit = 0;
       pOffset = p->pOffset;
       p->pOffset = 0;
       uniondest.eDest = op;
-      rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0);
+      rc = sqlite3Select(pParse, p, &uniondest);
       /* Query flattening in sqlite3Select() might refill p->pOrderBy.
       ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
       sqlite3ExprListDelete(db, p->pOrderBy);
@@ -68823,7 +69826,7 @@
       if( dest.eDest!=priorOp || unionTab!=dest.iParm ){
         int iCont, iBreak, iStart;
         assert( p->pEList );
-        if( dest.eDest==SRT_Callback ){
+        if( dest.eDest==SRT_Output ){
           Select *pFirst = p;
           while( pFirst->pPrior ) pFirst = pFirst->pPrior;
           generateColumnNames(pParse, 0, pFirst->pEList);
@@ -68861,13 +69864,13 @@
       addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
       assert( p->addrOpenEphm[0] == -1 );
       p->addrOpenEphm[0] = addr;
-      p->pRightmost->usesEphm = 1;
+      p->pRightmost->selFlags |= SF_UsesEphemeral;
       assert( p->pEList );
 
       /* Code the SELECTs to our left into temporary table "tab1".
       */
       sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
-      rc = sqlite3Select(pParse, pPrior, &intersectdest, 0, 0, 0);
+      rc = sqlite3Select(pParse, pPrior, &intersectdest);
       if( rc ){
         goto multi_select_end;
       }
@@ -68883,7 +69886,7 @@
       pOffset = p->pOffset;
       p->pOffset = 0;
       intersectdest.iParm = tab2;
-      rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0);
+      rc = sqlite3Select(pParse, p, &intersectdest);
       pDelete = p->pPrior;
       p->pPrior = pPrior;
       sqlite3ExprDelete(db, p->pLimit);
@@ -68897,7 +69900,7 @@
       ** tables.
       */
       assert( p->pEList );
-      if( dest.eDest==SRT_Callback ){
+      if( dest.eDest==SRT_Output ){
         Select *pFirst = p;
         while( pFirst->pPrior ) pFirst = pFirst->pPrior;
         generateColumnNames(pParse, 0, pFirst->pEList);
@@ -68930,7 +69933,7 @@
   ** SELECT might also skip this part if it has no ORDER BY clause and
   ** no temp tables are required.
   */
-  if( p->usesEphm ){
+  if( p->selFlags & SF_UsesEphemeral ){
     int i;                        /* Loop counter */
     KeyInfo *pKeyInfo;            /* Collating sequence for the result set */
     Select *pLoop;                /* For looping through SELECT statements */
@@ -69093,9 +70096,8 @@
     }
 #endif /* #ifndef SQLITE_OMIT_SUBQUERY */
 
-    /* Send the data to the callback function or to a subroutine.  In the
-    ** case of a subroutine, the subroutine itself is responsible for
-    ** popping the data from the stack.
+    /* The results are stored in a sequence of registers
+    ** starting at pDest->iMem.  Then the co-routine yields.
     */
     case SRT_Coroutine: {
       if( pDest->iMem==0 ){
@@ -69107,7 +70109,11 @@
       break;
     }
 
-    case SRT_Callback: {
+    /* Results are stored in a sequence of registers.  Then the
+    ** OP_ResultRow opcode is used to cause sqlite3_step() to return
+    ** the next row of result.
+    */
+    case SRT_Output: {
       sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem);
       sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem);
       break;
@@ -69266,7 +70272,6 @@
   ExprList *pOrderBy;   /* The ORDER BY clause */
   int nOrderBy;         /* Number of terms in the ORDER BY clause */
   int *aPermute;        /* Mapping from ORDER BY terms to result set columns */
-  u8 NotUsed;           /* Dummy variables */
 
   assert( p->pOrderBy!=0 );
   db = pParse->db;
@@ -69283,9 +70288,6 @@
   assert( pPrior->pOrderBy==0 );
   pOrderBy = p->pOrderBy;
   assert( pOrderBy );
-  if( processCompoundOrderBy(pParse, p) ){
-    return SQLITE_ERROR;
-  }
   nOrderBy = pOrderBy->nExpr;
 
   /* For operators other than UNION ALL we have to make sure that
@@ -69294,11 +70296,10 @@
   */
   if( op!=TK_ALL ){
     for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
-      for(j=0; j<nOrderBy; j++){
-        Expr *pTerm = pOrderBy->a[j].pExpr;
-        assert( pTerm->op==TK_INTEGER );
-        assert( (pTerm->flags & EP_IntValue)!=0 );
-        if( pTerm->iTable==i ) break;
+      struct ExprList_item *pItem;
+      for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
+        assert( pItem->iCol>0 );
+        if( pItem->iCol==i ) break;
       }
       if( j==nOrderBy ){
         Expr *pNew = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0);
@@ -69306,7 +70307,7 @@
         pNew->flags |= EP_IntValue;
         pNew->iTable = i;
         pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0);
-        nOrderBy++;
+        pOrderBy->a[nOrderBy++].iCol = i;
       }
     }
   }
@@ -69320,12 +70321,10 @@
   */
   aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy);
   if( aPermute ){
-    for(i=0; i<nOrderBy; i++){
-      Expr *pTerm = pOrderBy->a[i].pExpr;
-      assert( pTerm->op==TK_INTEGER );
-      assert( (pTerm->flags & EP_IntValue)!=0 );
-      aPermute[i] = pTerm->iTable-1;
-      assert( aPermute[i]>=0 && aPermute[i]<p->pEList->nExpr );
+    struct ExprList_item *pItem;
+    for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
+      assert( pItem->iCol>0  && pItem->iCol<=p->pEList->nExpr );
+      aPermute[i] = pItem->iCol - 1;
     }
     pKeyMerge =
       sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
@@ -69384,9 +70383,9 @@
   */
   p->pPrior = 0;
   pPrior->pRightmost = 0;
-  processOrderGroupBy(pParse, p, p->pOrderBy, 1, &NotUsed);
+  sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
   if( pPrior->pPrior==0 ){
-    processOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, 1, &NotUsed);
+    sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
   }
 
   /* Compute the limit registers */
@@ -69426,7 +70425,7 @@
   */
   VdbeNoopComment((v, "Begin coroutine for left SELECT"));
   pPrior->iLimit = regLimitA;
-  sqlite3Select(pParse, pPrior, &destA, 0, 0, 0);
+  sqlite3Select(pParse, pPrior, &destA);
   sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA);
   sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
   VdbeNoopComment((v, "End coroutine for left SELECT"));
@@ -69440,7 +70439,7 @@
   savedOffset = p->iOffset;
   p->iLimit = regLimitB;
   p->iOffset = 0;  
-  sqlite3Select(pParse, p, &destB, 0, 0, 0);
+  sqlite3Select(pParse, p, &destB);
   p->iLimit = savedLimit;
   p->iOffset = savedOffset;
   sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB);
@@ -69555,7 +70554,7 @@
 
   /* Set the number of output columns
   */
-  if( pDest->eDest==SRT_Callback ){
+  if( pDest->eDest==SRT_Output ){
     Select *pFirst = pPrior;
     while( pFirst->pPrior ) pFirst = pFirst->pPrior;
     generateColumnNames(pParse, 0, pFirst->pEList);
@@ -69693,8 +70692,8 @@
 **
 **   (2)  The subquery is not an aggregate or the outer query is not a join.
 **
-**   (3)  The subquery is not the right operand of a left outer join, or
-**        the subquery is not itself a join.  (Ticket #306)
+**   (3)  The subquery is not the right operand of a left outer join
+**        (Originally ticket #306.  Strenghtened by ticket #3300)
 **
 **   (4)  The subquery is not DISTINCT or the outer query is not a join.
 **
@@ -69716,8 +70715,8 @@
 **
 **  (11)  The subquery and the outer query do not both have ORDER BY clauses.
 **
-**  (12)  The subquery is not the right term of a LEFT OUTER JOIN or the
-**        subquery has no WHERE clause.  (added by ticket #350)
+**  (12)  Not implemented.  Subsumed into restriction (3).  Was previously
+**        a separate restriction deriving from ticket #350.
 **
 **  (13)  The subquery and outer query do not both use LIMIT
 **
@@ -69747,6 +70746,9 @@
 **        ORDER by clause of the parent must be simple references to 
 **        columns of the sub-query.
 **
+**  (19)  The subquery does not use LIMIT or the outer query does not
+**        have a WHERE clause.
+**
 ** In this routine, the "p" parameter is a pointer to the outer query.
 ** The subquery is p->pSrc->a[iFrom].  isAgg is true if the outer query
 ** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
@@ -69801,17 +70803,21 @@
     return 0;                                            /* Restriction (15) */
   }
   if( pSubSrc->nSrc==0 ) return 0;                       /* Restriction (7)  */
-  if( (pSub->isDistinct || pSub->pLimit) 
+  if( ((pSub->selFlags & SF_Distinct)!=0 || pSub->pLimit) 
          && (pSrc->nSrc>1 || isAgg) ){          /* Restrictions (4)(5)(8)(9) */
      return 0;       
   }
-  if( p->isDistinct && subqueryIsAgg ) return 0;         /* Restriction (6)  */
-  if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){
+  if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
+     return 0;         /* Restriction (6)  */
+  }
+  if( p->pOrderBy && pSub->pOrderBy ){
      return 0;                                           /* Restriction (11) */
   }
   if( isAgg && pSub->pOrderBy ) return 0;                /* Restriction (16) */
+  if( pSub->pLimit && p->pWhere ) return 0;              /* Restriction (19) */
 
-  /* Restriction 3:  If the subquery is a join, make sure the subquery is 
+  /* OBSOLETE COMMENT 1:
+  ** Restriction 3:  If the subquery is a join, make sure the subquery is 
   ** not used as the right operand of an outer join.  Examples of why this
   ** is not allowed:
   **
@@ -69822,12 +70828,9 @@
   **         (t1 LEFT OUTER JOIN t2) JOIN t3
   **
   ** which is not at all the same thing.
-  */
-  if( pSubSrc->nSrc>1 && (pSubitem->jointype & JT_OUTER)!=0 ){
-    return 0;
-  }
-
-  /* Restriction 12:  If the subquery is the right operand of a left outer
+  **
+  ** OBSOLETE COMMENT 2:
+  ** Restriction 12:  If the subquery is the right operand of a left outer
   ** join, make sure the subquery has no WHERE clause.
   ** An examples of why this is not allowed:
   **
@@ -69839,8 +70842,13 @@
   **
   ** But the t2.x>0 test will always fail on a NULL row of t2, which
   ** effectively converts the OUTER JOIN into an INNER JOIN.
+  **
+  ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE:
+  ** Ticket #3300 shows that flattening the right term of a LEFT JOIN
+  ** is fraught with danger.  Best to avoid the whole thing.  If the
+  ** subquery is the right term of a LEFT JOIN, then do not flatten.
   */
-  if( (pSubitem->jointype & JT_OUTER)!=0 && pSub->pWhere!=0 ){
+  if( (pSubitem->jointype & JT_OUTER)!=0 ){
     return 0;
   }
 
@@ -69850,11 +70858,11 @@
   ** queries.
   */
   if( pSub->pPrior ){
-    if( p->pPrior || isAgg || p->isDistinct || pSrc->nSrc!=1 ){
+    if( p->pPrior || isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
       return 0;
     }
     for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
-      if( pSub1->isAgg || pSub1->isDistinct 
+      if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
        || (pSub1->pPrior && pSub1->op!=TK_ALL) 
        || !pSub1->pSrc || pSub1->pSrc->nSrc!=1
       ){
@@ -69866,20 +70874,21 @@
     if( p->pOrderBy ){
       int ii;
       for(ii=0; ii<p->pOrderBy->nExpr; ii++){
-        Expr *pExpr = p->pOrderBy->a[ii].pExpr;
-        if( pExpr->op!=TK_COLUMN || pExpr->iTable!=iParent ){ 
-          return 0;
-        }
+        if( p->pOrderBy->a[ii].iCol==0 ) return 0;
       }
     }
   }
 
+  /***** If we reach this point, flattening is permitted. *****/
+
+  /* Authorize the subquery */
   pParse->zAuthContext = pSubitem->zName;
   sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
   pParse->zAuthContext = zSavedAuthContext;
 
-  /* If the sub-query is a compound SELECT statement, then it must be
-  ** a UNION ALL and the parent query must be of the form:
+  /* If the sub-query is a compound SELECT statement, then (by restrictions
+  ** 17 and 18 above) it must be a UNION ALL and the parent query must 
+  ** be of the form:
   **
   **     SELECT <expr-list> FROM (<sub-query>) <where-clause> 
   **
@@ -69911,8 +70920,8 @@
     pNew->pRightmost = 0;
   }
 
-  /* If we reach this point, it means flattening is permitted for the
-  ** iFrom-th entry of the FROM clause in the outer query.
+  /* Begin flattening the iFrom-th entry of the FROM clause 
+  ** in the outer query.
   */
   pSub = pSub1 = pSubitem->pSelect;
   for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
@@ -70016,7 +71025,7 @@
     /* The flattened query is distinct if either the inner or the
     ** outer query is distinct. 
     */
-    pParent->isDistinct = pParent->isDistinct || pSub->isDistinct;
+    pParent->selFlags |= pSub->selFlags & SF_Distinct;
   
     /*
     ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
@@ -70069,133 +71078,369 @@
 }
 
 /*
-** This routine resolves any names used in the result set of the
-** supplied SELECT statement. If the SELECT statement being resolved
-** is a sub-select, then pOuterNC is a pointer to the NameContext 
-** of the parent SELECT.
+** This routine is a Walker callback for "expanding" a SELECT statement.
+** "Expanding" means to do the following:
+**
+**    (1)  Make sure VDBE cursor numbers have been assigned to every
+**         element of the FROM clause.
+**
+**    (2)  Fill in the pTabList->a[].pTab fields in the SrcList that 
+**         defines FROM clause.  When views appear in the FROM clause,
+**         fill pTabList->a[].pSelect with a copy of the SELECT statement
+**         that implements the view.  A copy is made of the view's SELECT
+**         statement so that we can freely modify or delete that statement
+**         without worrying about messing up the presistent representation
+**         of the view.
+**
+**    (3)  Add terms to the WHERE clause to accomodate the NATURAL keyword
+**         on joins and the ON and USING clause of joins.
+**
+**    (4)  Scan the list of columns in the result set (pEList) looking
+**         for instances of the "*" operator or the TABLE.* operator.
+**         If found, expand each "*" to be every column in every table
+**         and TABLE.* to be every column in TABLE.
+**
 */
-SQLITE_PRIVATE int sqlite3SelectResolve(
-  Parse *pParse,         /* The parser context */
-  Select *p,             /* The SELECT statement being coded. */
-  NameContext *pOuterNC  /* The outer name context. May be NULL. */
-){
-  ExprList *pEList;          /* Result set. */
-  int i;                     /* For-loop variable used in multiple places */
-  NameContext sNC;           /* Local name-context */
-  ExprList *pGroupBy;        /* The group by clause */
-
-  /* If this routine has run before, return immediately. */
-  if( p->isResolved ){
-    assert( !pOuterNC );
-    return SQLITE_OK;
-  }
-  p->isResolved = 1;
+static int selectExpander(Walker *pWalker, Select *p){
+  Parse *pParse = pWalker->pParse;
+  int i, j, k;
+  SrcList *pTabList;
+  ExprList *pEList;
+  struct SrcList_item *pFrom;
+  sqlite3 *db = pParse->db;
 
-  /* If there have already been errors, do nothing. */
-  if( pParse->nErr>0 ){
-    return SQLITE_ERROR;
+  if( db->mallocFailed  ){
+    return WRC_Abort;
   }
-
-  /* Prepare the select statement. This call will allocate all cursors
-  ** required to handle the tables and subqueries in the FROM clause.
-  */
-  if( prepSelectStmt(pParse, p) ){
-    return SQLITE_ERROR;
+  if( p->pSrc==0 || (p->selFlags & SF_Expanded)!=0 ){
+    return WRC_Prune;
   }
+  p->selFlags |= SF_Expanded;
+  pTabList = p->pSrc;
+  pEList = p->pEList;
 
-  /* Resolve the expressions in the LIMIT and OFFSET clauses. These
-  ** are not allowed to refer to any names, so pass an empty NameContext.
+  /* Make sure cursor numbers have been assigned to all entries in
+  ** the FROM clause of the SELECT statement.
   */
-  memset(&sNC, 0, sizeof(sNC));
-  sNC.pParse = pParse;
-  if( sqlite3ExprResolveNames(&sNC, p->pLimit) ||
-      sqlite3ExprResolveNames(&sNC, p->pOffset) ){
-    return SQLITE_ERROR;
-  }
+  sqlite3SrcListAssignCursors(pParse, pTabList);
 
-  /* Set up the local name-context to pass to ExprResolveNames() to
-  ** resolve the expression-list.
+  /* Look up every table named in the FROM clause of the select.  If
+  ** an entry of the FROM clause is a subquery instead of a table or view,
+  ** then create a transient table structure to describe the subquery.
   */
-  sNC.allowAgg = 1;
-  sNC.pSrcList = p->pSrc;
-  sNC.pNext = pOuterNC;
-
-  /* Resolve names in the result set. */
-  pEList = p->pEList;
-  if( !pEList ) return SQLITE_ERROR;
-  for(i=0; i<pEList->nExpr; i++){
-    Expr *pX = pEList->a[i].pExpr;
-    if( sqlite3ExprResolveNames(&sNC, pX) ){
-      return SQLITE_ERROR;
+  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+    Table *pTab;
+    if( pFrom->pTab!=0 ){
+      /* This statement has already been prepared.  There is no need
+      ** to go further. */
+      assert( i==0 );
+      return WRC_Prune;
     }
-  }
+    if( pFrom->zName==0 ){
+#ifndef SQLITE_OMIT_SUBQUERY
+      Select *pSel = pFrom->pSelect;
+      /* A sub-query in the FROM clause of a SELECT */
+      assert( pSel!=0 );
+      assert( pFrom->pTab==0 );
+      sqlite3WalkSelect(pWalker, pSel);
+      pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
+      if( pTab==0 ) return WRC_Abort;
+      pTab->db = db;
+      pTab->nRef = 1;
+      pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
+      while( pSel->pPrior ){ pSel = pSel->pPrior; }
+      selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
+      pTab->iPKey = -1;
+      pTab->tabFlags |= TF_Ephemeral;
+#endif
+    }else{
+      /* An ordinary table or view name in the FROM clause */
+      assert( pFrom->pTab==0 );
+      pFrom->pTab = pTab = 
+        sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
+      if( pTab==0 ) return WRC_Abort;
+      pTab->nRef++;
+#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
+      if( pTab->pSelect || IsVirtual(pTab) ){
+        /* We reach here if the named table is a really a view */
+        if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
 
-  /* If there are no aggregate functions in the result-set, and no GROUP BY 
-  ** expression, do not allow aggregates in any of the other expressions.
-  */
-  assert( !p->isAgg );
-  pGroupBy = p->pGroupBy;
-  if( pGroupBy || sNC.hasAgg ){
-    p->isAgg = 1;
-  }else{
-    sNC.allowAgg = 0;
+        /* If pFrom->pSelect!=0 it means we are dealing with a
+        ** view within a view.  The SELECT structure has already been
+        ** copied by the outer view so we can skip the copy step here
+        ** in the inner view.
+        */
+        if( pFrom->pSelect==0 ){
+          pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
+          sqlite3WalkSelect(pWalker, pFrom->pSelect);
+        }
+      }
+#endif
+    }
   }
 
-  /* If a HAVING clause is present, then there must be a GROUP BY clause.
+  /* Process NATURAL keywords, and ON and USING clauses of joins.
   */
-  if( p->pHaving && !pGroupBy ){
-    sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
-    return SQLITE_ERROR;
+  if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
+    return WRC_Abort;
   }
 
-  /* Add the expression list to the name-context before parsing the
-  ** other expressions in the SELECT statement. This is so that
-  ** expressions in the WHERE clause (etc.) can refer to expressions by
-  ** aliases in the result set.
+  /* For every "*" that occurs in the column list, insert the names of
+  ** all columns in all tables.  And for every TABLE.* insert the names
+  ** of all columns in TABLE.  The parser inserted a special expression
+  ** with the TK_ALL operator for each "*" that it found in the column list.
+  ** The following code just has to locate the TK_ALL expressions and expand
+  ** each one to the list of all columns in all tables.
   **
-  ** Minor point: If this is the case, then the expression will be
-  ** re-evaluated for each reference to it.
+  ** The first loop just checks to see if there are any "*" operators
+  ** that need expanding.
   */
-  sNC.pEList = p->pEList;
-  if( sqlite3ExprResolveNames(&sNC, p->pWhere) ||
-     sqlite3ExprResolveNames(&sNC, p->pHaving) ){
-    return SQLITE_ERROR;
+  for(k=0; k<pEList->nExpr; k++){
+    Expr *pE = pEList->a[k].pExpr;
+    if( pE->op==TK_ALL ) break;
+    if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
+         && pE->pLeft && pE->pLeft->op==TK_ID ) break;
   }
-  if( p->pPrior==0 ){
-    if( processOrderGroupBy(pParse, p, p->pOrderBy, 1, &sNC.hasAgg) ){
-      return SQLITE_ERROR;
+  if( k<pEList->nExpr ){
+    /*
+    ** If we get here it means the result set contains one or more "*"
+    ** operators that need to be expanded.  Loop through each expression
+    ** in the result set and expand them one by one.
+    */
+    struct ExprList_item *a = pEList->a;
+    ExprList *pNew = 0;
+    int flags = pParse->db->flags;
+    int longNames = (flags & SQLITE_FullColNames)!=0
+                      && (flags & SQLITE_ShortColNames)==0;
+
+    for(k=0; k<pEList->nExpr; k++){
+      Expr *pE = a[k].pExpr;
+      if( pE->op!=TK_ALL &&
+           (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
+        /* This particular expression does not need to be expanded.
+        */
+        pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
+        if( pNew ){
+          pNew->a[pNew->nExpr-1].zName = a[k].zName;
+        }
+        a[k].pExpr = 0;
+        a[k].zName = 0;
+      }else{
+        /* This expression is a "*" or a "TABLE.*" and needs to be
+        ** expanded. */
+        int tableSeen = 0;      /* Set to 1 when TABLE matches */
+        char *zTName;            /* text of name of TABLE */
+        if( pE->op==TK_DOT && pE->pLeft ){
+          zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
+        }else{
+          zTName = 0;
+        }
+        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+          Table *pTab = pFrom->pTab;
+          char *zTabName = pFrom->zAlias;
+          if( zTabName==0 || zTabName[0]==0 ){ 
+            zTabName = pTab->zName;
+          }
+          if( db->mallocFailed ) break;
+          if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
+            continue;
+          }
+          tableSeen = 1;
+          for(j=0; j<pTab->nCol; j++){
+            Expr *pExpr, *pRight;
+            char *zName = pTab->aCol[j].zName;
+
+            /* If a column is marked as 'hidden' (currently only possible
+            ** for virtual tables), do not include it in the expanded
+            ** result-set list.
+            */
+            if( IsHiddenColumn(&pTab->aCol[j]) ){
+              assert(IsVirtual(pTab));
+              continue;
+            }
+
+            if( i>0 ){
+              struct SrcList_item *pLeft = &pTabList->a[i-1];
+              if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
+                        columnIndex(pLeft->pTab, zName)>=0 ){
+                /* In a NATURAL join, omit the join columns from the 
+                ** table on the right */
+                continue;
+              }
+              if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
+                /* In a join with a USING clause, omit columns in the
+                ** using clause from the table on the right. */
+                continue;
+              }
+            }
+            pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
+            if( pRight==0 ) break;
+            setQuotedToken(pParse, &pRight->token, zName);
+            if( longNames || pTabList->nSrc>1 ){
+              Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
+              pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+              if( pExpr==0 ) break;
+              setQuotedToken(pParse, &pLeft->token, zTabName);
+              setToken(&pExpr->span, 
+                  sqlite3MPrintf(db, "%s.%s", zTabName, zName));
+              pExpr->span.dyn = 1;
+              pExpr->token.z = 0;
+              pExpr->token.n = 0;
+              pExpr->token.dyn = 0;
+            }else{
+              pExpr = pRight;
+              pExpr->span = pExpr->token;
+              pExpr->span.dyn = 0;
+            }
+            if( longNames ){
+              pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
+            }else{
+              pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
+            }
+          }
+        }
+        if( !tableSeen ){
+          if( zTName ){
+            sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
+          }else{
+            sqlite3ErrorMsg(pParse, "no tables specified");
+          }
+        }
+        sqlite3DbFree(db, zTName);
+      }
     }
+    sqlite3ExprListDelete(db, pEList);
+    p->pEList = pNew;
   }
-  if( processOrderGroupBy(pParse, p, pGroupBy, 0, &sNC.hasAgg) ){
-    return SQLITE_ERROR;
+#if SQLITE_MAX_COLUMN
+  if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+    sqlite3ErrorMsg(pParse, "too many columns in result set");
   }
+#endif
+  return WRC_Continue;
+}
 
-  if( pParse->db->mallocFailed ){
-    return SQLITE_NOMEM;
-  }
+/*
+** No-op routine for the parse-tree walker.
+**
+** When this routine is the Walker.xExprCallback then expression trees
+** are walked without any actions being taken at each node.  Presumably,
+** when this routine is used for Walker.xExprCallback then 
+** Walker.xSelectCallback is set to do something useful for every 
+** subquery in the parser tree.
+*/
+static int exprWalkNoop(Walker *pWalker, Expr *pExpr){
+  return WRC_Continue;
+}
 
-  /* Make sure the GROUP BY clause does not contain aggregate functions.
-  */
-  if( pGroupBy ){
-    struct ExprList_item *pItem;
-  
-    for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
-      if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
-        sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
-            "the GROUP BY clause");
-        return SQLITE_ERROR;
+/*
+** This routine "expands" a SELECT statement and all of its subqueries.
+** For additional information on what it means to "expand" a SELECT
+** statement, see the comment on the selectExpand worker callback above.
+**
+** Expanding a SELECT statement is the first step in processing a
+** SELECT statement.  The SELECT statement must be expanded before
+** name resolution is performed.
+**
+** If anything goes wrong, an error message is written into pParse.
+** The calling function can detect the problem by looking at pParse->nErr
+** and/or pParse->db->mallocFailed.
+*/
+static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
+  Walker w;
+  w.xSelectCallback = selectExpander;
+  w.xExprCallback = exprWalkNoop;
+  w.pParse = pParse;
+  sqlite3WalkSelect(&w, pSelect);
+}
+
+
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo()
+** interface.
+**
+** For each FROM-clause subquery, add Column.zType and Column.zColl
+** information to the Table structure that represents the result set
+** of that subquery.
+**
+** The Table structure that represents the result set was constructed
+** by selectExpander() but the type and collation information was omitted
+** at that point because identifiers had not yet been resolved.  This
+** routine is called after identifier resolution.
+*/
+static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
+  Parse *pParse;
+  int i;
+  SrcList *pTabList;
+  struct SrcList_item *pFrom;
+
+  assert( p->selFlags & SF_Resolved );
+  if( (p->selFlags & SF_HasTypeInfo)==0 ){
+    p->selFlags |= SF_HasTypeInfo;
+    pParse = pWalker->pParse;
+    pTabList = p->pSrc;
+    for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+      Table *pTab = pFrom->pTab;
+      if( pTab && (pTab->tabFlags & TF_Ephemeral)!=0 ){
+        /* A sub-query in the FROM clause of a SELECT */
+        Select *pSel = pFrom->pSelect;
+        assert( pSel );
+        while( pSel->pPrior ) pSel = pSel->pPrior;
+        selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
       }
     }
   }
+  return WRC_Continue;
+}
+#endif
 
-  /* If this is one SELECT of a compound, be sure to resolve names
-  ** in the other SELECTs.
-  */
-  if( p->pPrior ){
-    return sqlite3SelectResolve(pParse, p->pPrior, pOuterNC);
-  }else{
-    return SQLITE_OK;
-  }
+
+/*
+** This routine adds datatype and collating sequence information to
+** the Table structures of all FROM-clause subqueries in a
+** SELECT statement.
+**
+** Use this routine after name resolution.
+*/
+static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
+#ifndef SQLITE_OMIT_SUBQUERY
+  Walker w;
+  w.xSelectCallback = selectAddSubqueryTypeInfo;
+  w.xExprCallback = exprWalkNoop;
+  w.pParse = pParse;
+  sqlite3WalkSelect(&w, pSelect);
+#endif
+}
+
+
+/*
+** This routine sets of a SELECT statement for processing.  The
+** following is accomplished:
+**
+**     *  VDBE Cursor numbers are assigned to all FROM-clause terms.
+**     *  Ephemeral Table objects are created for all FROM-clause subqueries.
+**     *  ON and USING clauses are shifted into WHERE statements
+**     *  Wildcards "*" and "TABLE.*" in result sets are expanded.
+**     *  Identifiers in expression are matched to tables.
+**
+** This routine acts recursively on all subqueries within the SELECT.
+*/
+SQLITE_PRIVATE void sqlite3SelectPrep(
+  Parse *pParse,         /* The parser context */
+  Select *p,             /* The SELECT statement being coded. */
+  NameContext *pOuterNC  /* Name context for container */
+){
+  sqlite3 *db;
+  if( p==0 ) return;
+  db = pParse->db;
+  if( p->selFlags & SF_HasTypeInfo ) return;
+  if( pParse->nErr || db->mallocFailed ) return;
+  sqlite3SelectExpand(pParse, p);
+  if( pParse->nErr || db->mallocFailed ) return;
+  sqlite3ResolveSelectNames(pParse, p, pOuterNC);
+  if( pParse->nErr || db->mallocFailed ) return;
+  sqlite3SelectAddTypeInfo(pParse, p);
 }
 
 /*
@@ -70305,7 +71550,7 @@
 }
 
 /*
-** Generate code for the given SELECT statement.
+** Generate code for the SELECT statement given in the p argument.  
 **
 ** The results are distributed in various ways depending on the
 ** contents of the SelectDest structure pointed to by argument pDest
@@ -70313,33 +71558,43 @@
 **
 **     pDest->eDest    Result
 **     ------------    -------------------------------------------
-**     SRT_Callback    Invoke the callback for each row of the result.
-**
-**     SRT_Mem         Store first result in memory cell pDest->iParm
+**     SRT_Output      Generate a row of output (using the OP_ResultRow
+**                     opcode) for each row in the result set.
 **
-**     SRT_Set         Store results as keys of table pDest->iParm. 
-**                     Apply the affinity pDest->affinity before storing them.
+**     SRT_Mem         Only valid if the result is a single column.
+**                     Store the first column of the first result row
+**                     in register pDest->iParm then abandon the rest
+**                     of the query.  This destination implies "LIMIT 1".
+**
+**     SRT_Set         The result must be a single column.  Store each
+**                     row of result as the key in table pDest->iParm. 
+**                     Apply the affinity pDest->affinity before storing
+**                     results.  Used to implement "IN (SELECT ...)".
 **
 **     SRT_Union       Store results as a key in a temporary table pDest->iParm.
 **
 **     SRT_Except      Remove results from the temporary table pDest->iParm.
 **
-**     SRT_Table       Store results in temporary table pDest->iParm
+**     SRT_Table       Store results in temporary table pDest->iParm.
+**                     This is like SRT_EphemTab except that the table
+**                     is assumed to already be open.
 **
 **     SRT_EphemTab    Create an temporary table pDest->iParm and store
 **                     the result there. The cursor is left open after
-**                     returning.
-**
-**     SRT_Coroutine   Invoke a co-routine to compute a single row of 
-**                     the result
+**                     returning.  This is like SRT_Table except that
+**                     this destination uses OP_OpenEphemeral to create
+**                     the table first.
+**
+**     SRT_Coroutine   Generate a co-routine that returns a new row of
+**                     results each time it is invoked.  The entry point
+**                     of the co-routine is stored in register pDest->iParm.
 **
 **     SRT_Exists      Store a 1 in memory cell pDest->iParm if the result
 **                     set is not empty.
 **
-**     SRT_Discard     Throw the results away.
-**
-** See the selectInnerLoop() function for a canonical listing of the 
-** allowed values of eDest and their meanings.
+**     SRT_Discard     Throw the results away.  This is used by SELECT
+**                     statements within triggers whose only purpose is
+**                     the side-effects of functions.
 **
 ** This routine returns the number of errors.  If any errors are
 ** encountered, then an appropriate error message is left in
@@ -70347,35 +71602,11 @@
 **
 ** This routine does NOT free the Select structure passed in.  The
 ** calling function needs to do that.
-**
-** The pParent, parentTab, and *pParentAgg fields are filled in if this
-** SELECT is a subquery.  This routine may try to combine this SELECT
-** with its parent to form a single flat query.  In so doing, it might
-** change the parent query from a non-aggregate to an aggregate query.
-** For that reason, the pParentAgg flag is passed as a pointer, so it
-** can be changed.
-**
-** Example 1:   The meaning of the pParent parameter.
-**
-**    SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3;
-**    \                      \_______ subquery _______/        /
-**     \                                                      /
-**      \____________________ outer query ___________________/
-**
-** This routine is called for the outer query first.   For that call,
-** pParent will be NULL.  During the processing of the outer query, this 
-** routine is called recursively to handle the subquery.  For the recursive
-** call, pParent will point to the outer query.  Because the subquery is
-** the second element in a three-way join, the parentTab parameter will
-** be 1 (the 2nd value of a 0-indexed array.)
 */
 SQLITE_PRIVATE int sqlite3Select(
   Parse *pParse,         /* The parser context */
   Select *p,             /* The SELECT statement being coded. */
-  SelectDest *pDest,     /* What to do with the query results */
-  Select *pParent,       /* Another SELECT for which this is a sub-query */
-  int parentTab,         /* Index in pParent->pSrc of this query */
-  int *pParentAgg        /* True if pParent uses aggregate functions */
+  SelectDest *pDest      /* What to do with the query results */
 ){
   int i, j;              /* Loop counters */
   WhereInfo *pWInfo;     /* Return from sqlite3WhereBegin() */
@@ -70411,9 +71642,10 @@
     */
     assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || 
            pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
-    p->isDistinct = 0;
+    p->selFlags &= ~SF_Distinct;
   }
-  if( sqlite3SelectResolve(pParse, p, 0) ){
+  sqlite3SelectPrep(pParse, p, 0);
+  if( pParse->nErr ){
     goto select_end;
   }
   p->pOrderBy = pOrderBy;
@@ -70422,7 +71654,7 @@
   /* Make local copies of the parameters for this query.
   */
   pTabList = p->pSrc;
-  isAgg = p->isAgg;
+  isAgg = (p->selFlags & SF_Aggregate)!=0;
   pEList = p->pEList;
   if( pEList==0 ) goto select_end;
 
@@ -70451,18 +71683,8 @@
     SelectDest dest;
     Select *pSub = pItem->pSelect;
     int isAggSub;
-    char *zName = pItem->zName;
 
     if( pSub==0 || pItem->isPopulated ) continue;
-    if( zName!=0 ){   /* An sql view */
-      const char *zSavedAuthContext = pParse->zAuthContext;
-      pParse->zAuthContext = zName;
-      rc = sqlite3SelectResolve(pParse, pSub, 0);
-      pParse->zAuthContext = zSavedAuthContext;
-      if( rc ){
-        goto select_end;
-      }
-    }
 
     /* Increment Parse.nHeight by the height of the largest expression
     ** tree refered to by this, the parent select. The child select
@@ -70474,15 +71696,18 @@
     pParse->nHeight += sqlite3SelectExprHeight(p);
 
     /* Check to see if the subquery can be absorbed into the parent. */
-    isAggSub = pSub->isAgg;
+    isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
     if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
       if( isAggSub ){
-        p->isAgg = isAgg = 1;
+        isAgg = 1;
+        p->selFlags |= SF_Aggregate;
       }
       i = -1;
     }else{
       sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
-      sqlite3Select(pParse, pSub, &dest, p, i, &isAgg);
+      assert( pItem->isPopulated==0 );
+      sqlite3Select(pParse, pSub, &dest);
+      pItem->isPopulated = 1;
     }
     if( pParse->nErr || db->mallocFailed ){
       goto select_end;
@@ -70498,7 +71723,7 @@
   pWhere = p->pWhere;
   pGroupBy = p->pGroupBy;
   pHaving = p->pHaving;
-  isDistinct = p->isDistinct;
+  isDistinct = (p->selFlags & SF_Distinct)!=0;
 
 #ifndef SQLITE_OMIT_COMPOUND_SELECT
   /* If there is are a sequence of queries, do the earlier ones first.
@@ -70533,12 +71758,12 @@
 #endif
 
   /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
-  ** GROUP BY may use an index, DISTINCT never does.
+  ** GROUP BY might use an index, DISTINCT never does.
   */
-  if( p->isDistinct && !p->isAgg && !p->pGroupBy ){
+  if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct && !p->pGroupBy ){
     p->pGroupBy = sqlite3ExprListDup(db, p->pEList);
     pGroupBy = p->pGroupBy;
-    p->isDistinct = 0;
+    p->selFlags &= ~SF_Distinct;
     isDistinct = 0;
   }
 
@@ -70772,20 +71997,14 @@
           struct AggInfo_col *pCol = &sAggInfo.aCol[i];
           if( pCol->iSorterColumn>=j ){
             int r1 = j + regBase;
-#ifndef NDEBUG
-            int r2 = 
-#endif
-                     sqlite3ExprCodeGetColumn(pParse, 
+            int r2;
+
+            r2 = sqlite3ExprCodeGetColumn(pParse, 
                                pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
+            if( r1!=r2 ){
+              sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
+            }
             j++;
-
-            /* sAggInfo.aCol[] only contains one entry per column.  So
-            ** The reference to pCol->iColumn,pCol->iTable must have been
-            ** the first reference to that column.  Hence, 
-            ** sqliteExprCodeGetColumn is guaranteed to put the result in
-            ** the column requested. 
-            */
-            assert( r1==r2 );
           }
         }
         regRecord = sqlite3GetTempReg(pParse);
@@ -70934,19 +72153,6 @@
     generateSortTail(pParse, p, v, pEList->nExpr, pDest);
   }
 
-#ifndef SQLITE_OMIT_SUBQUERY
-  /* If this was a subquery, we have now converted the subquery into a
-  ** temporary table.  So set the SrcList_item.isPopulated flag to prevent
-  ** this subquery from being evaluated again and to force the use of
-  ** the temporary table.
-  */
-  if( pParent ){
-    assert( pParent->pSrc->nSrc>parentTab );
-    assert( pParent->pSrc->a[parentTab].pSelect==p );
-    pParent->pSrc->a[parentTab].isPopulated = 1;
-  }
-#endif
-
   /* Jump here to skip this query
   */
   sqlite3VdbeResolveLabel(v, iEnd);
@@ -70961,10 +72167,9 @@
   */
 select_end:
 
-  /* Identify column names if we will be using them in a callback.  This
-  ** step is skipped if the output is going to some other destination.
+  /* Identify column names if results of the SELECT are to be output.
   */
-  if( rc==SQLITE_OK && pDest->eDest==SRT_Callback ){
+  if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
     generateColumnNames(pParse, pTabList, pEList);
   }
 
@@ -71284,7 +72489,7 @@
 *************************************************************************
 **
 **
-** $Id: trigger.c,v 1.128 2008/07/28 19:34:54 drh Exp $
+** $Id: trigger.c,v 1.129 2008/08/20 16:35:10 drh Exp $
 */
 
 #ifndef SQLITE_OMIT_TRIGGER
@@ -71952,8 +73157,7 @@
           SelectDest dest;
 
           sqlite3SelectDestInit(&dest, SRT_Discard, 0);
-          sqlite3SelectResolve(pParse, ss, 0);
-          sqlite3Select(pParse, ss, &dest, 0, 0, 0);
+          sqlite3Select(pParse, ss, &dest);
           sqlite3SelectDelete(db, ss);
         }
         break;
@@ -72102,7 +73306,7 @@
       /* code the WHEN clause */
       endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
       whenExpr = sqlite3ExprDup(db, p->pWhen);
-      if( db->mallocFailed || sqlite3ExprResolveNames(&sNC, whenExpr) ){
+      if( db->mallocFailed || sqlite3ResolveExprNames(&sNC, whenExpr) ){
         pParse->trigStack = trigStackEntry.pNext;
         sqlite3ExprDelete(db, whenExpr);
         return 1;
@@ -72141,7 +73345,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle UPDATE statements.
 **
-** $Id: update.c,v 1.181 2008/07/28 19:34:54 drh Exp $
+** $Id: update.c,v 1.183 2008/08/22 12:30:52 drh Exp $
 */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -72322,7 +73526,7 @@
   */
   chngRowid = 0;
   for(i=0; i<pChanges->nExpr; i++){
-    if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
+    if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
       goto update_cleanup;
     }
     for(j=0; j<pTab->nCol; j++){
@@ -72457,13 +73661,13 @@
   ** a ephemeral table.
   */
   if( isView ){
-    sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur);
+    sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
   }
 
   /* Resolve the column names in all the expressions in the
   ** WHERE clause.
   */
-  if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+  if( sqlite3ResolveExprNames(&sNC, pWhere) ){
     goto update_cleanup;
   }
 
@@ -72777,7 +73981,7 @@
   /* fill the ephemeral table 
   */
   sqlite3SelectDestInit(&dest, SRT_Table, ephemTab);
-  sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
+  sqlite3Select(pParse, pSelect, &dest);
 
   /* Generate code to scan the ephemeral table and call VUpdate. */
   iReg = ++pParse->nMem;
@@ -72823,7 +74027,7 @@
 ** Most of the code in this file may be omitted by defining the
 ** SQLITE_OMIT_VACUUM macro.
 **
-** $Id: vacuum.c,v 1.81 2008/07/08 19:34:07 drh Exp $
+** $Id: vacuum.c,v 1.83 2008/08/26 21:07:27 drh Exp $
 */
 
 #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
@@ -72888,12 +74092,14 @@
 SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
   int rc = SQLITE_OK;     /* Return code from service routines */
   Btree *pMain;           /* The database being vacuumed */
+  Pager *pMainPager;      /* Pager for database being vacuumed */
   Btree *pTemp;           /* The temporary database we vacuum into */
   char *zSql = 0;         /* SQL statements */
   int saved_flags;        /* Saved value of the db->flags */
   int saved_nChange;      /* Saved value of db->nChange */
   int saved_nTotalChange; /* Saved value of db->nTotalChange */
   Db *pDb = 0;            /* Database to detach at end of vacuum */
+  int isMemDb;            /* True is vacuuming a :memory: database */
   int nRes;
 
   /* Save the current value of the write-schema flag before setting it. */
@@ -72908,6 +74114,8 @@
     goto end_of_vacuum;
   }
   pMain = db->aDb[0].pBt;
+  pMainPager = sqlite3BtreePager(pMain);
+  isMemDb = sqlite3PagerFile(pMainPager)->pMethods==0;
 
   /* Attach the temporary database as 'vacuum_db'. The synchronous pragma
   ** can be set to 'off' for this file, as it is not recovered if a crash
@@ -72944,7 +74152,7 @@
 #endif
 
   if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes)
-   || sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes)
+   || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes))
    || db->mallocFailed 
   ){
     rc = SQLITE_NOMEM;
@@ -73065,6 +74273,9 @@
     if( rc!=SQLITE_OK ) goto end_of_vacuum;
     rc = sqlite3BtreeCommit(pTemp);
     if( rc!=SQLITE_OK ) goto end_of_vacuum;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
+#endif
     rc = sqlite3BtreeCommit(pMain);
   }
 
@@ -73114,7 +74325,7 @@
 *************************************************************************
 ** This file contains code used to help implement virtual tables.
 **
-** $Id: vtab.c,v 1.74 2008/08/02 03:50:39 drh Exp $
+** $Id: vtab.c,v 1.76 2008/08/20 16:35:10 drh Exp $
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 
@@ -73288,7 +74499,7 @@
   iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
   assert( iDb>=0 );
 
-  pTable->isVirtual = 1;
+  pTable->tabFlags |= TF_Virtual;
   pTable->nModuleArg = 0;
   addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
   addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
@@ -73544,7 +74755,7 @@
   Module *pMod;
   int rc = SQLITE_OK;
 
-  if( !pTab || !pTab->isVirtual || pTab->pVtab ){
+  if( !pTab || (pTab->tabFlags & TF_Virtual)==0 || pTab->pVtab ){
     return SQLITE_OK;
   }
 
@@ -73605,7 +74816,7 @@
   const char *zModule;
 
   pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
-  assert(pTab && pTab->isVirtual && !pTab->pVtab);
+  assert(pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVtab);
   pMod = pTab->pMod;
   zModule = pTab->azModuleArg[0];
 
@@ -73646,7 +74857,7 @@
     sqlite3_mutex_leave(db->mutex);
     return SQLITE_MISUSE;
   }
-  assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);
+  assert((pTab->tabFlags & TF_Virtual)!=0 && pTab->nCol==0 && pTab->aCol==0);
 
   memset(&sParse, 0, sizeof(Parse));
   sParse.declareVtab = 1;
@@ -73656,7 +74867,7 @@
       SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) && 
       sParse.pNewTable && 
       !sParse.pNewTable->pSelect && 
-      !sParse.pNewTable->isVirtual 
+      (sParse.pNewTable->tabFlags & TF_Virtual)==0
   ){
     pTab->aCol = sParse.pNewTable->aCol;
     pTab->nCol = sParse.pNewTable->nCol;
@@ -73875,7 +75086,7 @@
   if( pExpr->op!=TK_COLUMN ) return pDef;
   pTab = pExpr->pTab;
   if( pTab==0 ) return pDef;
-  if( !pTab->isVirtual ) return pDef;
+  if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef;
   pVtab = pTab->pVtab;
   assert( pVtab!=0 );
   assert( pVtab->pModule!=0 );
@@ -73909,6 +75120,7 @@
     return pDef;
   }
   *pNew = *pDef;
+  pNew->zName = (char *)&pNew[1];
   memcpy(pNew->zName, pDef->zName, strlen(pDef->zName)+1);
   pNew->xFunc = xFunc;
   pNew->pUserData = pArg;
@@ -73959,7 +75171,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.319 2008/08/01 17:37:41 danielk1977 Exp $
+** $Id: where.c,v 1.321 2008/08/25 12:08:22 drh Exp $
 */
 
 /*
@@ -74262,9 +75474,9 @@
 ** tree.
 **
 ** In order for this routine to work, the calling function must have
-** previously invoked sqlite3ExprResolveNames() on the expression.  See
+** previously invoked sqlite3ResolveExprNames() on the expression.  See
 ** the header comment on that routine for additional information.
-** The sqlite3ExprResolveNames() routines looks for column names and
+** The sqlite3ResolveExprNames() routines looks for column names and
 ** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
 ** the VDBE cursor number of the table.  This routine just has to
 ** translate the cursor numbers into bitmask values and OR all
@@ -74338,10 +75550,12 @@
 ** attached to the right. For the same reason the EP_ExpCollate flag
 ** is not commuted.
 */
-static void exprCommute(Expr *pExpr){
+static void exprCommute(Parse *pParse, Expr *pExpr){
   u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
   u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
   assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
+  pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
+  pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
   SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
   pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
   pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
@@ -74461,7 +75675,7 @@
 ** literal that does not begin with a wildcard.  
 */
 static int isLikeOrGlob(
-  sqlite3 *db,      /* The database */
+  Parse *pParse,    /* Parsing and code generating context */
   Expr *pExpr,      /* Test this expression */
   int *pnPattern,   /* Number of non-wildcard prefix characters */
   int *pisComplete, /* True if the only wildcard is % in the last character */
@@ -74473,6 +75687,7 @@
   int c, cnt;
   char wc[3];
   CollSeq *pColl;
+  sqlite3 *db = pParse->db;
 
   if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
     return 0;
@@ -74490,7 +75705,7 @@
   if( pLeft->op!=TK_COLUMN ){
     return 0;
   }
-  pColl = pLeft->pColl;
+  pColl = sqlite3ExprCollSeq(pParse, pLeft);
   assert( pColl!=0 || pLeft->iColumn==-1 );
   if( pColl==0 ){
     /* No collation is defined for the ROWID.  Use the default. */
@@ -74730,7 +75945,7 @@
         pDup = pExpr;
         pNew = pTerm;
       }
-      exprCommute(pDup);
+      exprCommute(pParse, pDup);
       pLeft = pDup->pLeft;
       pNew->leftCursor = pLeft->iTable;
       pNew->leftColumn = pLeft->iColumn;
@@ -74851,7 +76066,7 @@
   ** The last character of the prefix "abc" is incremented to form the
   ** termination condition "abd".
   */
-  if( isLikeOrGlob(db, pExpr, &nPattern, &isComplete, &noCase) ){
+  if( isLikeOrGlob(pParse, pExpr, &nPattern, &isComplete, &noCase) ){
     Expr *pLeft, *pRight;
     Expr *pStr1, *pStr2;
     Expr *pNewExpr1, *pNewExpr2;
@@ -75225,7 +76440,7 @@
     ** to this virtual table */
     for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
       if( pTerm->leftCursor != pSrc->iCursor ) continue;
-      if( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
+      assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
       testcase( pTerm->eOperator==WO_IN );
       testcase( pTerm->eOperator==WO_ISNULL );
       if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
@@ -75275,7 +76490,7 @@
 
     for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
       if( pTerm->leftCursor != pSrc->iCursor ) continue;
-      if( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
+      assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
       testcase( pTerm->eOperator==WO_IN );
       testcase( pTerm->eOperator==WO_ISNULL );
       if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
@@ -76220,7 +77435,7 @@
     pTabItem = &pTabList->a[pLevel->iFrom];
     pTab = pTabItem->pTab;
     iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
-    if( pTab->isEphem || pTab->pSelect ) continue;
+    if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
     if( pLevel->pBestIdx ){
       int iCur = pTabItem->iCursor;
@@ -76779,7 +77994,7 @@
     struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
     Table *pTab = pTabItem->pTab;
     assert( pTab!=0 );
-    if( pTab->isEphem || pTab->pSelect ) continue;
+    if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
     if( !pWInfo->okOnePass && (pLevel->flags & WHERE_IDX_ONLY)==0 ){
       sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
     }
@@ -76929,23 +78144,23 @@
 **                       defined, then do no error processing.
 */
 #define YYCODETYPE unsigned char
-#define YYNOCODE 248
+#define YYNOCODE 247
 #define YYACTIONTYPE unsigned short int
 #define YYWILDCARD 59
 #define sqlite3ParserTOKENTYPE Token
 typedef union {
   sqlite3ParserTOKENTYPE yy0;
-  int yy46;
-  struct LikeOp yy72;
-  Expr* yy172;
-  ExprList* yy174;
-  Select* yy219;
-  struct LimitVal yy234;
-  TriggerStep* yy243;
-  struct TrigEvent yy370;
-  SrcList* yy373;
-  struct {int value; int mask;} yy405;
-  IdList* yy432;
+  struct TrigEvent yy30;
+  Expr* yy62;
+  SrcList* yy151;
+  struct LimitVal yy220;
+  struct LikeOp yy222;
+  IdList* yy240;
+  int yy280;
+  struct {int value; int mask;} yy359;
+  TriggerStep* yy360;
+  Select* yy375;
+  ExprList* yy418;
 } YYMINORTYPE;
 #ifndef YYSTACKDEPTH
 #define YYSTACKDEPTH 100
@@ -76954,8 +78169,8 @@
 #define sqlite3ParserARG_PDECL ,Parse *pParse
 #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
 #define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 589
-#define YYNRULE 313
+#define YYNSTATE 590
+#define YYNRULE 312
 #define YYFALLBACK 1
 #define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
 #define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
@@ -76963,7 +78178,11 @@
 
 /* The yyzerominor constant is used to initialize instances of
 ** YYMINORTYPE objects to zero. */
+#if 0
+static YYMINORTYPE yyzerominor;
+#else
 static const YYMINORTYPE yyzerominor;
+#endif
 
 /* Next are the tables used to determine what action to take based on the
 ** current state and lookahead token.  These tables are used to implement
@@ -77013,416 +78232,417 @@
 **  yy_default[]       Default action for each state.
 */
 static const YYACTIONTYPE yy_action[] = {
- /*     0 */   292,  903,  124,  588,  409,  172,    2,  418,   61,   61,
- /*    10 */    61,   61,  519,   63,   63,   63,   63,   64,   64,   65,
- /*    20 */    65,   65,   66,  210,  447,  212,  425,  431,   68,   63,
- /*    30 */    63,   63,   63,   64,   64,   65,   65,   65,   66,  210,
- /*    40 */   391,  388,  396,  451,   60,   59,  297,  435,  436,  432,
- /*    50 */   432,   62,   62,   61,   61,   61,   61,  263,   63,   63,
- /*    60 */    63,   63,   64,   64,   65,   65,   65,   66,  210,  292,
- /*    70 */   493,  494,  418,  489,  208,   82,   67,  420,   69,  154,
- /*    80 */    63,   63,   63,   63,   64,   64,   65,   65,   65,   66,
- /*    90 */   210,   67,  462,   69,  154,  425,  431,  574,  264,   58,
- /*   100 */    64,   64,   65,   65,   65,   66,  210,  397,  398,  422,
- /*   110 */   422,  422,  292,   60,   59,  297,  435,  436,  432,  432,
- /*   120 */    62,   62,   61,   61,   61,   61,  317,   63,   63,   63,
- /*   130 */    63,   64,   64,   65,   65,   65,   66,  210,  425,  431,
- /*   140 */    94,   65,   65,   65,   66,  210,  396,  210,  414,   34,
- /*   150 */    56,  298,  442,  443,  410,  418,   60,   59,  297,  435,
- /*   160 */   436,  432,  432,   62,   62,   61,   61,   61,   61,  208,
- /*   170 */    63,   63,   63,   63,   64,   64,   65,   65,   65,   66,
- /*   180 */   210,  292,  372,  524,  295,  572,  113,  408,  522,  451,
- /*   190 */   331,  317,  407,   20,  244,  340,  519,  396,  478,  531,
- /*   200 */   505,  447,  212,  571,  570,  245,  530,  425,  431,  149,
- /*   210 */   150,  397,  398,  414,   41,  211,  151,  533,  488,  489,
- /*   220 */   418,  568,  569,  420,  292,   60,   59,  297,  435,  436,
- /*   230 */   432,  432,   62,   62,   61,   61,   61,   61,  317,   63,
- /*   240 */    63,   63,   63,   64,   64,   65,   65,   65,   66,  210,
- /*   250 */   425,  431,  447,  333,  215,  422,  422,  422,  363,  299,
- /*   260 */   414,   41,  397,  398,  366,  567,  211,  292,   60,   59,
- /*   270 */   297,  435,  436,  432,  432,   62,   62,   61,   61,   61,
- /*   280 */    61,  396,   63,   63,   63,   63,   64,   64,   65,   65,
- /*   290 */    65,   66,  210,  425,  431,  491,  300,  524,  474,   66,
- /*   300 */   210,  214,  474,  229,  411,  286,  534,   20,  449,  523,
- /*   310 */   168,   60,   59,  297,  435,  436,  432,  432,   62,   62,
- /*   320 */    61,   61,   61,   61,  474,   63,   63,   63,   63,   64,
- /*   330 */    64,   65,   65,   65,   66,  210,  209,  480,  317,   77,
- /*   340 */   292,  239,  300,   55,  484,  490,  397,  398,  181,  547,
- /*   350 */   494,  345,  348,  349,   67,  152,   69,  154,  339,  524,
- /*   360 */   414,   35,  350,  241,  221,  370,  425,  431,  579,   20,
- /*   370 */   164,  118,  243,  343,  248,  344,  176,  322,  442,  443,
- /*   380 */   414,    3,   80,  252,   60,   59,  297,  435,  436,  432,
- /*   390 */   432,   62,   62,   61,   61,   61,   61,  174,   63,   63,
- /*   400 */    63,   63,   64,   64,   65,   65,   65,   66,  210,  292,
- /*   410 */   221,  550,  236,  487,  510,  353,  317,  118,  243,  343,
- /*   420 */   248,  344,  176,  181,  317,  532,  345,  348,  349,  252,
- /*   430 */   223,  415,  155,  464,  511,  425,  431,  350,  414,   34,
- /*   440 */   465,  211,  177,  175,  160,  525,  414,   34,  338,  549,
- /*   450 */   449,  323,  168,   60,   59,  297,  435,  436,  432,  432,
- /*   460 */    62,   62,   61,   61,   61,   61,  415,   63,   63,   63,
- /*   470 */    63,   64,   64,   65,   65,   65,   66,  210,  292,  542,
- /*   480 */   335,  517,  504,  541,  456,  572,  302,   19,  331,  144,
- /*   490 */   317,  390,  317,  330,    2,  362,  457,  294,  483,  373,
- /*   500 */   269,  268,  252,  571,  425,  431,  589,  391,  388,  458,
- /*   510 */   208,  495,  414,   49,  414,   49,  303,  586,  894,  230,
- /*   520 */   894,  496,   60,   59,  297,  435,  436,  432,  432,   62,
- /*   530 */    62,   61,   61,   61,   61,  201,   63,   63,   63,   63,
- /*   540 */    64,   64,   65,   65,   65,   66,  210,  292,  317,  181,
- /*   550 */   439,  255,  345,  348,  349,  370,  153,  583,  308,  251,
- /*   560 */   309,  452,   76,  350,   78,  382,  211,  426,  427,  415,
- /*   570 */   414,   27,  319,  425,  431,  440,    1,   22,  586,  893,
- /*   580 */   396,  893,  544,  478,  320,  263,  438,  438,  429,  430,
- /*   590 */   415,   60,   59,  297,  435,  436,  432,  432,   62,   62,
- /*   600 */    61,   61,   61,   61,  237,   63,   63,   63,   63,   64,
- /*   610 */    64,   65,   65,   65,   66,  210,  292,  428,  583,  374,
- /*   620 */   224,   93,  517,    9,  159,  396,  557,  396,  456,   67,
- /*   630 */   396,   69,  154,  399,  400,  401,  320,  328,  438,  438,
- /*   640 */   457,  336,  425,  431,  361,  397,  398,  320,  433,  438,
- /*   650 */   438,  582,  291,  458,  238,  327,  318,  222,  546,  292,
- /*   660 */    60,   59,  297,  435,  436,  432,  432,   62,   62,   61,
- /*   670 */    61,   61,   61,  225,   63,   63,   63,   63,   64,   64,
- /*   680 */    65,   65,   65,   66,  210,  425,  431,  482,  313,  392,
- /*   690 */   397,  398,  397,  398,  207,  397,  398,  825,  273,  517,
- /*   700 */   251,  200,  292,   60,   59,  297,  435,  436,  432,  432,
- /*   710 */    62,   62,   61,   61,   61,   61,  470,   63,   63,   63,
- /*   720 */    63,   64,   64,   65,   65,   65,   66,  210,  425,  431,
- /*   730 */   171,  160,  263,  263,  304,  415,  276,  395,  274,  263,
- /*   740 */   517,  517,  263,  517,  192,  292,   60,   70,  297,  435,
- /*   750 */   436,  432,  432,   62,   62,   61,   61,   61,   61,  379,
- /*   760 */    63,   63,   63,   63,   64,   64,   65,   65,   65,   66,
- /*   770 */   210,  425,  431,  384,  559,  305,  306,  251,  415,  320,
- /*   780 */   560,  438,  438,  561,  540,  360,  540,  387,  292,  196,
- /*   790 */    59,  297,  435,  436,  432,  432,   62,   62,   61,   61,
- /*   800 */    61,   61,  371,   63,   63,   63,   63,   64,   64,   65,
- /*   810 */    65,   65,   66,  210,  425,  431,  396,  275,  251,  251,
- /*   820 */   172,  250,  418,  415,  386,  367,  178,  179,  180,  469,
- /*   830 */   311,  123,  156,    5,  297,  435,  436,  432,  432,   62,
- /*   840 */    62,   61,   61,   61,   61,  317,   63,   63,   63,   63,
- /*   850 */    64,   64,   65,   65,   65,   66,  210,   72,  324,  194,
- /*   860 */     4,  317,  263,  317,  296,  263,  415,  414,   28,  317,
- /*   870 */   257,  317,  321,   72,  324,  317,    4,  119,  165,  177,
- /*   880 */   296,  397,  398,  414,   23,  414,   32,  418,  321,  326,
- /*   890 */   421,  414,   53,  414,   52,  317,  158,  414,   98,  451,
- /*   900 */   317,  263,  317,  277,  317,  326,  378,  471,  261,  317,
- /*   910 */   259,   18,  478,  445,  445,  451,  317,  414,   96,   75,
- /*   920 */    74,  469,  414,  101,  414,  102,  414,  112,   73,  315,
- /*   930 */   316,  414,  114,  420,  294,   75,   74,  481,  414,   16,
- /*   940 */   381,  317,  279,  467,   73,  315,  316,   72,  324,  420,
- /*   950 */     4,  208,  317,  183,  296,  317,  186,  128,   84,  208,
- /*   960 */     8,  341,  321,  414,   99,  422,  422,  422,  423,  424,
- /*   970 */    11,  623,  380,  307,  414,   33,  413,  414,   97,  326,
- /*   980 */   412,  422,  422,  422,  423,  424,   11,  415,  413,  451,
- /*   990 */   415,  162,  412,  317,  499,  500,  226,  227,  228,  104,
- /*  1000 */   448,  476,  317,  173,  507,  317,  509,  508,  317,   75,
- /*  1010 */    74,  329,  205,   21,  281,  414,   24,  418,   73,  315,
- /*  1020 */   316,  282,  317,  420,  414,   54,  460,  414,  115,  317,
- /*  1030 */   414,  116,  502,  203,  147,  549,  514,  468,  128,  202,
- /*  1040 */   317,  473,  204,  317,  414,  117,  317,  477,  317,  584,
- /*  1050 */   317,  414,   25,  317,  249,  422,  422,  422,  423,  424,
- /*  1060 */    11,  506,  414,   36,  512,  414,   37,  317,  414,   26,
- /*  1070 */   414,   38,  414,   39,  526,  414,   40,  317,  254,  317,
- /*  1080 */   128,  317,  418,  317,  256,  377,  278,  268,  585,  414,
- /*  1090 */    42,  293,  317,  352,  317,  128,  208,  513,  258,  414,
- /*  1100 */    43,  414,   44,  414,   29,  414,   30,  545,  260,  128,
- /*  1110 */   317,  553,  317,  173,  414,   45,  414,   46,  317,  262,
- /*  1120 */   383,  554,  317,   91,  564,  317,   91,  317,  581,  189,
- /*  1130 */   290,  357,  414,   47,  414,   48,  267,  365,  368,  369,
- /*  1140 */   414,   31,  270,  271,  414,   10,  272,  414,   50,  414,
- /*  1150 */    51,  556,  566,  280,  283,  284,  578,  146,  419,  405,
- /*  1160 */   231,  505,  444,  325,  516,  463,  163,  446,  552,  394,
- /*  1170 */   466,  563,  246,  515,  518,  520,  402,  403,  404,    7,
- /*  1180 */   314,   84,  232,  334,  347,   83,  332,   57,  170,   79,
- /*  1190 */   213,  461,  125,   85,  337,  342,  492,  502,  497,  301,
- /*  1200 */   498,  416,  105,  219,  247,  218,  503,  501,  233,  220,
- /*  1210 */   287,  234,  527,  528,  235,  529,  417,  521,  354,  288,
- /*  1220 */   184,  121,  185,  240,  535,  475,  242,  356,  187,  479,
- /*  1230 */   188,  358,  537,   88,  190,  548,  364,  193,  132,  376,
- /*  1240 */   555,  375,  133,  134,  135,  310,  562,  138,  136,  575,
- /*  1250 */   576,  577,  580,  100,  393,  406,  217,  142,  624,  625,
- /*  1260 */   103,  141,  265,  166,  167,  434,   71,  453,  441,  437,
- /*  1270 */   450,  143,  538,  157,  120,  454,  161,  472,  455,  169,
- /*  1280 */   459,   81,    6,   12,   13,   92,   95,  126,  216,  127,
- /*  1290 */   111,  485,  486,   17,   86,  346,  106,  122,  253,  107,
- /*  1300 */    87,  108,  182,  245,  355,  145,  351,  536,  129,  359,
- /*  1310 */   312,  130,  543,  173,  539,  266,  191,  109,  289,  551,
- /*  1320 */   195,   14,  131,  198,  197,  558,  137,  199,  139,  140,
- /*  1330 */    15,  565,   89,   90,  573,  110,  385,  206,  148,  389,
- /*  1340 */   285,  587,
+ /*     0 */   292,  903,  120,  589,    2,  172,  419,  419,   62,   62,
+ /*    10 */    62,   62,  209,   64,   64,   64,   64,   65,   65,   66,
+ /*    20 */    66,   66,   67,  211,  392,  389,  426,  432,   69,   64,
+ /*    30 */    64,   64,   64,   65,   65,   66,   66,   66,   67,  211,
+ /*    40 */   448,  213,  397,  452,   61,   60,  297,  436,  437,  433,
+ /*    50 */   433,   63,   63,   62,   62,   62,   62,  264,   64,   64,
+ /*    60 */    64,   64,   65,   65,   66,   66,   66,   67,  211,  292,
+ /*    70 */   317,  419,  419,  490,  211,   83,   68,  421,   70,  154,
+ /*    80 */    64,   64,   64,   64,   65,   65,   66,   66,   66,   67,
+ /*    90 */   211,  489,  415,   36,  181,  426,  432,  448,  265,   59,
+ /*   100 */    65,   65,   66,   66,   66,   67,  211,  398,  399,  423,
+ /*   110 */   423,  423,  292,   61,   60,  297,  436,  437,  433,  433,
+ /*   120 */    63,   63,   62,   62,   62,   62,  317,   64,   64,   64,
+ /*   130 */    64,   65,   65,   66,   66,   66,   67,  211,  426,  432,
+ /*   140 */    95,  313,  394,  475,  237,  172,  208,  419,  415,   35,
+ /*   150 */    57,   67,  211,  201,  411,  475,   61,   60,  297,  436,
+ /*   160 */   437,  433,  433,   63,   63,   62,   62,   62,   62,  503,
+ /*   170 */    64,   64,   64,   64,   65,   65,   66,   66,   66,   67,
+ /*   180 */   211,  292,  481,  524,  542,  573,  109,  416,  541,  452,
+ /*   190 */   331,  317,  408,   21,  240,  340,  409,  522,  317,   68,
+ /*   200 */   362,   70,  154,  572,  571,  519,  492,  426,  432,  149,
+ /*   210 */   150,  380,  419,  415,   42,  412,  151,  533,  202,  490,
+ /*   220 */   415,   50,  532,  421,  292,   61,   60,  297,  436,  437,
+ /*   230 */   433,  433,   63,   63,   62,   62,   62,   62,  388,   64,
+ /*   240 */    64,   64,   64,   65,   65,   66,   66,   66,   67,  211,
+ /*   250 */   426,  432,  416,  333,  216,  423,  423,  423,   66,   66,
+ /*   260 */    66,   67,  211,  491,  568,  212,  308,  292,   61,   60,
+ /*   270 */   297,  436,  437,  433,  433,   63,   63,   62,   62,   62,
+ /*   280 */    62,  397,   64,   64,   64,   64,   65,   65,   66,   66,
+ /*   290 */    66,   67,  211,  426,  432,  182,  300,  410,  345,  348,
+ /*   300 */   349,  531,  506,  252,   68,  519,   70,  154,  530,  350,
+ /*   310 */   231,   61,   60,  297,  436,  437,  433,  433,   63,   63,
+ /*   320 */    62,   62,   62,   62,  575,   64,   64,   64,   64,   65,
+ /*   330 */    65,   66,   66,   66,   67,  211,  525,  317,  303,   78,
+ /*   340 */   292,  238,  300,  511,  485,  153,  398,  399,  182,  494,
+ /*   350 */   495,  345,  348,  349,  320,  152,  439,  439,  339,  415,
+ /*   360 */    28,  328,  350,  512,  222,  370,  426,  432,  547,  495,
+ /*   370 */   164,  114,  244,  343,  249,  344,  176,  583,  291,  416,
+ /*   380 */   415,    3,   81,  253,   61,   60,  297,  436,  437,  433,
+ /*   390 */   433,   63,   63,   62,   62,   62,   62,  174,   64,   64,
+ /*   400 */    64,   64,   65,   65,   66,   66,   66,   67,  211,  292,
+ /*   410 */   222,  587,  894,  488,  894,  302,  573,  114,  244,  343,
+ /*   420 */   249,  344,  176,  182,  317,  397,  345,  348,  349,  253,
+ /*   430 */   224,  416,  155,  549,  572,  426,  432,  350,   68,  463,
+ /*   440 */    70,  154,  397,  175,  160,  397,  415,   35,  338,  587,
+ /*   450 */   893,  584,  893,   61,   60,  297,  436,  437,  433,  433,
+ /*   460 */    63,   63,   62,   62,   62,   62,  416,   64,   64,   64,
+ /*   470 */    64,   65,   65,   66,   66,   66,   67,  211,  292,  550,
+ /*   480 */   448,  213,  505,  373,  270,  269,  171,  160,  331,  584,
+ /*   490 */   398,  399,  317,  330,  209,  383,  212,  159,  427,  428,
+ /*   500 */   569,  570,  483,  524,  426,  432,  336,  398,  399,  230,
+ /*   510 */   398,  399,  534,   21,  415,   42,  239,  549,  479,  430,
+ /*   520 */   431,  475,   61,   60,  297,  436,  437,  433,  433,   63,
+ /*   530 */    63,   62,   62,   62,   62,  264,   64,   64,   64,   64,
+ /*   540 */    65,   65,   66,   66,   66,   67,  211,  292,  429,  287,
+ /*   550 */   457,  256,  450,  523,  168,  215,  197,  295,  317,  353,
+ /*   560 */   242,  317,  458,  298,  443,  444,  468,  373,  270,  269,
+ /*   570 */   322,  443,  444,  426,  432,  459,  558,  496,  209,  299,
+ /*   580 */   415,   35,  544,  415,   50,    1,  177,  497,  479,  397,
+ /*   590 */   416,   61,   60,  297,  436,  437,  433,  433,   63,   63,
+ /*   600 */    62,   62,   62,   62,  484,   64,   64,   64,   64,   65,
+ /*   610 */    65,   66,   66,   66,   67,  211,  292,  317,  524,  375,
+ /*   620 */   457,   94,  335,  590,  392,  389,  212,  580,   21,  309,
+ /*   630 */    10,  363,  458,  212,  397,  209,  366,  391,    2,  415,
+ /*   640 */    29,  294,  426,  432,  195,  459,  253,  327,  372,  361,
+ /*   650 */   440,  450,  323,  168,  398,  399,  252,  147,  546,  292,
+ /*   660 */    61,   60,  297,  436,  437,  433,  433,   63,   63,   62,
+ /*   670 */    62,   62,   62,  317,   64,   64,   64,   64,   65,   65,
+ /*   680 */    66,   66,   66,   67,  211,  426,  432,  210,  318,  453,
+ /*   690 */   320,  223,  439,  439,   56,  415,   24,  826,  252,  398,
+ /*   700 */   399,  193,  292,   61,   60,  297,  436,  437,  433,  433,
+ /*   710 */    63,   63,   62,   62,   62,   62,  226,   64,   64,   64,
+ /*   720 */    64,   65,   65,   66,   66,   66,   67,  211,  426,  432,
+ /*   730 */   311,  119,  264,  304,  396,  416,  320,   19,  439,  439,
+ /*   740 */   400,  401,  402,   85,  274,  292,   61,   71,  297,  436,
+ /*   750 */   437,  433,  433,   63,   63,   62,   62,   62,   62,  371,
+ /*   760 */    64,   64,   64,   64,   65,   65,   66,   66,   66,   67,
+ /*   770 */   211,  426,  432,  385,  115,  320,   18,  439,  439,  446,
+ /*   780 */   446,  374,  277,    5,  275,  264,    8,  252,  292,  341,
+ /*   790 */    60,  297,  436,  437,  433,  433,   63,   63,   62,   62,
+ /*   800 */    62,   62,  397,   64,   64,   64,   64,   65,   65,   66,
+ /*   810 */    66,   66,   67,  211,  426,  432,  414,  397,  422,  470,
+ /*   820 */   413,   22,  305,  387,  252,  419,  560,  193,  414,  264,
+ /*   830 */   264,  370,  413,  190,  297,  436,  437,  433,  433,   63,
+ /*   840 */    63,   62,   62,   62,   62,  479,   64,   64,   64,   64,
+ /*   850 */    65,   65,   66,   66,   66,   67,  211,   73,  324,  306,
+ /*   860 */     4,  416,  264,  276,  296,  449,  177,  398,  399,  317,
+ /*   870 */   561,  562,  321,   73,  324,  317,    4,  540,  360,  540,
+ /*   880 */   296,  329,  398,  399,  461,  371,  158,  317,  321,  326,
+ /*   890 */   419,  415,   33,  471,  317,  165,  225,  415,   54,  452,
+ /*   900 */   317,  264,  317,  278,  317,  326,  307,  367,  472,  415,
+ /*   910 */    53,  470,  178,  179,  180,  452,  415,   99,  317,   76,
+ /*   920 */    75,  294,  415,   97,  415,  102,  415,  103,   74,  315,
+ /*   930 */   316,  319,  264,  421,  469,   76,   75,  482,  317,  382,
+ /*   940 */   415,  108,  379,  474,   74,  315,  316,   73,  324,  421,
+ /*   950 */     4,  209,  317,  156,  296,  317,  184,  465,  209,  187,
+ /*   960 */   415,  110,  321,  258,  466,  423,  423,  423,  424,  425,
+ /*   970 */    12,  381,  478,  280,  415,   17,  250,  415,  100,  326,
+ /*   980 */   507,  423,  423,  423,  424,  425,   12,  416,  624,  452,
+ /*   990 */   416,  162,  508,  416,  317,  513,  227,  228,  229,  105,
+ /*  1000 */   514,  262,  317,  260,   20,  317,  144,  434,  317,   76,
+ /*  1010 */    75,   77,  206,   79,  282,  317,  415,   34,   74,  315,
+ /*  1020 */   316,  283,  317,  421,  415,   98,  251,  415,   25,  526,
+ /*  1030 */   415,   55,  441,  204,   23,  549,  257,  415,  111,  203,
+ /*  1040 */   317,  477,  205,  173,  415,  112,  317,  259,  317,  515,
+ /*  1050 */   317,  181,  317,  261,  245,  423,  423,  423,  424,  425,
+ /*  1060 */    12,  263,  415,  113,  357,  246,  317,  268,  415,   26,
+ /*  1070 */   415,   37,  415,   38,  415,   27,  317,  500,  501,  510,
+ /*  1080 */   509,  317,  365,  317,  368,  378,  279,  269,  415,   39,
+ /*  1090 */   369,  293,  317,  255,  317,  181,  209,  271,  415,   40,
+ /*  1100 */   317,  272,  317,  415,   41,  415,   43,  352,  317,  181,
+ /*  1110 */   317,  273,  557,  317,  415,   44,  415,   45,  317,  545,
+ /*  1120 */   384,  181,  415,   30,  415,   31,  317,  585,  567,  317,
+ /*  1130 */   415,   46,  415,   47,  317,  415,   48,  317,  281,  284,
+ /*  1140 */   415,   49,  553,  554,  173,   92,  285,  579,  415,   32,
+ /*  1150 */   406,  415,   11,  565,  420,   92,  415,   51,  146,  415,
+ /*  1160 */    52,  582,  232,  290,  325,  517,  586,  445,  447,  464,
+ /*  1170 */   467,  506,  520,  163,  247,  516,  395,  518,  552,  347,
+ /*  1180 */   403,  404,  405,  564,    7,  314,   85,  334,  332,  233,
+ /*  1190 */    84,  234,   80,  170,   58,  214,  417,  462,  121,   86,
+ /*  1200 */   337,  342,  499,  493,  235,  301,  236,  503,  418,  498,
+ /*  1210 */   248,  124,  504,  502,  220,  354,  288,  241,  527,  476,
+ /*  1220 */   243,  528,  480,  521,  529,  289,  185,  358,  535,  186,
+ /*  1230 */    89,  356,  189,  188,  117,  537,  364,  191,  548,  194,
+ /*  1240 */   219,  132,  142,  221,  376,  377,  555,  133,  134,  310,
+ /*  1250 */   135,  136,  266,  563,  538,  581,  576,  141,   93,  393,
+ /*  1260 */    96,  138,  407,  577,  578,  107,  218,  101,  104,  118,
+ /*  1270 */   312,  625,  626,  166,  435,  167,  438,  442,   72,  454,
+ /*  1280 */   451,  143,  157,  169,  455,  456,  460,    6,   14,   82,
+ /*  1290 */   473,   13,  122,  161,  123,  486,  487,  217,   87,  346,
+ /*  1300 */   125,  126,  116,  254,   88,  127,  183,  246,  355,  145,
+ /*  1310 */   536,  128,  173,  359,  192,  351,  267,  130,    9,  551,
+ /*  1320 */   131,  196,   90,  539,   91,  129,   15,  198,  556,  543,
+ /*  1330 */   199,  559,  200,  137,  139,  566,   16,  140,  106,  574,
+ /*  1340 */   207,  148,  286,  390,  386,  588,
 };
 static const YYCODETYPE yy_lookahead[] = {
- /*     0 */    16,  139,  140,  141,  168,   21,  144,   23,   69,   70,
- /*    10 */    71,   72,  176,   74,   75,   76,   77,   78,   79,   80,
- /*    20 */    81,   82,   83,   84,   78,   79,   42,   43,   73,   74,
+ /*     0 */    16,  139,  140,  141,  142,   21,   23,   23,   69,   70,
+ /*    10 */    71,   72,  110,   74,   75,   76,   77,   78,   79,   80,
+ /*    20 */    81,   82,   83,   84,    1,    2,   42,   43,   73,   74,
  /*    30 */    75,   76,   77,   78,   79,   80,   81,   82,   83,   84,
- /*    40 */     1,    2,   23,   58,   60,   61,   62,   63,   64,   65,
+ /*    40 */    78,   79,   23,   58,   60,   61,   62,   63,   64,   65,
  /*    50 */    66,   67,   68,   69,   70,   71,   72,  147,   74,   75,
  /*    60 */    76,   77,   78,   79,   80,   81,   82,   83,   84,   16,
- /*    70 */   185,  186,   88,   88,  110,   22,  217,   92,  219,  220,
+ /*    70 */   147,   88,   88,   88,   84,   22,  217,   92,  219,  220,
  /*    80 */    74,   75,   76,   77,   78,   79,   80,   81,   82,   83,
- /*    90 */    84,  217,  218,  219,  220,   42,   43,  238,  188,   46,
+ /*    90 */    84,  169,  169,  170,   22,   42,   43,   78,  188,   46,
  /*   100 */    78,   79,   80,   81,   82,   83,   84,   88,   89,  124,
  /*   110 */   125,  126,   16,   60,   61,   62,   63,   64,   65,   66,
  /*   120 */    67,   68,   69,   70,   71,   72,  147,   74,   75,   76,
  /*   130 */    77,   78,   79,   80,   81,   82,   83,   84,   42,   43,
- /*   140 */    44,   80,   81,   82,   83,   84,   23,   84,  169,  170,
- /*   150 */    19,  164,  165,  166,   23,   23,   60,   61,   62,   63,
- /*   160 */    64,   65,   66,   67,   68,   69,   70,   71,   72,  110,
+ /*   140 */    44,  143,  144,  161,  221,   21,  148,   23,  169,  170,
+ /*   150 */    19,   83,   84,  155,   23,  161,   60,   61,   62,   63,
+ /*   160 */    64,   65,   66,   67,   68,   69,   70,   71,   72,   97,
  /*   170 */    74,   75,   76,   77,   78,   79,   80,   81,   82,   83,
- /*   180 */    84,   16,  123,  147,  150,  147,   21,  167,  168,   58,
- /*   190 */   211,  147,  156,  157,   92,  216,  176,   23,  147,  176,
- /*   200 */   177,   78,   79,  165,  166,  103,  183,   42,   43,   78,
- /*   210 */    79,   88,   89,  169,  170,  228,  180,  181,  169,   88,
- /*   220 */    88,   98,   99,   92,   16,   60,   61,   62,   63,   64,
- /*   230 */    65,   66,   67,   68,   69,   70,   71,   72,  147,   74,
+ /*   180 */    84,   16,  200,  147,   25,  147,   21,  189,   29,   58,
+ /*   190 */   211,  147,  156,  157,  200,  216,  167,  168,  147,  217,
+ /*   200 */    41,  219,  220,  165,  166,  176,  160,   42,   43,   78,
+ /*   210 */    79,  213,   88,  169,  170,  169,  180,  181,  155,   88,
+ /*   220 */   169,  170,  181,   92,   16,   60,   61,   62,   63,   64,
+ /*   230 */    65,   66,   67,   68,   69,   70,   71,   72,  240,   74,
  /*   240 */    75,   76,   77,   78,   79,   80,   81,   82,   83,   84,
- /*   250 */    42,   43,   78,  209,  210,  124,  125,  126,  224,  208,
- /*   260 */   169,  170,   88,   89,  230,  227,  228,   16,   60,   61,
+ /*   250 */    42,   43,  189,  209,  210,  124,  125,  126,   80,   81,
+ /*   260 */    82,   83,   84,  169,  226,  227,  215,   16,   60,   61,
  /*   270 */    62,   63,   64,   65,   66,   67,   68,   69,   70,   71,
  /*   280 */    72,   23,   74,   75,   76,   77,   78,   79,   80,   81,
- /*   290 */    82,   83,   84,   42,   43,  160,   16,  147,  161,   83,
- /*   300 */    84,  210,  161,  153,  169,  158,  156,  157,  161,  162,
- /*   310 */   163,   60,   61,   62,   63,   64,   65,   66,   67,   68,
- /*   320 */    69,   70,   71,   72,  161,   74,   75,   76,   77,   78,
- /*   330 */    79,   80,   81,   82,   83,   84,  192,  200,  147,  131,
- /*   340 */    16,  200,   16,  199,   20,  169,   88,   89,   90,  185,
- /*   350 */   186,   93,   94,   95,  217,   22,  219,  220,  147,  147,
- /*   360 */   169,  170,  104,  200,   84,  147,   42,   43,  156,  157,
- /*   370 */    90,   91,   92,   93,   94,   95,   96,  164,  165,  166,
+ /*   290 */    82,   83,   84,   42,   43,   90,   16,  168,   93,   94,
+ /*   300 */    95,  176,  177,  147,  217,  176,  219,  220,  183,  104,
+ /*   310 */   190,   60,   61,   62,   63,   64,   65,   66,   67,   68,
+ /*   320 */    69,   70,   71,   72,  237,   74,   75,   76,   77,   78,
+ /*   330 */    79,   80,   81,   82,   83,   84,  181,  147,  182,  131,
+ /*   340 */    16,  147,   16,   30,   20,  155,   88,   89,   90,  185,
+ /*   350 */   186,   93,   94,   95,  106,   22,  108,  109,  147,  169,
+ /*   360 */   170,  186,  104,   50,   84,  147,   42,   43,  185,  186,
+ /*   370 */    90,   91,   92,   93,   94,   95,   96,  243,  244,  189,
  /*   380 */   169,  170,  131,  103,   60,   61,   62,   63,   64,   65,
  /*   390 */    66,   67,   68,   69,   70,   71,   72,  155,   74,   75,
  /*   400 */    76,   77,   78,   79,   80,   81,   82,   83,   84,   16,
- /*   410 */    84,   11,  221,   20,   30,   16,  147,   91,   92,   93,
- /*   420 */    94,   95,   96,   90,  147,  181,   93,   94,   95,  103,
- /*   430 */   212,  189,  155,   27,   50,   42,   43,  104,  169,  170,
- /*   440 */    34,  228,   43,  201,  202,  181,  169,  170,  206,   49,
- /*   450 */   161,  162,  163,   60,   61,   62,   63,   64,   65,   66,
+ /*   410 */    84,   19,   20,   20,   22,  102,  147,   91,   92,   93,
+ /*   420 */    94,   95,   96,   90,  147,   23,   93,   94,   95,  103,
+ /*   430 */   212,  189,  155,   49,  165,   42,   43,  104,  217,  218,
+ /*   440 */   219,  220,   23,  201,  202,   23,  169,  170,  206,   19,
+ /*   450 */    20,   59,   22,   60,   61,   62,   63,   64,   65,   66,
  /*   460 */    67,   68,   69,   70,   71,   72,  189,   74,   75,   76,
- /*   470 */    77,   78,   79,   80,   81,   82,   83,   84,   16,   25,
- /*   480 */   211,  147,   20,   29,   12,  147,  102,   19,  211,   21,
- /*   490 */   147,  141,  147,  216,  144,   41,   24,   98,   20,   99,
- /*   500 */   100,  101,  103,  165,   42,   43,    0,    1,    2,   37,
- /*   510 */   110,   39,  169,  170,  169,  170,  182,   19,   20,  190,
- /*   520 */    22,   49,   60,   61,   62,   63,   64,   65,   66,   67,
- /*   530 */    68,   69,   70,   71,   72,  155,   74,   75,   76,   77,
- /*   540 */    78,   79,   80,   81,   82,   83,   84,   16,  147,   90,
- /*   550 */    20,   20,   93,   94,   95,  147,  155,   59,  215,  225,
- /*   560 */   215,   20,  130,  104,  132,  227,  228,   42,   43,  189,
- /*   570 */   169,  170,   16,   42,   43,   20,   19,   22,   19,   20,
- /*   580 */    23,   22,   18,  147,  106,  147,  108,  109,   63,   64,
+ /*   470 */    77,   78,   79,   80,   81,   82,   83,   84,   16,   11,
+ /*   480 */    78,   79,   20,   99,  100,  101,  201,  202,  211,   59,
+ /*   490 */    88,   89,  147,  216,  110,  226,  227,  147,   42,   43,
+ /*   500 */    98,   99,   80,  147,   42,   43,  147,   88,   89,  153,
+ /*   510 */    88,   89,  156,  157,  169,  170,  147,   49,  147,   63,
+ /*   520 */    64,  161,   60,   61,   62,   63,   64,   65,   66,   67,
+ /*   530 */    68,   69,   70,   71,   72,  147,   74,   75,   76,   77,
+ /*   540 */    78,   79,   80,   81,   82,   83,   84,   16,   92,  158,
+ /*   550 */    12,   20,  161,  162,  163,  210,  155,  150,  147,   16,
+ /*   560 */   200,  147,   24,  164,  165,  166,   22,   99,  100,  101,
+ /*   570 */   164,  165,  166,   42,   43,   37,  188,   39,  110,  208,
+ /*   580 */   169,  170,   18,  169,  170,   19,   43,   49,  147,   23,
  /*   590 */   189,   60,   61,   62,   63,   64,   65,   66,   67,   68,
- /*   600 */    69,   70,   71,   72,  147,   74,   75,   76,   77,   78,
- /*   610 */    79,   80,   81,   82,   83,   84,   16,   92,   59,   55,
- /*   620 */   212,   21,  147,   19,  147,   23,  188,   23,   12,  217,
- /*   630 */    23,  219,  220,    7,    8,    9,  106,  186,  108,  109,
- /*   640 */    24,  147,   42,   43,  208,   88,   89,  106,   92,  108,
- /*   650 */   109,  244,  245,   37,  147,   39,  147,  182,   94,   16,
+ /*   600 */    69,   70,   71,   72,   20,   74,   75,   76,   77,   78,
+ /*   610 */    79,   80,   81,   82,   83,   84,   16,  147,  147,   55,
+ /*   620 */    12,   21,  211,    0,    1,    2,  227,  156,  157,  215,
+ /*   630 */    19,  224,   24,  227,   23,  110,  229,  141,  142,  169,
+ /*   640 */   170,   98,   42,   43,   22,   37,  103,   39,  123,  208,
+ /*   650 */    20,  161,  162,  163,   88,   89,  147,  113,   94,   16,
  /*   660 */    60,   61,   62,   63,   64,   65,   66,   67,   68,   69,
- /*   670 */    70,   71,   72,  145,   74,   75,   76,   77,   78,   79,
- /*   680 */    80,   81,   82,   83,   84,   42,   43,   80,  142,  143,
- /*   690 */    88,   89,   88,   89,  148,   88,   89,  133,   14,  147,
- /*   700 */   225,  155,   16,   60,   61,   62,   63,   64,   65,   66,
- /*   710 */    67,   68,   69,   70,   71,   72,  114,   74,   75,   76,
+ /*   670 */    70,   71,   72,  147,   74,   75,   76,   77,   78,   79,
+ /*   680 */    80,   81,   82,   83,   84,   42,   43,  192,  147,   20,
+ /*   690 */   106,  182,  108,  109,  199,  169,  170,  133,  147,   88,
+ /*   700 */    89,  155,   16,   60,   61,   62,   63,   64,   65,   66,
+ /*   710 */    67,   68,   69,   70,   71,   72,  145,   74,   75,   76,
  /*   720 */    77,   78,   79,   80,   81,   82,   83,   84,   42,   43,
- /*   730 */   201,  202,  147,  147,  182,  189,   52,  147,   54,  147,
- /*   740 */   147,  147,  147,  147,  155,   16,   60,   61,   62,   63,
+ /*   730 */   241,  242,  147,  182,  147,  189,  106,   19,  108,  109,
+ /*   740 */     7,    8,    9,  121,   14,   16,   60,   61,   62,   63,
  /*   750 */    64,   65,   66,   67,   68,   69,   70,   71,   72,  213,
  /*   760 */    74,   75,   76,   77,   78,   79,   80,   81,   82,   83,
- /*   770 */    84,   42,   43,  188,  188,  182,  182,  225,  189,  106,
- /*   780 */   188,  108,  109,  188,   99,  100,  101,  241,   16,  155,
+ /*   770 */    84,   42,   43,  188,  147,  106,  230,  108,  109,  124,
+ /*   780 */   125,  235,   52,  191,   54,  147,   68,  147,   16,   80,
  /*   790 */    61,   62,   63,   64,   65,   66,   67,   68,   69,   70,
- /*   800 */    71,   72,  213,   74,   75,   76,   77,   78,   79,   80,
- /*   810 */    81,   82,   83,   84,   42,   43,   23,  133,  225,  225,
- /*   820 */    21,  225,   23,  189,  239,  236,   99,  100,  101,   22,
- /*   830 */   242,  243,  155,  191,   62,   63,   64,   65,   66,   67,
+ /*   800 */    71,   72,   23,   74,   75,   76,   77,   78,   79,   80,
+ /*   810 */    81,   82,   83,   84,   42,   43,  107,   23,  147,   22,
+ /*   820 */   111,   19,  182,  238,  147,   23,  188,  155,  107,  147,
+ /*   830 */   147,  147,  111,  231,   62,   63,   64,   65,   66,   67,
  /*   840 */    68,   69,   70,   71,   72,  147,   74,   75,   76,   77,
- /*   850 */    78,   79,   80,   81,   82,   83,   84,   16,   17,   22,
- /*   860 */    19,  147,  147,  147,   23,  147,  189,  169,  170,  147,
- /*   870 */    14,  147,   31,   16,   17,  147,   19,  147,   19,   43,
- /*   880 */    23,   88,   89,  169,  170,  169,  170,   88,   31,   48,
- /*   890 */   147,  169,  170,  169,  170,  147,   89,  169,  170,   58,
- /*   900 */   147,  147,  147,  188,  147,   48,  188,  114,   52,  147,
- /*   910 */    54,   19,  147,  124,  125,   58,  147,  169,  170,   78,
- /*   920 */    79,  114,  169,  170,  169,  170,  169,  170,   87,   88,
- /*   930 */    89,  169,  170,   92,   98,   78,   79,   80,  169,  170,
- /*   940 */    91,  147,  188,   22,   87,   88,   89,   16,   17,   92,
- /*   950 */    19,  110,  147,  155,   23,  147,  155,   22,  121,  110,
- /*   960 */    68,   80,   31,  169,  170,  124,  125,  126,  127,  128,
- /*   970 */   129,  112,  123,  208,  169,  170,  107,  169,  170,   48,
- /*   980 */   111,  124,  125,  126,  127,  128,  129,  189,  107,   58,
- /*   990 */   189,    5,  111,  147,    7,    8,   10,   11,   12,   13,
- /*  1000 */   161,   20,  147,   22,  178,  147,   91,   92,  147,   78,
- /*  1010 */    79,  147,   26,   19,   28,  169,  170,   23,   87,   88,
+ /*   850 */    78,   79,   80,   81,   82,   83,   84,   16,   17,  182,
+ /*   860 */    19,  189,  147,  133,   23,  161,   43,   88,   89,  147,
+ /*   870 */   188,  188,   31,   16,   17,  147,   19,   99,  100,  101,
+ /*   880 */    23,  147,   88,   89,  147,  213,   89,  147,   31,   48,
+ /*   890 */    88,  169,  170,  114,  147,   19,  212,  169,  170,   58,
+ /*   900 */   147,  147,  147,  188,  147,   48,  208,  235,  114,  169,
+ /*   910 */   170,  114,   99,  100,  101,   58,  169,  170,  147,   78,
+ /*   920 */    79,   98,  169,  170,  169,  170,  169,  170,   87,   88,
+ /*   930 */    89,   16,  147,   92,  203,   78,   79,   80,  147,   91,
+ /*   940 */   169,  170,  188,  147,   87,   88,   89,   16,   17,   92,
+ /*   950 */    19,  110,  147,  155,   23,  147,  155,   27,  110,  155,
+ /*   960 */   169,  170,   31,   14,   34,  124,  125,  126,  127,  128,
+ /*   970 */   129,  123,  147,  188,  169,  170,  147,  169,  170,   48,
+ /*   980 */   147,  124,  125,  126,  127,  128,  129,  189,  112,   58,
+ /*   990 */   189,    5,  178,  189,  147,  178,   10,   11,   12,   13,
+ /*  1000 */   178,   52,  147,   54,   19,  147,   21,   92,  147,   78,
+ /*  1010 */    79,  130,   26,  132,   28,  147,  169,  170,   87,   88,
  /*  1020 */    89,   35,  147,   92,  169,  170,  147,  169,  170,  147,
- /*  1030 */   169,  170,   97,   47,  113,   49,   20,  203,   22,   53,
- /*  1040 */   147,  147,   56,  147,  169,  170,  147,  147,  147,   20,
- /*  1050 */   147,  169,  170,  147,  147,  124,  125,  126,  127,  128,
- /*  1060 */   129,  147,  169,  170,  178,  169,  170,  147,  169,  170,
- /*  1070 */   169,  170,  169,  170,  147,  169,  170,  147,   20,  147,
- /*  1080 */    22,  147,   88,  147,  147,   99,  100,  101,   59,  169,
- /*  1090 */   170,  105,  147,   20,  147,   22,  110,  178,  147,  169,
- /*  1100 */   170,  169,  170,  169,  170,  169,  170,   20,  147,   22,
- /*  1110 */   147,   20,  147,   22,  169,  170,  169,  170,  147,  147,
- /*  1120 */   134,   20,  147,   22,   20,  147,   22,  147,   20,  232,
- /*  1130 */    22,  233,  169,  170,  169,  170,  147,  147,  147,  147,
- /*  1140 */   169,  170,  147,  147,  169,  170,  147,  169,  170,  169,
- /*  1150 */   170,  147,  147,  147,  147,  147,  147,  191,  161,  149,
- /*  1160 */   193,  177,  229,  223,  161,  172,    6,  229,  194,  146,
- /*  1170 */   172,  194,  172,  172,  172,  161,  146,  146,  146,   22,
- /*  1180 */   154,  121,  194,  118,  173,  119,  116,  120,  112,  130,
- /*  1190 */   222,  152,  152,   98,  115,   98,  171,   97,  171,   40,
- /*  1200 */   179,  189,   19,   84,  171,  226,  171,  173,  195,  226,
- /*  1210 */   174,  196,  171,  171,  197,  171,  198,  179,   15,  174,
- /*  1220 */   151,   60,  151,  204,  152,  205,  204,  152,  151,  205,
- /*  1230 */   152,   38,  152,  130,  151,  184,  152,  184,   19,   15,
- /*  1240 */   194,  152,  187,  187,  187,  152,  194,  184,  187,   33,
- /*  1250 */   152,  152,  137,  159,    1,   20,  175,  214,  112,  112,
- /*  1260 */   175,  214,  234,  112,  112,   92,   19,   11,   20,  107,
- /*  1270 */    20,   19,  235,   19,   32,   20,  112,  114,   20,   22,
- /*  1280 */    20,   22,  117,   22,  117,  237,  237,   19,   44,   20,
- /*  1290 */   240,   20,   20,  231,   19,   44,   19,  243,   20,   19,
- /*  1300 */    19,   19,   96,  103,   16,   21,   44,   17,   98,   36,
- /*  1310 */   246,   45,   45,   22,   51,  133,   98,   19,    5,    1,
- /*  1320 */   122,   19,  102,   14,  113,   17,  113,  115,  102,  122,
- /*  1330 */    19,  123,   68,   68,   20,   14,   57,  135,   19,    3,
- /*  1340 */   136,    4,
+ /*  1030 */   169,  170,   20,   47,   22,   49,  147,  169,  170,   53,
+ /*  1040 */   147,   20,   56,   22,  169,  170,  147,  147,  147,   20,
+ /*  1050 */   147,   22,  147,  147,   92,  124,  125,  126,  127,  128,
+ /*  1060 */   129,  147,  169,  170,  232,  103,  147,  147,  169,  170,
+ /*  1070 */   169,  170,  169,  170,  169,  170,  147,    7,    8,   91,
+ /*  1080 */    92,  147,  147,  147,  147,   99,  100,  101,  169,  170,
+ /*  1090 */   147,  105,  147,   20,  147,   22,  110,  147,  169,  170,
+ /*  1100 */   147,  147,  147,  169,  170,  169,  170,   20,  147,   22,
+ /*  1110 */   147,  147,  147,  147,  169,  170,  169,  170,  147,   20,
+ /*  1120 */   134,   22,  169,  170,  169,  170,  147,   20,  147,  147,
+ /*  1130 */   169,  170,  169,  170,  147,  169,  170,  147,  147,  147,
+ /*  1140 */   169,  170,   20,   20,   22,   22,  147,  147,  169,  170,
+ /*  1150 */   149,  169,  170,   20,  161,   22,  169,  170,  191,  169,
+ /*  1160 */   170,   20,  193,   22,  223,  161,   59,  228,  228,  172,
+ /*  1170 */   172,  177,  161,    6,  172,  172,  146,  172,  194,  173,
+ /*  1180 */   146,  146,  146,  194,   22,  154,  121,  118,  116,  194,
+ /*  1190 */   119,  195,  130,  112,  120,  222,  189,  152,  152,   98,
+ /*  1200 */   115,   98,  179,  171,  196,   40,  197,   97,  198,  171,
+ /*  1210 */   171,   19,  171,  173,   84,   15,  174,  204,  171,  205,
+ /*  1220 */   204,  171,  205,  179,  171,  174,  151,   38,  152,  151,
+ /*  1230 */   130,  152,  152,  151,   60,  152,  152,  151,  184,  184,
+ /*  1240 */   225,   19,  214,  225,  152,   15,  194,  187,  187,  152,
+ /*  1250 */   187,  187,  233,  194,  234,  137,   33,  214,  236,    1,
+ /*  1260 */   236,  184,   20,  152,  152,  239,  175,  159,  175,  242,
+ /*  1270 */   245,  112,  112,  112,   92,  112,  107,   20,   19,   11,
+ /*  1280 */    20,   19,   19,   22,   20,   20,   20,  117,  117,   22,
+ /*  1290 */   114,   22,   19,  112,   20,   20,   20,   44,   19,   44,
+ /*  1300 */    19,   19,   32,   20,   19,   19,   96,  103,   16,   21,
+ /*  1310 */    17,   98,   22,   36,   98,   44,  133,   19,    5,    1,
+ /*  1320 */   102,  122,   68,   51,   68,   45,   19,  113,    1,   45,
+ /*  1330 */    14,   17,  115,  113,  102,  123,   19,  122,   14,   20,
+ /*  1340 */   135,   19,  136,    3,   57,    4,
 };
-#define YY_SHIFT_USE_DFLT (-62)
-#define YY_SHIFT_MAX 389
+#define YY_SHIFT_USE_DFLT (-99)
+#define YY_SHIFT_MAX 390
 static const short yy_shift_ofst[] = {
- /*     0 */    39,  841,  986,  -16,  841,  931,  931,  258,  123,  -36,
- /*    10 */    96,  931,  931,  931,  931,  931,  -45,  400,  174,   19,
- /*    20 */   132,  -54,  -54,   53,  165,  208,  251,  324,  393,  462,
- /*    30 */   531,  600,  643,  686,  643,  643,  643,  643,  643,  643,
+ /*     0 */    23,  841,  986,  -16,  841,  931,  931,  258,  402,  384,
+ /*    10 */   -98,   96,  931,  931,  931,  931,  931,  -45,  468,   19,
+ /*    20 */   419,  -17,  -38,  -38,   53,  165,  208,  251,  324,  393,
+ /*    30 */   462,  531,  600,  643,  686,  643,  643,  643,  643,  643,
  /*    40 */   643,  643,  643,  643,  643,  643,  643,  643,  643,  643,
- /*    50 */   643,  643,  729,  772,  772,  857,  931,  931,  931,  931,
+ /*    50 */   643,  643,  643,  729,  772,  772,  857,  931,  931,  931,
  /*    60 */   931,  931,  931,  931,  931,  931,  931,  931,  931,  931,
  /*    70 */   931,  931,  931,  931,  931,  931,  931,  931,  931,  931,
  /*    80 */   931,  931,  931,  931,  931,  931,  931,  931,  931,  931,
- /*    90 */   931,  931,  931,  931,  931,  931,  -61,  -61,    6,    6,
- /*   100 */   280,   22,   61,  399,  564,   19,   19,   19,   19,   19,
- /*   110 */    19,   19,  216,  132,   63,  -62,  -62,  -62,  131,  326,
- /*   120 */   472,  472,  498,  559,  506,  799,   19,  799,   19,   19,
- /*   130 */    19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
- /*   140 */    19,  849,   59,  -36,  -36,  -36,  -62,  -62,  -62,  -15,
- /*   150 */   -15,  333,  459,  478,  557,  530,  541,  616,  602,  793,
- /*   160 */   604,  607,  626,   19,   19,  881,   19,   19,  994,   19,
- /*   170 */    19,  807,   19,   19,  673,  807,   19,   19,  384,  384,
- /*   180 */   384,   19,   19,  673,   19,   19,  673,   19,  454,  685,
- /*   190 */    19,   19,  673,   19,   19,   19,  673,   19,   19,   19,
- /*   200 */   673,  673,   19,   19,   19,   19,   19,  468,  869,  921,
- /*   210 */   132,  789,  789,  432,  406,  406,  406,  836,  406,  132,
- /*   220 */   406,  132,  935,  837,  837, 1160, 1160, 1160, 1160, 1157,
- /*   230 */   -36, 1060, 1065, 1066, 1070, 1067, 1059, 1076, 1076, 1095,
- /*   240 */  1079, 1095, 1079, 1097, 1097, 1159, 1097, 1100, 1097, 1183,
- /*   250 */  1119, 1119, 1159, 1097, 1097, 1097, 1183, 1203, 1076, 1203,
- /*   260 */  1076, 1203, 1076, 1076, 1193, 1103, 1203, 1076, 1161, 1161,
- /*   270 */  1219, 1060, 1076, 1224, 1224, 1224, 1224, 1060, 1161, 1219,
- /*   280 */  1076, 1216, 1216, 1076, 1076, 1115,  -62,  -62,  -62,  -62,
- /*   290 */   -62,  -62,  525,  684,  727,  856,  859,  556,  555,  981,
- /*   300 */   102,  987,  915, 1016, 1058, 1073, 1087, 1091, 1101, 1104,
- /*   310 */   892, 1108, 1029, 1253, 1235, 1146, 1147, 1151, 1152, 1173,
- /*   320 */  1162, 1247, 1248, 1250, 1252, 1256, 1254, 1255, 1257, 1258,
- /*   330 */  1260, 1259, 1165, 1261, 1167, 1259, 1163, 1268, 1269, 1164,
- /*   340 */  1271, 1272, 1242, 1244, 1275, 1251, 1277, 1278, 1280, 1281,
- /*   350 */  1262, 1282, 1206, 1200, 1288, 1290, 1284, 1210, 1273, 1263,
- /*   360 */  1266, 1291, 1267, 1182, 1218, 1298, 1313, 1318, 1220, 1264,
- /*   370 */  1265, 1198, 1302, 1211, 1309, 1212, 1308, 1213, 1226, 1207,
- /*   380 */  1311, 1208, 1314, 1321, 1279, 1202, 1204, 1319, 1336, 1337,
+ /*    90 */   931,  931,  931,  931,  931,  931,  931,  -61,  -61,    6,
+ /*   100 */     6,  280,   22,  178,  543,  564,  419,  419,   68,  -17,
+ /*   110 */   -10,  -99,  -99,  -99,  131,  326,  538,  538,  392,  430,
+ /*   120 */   623,  124,  419,  124,  419,  419,  419,  419,  419,  419,
+ /*   130 */   419,  419,  419,  419,  419,  419,  419,  419,  419,  419,
+ /*   140 */   419,  848,  525,  -98,  -98,  -98,  -99,  -99,  -99,  -15,
+ /*   150 */   -15,  333,  205,  584,  566,  630,  669,  608,  779,  794,
+ /*   160 */   611,  422,  733,  419,  419,  709,  419,  419,  802,  419,
+ /*   170 */   419,  797,  419,  419,  248,  797,  419,  419,  313,  313,
+ /*   180 */   313,  419,  419,  419,  248,  419,  419,  248,  419,  159,
+ /*   190 */   778,  419,  419,  248,  419,  419,  419,  248,  419,  419,
+ /*   200 */   419,  248,  248,  419,  419,  419,  419,  419,  985,  721,
+ /*   210 */   544,  -17,  655,  655,  881,  930,  930,  930,  823,  930,
+ /*   220 */   -17,  930,  -17,   72,  622,  622, 1167, 1167, 1167, 1167,
+ /*   230 */  1162,  -98, 1065, 1069, 1071, 1072, 1074, 1062, 1081, 1081,
+ /*   240 */  1101, 1085, 1101, 1085, 1103, 1103, 1165, 1103, 1110, 1103,
+ /*   250 */  1192, 1130, 1130, 1165, 1103, 1103, 1103, 1192, 1200, 1081,
+ /*   260 */  1200, 1081, 1200, 1081, 1081, 1189, 1100, 1200, 1081, 1174,
+ /*   270 */  1174, 1222, 1065, 1081, 1230, 1230, 1230, 1230, 1065, 1174,
+ /*   280 */  1222, 1081, 1223, 1223, 1081, 1081, 1118,  -99,  -99,  -99,
+ /*   290 */   -99,  -99,  456,  730,  813,  949,  876,  915, 1012, 1021,
+ /*   300 */   962, 1070,  988, 1029, 1073, 1087, 1099, 1122, 1123, 1133,
+ /*   310 */   718, 1141, 1107, 1258, 1242, 1159, 1160, 1161, 1163, 1182,
+ /*   320 */  1169, 1259, 1257, 1260, 1262, 1268, 1263, 1264, 1261, 1265,
+ /*   330 */  1266, 1267, 1170, 1269, 1171, 1267, 1176, 1273, 1274, 1181,
+ /*   340 */  1275, 1276, 1270, 1253, 1279, 1255, 1281, 1283, 1282, 1285,
+ /*   350 */  1271, 1286, 1210, 1204, 1292, 1293, 1288, 1213, 1277, 1272,
+ /*   360 */  1280, 1290, 1284, 1183, 1216, 1298, 1313, 1318, 1218, 1254,
+ /*   370 */  1256, 1199, 1307, 1214, 1327, 1316, 1217, 1314, 1220, 1232,
+ /*   380 */  1215, 1317, 1212, 1319, 1324, 1287, 1205, 1206, 1322, 1340,
+ /*   390 */  1341,
 };
-#define YY_REDUCE_USE_DFLT (-165)
+#define YY_REDUCE_USE_DFLT (-142)
 #define YY_REDUCE_MAX 291
 static const short yy_reduce_ofst[] = {
- /*     0 */  -138,  277,  546,  137,  401,  -21,   44,   36,   38,  242,
- /*    10 */  -141,  191,   91,  269,  343,  345, -126,  589,  338,  150,
- /*    20 */   147,  -13,  213,  412,  412,  412,  412,  412,  412,  412,
- /*    30 */   412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
- /*    40 */   412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
- /*    50 */   412,  412,  412,  412,  412,  211,  698,  714,  716,  722,
- /*    60 */   724,  728,  748,  753,  755,  757,  762,  769,  794,  805,
- /*    70 */   808,  846,  855,  858,  861,  875,  882,  893,  896,  899,
- /*    80 */   901,  903,  906,  920,  930,  932,  934,  936,  945,  947,
- /*    90 */   963,  965,  971,  975,  978,  980,  412,  412,  412,  412,
- /*   100 */    20,  412,  412,   23,   34,  334,  475,  552,  593,  594,
- /*   110 */   585,  212,  412,  289,  412,  412,  412,  412,  135, -164,
- /*   120 */  -115,  164,  407,  407,  350,  141,   51,  163,  596,  -90,
- /*   130 */   436,  218,  765,  438,  586,  592,  595,  715,  718,  408,
- /*   140 */   754,  380,  634,  677,  798,  801,  144,  529,  588,   49,
- /*   150 */   176,  244,  264,  329,  457,  329,  329,  451,  477,  494,
- /*   160 */   507,  509,  528,  590,  730,  642,  509,  743,  839,  864,
- /*   170 */   879,  834,  894,  900,  329,  834,  907,  914,  826,  886,
- /*   180 */   919,  927,  937,  329,  951,  961,  329,  972,  897,  898,
- /*   190 */   989,  990,  329,  991,  992,  995,  329,  996,  999, 1004,
- /*   200 */   329,  329, 1005, 1006, 1007, 1008, 1009, 1010,  966,  967,
- /*   210 */   997,  933,  938,  940,  993,  998, 1000,  984, 1001, 1003,
- /*   220 */  1002, 1014, 1011,  974,  977, 1023, 1030, 1031, 1032, 1026,
- /*   230 */  1012,  988, 1013, 1015, 1017, 1018,  968, 1039, 1040, 1019,
- /*   240 */  1020, 1022, 1024, 1025, 1027, 1021, 1033, 1034, 1035, 1036,
- /*   250 */   979,  983, 1038, 1041, 1042, 1044, 1045, 1069, 1072, 1071,
- /*   260 */  1075, 1077, 1078, 1080, 1028, 1037, 1083, 1084, 1051, 1053,
- /*   270 */  1043, 1046, 1089, 1055, 1056, 1057, 1061, 1052, 1063, 1047,
- /*   280 */  1093, 1048, 1049, 1098, 1099, 1050, 1094, 1081, 1085, 1062,
- /*   290 */  1054, 1064,
+ /*     0 */  -138,  277,   -2,  -18,  190,  -21,   44,   36,   38,  546,
+ /*    10 */   242,   87,  -77,  345,  411,   51,  414,  221,  672,  269,
+ /*    20 */   356,  391,  399,  406, -141, -141, -141, -141, -141, -141,
+ /*    30 */  -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+ /*    40 */  -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+ /*    50 */  -141, -141, -141, -141, -141, -141,  211,  470,  526,  722,
+ /*    60 */   728,  740,  747,  753,  755,  757,  771,  791,  805,  808,
+ /*    70 */   847,  855,  858,  861,  868,  875,  893,  899,  901,  903,
+ /*    80 */   905,  919,  929,  934,  936,  945,  947,  953,  955,  961,
+ /*    90 */   963,  966,  971,  979,  982,  987,  990, -141, -141, -141,
+ /*   100 */  -141,   29, -141, -141,  125,  407,  585,  471, -141,  490,
+ /*   110 */  -141, -141, -141, -141,   46,  129,  164,  183,  134,  134,
+ /*   120 */   496,   -6,  371,  360,  156,  509,  551,  640,  -90,  441,
+ /*   130 */   677,  218,  698,  388,  638,  682,  683,  715,  754,  684,
+ /*   140 */   785,   63,  401,  798,  801,  804,  495,  285,  489,  -78,
+ /*   150 */    94,   41,  155,  120,  194,  120,  120,  175,  350,  359,
+ /*   160 */   369,  541,  571,  587,  627,  592,  541,  671,  704,  734,
+ /*   170 */   737,  731,  796,  825,  120,  731,  829,  833,  814,  817,
+ /*   180 */   822,  879,  882,  889,  120,  900,  906,  120,  914,  602,
+ /*   190 */   832,  920,  935,  120,  937,  943,  950,  120,  954,  964,
+ /*   200 */   965,  120,  120,  981,  991,  992,  999, 1000, 1001,  967,
+ /*   210 */   969,  993,  939,  940,  941,  997,  998, 1002,  994, 1003,
+ /*   220 */  1004, 1005, 1011, 1006,  984,  989, 1030, 1034, 1035, 1036,
+ /*   230 */  1031, 1007,  995,  996, 1008, 1009, 1010,  973, 1045, 1046,
+ /*   240 */  1013, 1014, 1016, 1017, 1032, 1038, 1023, 1039, 1040, 1041,
+ /*   250 */  1042, 1015, 1018, 1044, 1047, 1050, 1053, 1051, 1075, 1076,
+ /*   260 */  1078, 1079, 1082, 1080, 1083, 1019, 1020, 1086, 1084, 1054,
+ /*   270 */  1055, 1028, 1052, 1092, 1060, 1061, 1063, 1064, 1059, 1077,
+ /*   280 */  1043, 1097, 1022, 1024, 1111, 1112, 1026, 1108, 1091, 1093,
+ /*   290 */  1027, 1025,
 };
 static const YYACTIONTYPE yy_default[] = {
- /*     0 */   595,  820,  902,  710,  902,  820,  902,  902,  848,  714,
- /*    10 */   877,  818,  902,  902,  902,  902,  792,  902,  848,  902,
- /*    20 */   626,  848,  848,  743,  902,  902,  902,  902,  902,  902,
- /*    30 */   902,  902,  744,  902,  822,  817,  813,  815,  814,  821,
- /*    40 */   745,  734,  741,  748,  726,  861,  750,  751,  757,  758,
- /*    50 */   878,  876,  780,  779,  798,  902,  902,  902,  902,  902,
+ /*     0 */   595,  821,  902,  711,  902,  821,  902,  902,  848,  902,
+ /*    10 */   715,  877,  819,  902,  902,  902,  902,  793,  902,  848,
+ /*    20 */   902,  627,  848,  848,  744,  902,  902,  902,  902,  902,
+ /*    30 */   902,  902,  902,  745,  902,  823,  818,  814,  816,  815,
+ /*    40 */   822,  746,  735,  742,  749,  727,  861,  751,  752,  758,
+ /*    50 */   759,  878,  876,  781,  780,  799,  902,  902,  902,  902,
  /*    60 */   902,  902,  902,  902,  902,  902,  902,  902,  902,  902,
  /*    70 */   902,  902,  902,  902,  902,  902,  902,  902,  902,  902,
  /*    80 */   902,  902,  902,  902,  902,  902,  902,  902,  902,  902,
- /*    90 */   902,  902,  902,  902,  902,  902,  782,  804,  781,  791,
- /*   100 */   619,  783,  784,  679,  614,  902,  902,  902,  902,  902,
- /*   110 */   902,  902,  785,  902,  786,  799,  800,  801,  902,  902,
- /*   120 */   902,  902,  902,  902,  595,  710,  902,  710,  902,  902,
+ /*    90 */   902,  902,  902,  902,  902,  902,  902,  783,  805,  782,
+ /*   100 */   792,  620,  784,  785,  680,  615,  902,  902,  786,  902,
+ /*   110 */   787,  800,  801,  802,  902,  902,  902,  902,  902,  902,
+ /*   120 */   595,  711,  902,  711,  902,  902,  902,  902,  902,  902,
  /*   130 */   902,  902,  902,  902,  902,  902,  902,  902,  902,  902,
- /*   140 */   902,  902,  902,  902,  902,  902,  704,  714,  895,  902,
- /*   150 */   902,  670,  902,  902,  902,  902,  902,  902,  902,  902,
- /*   160 */   902,  902,  602,  600,  902,  702,  902,  902,  628,  902,
- /*   170 */   902,  712,  902,  902,  717,  718,  902,  902,  902,  902,
- /*   180 */   902,  902,  902,  616,  902,  902,  691,  902,  854,  902,
- /*   190 */   902,  902,  868,  902,  902,  902,  866,  902,  902,  902,
- /*   200 */   693,  753,  834,  902,  881,  883,  902,  902,  702,  711,
- /*   210 */   902,  902,  902,  816,  737,  737,  737,  649,  737,  902,
- /*   220 */   737,  902,  652,  747,  747,  599,  599,  599,  599,  669,
- /*   230 */   902,  747,  738,  740,  730,  742,  902,  719,  719,  727,
- /*   240 */   729,  727,  729,  681,  681,  666,  681,  652,  681,  826,
- /*   250 */   831,  831,  666,  681,  681,  681,  826,  611,  719,  611,
- /*   260 */   719,  611,  719,  719,  858,  860,  611,  719,  683,  683,
- /*   270 */   759,  747,  719,  690,  690,  690,  690,  747,  683,  759,
- /*   280 */   719,  880,  880,  719,  719,  888,  636,  654,  654,  863,
- /*   290 */   895,  900,  902,  902,  902,  902,  766,  902,  902,  902,
+ /*   140 */   902,  902,  902,  902,  902,  902,  705,  715,  895,  902,
+ /*   150 */   902,  671,  902,  902,  902,  902,  902,  902,  902,  902,
+ /*   160 */   902,  902,  603,  601,  902,  703,  902,  902,  629,  902,
+ /*   170 */   902,  713,  902,  902,  718,  719,  902,  902,  902,  902,
+ /*   180 */   902,  902,  902,  902,  617,  902,  902,  692,  902,  854,
+ /*   190 */   902,  902,  902,  868,  902,  902,  902,  866,  902,  902,
+ /*   200 */   902,  694,  754,  834,  902,  881,  883,  902,  902,  703,
+ /*   210 */   712,  902,  902,  902,  817,  738,  738,  738,  650,  738,
+ /*   220 */   902,  738,  902,  653,  748,  748,  600,  600,  600,  600,
+ /*   230 */   670,  902,  748,  739,  741,  731,  743,  902,  720,  720,
+ /*   240 */   728,  730,  728,  730,  682,  682,  667,  682,  653,  682,
+ /*   250 */   827,  831,  831,  667,  682,  682,  682,  827,  612,  720,
+ /*   260 */   612,  720,  612,  720,  720,  858,  860,  612,  720,  684,
+ /*   270 */   684,  760,  748,  720,  691,  691,  691,  691,  748,  684,
+ /*   280 */   760,  720,  880,  880,  720,  720,  888,  637,  655,  655,
+ /*   290 */   895,  900,  902,  902,  902,  902,  767,  902,  902,  902,
  /*   300 */   902,  902,  902,  902,  902,  902,  902,  902,  902,  902,
- /*   310 */   841,  902,  902,  902,  902,  771,  767,  902,  768,  902,
- /*   320 */   696,  902,  902,  902,  902,  902,  902,  902,  902,  902,
- /*   330 */   902,  819,  902,  731,  902,  739,  902,  902,  902,  902,
+ /*   310 */   841,  902,  902,  902,  902,  772,  768,  902,  769,  902,
+ /*   320 */   697,  902,  902,  902,  902,  902,  902,  902,  902,  902,
+ /*   330 */   902,  820,  902,  732,  902,  740,  902,  902,  902,  902,
  /*   340 */   902,  902,  902,  902,  902,  902,  902,  902,  902,  902,
  /*   350 */   902,  902,  902,  902,  902,  902,  902,  902,  902,  902,
  /*   360 */   856,  857,  902,  902,  902,  902,  902,  902,  902,  902,
  /*   370 */   902,  902,  902,  902,  902,  902,  902,  902,  902,  902,
- /*   380 */   902,  902,  902,  902,  887,  902,  902,  890,  596,  902,
- /*   390 */   590,  593,  592,  594,  598,  601,  623,  624,  625,  603,
- /*   400 */   604,  605,  606,  607,  608,  609,  615,  617,  635,  637,
- /*   410 */   621,  639,  700,  701,  763,  694,  695,  699,  622,  774,
- /*   420 */   765,  769,  770,  772,  773,  787,  788,  790,  796,  803,
- /*   430 */   806,  789,  794,  795,  797,  802,  805,  697,  698,  809,
- /*   440 */   629,  630,  633,  634,  844,  846,  845,  847,  632,  631,
- /*   450 */   775,  778,  811,  812,  869,  870,  871,  872,  873,  807,
- /*   460 */   720,  810,  793,  732,  735,  736,  733,  703,  713,  722,
- /*   470 */   723,  724,  725,  708,  709,  715,  728,  761,  762,  716,
- /*   480 */   705,  706,  707,  808,  764,  776,  777,  640,  641,  771,
- /*   490 */   642,  643,  644,  682,  685,  686,  687,  645,  664,  667,
- /*   500 */   668,  646,  653,  647,  648,  655,  656,  657,  660,  661,
- /*   510 */   662,  663,  658,  659,  827,  828,  832,  830,  829,  650,
- /*   520 */   651,  665,  638,  627,  620,  671,  674,  675,  676,  677,
- /*   530 */   678,  680,  672,  673,  618,  610,  612,  721,  850,  859,
- /*   540 */   855,  851,  852,  853,  613,  823,  824,  684,  755,  756,
- /*   550 */   849,  862,  864,  760,  865,  867,  892,  688,  689,  692,
- /*   560 */   833,  874,  746,  749,  752,  754,  835,  836,  837,  838,
- /*   570 */   839,  842,  843,  840,  875,  879,  882,  884,  885,  886,
- /*   580 */   889,  891,  896,  897,  898,  901,  899,  597,  591,
+ /*   380 */   902,  902,  902,  902,  902,  887,  902,  902,  890,  596,
+ /*   390 */   902,  591,  593,  594,  598,  599,  602,  624,  625,  626,
+ /*   400 */   604,  605,  606,  607,  608,  609,  610,  616,  618,  636,
+ /*   410 */   638,  622,  640,  701,  702,  764,  695,  696,  700,  623,
+ /*   420 */   775,  766,  770,  771,  773,  774,  788,  789,  791,  797,
+ /*   430 */   804,  807,  790,  795,  796,  798,  803,  806,  698,  699,
+ /*   440 */   810,  630,  631,  634,  635,  844,  846,  845,  847,  633,
+ /*   450 */   632,  776,  779,  812,  813,  869,  870,  871,  872,  873,
+ /*   460 */   808,  721,  811,  794,  733,  736,  737,  734,  704,  714,
+ /*   470 */   723,  724,  725,  726,  709,  710,  716,  729,  762,  763,
+ /*   480 */   717,  706,  707,  708,  809,  765,  777,  778,  641,  642,
+ /*   490 */   772,  643,  644,  645,  683,  686,  687,  688,  646,  665,
+ /*   500 */   668,  669,  647,  654,  648,  649,  656,  657,  658,  661,
+ /*   510 */   662,  663,  664,  659,  660,  828,  829,  832,  830,  651,
+ /*   520 */   652,  666,  639,  628,  621,  672,  675,  676,  677,  678,
+ /*   530 */   679,  681,  673,  674,  619,  611,  613,  722,  850,  859,
+ /*   540 */   855,  851,  852,  853,  614,  824,  825,  685,  756,  757,
+ /*   550 */   849,  862,  864,  761,  865,  867,  863,  892,  689,  690,
+ /*   560 */   693,  833,  874,  747,  750,  753,  755,  835,  836,  837,
+ /*   570 */   838,  839,  842,  843,  840,  875,  879,  882,  884,  885,
+ /*   580 */   886,  889,  891,  896,  897,  898,  901,  899,  597,  592,
 };
 #define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
 
@@ -77688,8 +78908,8 @@
   "VARIABLE",      "CASE",          "WHEN",          "THEN",        
   "ELSE",          "INDEX",         "ALTER",         "TO",          
   "ADD",           "COLUMNKW",      "error",         "input",       
-  "cmdlist",       "ecmd",          "cmdx",          "cmd",         
-  "explain",       "transtype",     "trans_opt",     "nm",          
+  "cmdlist",       "ecmd",          "explain",       "cmdx",        
+  "cmd",           "transtype",     "trans_opt",     "nm",          
   "create_table",  "create_table_args",  "temp",          "ifnotexists", 
   "dbnm",          "columnlist",    "conslist_opt",  "select",      
   "column",        "columnid",      "type",          "carglist",    
@@ -77709,12 +78929,12 @@
   "setlist",       "insert_cmd",    "inscollist_opt",  "itemlist",    
   "exprlist",      "likeop",        "escape",        "between_op",  
   "in_op",         "case_operand",  "case_exprlist",  "case_else",   
-  "uniqueflag",    "idxitem",       "collate",       "nmnum",       
-  "plus_opt",      "number",        "trigger_decl",  "trigger_cmd_list",
-  "trigger_time",  "trigger_event",  "foreach_clause",  "when_clause", 
-  "trigger_cmd",   "database_kw_opt",  "key_opt",       "add_column_fullname",
-  "kwcolumn_opt",  "create_vtab",   "vtabarglist",   "vtabarg",     
-  "vtabargtoken",  "lp",            "anylist",     
+  "uniqueflag",    "collate",       "nmnum",         "plus_opt",    
+  "number",        "trigger_decl",  "trigger_cmd_list",  "trigger_time",
+  "trigger_event",  "foreach_clause",  "when_clause",   "trigger_cmd", 
+  "database_kw_opt",  "key_opt",       "add_column_fullname",  "kwcolumn_opt",
+  "create_vtab",   "vtabarglist",   "vtabarg",       "vtabargtoken",
+  "lp",            "anylist",     
 };
 #endif /* NDEBUG */
 
@@ -77725,12 +78945,12 @@
  /*   0 */ "input ::= cmdlist",
  /*   1 */ "cmdlist ::= cmdlist ecmd",
  /*   2 */ "cmdlist ::= ecmd",
- /*   3 */ "cmdx ::= cmd",
- /*   4 */ "ecmd ::= SEMI",
- /*   5 */ "ecmd ::= explain cmdx SEMI",
- /*   6 */ "explain ::=",
- /*   7 */ "explain ::= EXPLAIN",
- /*   8 */ "explain ::= EXPLAIN QUERY PLAN",
+ /*   3 */ "ecmd ::= SEMI",
+ /*   4 */ "ecmd ::= explain cmdx SEMI",
+ /*   5 */ "explain ::=",
+ /*   6 */ "explain ::= EXPLAIN",
+ /*   7 */ "explain ::= EXPLAIN QUERY PLAN",
+ /*   8 */ "cmdx ::= cmd",
  /*   9 */ "cmd ::= BEGIN transtype trans_opt",
  /*  10 */ "trans_opt ::=",
  /*  11 */ "trans_opt ::= TRANSACTION",
@@ -77961,80 +79181,79 @@
  /* 236 */ "uniqueflag ::=",
  /* 237 */ "idxlist_opt ::=",
  /* 238 */ "idxlist_opt ::= LP idxlist RP",
- /* 239 */ "idxlist ::= idxlist COMMA idxitem collate sortorder",
- /* 240 */ "idxlist ::= idxitem collate sortorder",
- /* 241 */ "idxitem ::= nm",
- /* 242 */ "collate ::=",
- /* 243 */ "collate ::= COLLATE ids",
- /* 244 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 245 */ "cmd ::= VACUUM",
- /* 246 */ "cmd ::= VACUUM nm",
- /* 247 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 248 */ "cmd ::= PRAGMA nm dbnm EQ ON",
- /* 249 */ "cmd ::= PRAGMA nm dbnm EQ DELETE",
- /* 250 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 251 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 252 */ "cmd ::= PRAGMA nm dbnm",
- /* 253 */ "nmnum ::= plus_num",
- /* 254 */ "nmnum ::= nm",
- /* 255 */ "plus_num ::= plus_opt number",
- /* 256 */ "minus_num ::= MINUS number",
- /* 257 */ "number ::= INTEGER|FLOAT",
- /* 258 */ "plus_opt ::= PLUS",
- /* 259 */ "plus_opt ::=",
- /* 260 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 261 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 262 */ "trigger_time ::= BEFORE",
- /* 263 */ "trigger_time ::= AFTER",
- /* 264 */ "trigger_time ::= INSTEAD OF",
- /* 265 */ "trigger_time ::=",
- /* 266 */ "trigger_event ::= DELETE|INSERT",
- /* 267 */ "trigger_event ::= UPDATE",
- /* 268 */ "trigger_event ::= UPDATE OF inscollist",
- /* 269 */ "foreach_clause ::=",
- /* 270 */ "foreach_clause ::= FOR EACH ROW",
- /* 271 */ "when_clause ::=",
- /* 272 */ "when_clause ::= WHEN expr",
- /* 273 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 274 */ "trigger_cmd_list ::=",
- /* 275 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 277 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 278 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 279 */ "trigger_cmd ::= select",
- /* 280 */ "expr ::= RAISE LP IGNORE RP",
- /* 281 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 282 */ "raisetype ::= ROLLBACK",
- /* 283 */ "raisetype ::= ABORT",
- /* 284 */ "raisetype ::= FAIL",
- /* 285 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 286 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 287 */ "cmd ::= DETACH database_kw_opt expr",
- /* 288 */ "key_opt ::=",
- /* 289 */ "key_opt ::= KEY expr",
- /* 290 */ "database_kw_opt ::= DATABASE",
- /* 291 */ "database_kw_opt ::=",
- /* 292 */ "cmd ::= REINDEX",
- /* 293 */ "cmd ::= REINDEX nm dbnm",
- /* 294 */ "cmd ::= ANALYZE",
- /* 295 */ "cmd ::= ANALYZE nm dbnm",
- /* 296 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 297 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
- /* 298 */ "add_column_fullname ::= fullname",
- /* 299 */ "kwcolumn_opt ::=",
- /* 300 */ "kwcolumn_opt ::= COLUMNKW",
- /* 301 */ "cmd ::= create_vtab",
- /* 302 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 303 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
- /* 304 */ "vtabarglist ::= vtabarg",
- /* 305 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 306 */ "vtabarg ::=",
- /* 307 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 308 */ "vtabargtoken ::= ANY",
- /* 309 */ "vtabargtoken ::= lp anylist RP",
- /* 310 */ "lp ::= LP",
- /* 311 */ "anylist ::=",
- /* 312 */ "anylist ::= anylist ANY",
+ /* 239 */ "idxlist ::= idxlist COMMA nm collate sortorder",
+ /* 240 */ "idxlist ::= nm collate sortorder",
+ /* 241 */ "collate ::=",
+ /* 242 */ "collate ::= COLLATE ids",
+ /* 243 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 244 */ "cmd ::= VACUUM",
+ /* 245 */ "cmd ::= VACUUM nm",
+ /* 246 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 247 */ "cmd ::= PRAGMA nm dbnm EQ ON",
+ /* 248 */ "cmd ::= PRAGMA nm dbnm EQ DELETE",
+ /* 249 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 250 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 251 */ "cmd ::= PRAGMA nm dbnm",
+ /* 252 */ "nmnum ::= plus_num",
+ /* 253 */ "nmnum ::= nm",
+ /* 254 */ "plus_num ::= plus_opt number",
+ /* 255 */ "minus_num ::= MINUS number",
+ /* 256 */ "number ::= INTEGER|FLOAT",
+ /* 257 */ "plus_opt ::= PLUS",
+ /* 258 */ "plus_opt ::=",
+ /* 259 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
+ /* 260 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 261 */ "trigger_time ::= BEFORE",
+ /* 262 */ "trigger_time ::= AFTER",
+ /* 263 */ "trigger_time ::= INSTEAD OF",
+ /* 264 */ "trigger_time ::=",
+ /* 265 */ "trigger_event ::= DELETE|INSERT",
+ /* 266 */ "trigger_event ::= UPDATE",
+ /* 267 */ "trigger_event ::= UPDATE OF inscollist",
+ /* 268 */ "foreach_clause ::=",
+ /* 269 */ "foreach_clause ::= FOR EACH ROW",
+ /* 270 */ "when_clause ::=",
+ /* 271 */ "when_clause ::= WHEN expr",
+ /* 272 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 273 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 274 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
+ /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
+ /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
+ /* 277 */ "trigger_cmd ::= DELETE FROM nm where_opt",
+ /* 278 */ "trigger_cmd ::= select",
+ /* 279 */ "expr ::= RAISE LP IGNORE RP",
+ /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 281 */ "raisetype ::= ROLLBACK",
+ /* 282 */ "raisetype ::= ABORT",
+ /* 283 */ "raisetype ::= FAIL",
+ /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 286 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 287 */ "key_opt ::=",
+ /* 288 */ "key_opt ::= KEY expr",
+ /* 289 */ "database_kw_opt ::= DATABASE",
+ /* 290 */ "database_kw_opt ::=",
+ /* 291 */ "cmd ::= REINDEX",
+ /* 292 */ "cmd ::= REINDEX nm dbnm",
+ /* 293 */ "cmd ::= ANALYZE",
+ /* 294 */ "cmd ::= ANALYZE nm dbnm",
+ /* 295 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 296 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
+ /* 297 */ "add_column_fullname ::= fullname",
+ /* 298 */ "kwcolumn_opt ::=",
+ /* 299 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 300 */ "cmd ::= create_vtab",
+ /* 301 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 302 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
+ /* 303 */ "vtabarglist ::= vtabarg",
+ /* 304 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 305 */ "vtabarg ::=",
+ /* 306 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 307 */ "vtabargtoken ::= ANY",
+ /* 308 */ "vtabargtoken ::= lp anylist RP",
+ /* 309 */ "lp ::= LP",
+ /* 310 */ "anylist ::=",
+ /* 311 */ "anylist ::= anylist ANY",
 };
 #endif /* NDEBUG */
 
@@ -78115,7 +79334,7 @@
     case 189: /* oneselect */
     case 206: /* seltablist_paren */
 {
-sqlite3SelectDelete(pParse->db, (yypminor->yy219));
+sqlite3SelectDelete(pParse->db, (yypminor->yy375));
 }
       break;
     case 169: /* term */
@@ -78127,10 +79346,10 @@
     case 218: /* escape */
     case 221: /* case_operand */
     case 223: /* case_else */
-    case 235: /* when_clause */
-    case 238: /* key_opt */
+    case 234: /* when_clause */
+    case 237: /* key_opt */
 {
-sqlite3ExprDelete(pParse->db, (yypminor->yy172));
+sqlite3ExprDelete(pParse->db, (yypminor->yy62));
 }
       break;
     case 174: /* idxlist_opt */
@@ -78146,7 +79365,7 @@
     case 216: /* exprlist */
     case 222: /* case_exprlist */
 {
-sqlite3ExprListDelete(pParse->db, (yypminor->yy174));
+sqlite3ExprListDelete(pParse->db, (yypminor->yy418));
 }
       break;
     case 188: /* fullname */
@@ -78154,25 +79373,25 @@
     case 201: /* seltablist */
     case 202: /* stl_prefix */
 {
-sqlite3SrcListDelete(pParse->db, (yypminor->yy373));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy151));
 }
       break;
     case 205: /* using_opt */
     case 208: /* inscollist */
     case 214: /* inscollist_opt */
 {
-sqlite3IdListDelete(pParse->db, (yypminor->yy432));
+sqlite3IdListDelete(pParse->db, (yypminor->yy240));
 }
       break;
-    case 231: /* trigger_cmd_list */
-    case 236: /* trigger_cmd */
+    case 230: /* trigger_cmd_list */
+    case 235: /* trigger_cmd */
 {
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy243));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy360));
 }
       break;
-    case 233: /* trigger_event */
+    case 232: /* trigger_event */
 {
-sqlite3IdListDelete(pParse->db, (yypminor->yy370).b);
+sqlite3IdListDelete(pParse->db, (yypminor->yy30).b);
 }
       break;
     default:  break;   /* If no destructor action specified: do nothing */
@@ -78407,13 +79626,13 @@
   { 139, 1 },
   { 140, 2 },
   { 140, 1 },
-  { 142, 1 },
   { 141, 1 },
   { 141, 3 },
-  { 144, 0 },
-  { 144, 1 },
+  { 142, 0 },
+  { 142, 1 },
+  { 142, 3 },
+  { 143, 1 },
   { 144, 3 },
-  { 143, 3 },
   { 146, 0 },
   { 146, 1 },
   { 146, 2 },
@@ -78421,10 +79640,10 @@
   { 145, 1 },
   { 145, 1 },
   { 145, 1 },
-  { 143, 2 },
-  { 143, 2 },
-  { 143, 2 },
-  { 143, 2 },
+  { 144, 2 },
+  { 144, 2 },
+  { 144, 2 },
+  { 144, 2 },
   { 148, 6 },
   { 151, 0 },
   { 151, 3 },
@@ -78503,12 +79722,12 @@
   { 185, 1 },
   { 185, 1 },
   { 185, 1 },
-  { 143, 4 },
+  { 144, 4 },
   { 187, 2 },
   { 187, 0 },
-  { 143, 8 },
-  { 143, 4 },
-  { 143, 1 },
+  { 144, 8 },
+  { 144, 4 },
+  { 144, 1 },
   { 155, 1 },
   { 155, 3 },
   { 190, 1 },
@@ -78561,15 +79780,15 @@
   { 198, 2 },
   { 198, 4 },
   { 198, 4 },
-  { 143, 4 },
+  { 144, 4 },
   { 194, 0 },
   { 194, 2 },
-  { 143, 6 },
+  { 144, 6 },
   { 212, 5 },
   { 212, 3 },
-  { 143, 8 },
-  { 143, 5 },
-  { 143, 6 },
+  { 144, 8 },
+  { 144, 5 },
+  { 144, 6 },
   { 213, 2 },
   { 213, 1 },
   { 215, 3 },
@@ -78638,85 +79857,84 @@
   { 216, 0 },
   { 211, 3 },
   { 211, 1 },
-  { 143, 11 },
+  { 144, 11 },
   { 224, 1 },
   { 224, 0 },
   { 174, 0 },
   { 174, 3 },
   { 182, 5 },
   { 182, 3 },
-  { 225, 1 },
-  { 226, 0 },
-  { 226, 2 },
-  { 143, 4 },
-  { 143, 1 },
-  { 143, 2 },
-  { 143, 5 },
-  { 143, 5 },
-  { 143, 5 },
-  { 143, 5 },
-  { 143, 6 },
-  { 143, 3 },
-  { 227, 1 },
-  { 227, 1 },
+  { 225, 0 },
+  { 225, 2 },
+  { 144, 4 },
+  { 144, 1 },
+  { 144, 2 },
+  { 144, 5 },
+  { 144, 5 },
+  { 144, 5 },
+  { 144, 5 },
+  { 144, 6 },
+  { 144, 3 },
+  { 226, 1 },
+  { 226, 1 },
   { 165, 2 },
   { 166, 2 },
-  { 229, 1 },
   { 228, 1 },
-  { 228, 0 },
-  { 143, 5 },
-  { 230, 11 },
+  { 227, 1 },
+  { 227, 0 },
+  { 144, 5 },
+  { 229, 11 },
+  { 231, 1 },
+  { 231, 1 },
+  { 231, 2 },
+  { 231, 0 },
   { 232, 1 },
   { 232, 1 },
-  { 232, 2 },
-  { 232, 0 },
-  { 233, 1 },
-  { 233, 1 },
+  { 232, 3 },
+  { 233, 0 },
   { 233, 3 },
   { 234, 0 },
-  { 234, 3 },
-  { 235, 0 },
-  { 235, 2 },
-  { 231, 3 },
-  { 231, 0 },
-  { 236, 6 },
-  { 236, 8 },
-  { 236, 5 },
-  { 236, 4 },
-  { 236, 1 },
+  { 234, 2 },
+  { 230, 3 },
+  { 230, 2 },
+  { 235, 6 },
+  { 235, 8 },
+  { 235, 5 },
+  { 235, 4 },
+  { 235, 1 },
   { 170, 4 },
   { 170, 6 },
   { 186, 1 },
   { 186, 1 },
   { 186, 1 },
-  { 143, 4 },
-  { 143, 6 },
-  { 143, 3 },
-  { 238, 0 },
-  { 238, 2 },
-  { 237, 1 },
+  { 144, 4 },
+  { 144, 6 },
+  { 144, 3 },
   { 237, 0 },
-  { 143, 1 },
-  { 143, 3 },
-  { 143, 1 },
-  { 143, 3 },
-  { 143, 6 },
-  { 143, 6 },
+  { 237, 2 },
+  { 236, 1 },
+  { 236, 0 },
+  { 144, 1 },
+  { 144, 3 },
+  { 144, 1 },
+  { 144, 3 },
+  { 144, 6 },
+  { 144, 6 },
+  { 238, 1 },
+  { 239, 0 },
   { 239, 1 },
-  { 240, 0 },
-  { 240, 1 },
-  { 143, 1 },
-  { 143, 4 },
-  { 241, 7 },
-  { 242, 1 },
-  { 242, 3 },
-  { 243, 0 },
-  { 243, 2 },
+  { 144, 1 },
+  { 144, 4 },
+  { 240, 7 },
+  { 241, 1 },
+  { 241, 3 },
+  { 242, 0 },
+  { 242, 2 },
+  { 243, 1 },
+  { 243, 3 },
   { 244, 1 },
-  { 244, 3 },
-  { 245, 1 },
-  { 246, 0 },
-  { 246, 2 },
+  { 245, 0 },
+  { 245, 2 },
 };
 
 static void yy_accept(yyParser*);  /* Forward Declaration */
@@ -78774,8 +79992,8 @@
       case 0: /* input ::= cmdlist */
       case 1: /* cmdlist ::= cmdlist ecmd */
       case 2: /* cmdlist ::= ecmd */
-      case 4: /* ecmd ::= SEMI */
-      case 5: /* ecmd ::= explain cmdx SEMI */
+      case 3: /* ecmd ::= SEMI */
+      case 4: /* ecmd ::= explain cmdx SEMI */
       case 10: /* trans_opt ::= */
       case 11: /* trans_opt ::= TRANSACTION */
       case 12: /* trans_opt ::= TRANSACTION nm */
@@ -78794,45 +80012,45 @@
       case 83: /* conslist ::= conslist tcons */
       case 84: /* conslist ::= tcons */
       case 85: /* tcons ::= CONSTRAINT nm */
-      case 258: /* plus_opt ::= PLUS */
-      case 259: /* plus_opt ::= */
-      case 269: /* foreach_clause ::= */
-      case 270: /* foreach_clause ::= FOR EACH ROW */
-      case 290: /* database_kw_opt ::= DATABASE */
-      case 291: /* database_kw_opt ::= */
-      case 299: /* kwcolumn_opt ::= */
-      case 300: /* kwcolumn_opt ::= COLUMNKW */
-      case 304: /* vtabarglist ::= vtabarg */
-      case 305: /* vtabarglist ::= vtabarglist COMMA vtabarg */
-      case 307: /* vtabarg ::= vtabarg vtabargtoken */
-      case 311: /* anylist ::= */
+      case 257: /* plus_opt ::= PLUS */
+      case 258: /* plus_opt ::= */
+      case 268: /* foreach_clause ::= */
+      case 269: /* foreach_clause ::= FOR EACH ROW */
+      case 289: /* database_kw_opt ::= DATABASE */
+      case 290: /* database_kw_opt ::= */
+      case 298: /* kwcolumn_opt ::= */
+      case 299: /* kwcolumn_opt ::= COLUMNKW */
+      case 303: /* vtabarglist ::= vtabarg */
+      case 304: /* vtabarglist ::= vtabarglist COMMA vtabarg */
+      case 306: /* vtabarg ::= vtabarg vtabargtoken */
+      case 310: /* anylist ::= */
 {
 }
         break;
-      case 3: /* cmdx ::= cmd */
-{ sqlite3FinishCoding(pParse); }
-        break;
-      case 6: /* explain ::= */
+      case 5: /* explain ::= */
 { sqlite3BeginParse(pParse, 0); }
         break;
-      case 7: /* explain ::= EXPLAIN */
+      case 6: /* explain ::= EXPLAIN */
 { sqlite3BeginParse(pParse, 1); }
         break;
-      case 8: /* explain ::= EXPLAIN QUERY PLAN */
+      case 7: /* explain ::= EXPLAIN QUERY PLAN */
 { sqlite3BeginParse(pParse, 2); }
         break;
+      case 8: /* cmdx ::= cmd */
+{ sqlite3FinishCoding(pParse); }
+        break;
       case 9: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy46);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy280);}
         break;
       case 13: /* transtype ::= */
-{yygotominor.yy46 = TK_DEFERRED;}
+{yygotominor.yy280 = TK_DEFERRED;}
         break;
       case 14: /* transtype ::= DEFERRED */
       case 15: /* transtype ::= IMMEDIATE */
       case 16: /* transtype ::= EXCLUSIVE */
       case 107: /* multiselect_op ::= UNION */
       case 109: /* multiselect_op ::= EXCEPT|INTERSECT */
-{yygotominor.yy46 = yymsp[0].major;}
+{yygotominor.yy280 = yymsp[0].major;}
         break;
       case 17: /* cmd ::= COMMIT trans_opt */
       case 18: /* cmd ::= END trans_opt */
@@ -78843,7 +80061,7 @@
         break;
       case 21: /* create_table ::= CREATE temp TABLE ifnotexists nm dbnm */
 {
-   sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy46,0,0,yymsp[-2].minor.yy46);
+   sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy280,0,0,yymsp[-2].minor.yy280);
 }
         break;
       case 22: /* ifnotexists ::= */
@@ -78857,7 +80075,7 @@
       case 113: /* distinct ::= */
       case 213: /* between_op ::= BETWEEN */
       case 216: /* in_op ::= IN */
-{yygotominor.yy46 = 0;}
+{yygotominor.yy280 = 0;}
         break;
       case 23: /* ifnotexists ::= IF NOT EXISTS */
       case 24: /* temp ::= TEMP */
@@ -78867,7 +80085,7 @@
       case 111: /* distinct ::= DISTINCT */
       case 214: /* between_op ::= NOT BETWEEN */
       case 217: /* in_op ::= NOT IN */
-{yygotominor.yy46 = 1;}
+{yygotominor.yy280 = 1;}
         break;
       case 26: /* create_table_args ::= LP columnlist conslist_opt RP */
 {
@@ -78876,8 +80094,8 @@
         break;
       case 27: /* create_table_args ::= AS select */
 {
-  sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy219);
-  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy219);
+  sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy375);
+  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy375);
 }
         break;
       case 30: /* column ::= columnid type carglist */
@@ -78902,13 +80120,12 @@
       case 119: /* as ::= AS nm */
       case 120: /* as ::= ids */
       case 131: /* dbnm ::= DOT nm */
-      case 241: /* idxitem ::= nm */
-      case 243: /* collate ::= COLLATE ids */
-      case 253: /* nmnum ::= plus_num */
-      case 254: /* nmnum ::= nm */
-      case 255: /* plus_num ::= plus_opt number */
-      case 256: /* minus_num ::= MINUS number */
-      case 257: /* number ::= INTEGER|FLOAT */
+      case 242: /* collate ::= COLLATE ids */
+      case 252: /* nmnum ::= plus_num */
+      case 253: /* nmnum ::= nm */
+      case 254: /* plus_num ::= plus_opt number */
+      case 255: /* minus_num ::= MINUS number */
+      case 256: /* number ::= INTEGER|FLOAT */
 {yygotominor.yy0 = yymsp[0].minor.yy0;}
         break;
       case 38: /* type ::= typetoken */
@@ -78931,14 +80148,14 @@
         break;
       case 50: /* ccons ::= DEFAULT term */
       case 52: /* ccons ::= DEFAULT PLUS term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy172);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy62);}
         break;
       case 51: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy172);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy62);}
         break;
       case 53: /* ccons ::= DEFAULT MINUS term */
 {
-  Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy172, 0, 0);
+  Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy62, 0, 0);
   sqlite3AddDefaultValue(pParse,p);
 }
         break;
@@ -78949,55 +80166,55 @@
 }
         break;
       case 56: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy46);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy280);}
         break;
       case 57: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy46,yymsp[0].minor.yy46,yymsp[-2].minor.yy46);}
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy280,yymsp[0].minor.yy280,yymsp[-2].minor.yy280);}
         break;
       case 58: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy46,0,0,0,0);}
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy280,0,0,0,0);}
         break;
       case 59: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy172);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy62);}
         break;
       case 60: /* ccons ::= REFERENCES nm idxlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy174,yymsp[0].minor.yy46);}
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy418,yymsp[0].minor.yy280);}
         break;
       case 61: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy46);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy280);}
         break;
       case 62: /* ccons ::= COLLATE ids */
 {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
         break;
       case 65: /* refargs ::= */
-{ yygotominor.yy46 = OE_Restrict * 0x010101; }
+{ yygotominor.yy280 = OE_Restrict * 0x010101; }
         break;
       case 66: /* refargs ::= refargs refarg */
-{ yygotominor.yy46 = (yymsp[-1].minor.yy46 & yymsp[0].minor.yy405.mask) | yymsp[0].minor.yy405.value; }
+{ yygotominor.yy280 = (yymsp[-1].minor.yy280 & yymsp[0].minor.yy359.mask) | yymsp[0].minor.yy359.value; }
         break;
       case 67: /* refarg ::= MATCH nm */
-{ yygotominor.yy405.value = 0;     yygotominor.yy405.mask = 0x000000; }
+{ yygotominor.yy359.value = 0;     yygotominor.yy359.mask = 0x000000; }
         break;
       case 68: /* refarg ::= ON DELETE refact */
-{ yygotominor.yy405.value = yymsp[0].minor.yy46;     yygotominor.yy405.mask = 0x0000ff; }
+{ yygotominor.yy359.value = yymsp[0].minor.yy280;     yygotominor.yy359.mask = 0x0000ff; }
         break;
       case 69: /* refarg ::= ON UPDATE refact */
-{ yygotominor.yy405.value = yymsp[0].minor.yy46<<8;  yygotominor.yy405.mask = 0x00ff00; }
+{ yygotominor.yy359.value = yymsp[0].minor.yy280<<8;  yygotominor.yy359.mask = 0x00ff00; }
         break;
       case 70: /* refarg ::= ON INSERT refact */
-{ yygotominor.yy405.value = yymsp[0].minor.yy46<<16; yygotominor.yy405.mask = 0xff0000; }
+{ yygotominor.yy359.value = yymsp[0].minor.yy280<<16; yygotominor.yy359.mask = 0xff0000; }
         break;
       case 71: /* refact ::= SET NULL */
-{ yygotominor.yy46 = OE_SetNull; }
+{ yygotominor.yy280 = OE_SetNull; }
         break;
       case 72: /* refact ::= SET DEFAULT */
-{ yygotominor.yy46 = OE_SetDflt; }
+{ yygotominor.yy280 = OE_SetDflt; }
         break;
       case 73: /* refact ::= CASCADE */
-{ yygotominor.yy46 = OE_Cascade; }
+{ yygotominor.yy280 = OE_Cascade; }
         break;
       case 74: /* refact ::= RESTRICT */
-{ yygotominor.yy46 = OE_Restrict; }
+{ yygotominor.yy280 = OE_Restrict; }
         break;
       case 75: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
       case 76: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
@@ -79006,7 +80223,7 @@
       case 95: /* orconf ::= OR resolvetype */
       case 96: /* resolvetype ::= raisetype */
       case 166: /* insert_cmd ::= INSERT orconf */
-{yygotominor.yy46 = yymsp[0].minor.yy46;}
+{yygotominor.yy280 = yymsp[0].minor.yy280;}
         break;
       case 80: /* conslist_opt ::= */
 {yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
@@ -79015,96 +80232,96 @@
 {yygotominor.yy0 = yymsp[-1].minor.yy0;}
         break;
       case 86: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy174,yymsp[0].minor.yy46,yymsp[-2].minor.yy46,0);}
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy418,yymsp[0].minor.yy280,yymsp[-2].minor.yy280,0);}
         break;
       case 87: /* tcons ::= UNIQUE LP idxlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy174,yymsp[0].minor.yy46,0,0,0,0);}
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy418,yymsp[0].minor.yy280,0,0,0,0);}
         break;
       case 88: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy172);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy62);}
         break;
       case 89: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
 {
-    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy174, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy174, yymsp[-1].minor.yy46);
-    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy46);
+    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy418, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy418, yymsp[-1].minor.yy280);
+    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy280);
 }
         break;
       case 92: /* onconf ::= */
       case 94: /* orconf ::= */
-{yygotominor.yy46 = OE_Default;}
+{yygotominor.yy280 = OE_Default;}
         break;
       case 97: /* resolvetype ::= IGNORE */
-{yygotominor.yy46 = OE_Ignore;}
+{yygotominor.yy280 = OE_Ignore;}
         break;
       case 98: /* resolvetype ::= REPLACE */
       case 167: /* insert_cmd ::= REPLACE */
-{yygotominor.yy46 = OE_Replace;}
+{yygotominor.yy280 = OE_Replace;}
         break;
       case 99: /* cmd ::= DROP TABLE ifexists fullname */
 {
-  sqlite3DropTable(pParse, yymsp[0].minor.yy373, 0, yymsp[-1].minor.yy46);
+  sqlite3DropTable(pParse, yymsp[0].minor.yy151, 0, yymsp[-1].minor.yy280);
 }
         break;
       case 102: /* cmd ::= CREATE temp VIEW ifnotexists nm dbnm AS select */
 {
-  sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy219, yymsp[-6].minor.yy46, yymsp[-4].minor.yy46);
+  sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy375, yymsp[-6].minor.yy280, yymsp[-4].minor.yy280);
 }
         break;
       case 103: /* cmd ::= DROP VIEW ifexists fullname */
 {
-  sqlite3DropTable(pParse, yymsp[0].minor.yy373, 1, yymsp[-1].minor.yy46);
+  sqlite3DropTable(pParse, yymsp[0].minor.yy151, 1, yymsp[-1].minor.yy280);
 }
         break;
       case 104: /* cmd ::= select */
 {
-  SelectDest dest = {SRT_Callback, 0, 0, 0, 0};
-  sqlite3Select(pParse, yymsp[0].minor.yy219, &dest, 0, 0, 0);
-  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy219);
+  SelectDest dest = {SRT_Output, 0, 0, 0, 0};
+  sqlite3Select(pParse, yymsp[0].minor.yy375, &dest);
+  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy375);
 }
         break;
       case 105: /* select ::= oneselect */
       case 128: /* seltablist_paren ::= select */
-{yygotominor.yy219 = yymsp[0].minor.yy219;}
+{yygotominor.yy375 = yymsp[0].minor.yy375;}
         break;
       case 106: /* select ::= select multiselect_op oneselect */
 {
-  if( yymsp[0].minor.yy219 ){
-    yymsp[0].minor.yy219->op = yymsp[-1].minor.yy46;
-    yymsp[0].minor.yy219->pPrior = yymsp[-2].minor.yy219;
+  if( yymsp[0].minor.yy375 ){
+    yymsp[0].minor.yy375->op = yymsp[-1].minor.yy280;
+    yymsp[0].minor.yy375->pPrior = yymsp[-2].minor.yy375;
   }else{
-    sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy219);
+    sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy375);
   }
-  yygotominor.yy219 = yymsp[0].minor.yy219;
+  yygotominor.yy375 = yymsp[0].minor.yy375;
 }
         break;
       case 108: /* multiselect_op ::= UNION ALL */
-{yygotominor.yy46 = TK_ALL;}
+{yygotominor.yy280 = TK_ALL;}
         break;
       case 110: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
 {
-  yygotominor.yy219 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy174,yymsp[-5].minor.yy373,yymsp[-4].minor.yy172,yymsp[-3].minor.yy174,yymsp[-2].minor.yy172,yymsp[-1].minor.yy174,yymsp[-7].minor.yy46,yymsp[0].minor.yy234.pLimit,yymsp[0].minor.yy234.pOffset);
+  yygotominor.yy375 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy418,yymsp[-5].minor.yy151,yymsp[-4].minor.yy62,yymsp[-3].minor.yy418,yymsp[-2].minor.yy62,yymsp[-1].minor.yy418,yymsp[-7].minor.yy280,yymsp[0].minor.yy220.pLimit,yymsp[0].minor.yy220.pOffset);
 }
         break;
       case 114: /* sclp ::= selcollist COMMA */
       case 238: /* idxlist_opt ::= LP idxlist RP */
-{yygotominor.yy174 = yymsp[-1].minor.yy174;}
+{yygotominor.yy418 = yymsp[-1].minor.yy418;}
         break;
       case 115: /* sclp ::= */
       case 141: /* orderby_opt ::= */
       case 149: /* groupby_opt ::= */
       case 231: /* exprlist ::= */
       case 237: /* idxlist_opt ::= */
-{yygotominor.yy174 = 0;}
+{yygotominor.yy418 = 0;}
         break;
       case 116: /* selcollist ::= sclp expr as */
 {
-   yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy174,yymsp[-1].minor.yy172,yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0);
+   yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy418,yymsp[-1].minor.yy62,yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0);
 }
         break;
       case 117: /* selcollist ::= sclp STAR */
 {
   Expr *p = sqlite3PExpr(pParse, TK_ALL, 0, 0, 0);
-  yygotominor.yy174 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy174, p, 0);
+  yygotominor.yy418 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy418, p, 0);
 }
         break;
       case 118: /* selcollist ::= sclp nm DOT STAR */
@@ -79112,63 +80329,63 @@
   Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
   Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
   Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
-  yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy174, pDot, 0);
+  yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy418, pDot, 0);
 }
         break;
       case 121: /* as ::= */
 {yygotominor.yy0.n = 0;}
         break;
       case 122: /* from ::= */
-{yygotominor.yy373 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy373));}
+{yygotominor.yy151 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy151));}
         break;
       case 123: /* from ::= FROM seltablist */
 {
-  yygotominor.yy373 = yymsp[0].minor.yy373;
-  sqlite3SrcListShiftJoinType(yygotominor.yy373);
+  yygotominor.yy151 = yymsp[0].minor.yy151;
+  sqlite3SrcListShiftJoinType(yygotominor.yy151);
 }
         break;
       case 124: /* stl_prefix ::= seltablist joinop */
 {
-   yygotominor.yy373 = yymsp[-1].minor.yy373;
-   if( yygotominor.yy373 && yygotominor.yy373->nSrc>0 ) yygotominor.yy373->a[yygotominor.yy373->nSrc-1].jointype = yymsp[0].minor.yy46;
+   yygotominor.yy151 = yymsp[-1].minor.yy151;
+   if( yygotominor.yy151 && yygotominor.yy151->nSrc>0 ) yygotominor.yy151->a[yygotominor.yy151->nSrc-1].jointype = yymsp[0].minor.yy280;
 }
         break;
       case 125: /* stl_prefix ::= */
-{yygotominor.yy373 = 0;}
+{yygotominor.yy151 = 0;}
         break;
       case 126: /* seltablist ::= stl_prefix nm dbnm as on_opt using_opt */
 {
-  yygotominor.yy373 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy373,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy172,yymsp[0].minor.yy432);
+  yygotominor.yy151 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy151,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy62,yymsp[0].minor.yy240);
 }
         break;
       case 127: /* seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt */
 {
-    yygotominor.yy373 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy373,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy219,yymsp[-1].minor.yy172,yymsp[0].minor.yy432);
+    yygotominor.yy151 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy151,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy375,yymsp[-1].minor.yy62,yymsp[0].minor.yy240);
   }
         break;
       case 129: /* seltablist_paren ::= seltablist */
 {
-     sqlite3SrcListShiftJoinType(yymsp[0].minor.yy373);
-     yygotominor.yy219 = sqlite3SelectNew(pParse,0,yymsp[0].minor.yy373,0,0,0,0,0,0,0);
+     sqlite3SrcListShiftJoinType(yymsp[0].minor.yy151);
+     yygotominor.yy375 = sqlite3SelectNew(pParse,0,yymsp[0].minor.yy151,0,0,0,0,0,0,0);
   }
         break;
       case 130: /* dbnm ::= */
 {yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
         break;
       case 132: /* fullname ::= nm dbnm */
-{yygotominor.yy373 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
+{yygotominor.yy151 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
         break;
       case 133: /* joinop ::= COMMA|JOIN */
-{ yygotominor.yy46 = JT_INNER; }
+{ yygotominor.yy280 = JT_INNER; }
         break;
       case 134: /* joinop ::= JOIN_KW JOIN */
-{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
         break;
       case 135: /* joinop ::= JOIN_KW nm JOIN */
-{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
+{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
         break;
       case 136: /* joinop ::= JOIN_KW nm nm JOIN */
-{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
+{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
         break;
       case 137: /* on_opt ::= ON expr */
       case 145: /* sortitem ::= expr */
@@ -79178,7 +80395,7 @@
       case 202: /* escape ::= ESCAPE expr */
       case 226: /* case_else ::= ELSE expr */
       case 228: /* case_operand ::= expr */
-{yygotominor.yy172 = yymsp[0].minor.yy172;}
+{yygotominor.yy62 = yymsp[0].minor.yy62;}
         break;
       case 138: /* on_opt ::= */
       case 151: /* having_opt ::= */
@@ -79186,107 +80403,107 @@
       case 203: /* escape ::= */
       case 227: /* case_else ::= */
       case 229: /* case_operand ::= */
-{yygotominor.yy172 = 0;}
+{yygotominor.yy62 = 0;}
         break;
       case 139: /* using_opt ::= USING LP inscollist RP */
       case 171: /* inscollist_opt ::= LP inscollist RP */
-{yygotominor.yy432 = yymsp[-1].minor.yy432;}
+{yygotominor.yy240 = yymsp[-1].minor.yy240;}
         break;
       case 140: /* using_opt ::= */
       case 170: /* inscollist_opt ::= */
-{yygotominor.yy432 = 0;}
+{yygotominor.yy240 = 0;}
         break;
       case 142: /* orderby_opt ::= ORDER BY sortlist */
       case 150: /* groupby_opt ::= GROUP BY nexprlist */
       case 230: /* exprlist ::= nexprlist */
-{yygotominor.yy174 = yymsp[0].minor.yy174;}
+{yygotominor.yy418 = yymsp[0].minor.yy418;}
         break;
       case 143: /* sortlist ::= sortlist COMMA sortitem sortorder */
 {
-  yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy174,yymsp[-1].minor.yy172,0);
-  if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
+  yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy418,yymsp[-1].minor.yy62,0);
+  if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280;
 }
         break;
       case 144: /* sortlist ::= sortitem sortorder */
 {
-  yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy172,0);
-  if( yygotominor.yy174 && yygotominor.yy174->a ) yygotominor.yy174->a[0].sortOrder = yymsp[0].minor.yy46;
+  yygotominor.yy418 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy62,0);
+  if( yygotominor.yy418 && yygotominor.yy418->a ) yygotominor.yy418->a[0].sortOrder = yymsp[0].minor.yy280;
 }
         break;
       case 146: /* sortorder ::= ASC */
       case 148: /* sortorder ::= */
-{yygotominor.yy46 = SQLITE_SO_ASC;}
+{yygotominor.yy280 = SQLITE_SO_ASC;}
         break;
       case 147: /* sortorder ::= DESC */
-{yygotominor.yy46 = SQLITE_SO_DESC;}
+{yygotominor.yy280 = SQLITE_SO_DESC;}
         break;
       case 153: /* limit_opt ::= */
-{yygotominor.yy234.pLimit = 0; yygotominor.yy234.pOffset = 0;}
+{yygotominor.yy220.pLimit = 0; yygotominor.yy220.pOffset = 0;}
         break;
       case 154: /* limit_opt ::= LIMIT expr */
-{yygotominor.yy234.pLimit = yymsp[0].minor.yy172; yygotominor.yy234.pOffset = 0;}
+{yygotominor.yy220.pLimit = yymsp[0].minor.yy62; yygotominor.yy220.pOffset = 0;}
         break;
       case 155: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yygotominor.yy234.pLimit = yymsp[-2].minor.yy172; yygotominor.yy234.pOffset = yymsp[0].minor.yy172;}
+{yygotominor.yy220.pLimit = yymsp[-2].minor.yy62; yygotominor.yy220.pOffset = yymsp[0].minor.yy62;}
         break;
       case 156: /* limit_opt ::= LIMIT expr COMMA expr */
-{yygotominor.yy234.pOffset = yymsp[-2].minor.yy172; yygotominor.yy234.pLimit = yymsp[0].minor.yy172;}
+{yygotominor.yy220.pOffset = yymsp[-2].minor.yy62; yygotominor.yy220.pLimit = yymsp[0].minor.yy62;}
         break;
       case 157: /* cmd ::= DELETE FROM fullname where_opt */
-{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy373,yymsp[0].minor.yy172);}
+{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy151,yymsp[0].minor.yy62);}
         break;
       case 160: /* cmd ::= UPDATE orconf fullname SET setlist where_opt */
 {
-  sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy174,"set list"); 
-  sqlite3Update(pParse,yymsp[-3].minor.yy373,yymsp[-1].minor.yy174,yymsp[0].minor.yy172,yymsp[-4].minor.yy46);
+  sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy418,"set list"); 
+  sqlite3Update(pParse,yymsp[-3].minor.yy151,yymsp[-1].minor.yy418,yymsp[0].minor.yy62,yymsp[-4].minor.yy280);
 }
         break;
       case 161: /* setlist ::= setlist COMMA nm EQ expr */
-{yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174,yymsp[0].minor.yy172,&yymsp[-2].minor.yy0);}
+{yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy418,yymsp[0].minor.yy62,&yymsp[-2].minor.yy0);}
         break;
       case 162: /* setlist ::= nm EQ expr */
-{yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy172,&yymsp[-2].minor.yy0);}
+{yygotominor.yy418 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy62,&yymsp[-2].minor.yy0);}
         break;
       case 163: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */
-{sqlite3Insert(pParse, yymsp[-5].minor.yy373, yymsp[-1].minor.yy174, 0, yymsp[-4].minor.yy432, yymsp[-7].minor.yy46);}
+{sqlite3Insert(pParse, yymsp[-5].minor.yy151, yymsp[-1].minor.yy418, 0, yymsp[-4].minor.yy240, yymsp[-7].minor.yy280);}
         break;
       case 164: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
-{sqlite3Insert(pParse, yymsp[-2].minor.yy373, 0, yymsp[0].minor.yy219, yymsp[-1].minor.yy432, yymsp[-4].minor.yy46);}
+{sqlite3Insert(pParse, yymsp[-2].minor.yy151, 0, yymsp[0].minor.yy375, yymsp[-1].minor.yy240, yymsp[-4].minor.yy280);}
         break;
       case 165: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
-{sqlite3Insert(pParse, yymsp[-3].minor.yy373, 0, 0, yymsp[-2].minor.yy432, yymsp[-5].minor.yy46);}
+{sqlite3Insert(pParse, yymsp[-3].minor.yy151, 0, 0, yymsp[-2].minor.yy240, yymsp[-5].minor.yy280);}
         break;
       case 168: /* itemlist ::= itemlist COMMA expr */
       case 232: /* nexprlist ::= nexprlist COMMA expr */
-{yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy174,yymsp[0].minor.yy172,0);}
+{yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy418,yymsp[0].minor.yy62,0);}
         break;
       case 169: /* itemlist ::= expr */
       case 233: /* nexprlist ::= expr */
-{yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy172,0);}
+{yygotominor.yy418 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy62,0);}
         break;
       case 172: /* inscollist ::= inscollist COMMA nm */
-{yygotominor.yy432 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy432,&yymsp[0].minor.yy0);}
+{yygotominor.yy240 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy240,&yymsp[0].minor.yy0);}
         break;
       case 173: /* inscollist ::= nm */
-{yygotominor.yy432 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
+{yygotominor.yy240 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
         break;
       case 175: /* expr ::= LP expr RP */
-{yygotominor.yy172 = yymsp[-1].minor.yy172; sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
+{yygotominor.yy62 = yymsp[-1].minor.yy62; sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
         break;
       case 176: /* term ::= NULL */
       case 181: /* term ::= INTEGER|FLOAT|BLOB */
       case 182: /* term ::= STRING */
-{yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
+{yygotominor.yy62 = sqlite3PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
         break;
       case 177: /* expr ::= ID */
       case 178: /* expr ::= JOIN_KW */
-{yygotominor.yy172 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);}
+{yygotominor.yy62 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);}
         break;
       case 179: /* expr ::= nm DOT nm */
 {
   Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
   Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
 }
         break;
       case 180: /* expr ::= nm DOT nm DOT nm */
@@ -79295,56 +80512,56 @@
   Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
   Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
   Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
 }
         break;
       case 183: /* expr ::= REGISTER */
-{yygotominor.yy172 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
+{yygotominor.yy62 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
         break;
       case 184: /* expr ::= VARIABLE */
 {
   Token *pToken = &yymsp[0].minor.yy0;
-  Expr *pExpr = yygotominor.yy172 = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken);
+  Expr *pExpr = yygotominor.yy62 = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken);
   sqlite3ExprAssignVarNumber(pParse, pExpr);
 }
         break;
       case 185: /* expr ::= expr COLLATE ids */
 {
-  yygotominor.yy172 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy172, &yymsp[0].minor.yy0);
+  yygotominor.yy62 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy62, &yymsp[0].minor.yy0);
 }
         break;
       case 186: /* expr ::= CAST LP expr AS typetoken RP */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy172, 0, &yymsp[-1].minor.yy0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy62, 0, &yymsp[-1].minor.yy0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
 }
         break;
       case 187: /* expr ::= ID LP distinct exprlist RP */
 {
-  if( yymsp[-1].minor.yy174 && yymsp[-1].minor.yy174->nExpr>SQLITE_MAX_FUNCTION_ARG ){
+  if( yymsp[-1].minor.yy418 && yymsp[-1].minor.yy418->nExpr>SQLITE_MAX_FUNCTION_ARG ){
     sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
   }
-  yygotominor.yy172 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy174, &yymsp[-4].minor.yy0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
-  if( yymsp[-2].minor.yy46 && yygotominor.yy172 ){
-    yygotominor.yy172->flags |= EP_Distinct;
+  yygotominor.yy62 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy418, &yymsp[-4].minor.yy0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+  if( yymsp[-2].minor.yy280 && yygotominor.yy62 ){
+    yygotominor.yy62->flags |= EP_Distinct;
   }
 }
         break;
       case 188: /* expr ::= ID LP STAR RP */
 {
-  yygotominor.yy172 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+  yygotominor.yy62 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
 }
         break;
       case 189: /* term ::= CTIME_KW */
 {
   /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
   ** treated as functions that return constants */
-  yygotominor.yy172 = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
-  if( yygotominor.yy172 ){
-    yygotominor.yy172->op = TK_CONST_FUNC;  
-    yygotominor.yy172->span = yymsp[0].minor.yy0;
+  yygotominor.yy62 = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
+  if( yygotominor.yy62 ){
+    yygotominor.yy62->op = TK_CONST_FUNC;  
+    yygotominor.yy62->span = yymsp[0].minor.yy0;
   }
 }
         break;
@@ -79356,391 +80573,400 @@
       case 195: /* expr ::= expr PLUS|MINUS expr */
       case 196: /* expr ::= expr STAR|SLASH|REM expr */
       case 197: /* expr ::= expr CONCAT expr */
-{yygotominor.yy172 = sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy172,yymsp[0].minor.yy172,0);}
+{yygotominor.yy62 = sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy62,yymsp[0].minor.yy62,0);}
         break;
       case 198: /* likeop ::= LIKE_KW */
       case 200: /* likeop ::= MATCH */
-{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 0;}
+{yygotominor.yy222.eOperator = yymsp[0].minor.yy0; yygotominor.yy222.not = 0;}
         break;
       case 199: /* likeop ::= NOT LIKE_KW */
       case 201: /* likeop ::= NOT MATCH */
-{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 1;}
+{yygotominor.yy222.eOperator = yymsp[0].minor.yy0; yygotominor.yy222.not = 1;}
         break;
       case 204: /* expr ::= expr likeop expr escape */
 {
   ExprList *pList;
-  pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy172, 0);
-  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy172, 0);
-  if( yymsp[0].minor.yy172 ){
-    pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy172, 0);
-  }
-  yygotominor.yy172 = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy72.eOperator);
-  if( yymsp[-2].minor.yy72.not ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy172->span, &yymsp[-1].minor.yy172->span);
-  if( yygotominor.yy172 ) yygotominor.yy172->flags |= EP_InfixFunc;
+  pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy62, 0);
+  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy62, 0);
+  if( yymsp[0].minor.yy62 ){
+    pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy62, 0);
+  }
+  yygotominor.yy62 = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy222.eOperator);
+  if( yymsp[-2].minor.yy222.not ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy62, &yymsp[-3].minor.yy62->span, &yymsp[-1].minor.yy62->span);
+  if( yygotominor.yy62 ) yygotominor.yy62->flags |= EP_InfixFunc;
 }
         break;
       case 205: /* expr ::= expr ISNULL|NOTNULL */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy172, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy172->span,&yymsp[0].minor.yy0);
+  yygotominor.yy62 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy62, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy62->span,&yymsp[0].minor.yy0);
 }
         break;
       case 206: /* expr ::= expr IS NULL */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy172, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy62, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy62->span,&yymsp[0].minor.yy0);
 }
         break;
       case 207: /* expr ::= expr NOT NULL */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy172, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy62, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy62->span,&yymsp[0].minor.yy0);
 }
         break;
       case 208: /* expr ::= expr IS NOT NULL */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy172, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,&yymsp[0].minor.yy0);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy62, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy62->span,&yymsp[0].minor.yy0);
 }
         break;
       case 209: /* expr ::= NOT expr */
       case 210: /* expr ::= BITNOT expr */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy172, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
+  yygotominor.yy62 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy62, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span);
 }
         break;
       case 211: /* expr ::= MINUS expr */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy172, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy62, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span);
 }
         break;
       case 212: /* expr ::= PLUS expr */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy172, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy62, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span);
 }
         break;
       case 215: /* expr ::= expr between_op expr AND expr */
 {
-  ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy172, 0);
-  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy172, 0);
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy172, 0, 0);
-  if( yygotominor.yy172 ){
-    yygotominor.yy172->pList = pList;
+  ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy62, 0);
+  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy62, 0);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy62, 0, 0);
+  if( yygotominor.yy62 ){
+    yygotominor.yy62->pList = pList;
   }else{
     sqlite3ExprListDelete(pParse->db, pList);
   } 
-  if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
-  sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy172->span);
+  if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0);
+  sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy62->span);
 }
         break;
       case 218: /* expr ::= expr in_op LP exprlist RP */
 {
-    yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy172, 0, 0);
-    if( yygotominor.yy172 ){
-      yygotominor.yy172->pList = yymsp[-1].minor.yy174;
-      sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+    yygotominor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy62, 0, 0);
+    if( yygotominor.yy62 ){
+      yygotominor.yy62->pList = yymsp[-1].minor.yy418;
+      sqlite3ExprSetHeight(pParse, yygotominor.yy62);
     }else{
-      sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy174);
+      sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy418);
     }
-    if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
-    sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0);
+    if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0);
+    sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy0);
   }
         break;
       case 219: /* expr ::= LP select RP */
 {
-    yygotominor.yy172 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
-    if( yygotominor.yy172 ){
-      yygotominor.yy172->pSelect = yymsp[-1].minor.yy219;
-      sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+    yygotominor.yy62 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
+    if( yygotominor.yy62 ){
+      yygotominor.yy62->pSelect = yymsp[-1].minor.yy375;
+      sqlite3ExprSetHeight(pParse, yygotominor.yy62);
     }else{
-      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
+      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy375);
     }
-    sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+    sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
   }
         break;
       case 220: /* expr ::= expr in_op LP select RP */
 {
-    yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy172, 0, 0);
-    if( yygotominor.yy172 ){
-      yygotominor.yy172->pSelect = yymsp[-1].minor.yy219;
-      sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+    yygotominor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy62, 0, 0);
+    if( yygotominor.yy62 ){
+      yygotominor.yy62->pSelect = yymsp[-1].minor.yy375;
+      sqlite3ExprSetHeight(pParse, yygotominor.yy62);
     }else{
-      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
+      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy375);
     }
-    if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
-    sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0);
+    if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0);
+    sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy0);
   }
         break;
       case 221: /* expr ::= expr in_op nm dbnm */
 {
     SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
-    yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy172, 0, 0);
-    if( yygotominor.yy172 ){
-      yygotominor.yy172->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
-      sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+    yygotominor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy62, 0, 0);
+    if( yygotominor.yy62 ){
+      yygotominor.yy62->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
+      sqlite3ExprSetHeight(pParse, yygotominor.yy62);
     }else{
       sqlite3SrcListDelete(pParse->db, pSrc);
     }
-    if( yymsp[-2].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
-    sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0);
+    if( yymsp[-2].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0);
+    sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy62->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0);
   }
         break;
       case 222: /* expr ::= EXISTS LP select RP */
 {
-    Expr *p = yygotominor.yy172 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
+    Expr *p = yygotominor.yy62 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
     if( p ){
-      p->pSelect = yymsp[-1].minor.yy219;
+      p->pSelect = yymsp[-1].minor.yy375;
       sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
-      sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+      sqlite3ExprSetHeight(pParse, yygotominor.yy62);
     }else{
-      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
+      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy375);
     }
   }
         break;
       case 223: /* expr ::= CASE case_operand case_exprlist case_else END */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, 0);
-  if( yygotominor.yy172 ){
-    yygotominor.yy172->pList = yymsp[-2].minor.yy174;
-    sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy62, yymsp[-1].minor.yy62, 0);
+  if( yygotominor.yy62 ){
+    yygotominor.yy62->pList = yymsp[-2].minor.yy418;
+    sqlite3ExprSetHeight(pParse, yygotominor.yy62);
   }else{
-    sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy174);
+    sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy418);
   }
-  sqlite3ExprSpan(yygotominor.yy172, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
+  sqlite3ExprSpan(yygotominor.yy62, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
 }
         break;
       case 224: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
 {
-  yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174, yymsp[-2].minor.yy172, 0);
-  yygotominor.yy174 = sqlite3ExprListAppend(pParse,yygotominor.yy174, yymsp[0].minor.yy172, 0);
+  yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy418, yymsp[-2].minor.yy62, 0);
+  yygotominor.yy418 = sqlite3ExprListAppend(pParse,yygotominor.yy418, yymsp[0].minor.yy62, 0);
 }
         break;
       case 225: /* case_exprlist ::= WHEN expr THEN expr */
 {
-  yygotominor.yy174 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy172, 0);
-  yygotominor.yy174 = sqlite3ExprListAppend(pParse,yygotominor.yy174, yymsp[0].minor.yy172, 0);
+  yygotominor.yy418 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy62, 0);
+  yygotominor.yy418 = sqlite3ExprListAppend(pParse,yygotominor.yy418, yymsp[0].minor.yy62, 0);
 }
         break;
       case 234: /* cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
 {
   sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, 
-                     sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy174, yymsp[-9].minor.yy46,
-                      &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy46);
+                     sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy418, yymsp[-9].minor.yy280,
+                      &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy280);
 }
         break;
       case 235: /* uniqueflag ::= UNIQUE */
-      case 283: /* raisetype ::= ABORT */
-{yygotominor.yy46 = OE_Abort;}
+      case 282: /* raisetype ::= ABORT */
+{yygotominor.yy280 = OE_Abort;}
         break;
       case 236: /* uniqueflag ::= */
-{yygotominor.yy46 = OE_None;}
+{yygotominor.yy280 = OE_None;}
         break;
-      case 239: /* idxlist ::= idxlist COMMA idxitem collate sortorder */
+      case 239: /* idxlist ::= idxlist COMMA nm collate sortorder */
 {
   Expr *p = 0;
   if( yymsp[-1].minor.yy0.n>0 ){
     p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
     sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy0);
   }
-  yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174, p, &yymsp[-2].minor.yy0);
-  sqlite3ExprListCheckLength(pParse, yygotominor.yy174, "index");
-  if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
+  yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy418, p, &yymsp[-2].minor.yy0);
+  sqlite3ExprListCheckLength(pParse, yygotominor.yy418, "index");
+  if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280;
 }
         break;
-      case 240: /* idxlist ::= idxitem collate sortorder */
+      case 240: /* idxlist ::= nm collate sortorder */
 {
   Expr *p = 0;
   if( yymsp[-1].minor.yy0.n>0 ){
     p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
     sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy0);
   }
-  yygotominor.yy174 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy0);
-  sqlite3ExprListCheckLength(pParse, yygotominor.yy174, "index");
-  if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
+  yygotominor.yy418 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy0);
+  sqlite3ExprListCheckLength(pParse, yygotominor.yy418, "index");
+  if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280;
 }
         break;
-      case 242: /* collate ::= */
+      case 241: /* collate ::= */
 {yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
         break;
-      case 244: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy373, yymsp[-1].minor.yy46);}
+      case 243: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy151, yymsp[-1].minor.yy280);}
         break;
-      case 245: /* cmd ::= VACUUM */
-      case 246: /* cmd ::= VACUUM nm */
+      case 244: /* cmd ::= VACUUM */
+      case 245: /* cmd ::= VACUUM nm */
 {sqlite3Vacuum(pParse);}
         break;
-      case 247: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
-      case 248: /* cmd ::= PRAGMA nm dbnm EQ ON */
-      case 249: /* cmd ::= PRAGMA nm dbnm EQ DELETE */
+      case 246: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+      case 247: /* cmd ::= PRAGMA nm dbnm EQ ON */
+      case 248: /* cmd ::= PRAGMA nm dbnm EQ DELETE */
 {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
         break;
-      case 250: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+      case 249: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
 {
   sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);
 }
         break;
-      case 251: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+      case 250: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
 {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
         break;
-      case 252: /* cmd ::= PRAGMA nm dbnm */
+      case 251: /* cmd ::= PRAGMA nm dbnm */
 {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
         break;
-      case 260: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */
+      case 259: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */
 {
   Token all;
   all.z = yymsp[-3].minor.yy0.z;
   all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
-  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy243, &all);
+  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy360, &all);
 }
         break;
-      case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+      case 260: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
 {
-  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy46, yymsp[-4].minor.yy370.a, yymsp[-4].minor.yy370.b, yymsp[-2].minor.yy373, yymsp[0].minor.yy172, yymsp[-10].minor.yy46, yymsp[-8].minor.yy46);
+  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy280, yymsp[-4].minor.yy30.a, yymsp[-4].minor.yy30.b, yymsp[-2].minor.yy151, yymsp[0].minor.yy62, yymsp[-10].minor.yy280, yymsp[-8].minor.yy280);
   yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
 }
         break;
-      case 262: /* trigger_time ::= BEFORE */
-      case 265: /* trigger_time ::= */
-{ yygotominor.yy46 = TK_BEFORE; }
+      case 261: /* trigger_time ::= BEFORE */
+      case 264: /* trigger_time ::= */
+{ yygotominor.yy280 = TK_BEFORE; }
         break;
-      case 263: /* trigger_time ::= AFTER */
-{ yygotominor.yy46 = TK_AFTER;  }
+      case 262: /* trigger_time ::= AFTER */
+{ yygotominor.yy280 = TK_AFTER;  }
         break;
-      case 264: /* trigger_time ::= INSTEAD OF */
-{ yygotominor.yy46 = TK_INSTEAD;}
+      case 263: /* trigger_time ::= INSTEAD OF */
+{ yygotominor.yy280 = TK_INSTEAD;}
         break;
-      case 266: /* trigger_event ::= DELETE|INSERT */
-      case 267: /* trigger_event ::= UPDATE */
-{yygotominor.yy370.a = yymsp[0].major; yygotominor.yy370.b = 0;}
+      case 265: /* trigger_event ::= DELETE|INSERT */
+      case 266: /* trigger_event ::= UPDATE */
+{yygotominor.yy30.a = yymsp[0].major; yygotominor.yy30.b = 0;}
         break;
-      case 268: /* trigger_event ::= UPDATE OF inscollist */
-{yygotominor.yy370.a = TK_UPDATE; yygotominor.yy370.b = yymsp[0].minor.yy432;}
+      case 267: /* trigger_event ::= UPDATE OF inscollist */
+{yygotominor.yy30.a = TK_UPDATE; yygotominor.yy30.b = yymsp[0].minor.yy240;}
         break;
-      case 271: /* when_clause ::= */
-      case 288: /* key_opt ::= */
-{ yygotominor.yy172 = 0; }
+      case 270: /* when_clause ::= */
+      case 287: /* key_opt ::= */
+{ yygotominor.yy62 = 0; }
         break;
-      case 272: /* when_clause ::= WHEN expr */
-      case 289: /* key_opt ::= KEY expr */
-{ yygotominor.yy172 = yymsp[0].minor.yy172; }
+      case 271: /* when_clause ::= WHEN expr */
+      case 288: /* key_opt ::= KEY expr */
+{ yygotominor.yy62 = yymsp[0].minor.yy62; }
         break;
-      case 273: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+      case 272: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
 {
-  if( yymsp[-2].minor.yy243 ){
-    yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243;
+/*
+  if( yymsp[-2].minor.yy360 ){
+    yymsp[-2].minor.yy360->pLast->pNext = yymsp[-1].minor.yy360;
   }else{
-    yymsp[-2].minor.yy243 = yymsp[-1].minor.yy243;
+    yymsp[-2].minor.yy360 = yymsp[-1].minor.yy360;
   }
-  yymsp[-2].minor.yy243->pLast = yymsp[-1].minor.yy243;
-  yygotominor.yy243 = yymsp[-2].minor.yy243;
+*/
+  assert( yymsp[-2].minor.yy360!=0 );
+  yymsp[-2].minor.yy360->pLast->pNext = yymsp[-1].minor.yy360;
+  yymsp[-2].minor.yy360->pLast = yymsp[-1].minor.yy360;
+  yygotominor.yy360 = yymsp[-2].minor.yy360;
 }
         break;
-      case 274: /* trigger_cmd_list ::= */
-{ yygotominor.yy243 = 0; }
+      case 273: /* trigger_cmd_list ::= trigger_cmd SEMI */
+{ 
+  /* if( yymsp[-1].minor.yy360 ) */
+  assert( yymsp[-1].minor.yy360!=0 );
+  yymsp[-1].minor.yy360->pLast = yymsp[-1].minor.yy360;
+  yygotominor.yy360 = yymsp[-1].minor.yy360;
+}
         break;
-      case 275: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
-{ yygotominor.yy243 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy174, yymsp[0].minor.yy172, yymsp[-4].minor.yy46); }
+      case 274: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
+{ yygotominor.yy360 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy418, yymsp[0].minor.yy62, yymsp[-4].minor.yy280); }
         break;
-      case 276: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
-{yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy432, yymsp[-1].minor.yy174, 0, yymsp[-7].minor.yy46);}
+      case 275: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
+{yygotominor.yy360 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy240, yymsp[-1].minor.yy418, 0, yymsp[-7].minor.yy280);}
         break;
-      case 277: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
-{yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy432, 0, yymsp[0].minor.yy219, yymsp[-4].minor.yy46);}
+      case 276: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
+{yygotominor.yy360 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy240, 0, yymsp[0].minor.yy375, yymsp[-4].minor.yy280);}
         break;
-      case 278: /* trigger_cmd ::= DELETE FROM nm where_opt */
-{yygotominor.yy243 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy172);}
+      case 277: /* trigger_cmd ::= DELETE FROM nm where_opt */
+{yygotominor.yy360 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy62);}
         break;
-      case 279: /* trigger_cmd ::= select */
-{yygotominor.yy243 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy219); }
+      case 278: /* trigger_cmd ::= select */
+{yygotominor.yy360 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy375); }
         break;
-      case 280: /* expr ::= RAISE LP IGNORE RP */
+      case 279: /* expr ::= RAISE LP IGNORE RP */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); 
-  if( yygotominor.yy172 ){
-    yygotominor.yy172->iColumn = OE_Ignore;
-    sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); 
+  if( yygotominor.yy62 ){
+    yygotominor.yy62->iColumn = OE_Ignore;
+    sqlite3ExprSpan(yygotominor.yy62, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
   }
 }
         break;
-      case 281: /* expr ::= RAISE LP raisetype COMMA nm RP */
+      case 280: /* expr ::= RAISE LP raisetype COMMA nm RP */
 {
-  yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); 
-  if( yygotominor.yy172 ) {
-    yygotominor.yy172->iColumn = yymsp[-3].minor.yy46;
-    sqlite3ExprSpan(yygotominor.yy172, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
+  yygotominor.yy62 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); 
+  if( yygotominor.yy62 ) {
+    yygotominor.yy62->iColumn = yymsp[-3].minor.yy280;
+    sqlite3ExprSpan(yygotominor.yy62, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
   }
 }
         break;
-      case 282: /* raisetype ::= ROLLBACK */
-{yygotominor.yy46 = OE_Rollback;}
+      case 281: /* raisetype ::= ROLLBACK */
+{yygotominor.yy280 = OE_Rollback;}
         break;
-      case 284: /* raisetype ::= FAIL */
-{yygotominor.yy46 = OE_Fail;}
+      case 283: /* raisetype ::= FAIL */
+{yygotominor.yy280 = OE_Fail;}
         break;
-      case 285: /* cmd ::= DROP TRIGGER ifexists fullname */
+      case 284: /* cmd ::= DROP TRIGGER ifexists fullname */
 {
-  sqlite3DropTrigger(pParse,yymsp[0].minor.yy373,yymsp[-1].minor.yy46);
+  sqlite3DropTrigger(pParse,yymsp[0].minor.yy151,yymsp[-1].minor.yy280);
 }
         break;
-      case 286: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+      case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
 {
-  sqlite3Attach(pParse, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, yymsp[0].minor.yy172);
+  sqlite3Attach(pParse, yymsp[-3].minor.yy62, yymsp[-1].minor.yy62, yymsp[0].minor.yy62);
 }
         break;
-      case 287: /* cmd ::= DETACH database_kw_opt expr */
+      case 286: /* cmd ::= DETACH database_kw_opt expr */
 {
-  sqlite3Detach(pParse, yymsp[0].minor.yy172);
+  sqlite3Detach(pParse, yymsp[0].minor.yy62);
 }
         break;
-      case 292: /* cmd ::= REINDEX */
+      case 291: /* cmd ::= REINDEX */
 {sqlite3Reindex(pParse, 0, 0);}
         break;
-      case 293: /* cmd ::= REINDEX nm dbnm */
+      case 292: /* cmd ::= REINDEX nm dbnm */
 {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
         break;
-      case 294: /* cmd ::= ANALYZE */
+      case 293: /* cmd ::= ANALYZE */
 {sqlite3Analyze(pParse, 0, 0);}
         break;
-      case 295: /* cmd ::= ANALYZE nm dbnm */
+      case 294: /* cmd ::= ANALYZE nm dbnm */
 {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
         break;
-      case 296: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+      case 295: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
 {
-  sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy373,&yymsp[0].minor.yy0);
+  sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy151,&yymsp[0].minor.yy0);
 }
         break;
-      case 297: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
+      case 296: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
 {
   sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
 }
         break;
-      case 298: /* add_column_fullname ::= fullname */
+      case 297: /* add_column_fullname ::= fullname */
 {
-  sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy373);
+  sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy151);
 }
         break;
-      case 301: /* cmd ::= create_vtab */
+      case 300: /* cmd ::= create_vtab */
 {sqlite3VtabFinishParse(pParse,0);}
         break;
-      case 302: /* cmd ::= create_vtab LP vtabarglist RP */
+      case 301: /* cmd ::= create_vtab LP vtabarglist RP */
 {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
         break;
-      case 303: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */
+      case 302: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */
 {
     sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
 }
         break;
-      case 306: /* vtabarg ::= */
+      case 305: /* vtabarg ::= */
 {sqlite3VtabArgInit(pParse);}
         break;
-      case 308: /* vtabargtoken ::= ANY */
-      case 309: /* vtabargtoken ::= lp anylist RP */
-      case 310: /* lp ::= LP */
-      case 312: /* anylist ::= anylist ANY */
+      case 307: /* vtabargtoken ::= ANY */
+      case 308: /* vtabargtoken ::= lp anylist RP */
+      case 309: /* lp ::= LP */
+      case 311: /* anylist ::= anylist ANY */
 {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
         break;
   };
@@ -80001,7 +81227,7 @@
 ** individual tokens and sends those tokens one-by-one over to the
 ** parser for analysis.
 **
-** $Id: tokenize.c,v 1.148 2008/07/28 19:34:54 drh Exp $
+** $Id: tokenize.c,v 1.151 2008/08/29 02:14:03 drh Exp $
 */
 
 /*
@@ -80230,7 +81456,7 @@
     case '-': {
       if( z[1]=='-' ){
         for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
-        *tokenType = TK_COMMENT;
+        *tokenType = TK_SPACE;
         return i;
       }
       *tokenType = TK_MINUS;
@@ -80263,7 +81489,7 @@
       }
       for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
       if( c ) i++;
-      *tokenType = TK_COMMENT;
+      *tokenType = TK_SPACE;
       return i;
     }
     case '%': {
@@ -80344,9 +81570,12 @@
           }
         }
       }
-      if( c ){
+      if( c=='\'' ){
         *tokenType = TK_STRING;
         return i+1;
+      }else if( c!=0 ){
+        *tokenType = TK_ID;
+        return i+1;
       }else{
         *tokenType = TK_ILLEGAL;
         return i;
@@ -80516,8 +81745,7 @@
       break;
     }
     switch( tokenType ){
-      case TK_SPACE:
-      case TK_COMMENT: {
+      case TK_SPACE: {
         if( db->u1.isInterrupted ){
           pParse->rc = SQLITE_INTERRUPT;
           sqlite3SetString(pzErrMsg, db, "interrupt");
@@ -80600,6 +81828,7 @@
 
   sqlite3DeleteTrigger(db, pParse->pNewTrigger);
   sqlite3DbFree(db, pParse->apVarExpr);
+  sqlite3DbFree(db, pParse->aAlias);
   if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
     pParse->rc = SQLITE_ERROR;
   }
@@ -80903,7 +82132,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.486 2008/08/04 20:13:27 drh Exp $
+** $Id: main.c,v 1.494 2008/08/27 19:01:58 danielk1977 Exp $
 */
 
 #ifdef SQLITE_ENABLE_FTS3
@@ -81002,68 +82231,126 @@
 ** Initialize SQLite.  
 **
 ** This routine must be called to initialize the memory allocation,
-** VFS, and mutex subsystesms prior to doing any serious work with
+** VFS, and mutex subsystems prior to doing any serious work with
 ** SQLite.  But as long as you do not compile with SQLITE_OMIT_AUTOINIT
 ** this routine will be called automatically by key routines such as
 ** sqlite3_open().  
 **
 ** This routine is a no-op except on its very first call for the process,
 ** or for the first call after a call to sqlite3_shutdown.
+**
+** The first thread to call this routine runs the initialization to
+** completion.  If subsequent threads call this routine before the first
+** thread has finished the initialization process, then the subsequent
+** threads must block until the first thread finishes with the initialization.
+**
+** The first thread might call this routine recursively.  Recursive
+** calls to this routine should not block, of course.  Otherwise the
+** initialization process would never complete.
+**
+** Let X be the first thread to enter this routine.  Let Y be some other
+** thread.  Then while the initial invocation of this routine by X is
+** incomplete, it is required that:
+**
+**    *  Calls to this routine from Y must block until the outer-most
+**       call by X completes.
+**
+**    *  Recursive calls to this routine from thread X return immediately
+**       without blocking.
 */
 SQLITE_API int sqlite3_initialize(void){
-  static int inProgress = 0;
-  int rc;
-
-  /* If SQLite is already initialized, this call is a no-op. */
+  static int inProgress = 0;        /* Prevent recursion */
+  sqlite3_mutex *pMaster;           /* The main static mutex */
+  int rc;                           /* Result code */
+
+  /* If SQLite is already completely initialized, then this call
+  ** to sqlite3_initialize() should be a no-op.  But the initialization
+  ** must be complete.  So isInit must not be set until the very end
+  ** of this routine.
+  */
   if( sqlite3Config.isInit ) return SQLITE_OK;
 
-  /* Make sure the mutex system is initialized. */
+  /* Make sure the mutex subsystem is initialized.  If unable to 
+  ** initialize the mutex subsystem, return early with the error.
+  ** If the system is so sick that we are unable to allocate a mutex,
+  ** there is not much SQLite is going to be able to do.
+  **
+  ** The mutex subsystem must take care of serializing its own
+  ** initialization.
+  */
   rc = sqlite3MutexInit();
+  if( rc ) return rc;
 
+  /* Initialize the malloc() system and the recursive pInitMutex mutex.
+  ** This operation is protected by the STATIC_MASTER mutex.  Note that
+  ** MutexAlloc() is called for a static mutex prior to initializing the
+  ** malloc subsystem - this implies that the allocation of a static
+  ** mutex must not require support from the malloc subsystem.
+  */
+  pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+  sqlite3_mutex_enter(pMaster);
+  if( !sqlite3Config.isMallocInit ){
+    rc = sqlite3MallocInit();
+  }
   if( rc==SQLITE_OK ){
-
-    /* Initialize the malloc() system and the recursive pInitMutex mutex.
-    ** This operation is protected by the STATIC_MASTER mutex.
-    */
-    sqlite3_mutex *pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-    sqlite3_mutex_enter(pMaster);
-    if( !sqlite3Config.isMallocInit ){
-      rc = sqlite3MallocInit();
-    }
-    if( rc==SQLITE_OK ){
-      sqlite3Config.isMallocInit = 1;
-      if( !sqlite3Config.pInitMutex ){
-        sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
-        if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){
-          rc = SQLITE_NOMEM;
-        }
+    sqlite3Config.isMallocInit = 1;
+    if( !sqlite3Config.pInitMutex ){
+      sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
+      if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){
+        rc = SQLITE_NOMEM;
       }
     }
-    sqlite3_mutex_leave(pMaster);
-    if( rc!=SQLITE_OK ){
-      return rc;
-    }
+    sqlite3Config.nRefInitMutex++;
+  }
+  sqlite3_mutex_leave(pMaster);
 
-    /* Enter the recursive pInitMutex mutex. After doing so, if the
-    ** sqlite3Config.isInit flag is true, then some other thread has
-    ** finished doing the initialization. If the inProgress flag is
-    ** true, then this function is being called recursively from within
-    ** the sqlite3_os_init() call below. In either case, exit early.
-    */
-    sqlite3_mutex_enter(sqlite3Config.pInitMutex);
-    if( sqlite3Config.isInit || inProgress ){
-      sqlite3_mutex_leave(sqlite3Config.pInitMutex);
-      return SQLITE_OK;
-    }
-    sqlite3StatusReset();
+  /* If unable to initialize the malloc subsystem, then return early.
+  ** There is little hope of getting SQLite to run if the malloc
+  ** subsystem cannot be initialized.
+  */
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+
+  /* Do the rest of the initialization under the recursive mutex so
+  ** that we will be able to handle recursive calls into
+  ** sqlite3_initialize().  The recursive calls normally come through
+  ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
+  ** recursive calls might also be possible.
+  */
+  sqlite3_mutex_enter(sqlite3Config.pInitMutex);
+  if( sqlite3Config.isInit==0 && inProgress==0 ){
     inProgress = 1;
+    memset(&sqlite3GlobalFunctions, 0, sizeof(sqlite3GlobalFunctions));
+    sqlite3RegisterGlobalFunctions();
     rc = sqlite3_os_init();
+    if( rc==SQLITE_OK ){
+      rc = sqlite3PcacheInitialize();
+      sqlite3PCacheBufferSetup(sqlite3Config.pPage, sqlite3Config.szPage, 
+          sqlite3Config.nPage);
+    }
     inProgress = 0;
     sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0);
-    sqlite3_mutex_leave(sqlite3Config.pInitMutex);
   }
+  sqlite3_mutex_leave(sqlite3Config.pInitMutex);
 
-  /* Check NaN support. */
+  /* Go back under the static mutex and clean up the recursive
+  ** mutex to prevent a resource leak.
+  */
+  sqlite3_mutex_enter(pMaster);
+  sqlite3Config.nRefInitMutex--;
+  if( sqlite3Config.nRefInitMutex<=0 ){
+    assert( sqlite3Config.nRefInitMutex==0 );
+    sqlite3_mutex_free(sqlite3Config.pInitMutex);
+    sqlite3Config.pInitMutex = 0;
+  }
+  sqlite3_mutex_leave(pMaster);
+
+  /* The following is just a sanity check to make sure SQLite has
+  ** been compiled correctly.  It is important to run this code, but
+  ** we don't want to run it too often and soak up CPU cycles for no
+  ** reason.  So we run it once during initialization.
+  */
 #ifndef NDEBUG
   /* This section of code's only "output" is via assert() statements. */
   if ( rc==SQLITE_OK ){
@@ -81086,9 +82373,8 @@
 ** routine is not threadsafe.  Not by a long shot.
 */
 SQLITE_API int sqlite3_shutdown(void){
-  sqlite3_mutex_free(sqlite3Config.pInitMutex);
-  sqlite3Config.pInitMutex = 0;
   sqlite3Config.isMallocInit = 0;
+  sqlite3PcacheShutdown();
   if( sqlite3Config.isInit ){
     sqlite3_os_end();
   }
@@ -81253,12 +82539,13 @@
   }
   if( sz<0 ) sz = 0;
   if( cnt<0 ) cnt = 0;
-  sz = (sz+7)&~7;
   if( pBuf==0 ){
+    sz = (sz + 7)&~7;
     sqlite3BeginBenignMalloc();
     pStart = sqlite3Malloc( sz*cnt );
     sqlite3EndBenignMalloc();
   }else{
+    sz = sz&~7;
     pStart = pBuf;
   }
   if( db->lookaside.bMalloced ){
@@ -81455,14 +82742,17 @@
   sqlite3ResetInternalSchema(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;
-      sqlite3DbFree(db, pFunc);
+  for(j=0; j<ArraySize(db->aFunc.a); j++){
+    FuncDef *pNext, *pHash, *p;
+    for(p=db->aFunc.a[j]; p; p=pHash){
+      pHash = p->pHash;
+      while( p ){
+        pNext = p->pNext;
+        sqlite3DbFree(db, p);
+        p = pNext;
+      }
     }
   }
-
   for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
     CollSeq *pColl = (CollSeq *)sqliteHashData(i);
     /* Invoke any destructors registered for collation sequence user data. */
@@ -81485,7 +82775,6 @@
   sqlite3HashClear(&db->aModule);
 #endif
 
-  sqlite3HashClear(&db->aFunc);
   sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
   if( db->pErr ){
     sqlite3ValueFree(db->pErr);
@@ -82251,8 +83540,8 @@
 #if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>127
 # error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127
 #endif
-#if SQLITE_MAX_ATTACH<0 || SQLITE_MAX_ATTACH>30
-# error SQLITE_MAX_ATTACH must be between 0 and 30
+#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>30
+# error SQLITE_MAX_ATTACHED must be between 0 and 30
 #endif
 #if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
 # error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
@@ -82260,6 +83549,9 @@
 #if SQLITE_MAX_VARIABLE_NUMBER<1
 # error SQLITE_MAX_VARIABLE_NUMBER must be at least 1
 #endif
+#if SQLITE_MAX_COLUMN>32767
+# error SQLITE_MAX_COLUMN must not exceed 32767
+#endif
 
 
 /*
@@ -82355,7 +83647,6 @@
                  | SQLITE_LoadExtension
 #endif
       ;
-  sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
   sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0);
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0);
@@ -82364,7 +83655,6 @@
   db->pVfs = sqlite3_vfs_find(zVfs);
   if( !db->pVfs ){
     rc = SQLITE_ERROR;
-    db->magic = SQLITE_MAGIC_SICK;
     sqlite3Error(db, rc, "no such vfs: %s", zVfs);
     goto opendb_out;
   }
@@ -82378,7 +83668,6 @@
   createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0);
   createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
   if( db->mallocFailed ){
-    db->magic = SQLITE_MAGIC_SICK;
     goto opendb_out;
   }
   db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
@@ -82401,7 +83690,6 @@
                            &db->aDb[0].pBt);
   if( rc!=SQLITE_OK ){
     sqlite3Error(db, rc, 0);
-    db->magic = SQLITE_MAGIC_SICK;
     goto opendb_out;
   }
   db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
@@ -82491,9 +83779,12 @@
     assert( db->mutex!=0 || isThreadsafe==0 || sqlite3Config.bFullMutex==0 );
     sqlite3_mutex_leave(db->mutex);
   }
-  if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
+  rc = sqlite3_errcode(db);
+  if( rc==SQLITE_NOMEM ){
     sqlite3_close(db);
     db = 0;
+  }else if( rc!=SQLITE_OK ){
+    db->magic = SQLITE_MAGIC_SICK;
   }
   *ppDb = db;
   return sqlite3ApiExit(0, rc);
@@ -82779,7 +84070,7 @@
     zCollSeq = pCol->zColl;
     notnull = pCol->notNull!=0;
     primarykey  = pCol->isPrimKey!=0;
-    autoinc = pTab->iPKey==iCol && pTab->autoInc;
+    autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
   }else{
     zDataType = "INTEGER";
     primarykey = 1;

Modified: trunk/libgda/sqlite/sqlite-src/sqlite3.h
==============================================================================
--- trunk/libgda/sqlite/sqlite-src/sqlite3.h	(original)
+++ trunk/libgda/sqlite/sqlite-src/sqlite3.h	Mon Sep 15 18:30:05 2008
@@ -52,6 +52,31 @@
 #endif
 
 /*
+** Add the ability to mark interfaces as deprecated.
+*/
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+  /* GCC added the deprecated attribute in version 3.1 */
+  #define SQLITE_DEPRECATED __attribute__ ((deprecated))
+#elif defined(_MSC_VER)
+  #define SQLITE_DEPRECATED __declspec(deprecated)
+#else
+  #define SQLITE_DEPRECATED
+#endif
+
+/*
+** Add the ability to mark interfaces as experimental.
+*/
+#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+  /* I can confirm that it does not work on version 4.1.0... */
+  /* First appears in GCC docs for version 4.3.0 */
+  #define SQLITE_EXPERIMENTAL __attribute__ ((warning ("is experimental")))
+#elif defined(_MSC_VER)
+  #define SQLITE_EXPERIMENTAL __declspec(deprecated("was declared experimental"))
+#else
+  #define SQLITE_EXPERIMENTAL
+#endif
+
+/*
 ** Ensure these symbols were not defined by some previous header file.
 */
 #ifdef SQLITE_VERSION
@@ -91,8 +116,8 @@
 **          with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z
 **          are the major version, minor version, and release number.
 */
-#define SQLITE_VERSION         "3.6.1"
-#define SQLITE_VERSION_NUMBER  3006001
+#define SQLITE_VERSION         "3.6.2"
+#define SQLITE_VERSION_NUMBER  3006002
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
@@ -491,6 +516,7 @@
 #define SQLITE_IOERR_NOMEM             (SQLITE_IOERR | (12<<8))
 #define SQLITE_IOERR_ACCESS            (SQLITE_IOERR | (13<<8))
 #define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8))
+#define SQLITE_IOERR_LOCK              (SQLITE_IOERR | (15<<8))
 
 /*
 ** CAPI3REF: Flags For File Open Operations {H10230} <H11120> <H12700>
@@ -513,6 +539,7 @@
 #define SQLITE_OPEN_SUBJOURNAL       0x00002000
 #define SQLITE_OPEN_MASTER_JOURNAL   0x00004000
 #define SQLITE_OPEN_NOMUTEX          0x00008000
+#define SQLITE_OPEN_FULLMUTEX        0x00010000
 
 /*
 ** CAPI3REF: Device Characteristics {H10240} <H11120>
@@ -966,7 +993,7 @@
 ** If the option is unknown or SQLite is unable to set the option
 ** then this routine returns a non-zero [error code].
 */
-int sqlite3_config(int, ...);
+SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
 
 /*
 ** CAPI3REF: Configure database connections  {H10180} <S20000>
@@ -987,7 +1014,7 @@
 ** New verbs are likely to be added in future releases of SQLite.
 ** Additional arguments depend on the verb.
 */
-int sqlite3_db_config(sqlite3*, int op, ...);
+SQLITE_EXPERIMENTAL int sqlite3_db_config(sqlite3*, int op, ...);
 
 /*
 ** CAPI3REF: Memory Allocation Routines {H10155} <S20120>
@@ -2076,6 +2103,11 @@
 ** previous call.  Disable the authorizer by installing a NULL callback.
 ** The authorizer is disabled by default.
 **
+** When [sqlite3_prepare_v2()] is used to prepare a statement, the
+** statement might be reprepared during [sqlite3_step()] due to a 
+** schema change.  Hence, the application should ensure that the
+** correct authorizer callback remains in place during the [sqlite3_step()].
+**
 ** Note that the authorizer callback is invoked only during
 ** [sqlite3_prepare()] or its variants.  Authorization is not
 ** performed during statement evaluation in [sqlite3_step()].
@@ -2086,11 +2118,11 @@
 **          authorizer callback with database connection D.
 **
 ** {H12502} The authorizer callback is invoked as SQL statements are
-**          being compiled.
+**          being parseed and compiled.
 **
 ** {H12503} If the authorizer callback returns any value other than
 **          [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY], then
-**          the [sqlite3_prepare_v2()] or equivalent call that caused
+**          the application interface call that caused
 **          the authorizer callback to run shall fail with an
 **          [SQLITE_ERROR] error code and an appropriate error message.
 **
@@ -2098,7 +2130,7 @@
 **          described is processed normally.
 **
 ** {H12505} When the authorizer callback returns [SQLITE_DENY], the
-**          [sqlite3_prepare_v2()] or equivalent call that caused the
+**          application interface call that caused the
 **          authorizer callback to run shall fail
 **          with an [SQLITE_ERROR] error code and an error message
 **          explaining that access is denied.
@@ -2172,21 +2204,21 @@
 ** INVARIANTS:
 **
 ** {H12551} The second parameter to an
-**          [sqlite3_set_authorizer | authorizer callback] is always an integer
+**          [sqlite3_set_authorizer | authorizer callback] shall be an integer
 **          [SQLITE_COPY | authorizer code] that specifies what action
 **          is being authorized.
 **
 ** {H12552} The 3rd and 4th parameters to the
 **          [sqlite3_set_authorizer | authorization callback]
-**          will be parameters or NULL depending on which
+**          shall be parameters or NULL depending on which
 **          [SQLITE_COPY | authorizer code] is used as the second parameter.
 **
 ** {H12553} The 5th parameter to the
-**          [sqlite3_set_authorizer | authorizer callback] is the name
+**          [sqlite3_set_authorizer | authorizer callback] shall be the name
 **          of the database (example: "main", "temp", etc.) if applicable.
 **
 ** {H12554} The 6th parameter to the
-**          [sqlite3_set_authorizer | authorizer callback] is the name
+**          [sqlite3_set_authorizer | authorizer callback] shall be the name
 **          of the inner-most trigger or view that is responsible for
 **          the access attempt or NULL if this access attempt is directly from
 **          top-level SQL code.
@@ -2246,16 +2278,17 @@
 **
 ** INVARIANTS:
 **
-** {H12281} The callback function registered by [sqlite3_trace()] is
+** {H12281} The callback function registered by [sqlite3_trace()] 
+**          shall be invoked
 **          whenever an SQL statement first begins to execute and
 **          whenever a trigger subprogram first begins to run.
 **
-** {H12282} Each call to [sqlite3_trace()] overrides the previously
+** {H12282} Each call to [sqlite3_trace()] shall override the previously
 **          registered trace callback.
 **
-** {H12283} A NULL trace callback disables tracing.
+** {H12283} A NULL trace callback shall disable tracing.
 **
-** {H12284} The first argument to the trace callback is a copy of
+** {H12284} The first argument to the trace callback shall be a copy of
 **          the pointer which was the 3rd argument to [sqlite3_trace()].
 **
 ** {H12285} The second argument to the trace callback is a
@@ -2279,8 +2312,8 @@
 **          of the number of nanoseconds of wall-clock time required to
 **          run the SQL statement from start to finish.
 */
-void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
-void *sqlite3_profile(sqlite3*,
+SQLITE_EXPERIMENTAL void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
+SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
    void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
 
 /*
@@ -2449,11 +2482,11 @@
 **          reading and writing if possible, or for reading only if the
 **          file is write protected by the operating system.
 **
-** {H12713} If the G parameter to [sqlite3_open(v2(F,D,G,V)] omits the
+** {H12713} If the G parameter to [sqlite3_open_v2(F,D,G,V)] omits the
 **          bit value [SQLITE_OPEN_CREATE] and the database does not
 **          previously exist, an error is returned.
 **
-** {H12714} If the G parameter to [sqlite3_open(v2(F,D,G,V)] contains the
+** {H12714} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
 **          bit value [SQLITE_OPEN_CREATE] and the database does not
 **          previously exist, then an attempt is made to create and
 **          initialize the database.
@@ -3947,12 +3980,12 @@
 ** the use of these functions.  To help encourage people to avoid
 ** using these functions, we are not going to tell you want they do.
 */
-int sqlite3_aggregate_count(sqlite3_context*);
-int sqlite3_expired(sqlite3_stmt*);
-int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
-int sqlite3_global_recover(void);
-void sqlite3_thread_cleanup(void);
-int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
+SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
+SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
+SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+SQLITE_DEPRECATED int sqlite3_global_recover(void);
+SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
+SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
 
 /*
 ** CAPI3REF: Obtaining SQL Function Parameter Values {H15100} <S20200>
@@ -5377,7 +5410,7 @@
 ** This interface is experimental and is subject to change or
 ** removal in future releases of SQLite.
 */
-int sqlite3_create_module(
+SQLITE_EXPERIMENTAL int sqlite3_create_module(
   sqlite3 *db,               /* SQLite connection to register module with */
   const char *zName,         /* Name of the module */
   const sqlite3_module *,    /* Methods for the module */
@@ -5392,7 +5425,7 @@
 ** except that it allows a destructor function to be specified. It is
 ** even more experimental than the rest of the virtual tables API.
 */
-int sqlite3_create_module_v2(
+SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
   sqlite3 *db,               /* SQLite connection to register module with */
   const char *zName,         /* Name of the module */
   const sqlite3_module *,    /* Methods for the module */
@@ -5464,7 +5497,7 @@
 ** This interface is experimental and is subject to change or
 ** removal in future releases of SQLite.
 */
-int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
+SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
 
 /*
 ** CAPI3REF: Overload A Function For A Virtual Table {H18300} <S20400>
@@ -5485,7 +5518,7 @@
 ** This API should be considered part of the virtual table interface,
 ** which is experimental and subject to change.
 */
-int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
 
 /*
 ** The interface to the virtual-table mechanism defined above (back up
@@ -6142,7 +6175,7 @@
 **
 ** See also: [sqlite3_db_status()]
 */
-int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
 
 /*
 ** CAPI3REF: Database Connection Status {H17201} <S60200>
@@ -6162,7 +6195,7 @@
 **
 ** See also: [sqlite3_status()].
 */
-int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
 
 /*
 ** CAPI3REF: Status Parameters {H17250} <H17200>

Modified: trunk/libgda/sqlite/virtual/gda-vprovider-data-model.c
==============================================================================
--- trunk/libgda/sqlite/virtual/gda-vprovider-data-model.c	(original)
+++ trunk/libgda/sqlite/virtual/gda-vprovider-data-model.c	Mon Sep 15 18:30:05 2008
@@ -619,10 +619,12 @@
 
 	TRACE ();
 
-	gda_data_model_iter_move_next (cursor->iter);
-	while (gda_data_model_iter_is_valid (cursor->iter) &&
-	       gda_data_proxy_row_is_deleted (vtable->proxy, gda_data_model_iter_get_row (cursor->iter)))
-		gda_data_model_iter_move_next (cursor->iter);
+	if (!gda_data_model_iter_move_next (cursor->iter)) {
+		if (gda_data_model_iter_is_valid (cursor->iter))
+			return SQLITE_IOERR;
+		else
+			return SQLITE_OK;
+	}
 	return SQLITE_OK;
 }
 

Modified: trunk/libgda/sqlite/virtual/virtual-test.c
==============================================================================
--- trunk/libgda/sqlite/virtual/virtual-test.c	(original)
+++ trunk/libgda/sqlite/virtual/virtual-test.c	Mon Sep 15 18:30:05 2008
@@ -41,7 +41,7 @@
 
 		GdaDataModelIter *iter;
 		iter = gda_data_model_create_iter (xml_model);
-		gda_data_model_iter_set_at_row (iter, -1);
+		gda_data_model_iter_move_at_row (iter, -1);
 		for (gda_data_model_iter_move_next (iter); gda_data_model_iter_is_valid (iter); 
 		     gda_data_model_iter_move_next (iter)) {
 			g_print ("has row %d\n", gda_data_model_iter_get_row (iter));
@@ -61,7 +61,7 @@
 
 		GdaDataModelIter *iter;
 		iter = gda_data_model_create_iter (csv_model);
-		gda_data_model_iter_set_at_row (iter, -1);
+		gda_data_model_iter_move_at_row (iter, -1);
 		for (gda_data_model_iter_move_next (iter); gda_data_model_iter_is_valid (iter); 
 		     gda_data_model_iter_move_next (iter)) {
 			g_print ("has row %d\n", gda_data_model_iter_get_row (iter));

Modified: trunk/tests/value-holders/check_holder.c
==============================================================================
--- trunk/tests/value-holders/check_holder.c	(original)
+++ trunk/tests/value-holders/check_holder.c	Mon Sep 15 18:30:05 2008
@@ -784,11 +784,11 @@
 }
 
 /*
- * "before_change" signal
+ * "validate-change" signal
  */
 
 static GError *
-t10_before_change_cb (GdaHolder *h, const GValue *value, gchar *token)
+t10_validate_change_cb (GdaHolder *h, const GValue *value, gchar *token)
 {
 	/* only accept GDA_VALUE_NULL or the "hi!" G_TYPE_STRING value */
 	g_assert (!strcmp (token, "AToken"));
@@ -828,8 +828,8 @@
 	gda_value_free (value);
 	
 	/***/
-	g_signal_connect (G_OBJECT (h), "before-change",
-			  G_CALLBACK (t10_before_change_cb), "AToken");
+	g_signal_connect (G_OBJECT (h), "validate-change",
+			  G_CALLBACK (t10_validate_change_cb), "AToken");
 
 	/***/
 	value = gda_value_new_from_string ("my other string", G_TYPE_STRING);

Modified: trunk/tests/value-holders/check_set.c
==============================================================================
--- trunk/tests/value-holders/check_set.c	(original)
+++ trunk/tests/value-holders/check_set.c	Mon Sep 15 18:30:05 2008
@@ -153,10 +153,10 @@
 }
 
 /*
- * "before_holder_change" signal
+ * "validate-holder-change" signal
  */
 static GError *
-t3_before_holder_change (GdaSet *set, GdaHolder *h, const GValue *value, gchar *token)
+t3_validate_holder_change (GdaSet *set, GdaHolder *h, const GValue *value, gchar *token)
 {
 	/* only accept GDA_VALUE_NULL or 444 value */
 	g_assert (!strcmp (token, "MyToken"));
@@ -192,8 +192,8 @@
 				  "H2", G_TYPE_INT, 1234,
 				  "H3", G_TYPE_CHAR, 'r');
 
-	g_signal_connect (G_OBJECT (set), "before-holder-change",
-			  G_CALLBACK (t3_before_holder_change), "MyToken");
+	g_signal_connect (G_OBJECT (set), "validate-holder-change",
+			  G_CALLBACK (t3_validate_holder_change), "MyToken");
 
 	h = gda_set_get_holder (set, "H2");
 	g_value_set_int ((value = gda_value_new (G_TYPE_INT)), 333);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]