[med-svn] [r-cran-rsqlite] 01/06: Imported Upstream version 1.0.0

Andreas Tille tille at debian.org
Sat Jun 27 10:59:34 UTC 2015


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository r-cran-rsqlite.

commit 322ce391d084709fb29812bb36b117d5e8bccf4e
Author: Andreas Tille <tille at debian.org>
Date:   Sat Jun 27 11:51:31 2015 +0200

    Imported Upstream version 1.0.0
---
 DESCRIPTION                                        |    46 +-
 MD5                                                |   157 +-
 NAMESPACE                                          |   150 +-
 R/Connect.R                                        |   130 +
 R/Connection.R                                     |   128 +
 R/ConnectionExtensions.R                           |    29 +
 R/ConnectionRead.R                                 |    85 +
 R/ConnectionTransactions.R                         |    77 +
 R/ConnectionWrite.R                                |   128 +
 R/Constants.R                                      |     1 +
 R/Driver.R                                         |    83 +
 R/Escaping.R                                       |    61 +
 R/Object.R                                         |   106 +
 R/Result.R                                         |   231 +
 R/S4R.R                                            |    19 -
 R/SQLite.R                                         |   340 -
 R/SQLiteSupport.R                                  |   724 -
 R/Summary.R                                        |    78 +
 R/Utils.R                                          |   147 +
 R/datasetsDb.R                                     |    17 +
 R/dbGetInfo.R                                      |    54 +
 R/dbObjectId.R                                     |    52 -
 R/extensions.R                                     |    36 +
 R/zzz.R                                            |    59 +-
 README.md                                          |    89 +
 configure                                          |  3700 +-
 configure.in                                       |     2 +-
 inst/HACKING                                       |    21 -
 inst/INSTALL                                       |    59 -
 inst/NEWS                                          |   460 -
 inst/ONEWS                                         |   168 -
 inst/README                                        |    19 -
 inst/THANKS                                        |     5 -
 inst/TODO                                          |    22 -
 inst/UnitTests/README                              |    22 -
 inst/UnitTests/basic_type_test.R                   |   148 -
 inst/UnitTests/bind_data_test.R                    |   198 -
 inst/UnitTests/blob_test.R                         |    93 -
 inst/UnitTests/connection_gc_test.R                |    25 -
 inst/UnitTests/dat2.txt                            |     6 -
 inst/UnitTests/dat4.txt                            |     5 -
 inst/UnitTests/dbConnect_test.R                    |    90 -
 inst/UnitTests/dbDataType_test.R                   |    76 -
 inst/UnitTests/dbGetInfo_test.R                    |    35 -
 inst/UnitTests/dbWriteTable_test.R                 |   194 -
 inst/UnitTests/multiple_cons_test.R                |   113 -
 inst/UnitTests/result_set_closing_test.R           |    63 -
 inst/UnitTests/sqliteCopyDatabase_test.R           |    55 -
 inst/UnitTests/sqliteQuickColumn_test.R            |    42 -
 inst/announce                                      |    22 -
 inst/db/datasets.sqlite                            |   Bin 0 -> 193536 bytes
 inst/include/sqlite3.h                             |  1299 +-
 inst/include/sqlite3ext.h                          |    91 +-
 inst/rsqlitePerf.txt                               |    49 -
 man/S4R.Rd                                         |    16 -
 man/SQLite.Rd                                      |   143 -
 man/SQLiteConnection-class.Rd                      |    65 +-
 man/SQLiteDriver-class.Rd                          |    96 +-
 man/SQLiteObject-class.Rd                          |    48 -
 man/SQLiteResult-class.Rd                          |    52 +-
 man/datasetsDb.Rd                                  |    21 +
 man/dbBeginTransaction.Rd                          |    17 +
 man/dbBuildTableDefinition.Rd                      |    47 -
 man/dbCallProc-methods.Rd                          |    39 -
 man/dbCommit-methods.Rd                            |    75 -
 man/dbConnect-SQLiteDriver-method.Rd               |    76 +
 man/dbConnect-methods.Rd                           |    74 -
 man/dbDataType-SQLiteConnection-method.Rd          |    34 +
 man/dbDataType-methods.Rd                          |    51 -
 man/dbDriver-methods.Rd                            |    64 -
 ...xistsTable-SQLiteConnection-character-method.Rd |    17 +
 man/dbGetException-SQLiteConnection-method.Rd      |    16 +
 man/dbGetInfo-methods.Rd                           |    89 -
 man/dbGetInfo.Rd                                   |    39 +
 man/dbIsValid.Rd                                   |    38 +
 ...ListFields-SQLiteConnection-character-method.Rd |    23 +
 man/dbListTables-SQLiteConnection-method.Rd        |    15 +
 man/dbListTables-methods.Rd                        |    52 -
 man/dbObjectId-class.Rd                            |    44 -
 ...bReadTable-SQLiteConnection-character-method.Rd |    53 +
 man/dbReadTable-methods.Rd                         |   147 -
 ...emoveTable-SQLiteConnection-character-method.Rd |    17 +
 man/dbSendPreparedQuery.Rd                         |    23 +
 man/dbSendQuery-methods.Rd                         |   130 -
 man/dbSetDataMappings-methods.Rd                   |    53 -
 man/dbUnloadDriver-SQLiteDriver-method.Rd          |    26 +
 man/dbWriteTable.Rd                                |    77 +
 man/fetch-methods.Rd                               |    76 -
 man/initExtension.Rd                               |    36 +
 man/isIdCurrent.Rd                                 |    44 -
 ...e.db.names-SQLiteConnection-character-method.Rd |    61 +
 man/make.db.names-methods.Rd                       |    87 -
 man/query.Rd                                       |    83 +
 man/safe.write.Rd                                  |    41 -
 man/sqlite-meta.Rd                                 |    57 +
 man/sqliteBuildTableDefinition.Rd                  |    31 +
 man/sqliteCopyDatabase.Rd                          |    66 +-
 man/sqliteQuickColumn.Rd                           |    43 +-
 man/sqliteSupport.Rd                               |   317 -
 man/summary-methods.Rd                             |    40 -
 man/summary.Rd                                     |    36 +
 man/transactions.Rd                                |    61 +
 src/RS-DBI.c                                       |  1229 -
 src/RS-DBI.h                                       |   289 -
 src/RS-SQLite.c                                    |  1673 -
 src/RS-SQLite.h                                    |   188 -
 src/Rhelpers.h                                     |   120 -
 src/connection.c                                   |   149 +
 src/driver.c                                       |   105 +
 src/exceptions.c                                   |    79 +
 src/extension-functions.c                          |  1938 +
 src/fetch.c                                        |   392 +
 src/fields.c                                       |    92 +
 src/importFile.c                                   |   248 +
 src/param_binding.c                                |   285 +-
 src/param_binding.h                                |    23 -
 src/quick_column.c                                 |   130 +
 src/result.c                                       |   180 +
 src/rsqlite.h                                      |   163 +
 src/sqlite-all.c                                   |     2 +-
 src/sqlite-all.o-68d98681                          |     0
 src/sqlite/sqlite3.c                               | 41120 +++++++++++--------
 src/sqlite/sqlite3.h                               |   575 +-
 src/sqlite/sqlite3ext.h                            |     3 +
 src/test-dbDisconnect.R                            |    18 +
 src/utils.c                                        |   110 +
 tests/RSQLite_unit_tests.R                         |     3 -
 tests/gc-tests.R                                   |    32 -
 tests/testthat.R                                   |     4 +
 .../UnitTests/dat1.txt => tests/testthat/dat-n.txt |     0
 .../dat3.txt => tests/testthat/dat-rn.txt          |     0
 tests/testthat/test-basic-types.R                  |    82 +
 tests/testthat/test-data-type.R                    |    49 +
 tests/testthat/test-dbClearResult.R                |    22 +
 tests/testthat/test-dbConnect.R                    |    78 +
 tests/testthat/test-dbSendQuery.R                  |    95 +
 tests/testthat/test-dbWriteTable.R                 |   145 +
 tests/testthat/test-sqliteCopyDatabase.R           |    37 +
 tests/testthat/test-sqliteQuickColumn.R            |    23 +
 139 files changed, 35005 insertions(+), 27641 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
index 8776312..e407c94 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,19 +1,35 @@
 Package: RSQLite
-Version: 0.11.4
-Title: SQLite interface for R
-Author: David A. James, Seth Falcon, and (for the included SQLite
-        sources) the authors of SQLite
-Maintainer: Seth Falcon <seth at userprimary.net>
-Description: Database Interface R driver for SQLite.  This package
-        embeds the SQLite database engine in R and provides an
-        interface compliant with the DBI package.  The source for the
-        SQLite engine (version 3.7.17) is included.
-Depends: R (>= 2.10.0), methods, DBI (>= 0.2-5)
-Imports: methods, DBI (>= 0.2-3)
-Suggests: RUnit (>= 0.4.22)
+Version: 1.0.0
+Title: SQLite Interface for R
+Authors at R: as.person(c(
+    "Hadley Wickham <hadley at rstudio.com> [aut, cre]",
+    "David A. James [aut]",
+    "Seth Falcon [aut]",
+    "SQLite Authors (for the included SQLite sources) [ctb]",
+    "Liam Healy (for the include SQLite extensions) [ctb]",
+    "RStudio [cph]"
+    ))
+Description: This package embeds the SQLite database engine in R and
+    provides an interface compliant with the DBI package.
+    The source for the SQLite engine (version 3.8.6) is included.
+Depends: R (>= 2.10.0), DBI (>= 0.3.1), methods
+Suggests: testthat
 License: LGPL (>= 2)
-Collate: zzz.R S4R.R dbObjectId.R SQLite.R SQLiteSupport.R
-Packaged: 2013-05-25 23:31:12 UTC; seth
+URL: https://github.com/rstats-db/RSQLite
+BugReports: https://github.com/rstats-db/RSQLite/issues
+Collate: 'ConnectionExtensions.R' 'Connection.R' 'Driver.R' 'Connect.R'
+        'ConnectionRead.R' 'ConnectionTransactions.R'
+        'ConnectionWrite.R' 'Constants.R' 'Escaping.R' 'Result.R'
+        'Object.R' 'Summary.R' 'Utils.R' 'datasetsDb.R' 'dbGetInfo.R'
+        'extensions.R' 'zzz.R'
+Packaged: 2014-10-24 18:38:41 UTC; hadley
+Author: Hadley Wickham [aut, cre],
+  David A. James [aut],
+  Seth Falcon [aut],
+  SQLite Authors [ctb] (for the included SQLite sources),
+  Liam Healy [ctb] (for the include SQLite extensions),
+  RStudio [cph]
+Maintainer: Hadley Wickham <hadley at rstudio.com>
 NeedsCompilation: yes
 Repository: CRAN
-Date/Publication: 2013-05-26 08:32:47
+Date/Publication: 2014-10-25 01:58:48
diff --git a/MD5 b/MD5
index 4dee5ca..a69f49d 100644
--- a/MD5
+++ b/MD5
@@ -1,79 +1,84 @@
-28e7597dfe7000eaa0ea472e9c858b4d *DESCRIPTION
-2fd28abc15ac7134eb4269ac8d286d94 *NAMESPACE
-2ffb54fb638385792c64dabdd9933c88 *R/S4R.R
-1fb38c47c73ac2c3327b3af7cb489fa9 *R/SQLite.R
-a43d84c652cad9171b9be85120a57130 *R/SQLiteSupport.R
-0bd5cbb18ce8fabdb42f120dbfe941ea *R/dbObjectId.R
-404726435b8242d2f6fd325503fb1316 *R/zzz.R
-ad0676ed89cf2d9aea2c074b3568538d *configure
-64a9fb389202feace65b17f204b2f172 *configure.in
-a24e39e8cda46699597f41074351a8d3 *inst/HACKING
-59a0a1835a537e561c449dd3494c79c9 *inst/INSTALL
-d1f499d28bc37f35932634a8b8d63fb1 *inst/NEWS
-b856a4253c0456c6d449e272cfdfa0e3 *inst/ONEWS
-9d3a54f75a69393f908aaebb8981fab9 *inst/README
-fe40264cf27f19fd9c1642132fc396ab *inst/THANKS
-9a609517c0058c28865d6b39526acb69 *inst/TODO
-955b354aa78d9dbf2b18bbb79c79ccf3 *inst/UnitTests/README
-752e13e167ea957db22c9d4db8ce811f *inst/UnitTests/basic_type_test.R
-7d829771152a4712322500a81125c927 *inst/UnitTests/bind_data_test.R
-b66820eff998fb2447fbac15ff7cbbde *inst/UnitTests/blob_test.R
-bcadff8f96ceb50c5564ced25e5fb0fe *inst/UnitTests/connection_gc_test.R
-a068d5330949c7f13f695ca5f62e1364 *inst/UnitTests/dat1.txt
-2fac31acda8ec0cf624b3d7cd3ccb500 *inst/UnitTests/dat2.txt
-d97f59133341d9a53539b8780331279b *inst/UnitTests/dat3.txt
-44dca0e99bf39dbf02f172e2c41892a4 *inst/UnitTests/dat4.txt
-50305f40b8611555e36930f81e6d4dd9 *inst/UnitTests/dbConnect_test.R
-7288a4c1fcd1d2981671d08b634e899e *inst/UnitTests/dbDataType_test.R
-c8c4082728a471aa151387504a6a3566 *inst/UnitTests/dbGetInfo_test.R
-e683776d6b66b74e04ed39b60acc9cdf *inst/UnitTests/dbWriteTable_test.R
-487c14ba9f89fa06f7af7825f8fb8856 *inst/UnitTests/multiple_cons_test.R
-a33a298c7f5b26e49977639a82cb97fb *inst/UnitTests/result_set_closing_test.R
-85688200ab5d5923b28e5d4b1c3917ba *inst/UnitTests/sqliteCopyDatabase_test.R
-425e930115e3818d47cf4f25e5fd6cd9 *inst/UnitTests/sqliteQuickColumn_test.R
-d662643e8e1c7f525d05619500925075 *inst/announce
-dc54e40dd31978de6b9c0a312aeb24e0 *inst/include/sqlite3.h
-37c99e0eb077c6bee5985d1d7e5dcea7 *inst/include/sqlite3ext.h
-5957130cb28032c070f04cf4a95b468b *inst/rsqlitePerf.txt
-6595cbe63b7663209e34ac1a25a5c3d1 *man/S4R.Rd
-55edc20ab19fc691163b69f9b10a1300 *man/SQLite.Rd
-b569b0f45e063987c5f2dba064806f3f *man/SQLiteConnection-class.Rd
-2d9465765feffd21fa9b5aaa03e08bd1 *man/SQLiteDriver-class.Rd
-68d8d8b6639fb97a13b8facf7137f761 *man/SQLiteObject-class.Rd
-ac2089f61fb78a2f7f948df404a32889 *man/SQLiteResult-class.Rd
-527ce1d48365b5c78e127b6d5d07c6e1 *man/dbBuildTableDefinition.Rd
-843e5ec06166a18903e0c2d7841125f5 *man/dbCallProc-methods.Rd
-b5b285df12d1a8f05f8d5ca423e4904f *man/dbCommit-methods.Rd
-7dd378ee15f2c7bdaf3cb67ab89ec5db *man/dbConnect-methods.Rd
-9bb314c1f91dacb46de699d2a8ab78ee *man/dbDataType-methods.Rd
-d506ee6392b12e235c0243777e9e1f2a *man/dbDriver-methods.Rd
-469b8a7ddac9a361c06e5fee74e9fed4 *man/dbGetInfo-methods.Rd
-eff26021ea0d2734662d051c490e8ab6 *man/dbListTables-methods.Rd
-3934cc60df5f7e77c1bcae3e78951ea9 *man/dbObjectId-class.Rd
-6f0c7b75138bca50742fcb3d28ef8ff6 *man/dbReadTable-methods.Rd
-e1ddd976c09a10d02bb68221725f3ef2 *man/dbSendQuery-methods.Rd
-fa492cec897e7b6a4fb0d556f39a4f75 *man/dbSetDataMappings-methods.Rd
-9720551a21e59466d727c4c299b6f638 *man/fetch-methods.Rd
-7f5303336390fa94c5a3681e4f5ecd40 *man/isIdCurrent.Rd
-625456c0c0c3c319f0ced49871959f7f *man/make.db.names-methods.Rd
-2646fb4b67f6c085a2d611a8e1a33661 *man/safe.write.Rd
-f3181df279afb2e1d8ffb653a9cdd1e7 *man/sqliteCopyDatabase.Rd
-acb91f044b6a7d62bc00e5a92a33e9a8 *man/sqliteQuickColumn.Rd
-5df92123a6fe28b6ec23cdde75ba97fe *man/sqliteSupport.Rd
-6c55deba7b97759eb05e8aa25f378f0c *man/summary-methods.Rd
+c08d0aeeeddd05a36c346fd8ca08fc43 *DESCRIPTION
+f1220a49a0e5397f5e9a079031bd79ba *NAMESPACE
+05ceb9d9065efc9cb4f85c6e5f3ab6bd *R/Connect.R
+6795db5f085892148c2219017ef4bd62 *R/Connection.R
+20b9d3b6c56e231d9e2e101ad80e5af4 *R/ConnectionExtensions.R
+dd0343bf373f85305f73f8a41ed9163d *R/ConnectionRead.R
+1330c9c38e2707e6e8ed6d6e31c54de1 *R/ConnectionTransactions.R
+83e10bfba0e345f9158a50ed1f23026c *R/ConnectionWrite.R
+02ed6061b34ca476f93738d6c7e41452 *R/Constants.R
+80ab362bd2c3f0996443f7e469b4dea2 *R/Driver.R
+07346046e80f8d749d1a0b8bef2ba57d *R/Escaping.R
+62971a67910e9da0e6b22750df3fd114 *R/Object.R
+db772f596b2907127b7a1ccfa5585fd3 *R/Result.R
+0dd28deb29d89c164532a7b0dcce8058 *R/Summary.R
+482adbb838b582889588147fc051974e *R/Utils.R
+4bfb64b60e190b1bbc2f8962856a42ad *R/datasetsDb.R
+e2490930d5c984d91391c54151052dec *R/dbGetInfo.R
+7f974b60f9ca715c873185a44e3715fc *R/extensions.R
+06ccf235324c8726543cf103c0660e36 *R/zzz.R
+d4805196b57b7952a749417c28502e00 *README.md
+62c8d17377f0766b352e3adec7764899 *configure
+a5936651da57e6a492201ead9beb8ca2 *configure.in
+6a6016ed370b49203dbc6e2c3f9160d3 *inst/db/datasets.sqlite
+e1ae1830573ac7005fa89a009f7fe643 *inst/include/sqlite3.h
+e19f65990098254b6527873d13777b02 *inst/include/sqlite3ext.h
+9203f172c266b4a9111f38ad1a331a68 *man/SQLiteConnection-class.Rd
+d0f0705ff2f4a898626cb20a2a77bef6 *man/SQLiteDriver-class.Rd
+800a401e50e673ce67f6ea39260557d9 *man/SQLiteResult-class.Rd
+50c56ffa7d7ace89f869ae02a3d48b25 *man/datasetsDb.Rd
+2e44d1fed5a81af3ae63f5bcbf25873c *man/dbBeginTransaction.Rd
+9e5f5404e5cbe85e0990437d981e9914 *man/dbConnect-SQLiteDriver-method.Rd
+6e8c3dcbfe7c06298429993be00f4a8b *man/dbDataType-SQLiteConnection-method.Rd
+52eddfefb1ebf636d4003eabab76c9e0 *man/dbExistsTable-SQLiteConnection-character-method.Rd
+9f881f02a8c77ca70bfc66af204785fe *man/dbGetException-SQLiteConnection-method.Rd
+9634a67f5ed99d25b0abf31c2118b928 *man/dbGetInfo.Rd
+eb33e3654b15f22ac14c2d12d6539d31 *man/dbIsValid.Rd
+c76832f37417b05f08f2ff95e7eb7cfb *man/dbListFields-SQLiteConnection-character-method.Rd
+0b3e1d10ceff75a09d473dbf188498ab *man/dbListTables-SQLiteConnection-method.Rd
+d55aa826adce5f64f4def1a8471b3dbe *man/dbReadTable-SQLiteConnection-character-method.Rd
+b9408362e377238eb551c904148f1cab *man/dbRemoveTable-SQLiteConnection-character-method.Rd
+6d6fa6493e8719ed0fbc4c035e2a365e *man/dbSendPreparedQuery.Rd
+3bdf7da408ea165f2baab5e0049e22eb *man/dbUnloadDriver-SQLiteDriver-method.Rd
+3a18a8204c042381a74c1c4126f14d30 *man/dbWriteTable.Rd
+347e1933ce92bc86dcb3e16e621b23f0 *man/initExtension.Rd
+2127e1399315f4c84166b0de306fbcfb *man/make.db.names-SQLiteConnection-character-method.Rd
+aae4a1e647f3ca9234a243acf1bec031 *man/query.Rd
+6a1459ac71945936d81d2a6299e24734 *man/sqlite-meta.Rd
+1e6e8005eaedcb1ef9ead133c7f5c8ca *man/sqliteBuildTableDefinition.Rd
+71dd82631f04f79416f0fea0a166e55e *man/sqliteCopyDatabase.Rd
+f45558d4beaaa595902557d3c69a395e *man/sqliteQuickColumn.Rd
+1d686f25328f076293cec3c607eedf64 *man/summary.Rd
+319ebabafecbfe4fc2d19202ba7c57b2 *man/transactions.Rd
 402dc8daa4362204bcad532beb0d1db3 *src/Makevars.in
 90edc5500cadb71688f020d62671dce7 *src/Makevars.win
-b5fbbdf65c593a0365e08cc041086e37 *src/RS-DBI.c
-71f81d066a1f123bbc2082f9b3ef63a0 *src/RS-DBI.h
-e4bcd41e499b4ba6b26f1dd9433e723b *src/RS-SQLite.c
-1ff17caf99328e3f7e5f80dc2ac2ec65 *src/RS-SQLite.h
-8526b1e7922e0089485249debd5b106b *src/Rhelpers.h
-7c8a358e4425e173f4e4b63671deba76 *src/param_binding.c
-e3d214e4b0c3f3d970ec0f7e9c950667 *src/param_binding.h
-b9e7c6744beeee3c22b21458fed9046c *src/sqlite-all.c
+19a226ffdff2fdfdd87803d2ed03a3f2 *src/connection.c
+6c2eb6b759947689944e7f1c0013c9f3 *src/driver.c
+b17e26332dec8dbf7cbebecd097be628 *src/exceptions.c
+f7c9df7685e65127d475347ac94bb183 *src/extension-functions.c
+e05f07f291200ef9ba60954e52e7af6b *src/fetch.c
+c2b01c62c121583047524332a24d33d1 *src/fields.c
+0bf15ff1f0090152d35263fc63ca658c *src/importFile.c
+624a1c5b115654f821323b30a2d7fa13 *src/param_binding.c
+138281b2abc6bd7afd4e66d5861e99d2 *src/quick_column.c
+17cc016c502daddc9d8ecf77bea7e84b *src/result.c
+4e89fe2059b5ef60c797c2fac0c586f6 *src/rsqlite.h
+649f6e78dd9cc8366a175a1a4c4d9ed0 *src/sqlite-all.c
+d41d8cd98f00b204e9800998ecf8427e *src/sqlite-all.o-68d98681
 ee45c6cd7c5345bdecfe3728e6321455 *src/sqlite.h
-25445a0da03134452ba39f0c09ca9722 *src/sqlite/sqlite3.c
-94f635c8f9f9ba78beae25e740960036 *src/sqlite/sqlite3.h
-5b9d7c31cc6a0bcbb2b4c3c1a297df53 *src/sqlite/sqlite3ext.h
-1e49d8ec611f7f514819aec12803b05b *tests/RSQLite_unit_tests.R
-73c6f6ff2086590e18527fb1704fc7cd *tests/gc-tests.R
+acbff8ef1b802c76a5d441fd4145f9bf *src/sqlite/sqlite3.c
+e1ae1830573ac7005fa89a009f7fe643 *src/sqlite/sqlite3.h
+e19f65990098254b6527873d13777b02 *src/sqlite/sqlite3ext.h
+faaecac01a2199c84d0e6f96d3d7f1bc *src/test-dbDisconnect.R
+ec13cbf708551eeedab3ff3eb19fe858 *src/utils.c
+0789cfb7c20ebde1c14973df737b8f85 *tests/testthat.R
+a068d5330949c7f13f695ca5f62e1364 *tests/testthat/dat-n.txt
+d97f59133341d9a53539b8780331279b *tests/testthat/dat-rn.txt
+d63f9d0e10a9852dbda9fa380b6396f0 *tests/testthat/test-basic-types.R
+796a11792447d05daaba958c29d92577 *tests/testthat/test-data-type.R
+ce0e0a381ecc9263428cdf67bcf3e9a2 *tests/testthat/test-dbClearResult.R
+6b7aea2ad13d61e6b91a1ea5eec152b7 *tests/testthat/test-dbConnect.R
+7cbe2d9def3212f81d28d348309655a9 *tests/testthat/test-dbSendQuery.R
+1061a043866d99a99398e03ada5f510d *tests/testthat/test-dbWriteTable.R
+a37f613e594c64b4e4bfde0f85b8422d *tests/testthat/test-sqliteCopyDatabase.R
+ed659094f988f7e0845248c893ce7248 *tests/testthat/test-sqliteQuickColumn.R
diff --git a/NAMESPACE b/NAMESPACE
index 43746cf..78d76a5 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,83 +1,69 @@
-import(methods)
-import(DBI)
-
-useDynLib(RSQLite)
-
-## Classes
-exportClasses(
-   dbObjectId,
-   SQLiteObject,
-   SQLiteDriver,
-   SQLiteConnection,
-   SQLiteResult
-)
+# Generated by roxygen2 (4.0.2): do not edit by hand
 
-## Methods/Generics
-exportMethods(
-   coerce,
-   dbBeginTransaction,
-   dbCallProc,
-   dbClearResult,
-   dbColumnInfo,
-   dbCommit,
-   dbConnect,
-   dbDataType,
-   dbDisconnect,
-   dbExistsTable,
-   dbGetException,
-   dbGetInfo,
-   dbGetPreparedQuery,
-   dbGetQuery,
-   dbGetRowCount,
-   dbGetRowsAffected,
-   dbGetStatement,
-   dbHasCompleted,
-   dbListConnections,
-   dbListFields,
-   dbListResults,
-   dbListTables,
-   dbReadTable,
-   dbRemoveTable,
-   dbRollback,
-   dbSendPreparedQuery,
-   dbSendQuery,
-   dbUnloadDriver,
-   dbWriteTable,
-   fetch,
-   initialize,
-   isSQLKeyword,
-   make.db.names,
-   show,
-   SQLKeywords,
-   summary
-)
-
-## regular functions (most of these will be made private)
-export(
-  SQLite,
-  dbBuildTableDefinition,
-  isIdCurrent,
-  sqliteInitDriver,
-  sqliteCloseDriver,
-  sqliteDescribeDriver,
-  sqliteDriverInfo,
-  sqliteNewConnection,
-  sqliteDescribeConnection,
-  sqliteCloseConnection,
-  sqliteConnectionInfo,
-  sqliteExecStatement,
-  sqliteQuickSQL,
-  sqliteFetch,
-  sqliteResultInfo,
-  sqliteDescribeResult,
-  sqliteCloseResult,
-  sqliteTableFields,
-  sqliteReadTable,
-  sqliteWriteTable,
-  sqliteDataType,
-  sqliteCopyDatabase,
-  safe.write
-)
-
-## constants
-export(SQLITE_RWC, SQLITE_RW, SQLITE_RO)
+export(SQLITE_RO)
+export(SQLITE_RW)
+export(SQLITE_RWC)
+export(SQLite)
+export(datasetsDb)
+export(dbBeginTransaction)
+export(dbBuildTableDefinition)
+export(dbGetPreparedQuery)
+export(dbSendPreparedQuery)
+export(initExtension)
+export(isIdCurrent)
+export(sqliteBuildTableDefinition)
+export(sqliteCopyDatabase)
+export(sqliteQuickColumn)
+exportClasses(SQLiteConnection)
+exportClasses(SQLiteDriver)
+exportClasses(SQLiteResult)
+exportMethods(SQLKeywords)
+exportMethods(dbBegin)
+exportMethods(dbClearResult)
+exportMethods(dbColumnInfo)
+exportMethods(dbCommit)
+exportMethods(dbConnect)
+exportMethods(dbDataType)
+exportMethods(dbDisconnect)
+exportMethods(dbExistsTable)
+exportMethods(dbFetch)
+exportMethods(dbGetException)
+exportMethods(dbGetInfo)
+exportMethods(dbGetPreparedQuery)
+exportMethods(dbGetQuery)
+exportMethods(dbGetRowCount)
+exportMethods(dbGetRowsAffected)
+exportMethods(dbGetStatement)
+exportMethods(dbHasCompleted)
+exportMethods(dbIsValid)
+exportMethods(dbListFields)
+exportMethods(dbListResults)
+exportMethods(dbListTables)
+exportMethods(dbReadTable)
+exportMethods(dbRemoveTable)
+exportMethods(dbRollback)
+exportMethods(dbSendPreparedQuery)
+exportMethods(dbSendQuery)
+exportMethods(dbUnloadDriver)
+exportMethods(dbWriteTable)
+exportMethods(isSQLKeyword)
+exportMethods(make.db.names)
+exportMethods(summary)
+import(DBI)
+import(methods)
+useDynLib(RSQLite,RS_SQLite_copy_database)
+useDynLib(RSQLite,RS_SQLite_importFile)
+useDynLib(RSQLite,rsqlite_connection_create)
+useDynLib(RSQLite,rsqlite_connection_destroy)
+useDynLib(RSQLite,rsqlite_connection_info)
+useDynLib(RSQLite,rsqlite_connection_valid)
+useDynLib(RSQLite,rsqlite_driver_close)
+useDynLib(RSQLite,rsqlite_driver_info)
+useDynLib(RSQLite,rsqlite_driver_init)
+useDynLib(RSQLite,rsqlite_driver_valid)
+useDynLib(RSQLite,rsqlite_exception_info)
+useDynLib(RSQLite,rsqlite_query_fetch)
+useDynLib(RSQLite,rsqlite_query_send)
+useDynLib(RSQLite,rsqlite_result_free_handle)
+useDynLib(RSQLite,rsqlite_result_info)
+useDynLib(RSQLite,rsqlite_result_valid)
diff --git a/R/Connect.R b/R/Connect.R
new file mode 100644
index 0000000..43603a1
--- /dev/null
+++ b/R/Connect.R
@@ -0,0 +1,130 @@
+#' @include Connection.R
+#' @include Driver.R
+NULL
+
+#' @export
+SQLITE_RWC <- 6L
+#' @export
+SQLITE_RW <- 2L
+#' @export
+SQLITE_RO <- 1L
+
+#' Connect to/disconnect from a SQLite database.
+#' 
+#' @param drv,conn An objected generated by \code{\link{SQLite}}, or an existing
+#'   \code{\linkS4class{SQLiteConnection}}. If an connection, the connection
+#'   will be cloned.
+#' @param dbname The path to the database file. There are two special values:
+#' 
+#'   \itemize{
+#'   \item \code{""}: creates a temporary on-disk database The file will be 
+#'      deleted when the connection is closed. 
+#'   \item \code{":memory:"}: create a temporary in-memory database.
+#'   }
+#' @param cache_size Advanced option. A positive integer to change the maximum 
+#'   number of disk pages that SQLite holds in memory (SQLite's default is 
+#'   2000 pages). See \url{http://www.sqlite.org/pragma.html#pragma_cache_size} 
+#'   for details.
+#' @param synchronous Advanced options. Possible values for \code{synchronous} 
+#'   are "off" (the default), "normal", or  "full".  Users have reported 
+#'   significant speed ups using \code{sychronous = "off"}, and the SQLite 
+#'   documentation itself implies considerable improved performance at the very 
+#'   modest risk of database corruption in the unlikely case of the operating 
+#'   system (\emph{not} the R application) crashing. See
+#'   \url{http://www.sqlite.org/pragma.html#pragma_synchronous} for details.
+#' @param flags \code{SQLITE_RWC}: open the database in read/write mode
+#'   and create the database file if it does not already exist; 
+#'   \code{SQLITE_RW}: open the database in read/write mode. Raise an error 
+#'   if the file does not already exist; \code{SQLITE_RO}: open the database in 
+#'   read only mode.  Raise an error if the file does not already exist
+#' @param loadable.extensions When \code{TRUE} (default) SQLite3
+#'   loadable extensions are enabled. Setting this value to \code{FALSE}
+#'   prevents extensions from being loaded.
+#' @param vfs Select the SQLite3 OS interface. See
+#'   \url{http://www.sqlite.org/vfs.html} for details. Allowed values are
+#'   \code{"unix-posix"}, \code{"unix-unix-afp"},
+#'   \code{"unix-unix-flock"}, \code{"unix-dotfile"}, and
+#'   \code{"unix-none"}.
+#' @aliases SQLITE_RWC SQLITE_RW SQLITE_RO
+#' @export
+#' @useDynLib RSQLite rsqlite_connection_create
+#' @examples
+#' # Create temporary in-memory db
+#' tmp <- dbConnect(SQLite(), ":memory:")
+#' summary(tmp)
+#' dbDisconnect(tmp)
+#' 
+#' # Create temporary on-disk db with bigger cache and safer synchronisation
+#' tmp <- dbConnect(SQLite(), "", cache_size = 5000, synchronous = "full")
+#' summary(tmp)
+#' dbDisconnect(tmp)
+setMethod("dbConnect", "SQLiteDriver",
+  function(drv, dbname = "", loadable.extensions = TRUE, cache_size = NULL, 
+           synchronous = "off", flags = SQLITE_RWC, vfs = NULL) {
+    
+    stopifnot(is.character(dbname), length(dbname) == 1, !is.na(dbname))
+    dbname <- path.expand(dbname)
+    loadable.extensions <- as.logical(loadable.extensions)
+    vfs <- check_vfs(vfs)
+    stopifnot(is.integer(flags), length(flags) == 1)
+
+    conId <- .Call(rsqlite_connection_create, dbname, loadable.extensions, flags, vfs)
+    con <- new("SQLiteConnection", 
+      Id = conId,
+      dbname = dbname,
+      loadable.extensions = loadable.extensions,
+      flags = flags,
+      vfs = vfs
+    )
+    
+    ## experimental PRAGMAs
+    if (!is.null(cache_size)) {
+      cache_size <- as.integer(cache_size)
+      try(dbGetQuery(con, sprintf("PRAGMA cache_size=%d", cache_size)))
+    }
+    
+    if (!is.null(synchronous)) {
+      synchronous <- match.arg(synchronous, c("off", "normal", "full"))
+      try(dbGetQuery(con, sprintf("PRAGMA synchronous=%s", synchronous)))
+    }
+    
+    con
+  }
+)
+
+check_vfs <- function(vfs) {
+  if (is.null(vfs) || vfs == "") return("")
+  
+  if (.Platform[["OS.type"]] == "windows") {
+    warning("vfs customization not available on this platform.",
+      " Ignoring value: vfs = ", vfs, call. = FALSE)
+    return("")
+  }
+
+  match.arg(vfs, c("unix-posix", "unix-afp", "unix-flock", "unix-dotfile",
+    "unix-none"))
+}
+
+#' @export
+#' @rdname dbConnect-SQLiteDriver-method
+setMethod("dbConnect", "SQLiteConnection", function(drv){
+  if (drv at dbname %in% c("", ":memory:")) {
+    stop("Can't clone a temporary database", call. = FALSE)
+  }
+  
+  dbConnect(SQLite(), drv at dbname, vfs = drv at vfs, flags = drv at flags, 
+    loadable.extensions = drv at loadable.extensions)
+})
+
+
+#' @export
+#' @rdname dbConnect-SQLiteDriver-method
+#' @useDynLib RSQLite rsqlite_connection_destroy
+setMethod("dbDisconnect", "SQLiteConnection", function(conn) {
+  if (!dbIsValid(conn)) {
+    warning("Expired SQLiteConnection.", call. = FALSE)
+    return(TRUE)
+  }
+  
+  .Call(rsqlite_connection_destroy, conn at Id)
+})
diff --git a/R/Connection.R b/R/Connection.R
new file mode 100644
index 0000000..1fadc99
--- /dev/null
+++ b/R/Connection.R
@@ -0,0 +1,128 @@
+#' @include ConnectionExtensions.R
+NULL
+
+#' Class SQLiteConnection.
+#' 
+#' \code{SQLiteConnection} objects are usually created by 
+#' \code{\link[DBI]{dbConnect}}
+#' 
+#' @examples
+#' con <- dbConnect(SQLite(), dbname = tempfile())
+#' dbDisconnect(con)
+#' @export
+setClass("SQLiteConnection", 
+  contains = "DBIConnection",
+  slots = list(
+    Id = "externalptr",
+    dbname = "character", 
+    loadable.extensions = "logical", 
+    flags = "integer", 
+    vfs = "character"
+  )
+)
+
+#' Get the last exception from the connection.
+#' 
+#' @param conn an object of class \code{\linkS4class{SQLiteConnection}}
+#' @export
+#' @useDynLib RSQLite rsqlite_exception_info
+#' @keywords internal
+setMethod("dbGetException", "SQLiteConnection", function(conn) {
+  .Call(rsqlite_exception_info, conn at Id)
+})
+
+#' Does the table exist?
+#' 
+#' @param conn An existing \code{\linkS4class{SQLiteConnection}}
+#' @param name String, name of table. Match is case insensitive.
+#' @export
+setMethod("dbExistsTable", c("SQLiteConnection", "character"),
+  function(conn, name) {
+    tolower(name) %in% tolower(dbListTables(conn))
+  }
+)
+
+#' Build the SQL CREATE TABLE definition as a string
+#' 
+#' The output SQL statement is a simple \code{CREATE TABLE} with suitable for
+#' \code{dbGetQuery}
+#' 
+#' @param conn A database connection.
+#' @param name Name of the new SQL table
+#' @param value A data.frame, for which we want to create a table.
+#' @param field.types Optional, named character vector of the types for each 
+#'   field in \code{value}
+#' @param row.names Logical. Should row.name of \code{value} be exported as a
+#'   \code{row\_names} field? Default is \code{TRUE}
+#' @return An SQL string
+#' @keywords internal
+#' @aliases dbBuildTableDefinition
+#' @export
+sqliteBuildTableDefinition <- function(con, name, value, field.types = NULL, 
+                                       row.names = NA) {
+  if (!is.data.frame(value)) {
+    value <- as.data.frame(value)
+  }
+  value <- explict_rownames(value, row.names)
+
+  if (is.null(field.types)) {
+    field.types <- vapply(value, dbDataType, dbObj = con, 
+      FUN.VALUE = character(1))
+  }
+  # Escape field names
+  names(field.types) <- dbQuoteIdentifier(con, names(field.types))
+    
+  flds <- paste(names(field.types), field.types)
+  paste("CREATE TABLE", name, "\n(", paste(flds, collapse = ",\n\t"), "\n)")
+}
+
+#' @export
+dbBuildTableDefinition <- function(...) {
+  .Deprecated("sqliteBuildTableDefinition")
+  sqliteBuildTableDefinition(...)
+}
+  
+
+#' Remove a table from the database.
+#' 
+#' Executes the SQL \code{DROP TABLE}.
+#' 
+#' @param conn An existing \code{\linkS4class{SQLiteConnection}}
+#' @param name character vector of length 1 giving name of table to remove
+#' @export
+setMethod("dbRemoveTable", c("SQLiteConnection", "character"),
+  function(conn, name) {
+    dbGetQuery(conn, paste("DROP TABLE ", name))
+    invisible(TRUE)
+  }
+)
+
+#' List available SQLite tables.
+#' 
+#' @param conn An existing \code{\linkS4class{SQLiteConnection}}
+#' @export
+setMethod("dbListTables", "SQLiteConnection", function(conn) {
+  dbGetQuery(conn, "SELECT name FROM
+    (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master)
+    WHERE type = 'table' OR type = 'view'
+    ORDER BY name")$name
+})
+
+#' List fields in specified table.
+#' 
+#' @param conn An existing \code{\linkS4class{SQLiteConnection}}
+#' @param name a length 1 character vector giving the name of a table.
+#' @export
+#' @examples
+#' con <- dbConnect(SQLite())
+#' dbWriteTable(con, "iris", iris)
+#' dbListFields(con, "iris")
+#' dbDisconnect(con)
+setMethod("dbListFields", c("SQLiteConnection", "character"),
+  function(conn, name) {
+    rs <- dbSendQuery(conn, paste("SELECT * FROM ", name, "LIMIT 1"))
+    on.exit(dbClearResult(rs))
+    
+    names(fetch(rs, n = 1))
+  }
+)
diff --git a/R/ConnectionExtensions.R b/R/ConnectionExtensions.R
new file mode 100644
index 0000000..2339de3
--- /dev/null
+++ b/R/ConnectionExtensions.R
@@ -0,0 +1,29 @@
+#' Generics for getting and sending prepared queries.
+#' 
+#' @param conn An \code{DBIConnection} object.
+#' @param statement A SQL string
+#' @param bind.data A data frame
+#' @param ... Other arguments used by methods
+#' @export
+setGeneric("dbSendPreparedQuery", function(conn, statement, bind.data, ...) {
+  standardGeneric("dbSendPreparedQuery")
+})
+
+#' @rdname dbSendPreparedQuery
+#' @export
+setGeneric("dbGetPreparedQuery", function(conn, statement, bind.data, ...) {
+  standardGeneric("dbGetPreparedQuery")
+})
+
+#' Generic for creating a new transaction.
+#' 
+#' See method documentation for details.
+#' 
+#' @export
+#' @param conn An \code{DBIConnection} object.
+#' @param ... Other arguments used by methods
+#' @keywords internal
+setGeneric("dbBeginTransaction", function(conn, ...) {
+  .Deprecated("dbBegin")
+  dbBegin(conn, ...)
+})
\ No newline at end of file
diff --git a/R/ConnectionRead.R b/R/ConnectionRead.R
new file mode 100644
index 0000000..01aa843
--- /dev/null
+++ b/R/ConnectionRead.R
@@ -0,0 +1,85 @@
+#' Convenience functions for importing/exporting DBMS tables
+#' 
+#' These functions mimic their R/S-Plus counterpart \code{get}, \code{assign},
+#' \code{exists}, \code{remove}, and \code{objects}, except that they generate
+#' code that gets remotely executed in a database engine.
+#' 
+#' @return A data.frame in the case of \code{dbReadTable}; otherwise a logical
+#' indicating whether the operation was successful.
+#' @note Note that the data.frame returned by \code{dbReadTable} only has
+#' primitive data, e.g., it does not coerce character data to factors.
+#' 
+#' @param conn a \code{\linkS4class{SQLiteConnection}} object, produced by
+#'   \code{\link[DBI]{dbConnect}}
+#' @param name a character string specifying a table name. SQLite table names 
+#'   are \emph{not} case sensitive, e.g., table names \code{ABC} and \code{abc} 
+#'   are considered equal.
+#' @param check.names If \code{TRUE}, the default, column names will be
+#'   converted to valid R identifiers.
+#' @param row.names A string or an index specifying the column in the DBMS table 
+#'   to use as \code{row.names} in the output data.frame. Defaults to using the
+#'   \code{row_names} column if present. Set to \code{NULL} to never use
+#'   row names.
+#' @param select.cols  A SQL statement (in the form of a character vector of 
+#'    length 1) giving the columns to select. E.g. "*" selects all columns, 
+#'    "x,y,z" selects three columns named as listed.
+#' @export
+#' @examples
+#' con <- dbConnect(SQLite())
+#' dbWriteTable(con, "mtcars", mtcars)
+#' dbReadTable(con, "mtcars")
+#' 
+#' # Supress row names
+#' dbReadTable(con, "mtcars", row.names = FALSE)
+#' 
+#' dbDisconnect(con)
+setMethod("dbReadTable", c("SQLiteConnection", "character"),
+  function(conn, name, row.names, check.names = TRUE, 
+           select.cols = "*") {
+    out <- dbGetQuery(conn, paste("SELECT", select.cols, "FROM", name))
+    
+    if (check.names) {
+      names(out) <- make.names(names(out), unique = TRUE)
+    }
+    
+    row.names <- rownames_column(out, row.names)
+    if (is.null(row.names)) return(out)
+    
+    rnms <- as.character(out[[row.names]])
+    if (anyDuplicated(rnms)) {
+      warning("row.names not set (duplicate elements in field)", call. = FALSE)
+    } else {
+      out <- out[, -row.names, drop = F]
+      row.names(out) <- rnms
+    }
+    out
+  }
+)
+
+# Figure out which column to 
+rownames_column <- function(df, row.names) {
+  if (missing(row.names)) {
+    if (!"row_names" %in% names(df)) {
+      return(NULL)
+    }
+
+    row.names <- "row_names"
+  } 
+  
+  if (is.null(row.names) || identical(row.names, FALSE)) {
+    NULL
+  } else if (is.character(row.names)) {
+    if (!(row.names %in% names(df))) {
+      stop("Column ", row.names, " not present in output", call. = FALSE)
+    }
+    match(row.names, names(df))
+  } else if (is.numeric(row.names)) {
+    if (row.names == 0) return(NULL)
+    if (row.names < 0 || row.names > ncol(df)) {
+      stop("Column ", row.names, " not present in output", call. = FALSE)
+    }
+    row.names
+  } else {
+    stop("Unknown specification for row.names")
+  }
+}
\ No newline at end of file
diff --git a/R/ConnectionTransactions.R b/R/ConnectionTransactions.R
new file mode 100644
index 0000000..bed1d9f
--- /dev/null
+++ b/R/ConnectionTransactions.R
@@ -0,0 +1,77 @@
+#' SQLite transaction management.
+#' 
+#' By default, SQLite is in auto-commit mode. \code{dbBegin} starts
+#' a SQLite transaction and turns auto-commit off. \code{dbCommit} and
+#' \code{dbRollback} commit and rollback the transaction, respectively and turn
+#' auto-commit on.
+#' 
+#' @param conn a \code{\linkS4class{SQLiteConnection}} object, produced by
+#'   \code{\link[DBI]{dbConnect}}
+#' @param name Supply a name to use a named savepoint. This allows you to
+#'   nest multiple transaction
+#' @return A boolean, indicating success or failure.
+#' @examples
+#' con <- dbConnect(SQLite(), ":memory:")
+#' dbWriteTable(con, "arrests", datasets::USArrests)
+#' dbGetQuery(con, "select count(*) from arrests")
+#' 
+#' dbBegin(con)
+#' rs <- dbSendQuery(con, "DELETE from arrests WHERE Murder > 1")
+#' dbGetRowsAffected(rs)
+#' dbClearResult(rs)
+#' 
+#' dbGetQuery(con, "select count(*) from arrests")
+#' 
+#' dbRollback(con)
+#' dbGetQuery(con, "select count(*) from arrests")[1, ]
+#' 
+#' dbBegin(con)
+#' rs <- dbSendQuery(con, "DELETE FROM arrests WHERE Murder > 5")
+#' dbClearResult(rs)
+#' dbCommit(con)
+#' dbGetQuery(con, "SELECT count(*) FROM arrests")[1, ]
+#' 
+#' # Named savepoints can be nested --------------------------------------------
+#' dbBegin(con, "a")
+#' dbBegin(con, "b")
+#' dbRollback(con, "b")
+#' dbCommit(con, "a")
+#' 
+#' dbDisconnect(con)
+#' @name transactions
+NULL
+
+#' @export
+#' @rdname transactions
+setMethod("dbBegin", "SQLiteConnection", function(conn, name = NULL) {
+  if (is.null(name)) {
+    dbGetQuery(conn, "BEGIN")  
+  } else {
+    dbGetQuery(conn, paste("SAVEPOINT ", name))
+  }
+  
+  TRUE
+})
+
+#' @export
+#' @rdname transactions
+setMethod("dbCommit", "SQLiteConnection", function(conn, name = NULL) {
+  if (is.null(name)) {
+    dbGetQuery(conn, "COMMIT")
+  } else {
+    dbGetQuery(conn, paste("RELEASE SAVEPOINT ", name))
+  }
+  
+  TRUE
+})
+
+#' @export
+#' @rdname transactions
+setMethod("dbRollback", "SQLiteConnection", function(conn, name = NULL) {
+  if (is.null(name)) {
+    dbGetQuery(conn, "ROLLBACK")
+  } else {
+    dbGetQuery(conn, paste("ROLLBACK TO ", name))
+  }
+  TRUE
+})
diff --git a/R/ConnectionWrite.R b/R/ConnectionWrite.R
new file mode 100644
index 0000000..38010fc
--- /dev/null
+++ b/R/ConnectionWrite.R
@@ -0,0 +1,128 @@
+#' Write a local data frame or file to the database.
+#' 
+#' @export
+#' @rdname dbWriteTable
+#' @param conn a \code{\linkS4class{SQLiteConnection}} object, produced by
+#'   \code{\link[DBI]{dbConnect}}
+#' @param name a character string specifying a table name. SQLite table names 
+#'   are \emph{not} case sensitive, e.g., table names \code{ABC} and \code{abc} 
+#'   are considered equal.
+#' @param value a data.frame (or coercible to data.frame) object or a 
+#'   file name (character).  In the first case, the data.frame is
+#'   written to a temporary file and then imported to SQLite; when \code{value}
+#'   is a character, it is interpreted as a file name and its contents imported
+#'   to SQLite.
+#' @param row.names A logical specifying whether the \code{row.names} should be 
+#'   output to the output DBMS table; if \code{TRUE}, an extra field whose name 
+#'   will be whatever the R identifier \code{"row.names"} maps to the DBMS (see
+#'   \code{\link[DBI]{make.db.names}}). If \code{NA} will add rows names if
+#'   they are characters, otherwise will ignore.
+#' @param overwrite a logical specifying whether to overwrite an existing table 
+#'   or not. Its default is \code{FALSE}. (See the BUGS section below)
+#' @param append a logical specifying whether to append to an existing table 
+#'   in the DBMS.  Its default is \code{FALSE}.
+#' @param field.types character vector of named  SQL field types where
+#'   the names are the names of new table's columns. If missing, types inferred
+#'   with \code{\link[DBI]{dbDataType}}).
+#' @export
+#' @examples
+#' con <- dbConnect(SQLite())
+#' dbWriteTable(con, "mtcars", mtcars)
+#' dbReadTable(con, "mtcars")
+#' 
+#' # A zero row data frame just creates a table definition.
+#' dbWriteTable(con, "mtcars2", mtcars[0, ])
+#' dbReadTable(con, "mtcars2")
+#' 
+#' dbDisconnect(con)
+setMethod("dbWriteTable", c("SQLiteConnection", "character", "data.frame"),
+  function(conn, name, value, row.names = NA, overwrite = FALSE, append = FALSE, 
+           field.types = NULL) {
+    
+    if (overwrite && append)
+      stop("overwrite and append cannot both be TRUE", call. = FALSE)
+    
+    dbBegin(conn, "dbWriteTable")
+    on.exit(dbRollback(conn, "dbWriteTable"))
+    
+    found <- dbExistsTable(conn, name)
+    if (found && !overwrite && !append) {
+      stop("Table ", name, " exists in database, and both overwrite and", 
+        " append are FALSE", call. = FALSE)
+    }
+    if (found && overwrite) {
+      dbRemoveTable(conn, name)
+    }
+    
+    value <- explict_rownames(value, row.names)
+    
+    if (!found || overwrite) {
+      sql <- sqliteBuildTableDefinition(conn, name, value, 
+        field.types = field.types, row.names = FALSE)
+      dbGetQuery(conn, sql)
+    }
+    
+    if (nrow(value) > 0) {
+      valStr <- paste(rep("?", ncol(value)), collapse = ",")
+      sql <- sprintf("insert into %s values (%s)", name, valStr)
+      rs <- dbSendPreparedQuery(conn, sql, bind.data = value)
+      dbClearResult(rs)
+    }
+
+    on.exit(NULL)
+    dbCommit(conn, "dbWriteTable")
+    TRUE
+  }
+)
+
+#' @param header is a logical indicating whether the first data line (but see
+#'   \code{skip}) has a header or not.  If missing, it value is determined
+#'   following \code{\link{read.table}} convention, namely, it is set to TRUE if
+#'   and only if the first row has one fewer field that the number of columns.
+#' @param sep The field separator, defaults to \code{','}.
+#' @param eol The end-of-line delimiter, defaults to \code{'\n'}.
+#' @param skip number of lines to skip before reading the data. Defaults to 0.
+#' @param nrows Number of rows to read to determine types.
+#' @param colClasses Character vector of R type names, used to override
+#'   defaults when imputing classes from on-disk file.
+#' @useDynLib RSQLite RS_SQLite_importFile
+#' @export
+#' @rdname dbWriteTable
+setMethod("dbWriteTable", c("SQLiteConnection", "character", "character"),
+  function(conn, name, value, field.types = NULL, overwrite = FALSE, 
+           append = FALSE, header = TRUE, colClasses = NA, row.names = FALSE, 
+           nrows = 50, sep = ",", eol="\n", skip = 0) {
+    if(overwrite && append)
+      stop("overwrite and append cannot both be TRUE")
+    value <- path.expand(value)
+    
+    dbBegin(conn)
+    on.exit(dbRollback(conn))
+    
+    found <- dbExistsTable(conn, name)
+    if (found && !overwrite && !append) {
+      stop("Table ", name, " exists in database, and both overwrite and", 
+        " append are FALSE", call. = FALSE)
+    }
+    if (found && overwrite) {
+      dbRemoveTable(conn, name)
+    }
+    
+    if (!found || overwrite) {
+      # Initialise table with first `nrows` lines
+      d <- read.table(value, sep = sep, header = header, skip = skip, nrows = nrows,
+        na.strings = .SQLite.NA.string, comment.char = "", colClasses = colClasses,
+        stringsAsFactors = FALSE)
+      sql <- sqliteBuildTableDefinition(conn, name, d, field.types = field.types,
+        row.names = row.names)
+      dbGetQuery(conn, sql)
+    }
+    
+    skip <- skip + as.integer(header)
+    .Call(RS_SQLite_importFile, conn at Id, name, value, sep, eol, as.integer(skip))
+    
+    on.exit(NULL)
+    dbCommit(conn)
+    TRUE
+  }
+)
diff --git a/R/Constants.R b/R/Constants.R
new file mode 100644
index 0000000..7673e02
--- /dev/null
+++ b/R/Constants.R
@@ -0,0 +1 @@
+.SQLite.NA.string <- "\\N"  ## on input SQLite interprets \N as NULL (NA)
diff --git a/R/Driver.R b/R/Driver.R
new file mode 100644
index 0000000..420e382
--- /dev/null
+++ b/R/Driver.R
@@ -0,0 +1,83 @@
+#' @include Connection.R
+NULL
+
+#' Class SQLiteDriver with constructor SQLite.
+#' 
+#' An SQLite driver implementing the R/S-Plus database (DBI) API.
+#' This class should always be initializes with the \code{SQLite()} function.
+#' It returns a singleton object that allows you to connect to the SQLite 
+#' engine embedded in R.
+#' 
+#' This implementation allows the R embedded SQLite engine to work with
+#' multiple database instances through multiple connections simultaneously.
+#' 
+#' SQLite keeps each database instance in one single file. The name of the
+#' database \emph{is} the file name, thus database names should be legal file
+#' names in the running platform.
+#' 
+#' @examples
+#' # initialize a new database to a tempfile and copy some data.frame
+#' # from the base package into it
+#' con <- dbConnect(SQLite(), ":memory:")
+#' data(USArrests)
+#' dbWriteTable(con, "USArrests", USArrests)
+#' 
+#' # query
+#' rs <- dbSendQuery(con, "select * from USArrests")
+#' d1 <- fetch(rs, n = 10)      # extract data in chunks of 10 rows
+#' dbHasCompleted(rs)
+#' d2 <- fetch(rs, n = -1)      # extract all remaining data
+#' dbHasCompleted(rs)
+#' dbClearResult(rs)
+#' dbListTables(con)
+#' 
+#' # clean up
+#' dbDisconnect(con)
+#' @export
+setClass("SQLiteDriver", 
+  contains = "DBIDriver"
+)
+
+#' @param fetch.default.rec default number of records to fetch at one time from
+#'   the database.  The \code{fetch} method will use this number as a default,
+#'   but individual calls can override it.
+#' @param shared.cache logical describing whether shared-cache mode should be
+#'   enabled on the SQLite driver. The default is \code{FALSE}.
+#' @param max.con,force.reload Ignored and deprecated.
+#' @return An object of class \code{SQLiteDriver} which extends \code{dbDriver}
+#'   and \code{dbObjectId}. This object is needed to create connections to the
+#'   embedded SQLite database. There can be many SQLite database instances
+#'   running simultaneously.
+#' 
+#' @rdname SQLiteDriver-class
+#' @export
+#' @import methods DBI
+#' @useDynLib RSQLite rsqlite_driver_init
+SQLite <- function(max.con = 200L, fetch.default.rec = 500, 
+                   force.reload = FALSE, shared.cache = FALSE) {
+
+  if (!missing(max.con)) warning("max.con is ignored", call. = FALSE)
+  if (!missing(force.reload)) warning("force.reload is ignored", call. = FALSE)
+  
+  records <- as.integer(fetch.default.rec)
+  cache <- as.logical(shared.cache)
+  
+  .Call(rsqlite_driver_init, records, cache)
+  new("SQLiteDriver")
+}
+
+#' Unload SQLite driver.
+#' 
+#' @param drv Object created by \code{\link{SQLite}}
+#' @param ... Ignored. Needed for compatibility with generic.
+#' @return A logical indicating whether the operation succeeded or not.
+#' @useDynLib RSQLite rsqlite_driver_close
+#' @export
+#' @examples
+#' \dontrun{
+#' db <- SQLite()
+#' dbUnloadDriver(db)
+#' }
+setMethod("dbUnloadDriver", "SQLiteDriver", function(drv, ...) {
+  .Call(rsqlite_driver_close)  
+})
diff --git a/R/Escaping.R b/R/Escaping.R
new file mode 100644
index 0000000..1f8c447
--- /dev/null
+++ b/R/Escaping.R
@@ -0,0 +1,61 @@
+#' @include Connection.R
+NULL
+
+#' Make R/S-Plus identifiers into legal SQL identifiers
+#' 
+#' These methods are straight-forward implementations of the corresponding
+#' generic functions.
+#' 
+#' @param dbObj any SQLite object (e.g., \code{SQLiteDriver}).
+#' @param snames a character vector of R identifiers (symbols) from which to 
+#'   make SQL identifiers.
+#' @param unique logical describing whether the resulting set of SQL names 
+#'   should be unique.  The default is \code{TRUE}. Following the SQL 92 
+#'   standard, uniqueness of SQL identifiers is determined regardless of whether 
+#'   letters are upper or lower case.
+#' @param allow.keywords logical describing whether SQL keywords should be
+#'   allowed in the resulting set of SQL names.  The default is \code{TRUE}.
+#' @param ... Not used. Included for compatiblity with generic.
+#' @keywords internal
+#' @examples
+#' \dontrun{
+#' # This example shows how we could export a bunch of data.frames
+#' # into tables on a remote database.
+#' 
+#' con <- dbConnect("SQLite", dbname = "sqlite.db")
+#' 
+#' export <- c("trantime.email", "trantime.print", "round.trip.time.email")
+#' tabs <- make.db.names(con, export, unique = TRUE, allow.keywords = TRUE)
+#' 
+#' for(i in seq_along(export) )
+#'    dbWriteTable(con, name = tabs[i],  get(export[i]))
+#' }
+#' 
+#' @export
+setMethod("make.db.names",
+  signature(dbObj="SQLiteConnection", snames = "character"),
+  function(dbObj, snames, keywords, unique, allow.keywords, ...) {
+    make.db.names.default(snames, keywords, unique, allow.keywords)
+  }
+)
+
+#' @export
+#' @rdname make.db.names-SQLiteConnection-character-method
+setMethod("SQLKeywords", "SQLiteConnection", function(dbObj, ...) {
+  .SQL92Keywords
+})
+
+#' @export
+#' @rdname make.db.names-SQLiteConnection-character-method
+#' @param name a character vector of SQL identifiers we want to check against
+#'   keywords from the DBMS. 
+#' @param keywords a character vector with SQL keywords, namely 
+#'   \code{.SQL92Keywords} defined in the \code{DBI} package.
+#' @param case a character string specifying whether to make the comparison 
+#'   as lower case, upper case, or any of the two.  it defaults to \code{"any"}.
+setMethod("isSQLKeyword",
+  signature(dbObj="SQLiteConnection", name="character"),
+  function(dbObj, name, keywords, case, ...) {
+    isSQLKeyword.default(name, keywords = .SQL92Keywords, case)
+  }
+)
diff --git a/R/Object.R b/R/Object.R
new file mode 100644
index 0000000..1a03e77
--- /dev/null
+++ b/R/Object.R
@@ -0,0 +1,106 @@
+#' @include Driver.R
+#' @include Connection.R
+#' @include Result.R
+NULL
+
+#' Determine the SQL Data Type of an R object.
+#' 
+#' This method is a straight-forward implementation of the corresponding
+#' generic function.
+#' 
+#' @param dbObj a \code{SQLiteDriver} object,
+#' @param obj an R object whose SQL type we want to determine.
+#' @param ... Needed for compatibility with generic. Otherwise ignored.
+#' @examples
+#' data(quakes)
+#' drv <- SQLite()
+#'
+#' sapply(quakes, function(x) dbDataType(drv, x))
+#' 
+#' dbDataType(drv, 1)
+#' dbDataType(drv, as.integer(1))
+#' dbDataType(drv, "1")
+#' dbDataType(drv, charToRaw("1"))
+#' @export
+setMethod("dbDataType", "SQLiteConnection", function(dbObj, obj, ...) {
+  sqliteDataType(obj, ...)
+})
+
+#' @rdname dbDataType-SQLiteConnection-method
+#' @export
+setMethod("dbDataType", "SQLiteDriver", function(dbObj, obj, ...) {
+  sqliteDataType(obj, ...)
+})
+
+sqliteDataType <- function(obj, ...) {
+  rs.class <- data.class(obj)
+  rs.mode <- storage.mode(obj)
+  switch(rs.class,
+    numeric = if (rs.mode=="integer") "INTEGER" else "REAL",
+    character = "TEXT",
+    logical = "INTEGER",
+    factor = "TEXT",
+    ordered = "TEXT",
+    ## list maps to BLOB. Although not checked, the list must
+    ## either be empty or contain only raw vectors or NULLs.
+    list = "BLOB",
+    ## attempt to store obj according to its storage mode if it has
+    ## an unrecognized class.
+    switch(rs.mode,
+      integer = "INTEGER",
+      double = "REAL",
+      ## you'll get this if class is AsIs for a list column
+      ## within a data.frame
+      list = if (rs.class == "AsIs") "BLOB" else "TEXT",
+      "TEXT"))
+}
+
+
+#' Check whether an SQLite object is valid or not.
+#' 
+#' Support function that verifies that the holding a reference to a
+#' foreign object is still valid for communicating with the RDBMS
+#' 
+#' @param dbObj,obj A driver, connection or result.
+#' @return A logical scalar.
+#' @examples
+#' dbIsValid(SQLite())
+#' 
+#' con <- dbConnect(SQLite())
+#' dbIsValid(con)
+#' 
+#' dbDisconnect(con)
+#' dbIsValid(con)
+#' @name dbIsValid
+NULL
+
+#' @rdname dbIsValid
+#' @useDynLib RSQLite rsqlite_driver_valid
+#' @export
+setMethod("dbIsValid", "SQLiteDriver", function(dbObj) {
+  .Call(rsqlite_driver_valid)
+})
+#' @rdname dbIsValid
+#' @useDynLib RSQLite rsqlite_connection_valid
+#' @export
+setMethod("dbIsValid", "SQLiteConnection", function(dbObj) {
+  .Call(rsqlite_connection_valid, dbObj at Id)
+})
+#' @rdname dbIsValid
+#' @useDynLib RSQLite rsqlite_result_valid
+#' @export
+setMethod("dbIsValid", "SQLiteResult", function(dbObj) {
+  .Call(rsqlite_result_valid, dbObj at Id)
+})
+
+#' @rdname dbIsValid
+#' @export
+isIdCurrent <- function(obj) {
+  .Deprecated("dbIsValid")
+  dbIsValid(obj)
+}
+
+check_valid <- function(x) {
+  if (dbIsValid(x)) return(TRUE)  
+  stop("Expired ", class(x)[1], call. = FALSE)
+}
diff --git a/R/Result.R b/R/Result.R
new file mode 100644
index 0000000..a644b14
--- /dev/null
+++ b/R/Result.R
@@ -0,0 +1,231 @@
+#' Class SQLiteResult
+#' 
+#' SQLite's query results class.  This classes encapsulates the result of an
+#' SQL statement (either \code{select} or not).
+#' 
+#' @export
+setClass("SQLiteResult", 
+  contains = "DBIResult",
+  slots = list(Id = "externalptr")
+)
+
+#' Execute a SQL statement on a database connection
+#' 
+#' To retrieve results a chunk at a time, use \code{dbSendQuery}, 
+#' \code{dbFetch}, then \code{ClearResult}. Alternatively, if you want all the 
+#' results (and they'll fit in memory) use \code{dbGetQuery} which sends, 
+#' fetches and clears for you.
+#' 
+#' @param conn an \code{\linkS4class{SQLiteConnection}} object.
+#' @param statement a character vector of length one specifying the SQL
+#'   statement that should be executed.  Only a single SQL statment should be
+#'   provided.
+#' @param ... Unused. Needed for compatibility with generic.
+#' @examples
+#' con <- dbConnect(SQLite(), ":memory:")
+#' dbWriteTable(con, "arrests", datasets::USArrests)
+#' 
+#' # Run query to get results as dataframe
+#' dbGetQuery(con, "SELECT * FROM arrests limit 3")
+#'
+#' # Send query to pull requests in batches
+#' res <- dbSendQuery(con, "SELECT * FROM arrests")
+#' data <- fetch(res, n = 2)
+#' data
+#' dbHasCompleted(res)
+#' 
+#' dbListResults(con)
+#' dbClearResult(res)
+#' 
+#' # Use dbSendPreparedQuery/dbGetPreparedQuery for "prepared" queries
+#' dbGetPreparedQuery(con, "SELECT * FROM arrests WHERE Murder < ?", 
+#'    data.frame(x = 3))
+#' dbGetPreparedQuery(con, "SELECT * FROM arrests WHERE Murder < (:x)", 
+#'    data.frame(x = 3))
+#' 
+#' dbDisconnect(con)
+#' @name query
+NULL 
+
+#' @rdname query
+#' @export
+setMethod("dbSendQuery", c("SQLiteConnection", "character"),
+  function(conn, statement) {
+    sqliteSendQuery(conn, statement)
+  }
+)
+
+#' @rdname query
+#' @param bind.data A data frame of data to be bound.
+#' @export
+setMethod("dbSendPreparedQuery", 
+  c("SQLiteConnection", "character", "data.frame"),
+  function(conn, statement, bind.data) {
+    sqliteSendQuery(conn, statement, bind.data)
+  }
+)
+
+#' @useDynLib RSQLite rsqlite_query_send
+sqliteSendQuery <- function(con, statement, bind.data = NULL) {
+  if (!is.null(bind.data)) {
+    if (!is.data.frame(bind.data)) {
+      bind.data <- as.data.frame(bind.data)
+    }
+    if (nrow(bind.data) == 0 || ncol(bind.data) == 0) {
+      stop("bind.data must have non-zero dimensions")
+    }
+  }
+  
+  rsId <- .Call(rsqlite_query_send, con at Id, as.character(statement), bind.data)
+  new("SQLiteResult", Id = rsId)
+}
+
+
+#' @param res an \code{\linkS4class{SQLiteResult}} object.
+#' @param n maximum number of records to retrieve per fetch. Use \code{-1} to 
+#'    retrieve all pending records; use \code{0} for to fetch the default 
+#'    number of rows as defined in \code{\link{SQLite}}
+#' @export
+#' @rdname query
+setMethod("dbFetch", "SQLiteResult", function(res, n = 0) {
+  sqliteFetch(res, n = n)
+})
+
+#' @rdname query
+#' @rdname dbFetch-SQLiteResult-method
+setMethod("fetch", "SQLiteResult", function(res, n = 0) {
+  sqliteFetch(res, n = n)
+})
+
+#' @useDynLib RSQLite rsqlite_query_fetch
+sqliteFetch <- function(res, n = 0) {  
+  check_valid(res)
+
+  # Returns NULL, or a list
+  rel <- .Call(rsqlite_query_fetch, res at Id, nrec = as.integer(n))
+  if (is.null(rel)) return(data.frame())
+  
+  attr(rel, "row.names") <- .set_row_names(length(rel[[1]]))
+  attr(rel, "class") <- "data.frame"
+  rel
+}
+
+#' @export
+#' @rdname query
+#' @useDynLib RSQLite rsqlite_result_free_handle
+setMethod("dbClearResult", "SQLiteResult", function(res, ...) {
+  check_valid(res)
+  .Call(rsqlite_result_free_handle, res at Id)
+})
+
+#' @export
+#' @rdname query
+#' @useDynLib RSQLite rsqlite_result_free_handle
+setMethod("dbClearResult", "SQLiteConnection", function(res, ...) {
+  check_valid(res)
+  .Call(rsqlite_result_free_handle, res at Id)
+})
+
+#' @export
+#' @rdname query
+#' @useDynLib RSQLite rsqlite_result_free_handle
+setMethod("dbListResults", "SQLiteConnection", function(conn, ...) {
+  check_valid(conn)
+  list(new("SQLiteResult", Id = conn at Id))
+})
+
+
+#' @rdname query
+#' @export
+setMethod("dbGetQuery", c("SQLiteConnection", "character"),
+  function(conn, statement){
+    sqliteGetQuery(conn, statement)
+  },
+)
+#' @rdname query
+#' @export
+setMethod("dbGetPreparedQuery", 
+  c("SQLiteConnection", "character", "data.frame"),
+  function(conn, statement, bind.data) {
+    sqliteGetQuery(conn, statement, bind.data)
+  }
+)
+
+sqliteGetQuery <- function(con, statement, bind.data = NULL) {
+  rs <- sqliteSendQuery(con, statement, bind.data)
+  on.exit(dbClearResult(rs))
+  
+  if (dbHasCompleted(rs)) {
+    return(invisible())
+  }
+  
+  res <- sqliteFetch(rs, n = -1)
+  if (!dbHasCompleted(rs)) {
+    warning("Pending rows")
+  }
+  
+  res
+}
+
+
+#' Database interface meta-data.
+#' 
+#' See documentation of generics for more details.
+#' 
+#' @param res An object of class \code{\linkS4class{SQLiteResult}}
+#' @param ... Ignored. Needed for compatibility with generic
+#' @examples
+#' data(USArrests)
+#' con <- dbConnect(SQLite(), dbname=":memory:")
+#' dbWriteTable(con, "t1", USArrests)
+#' dbWriteTable(con, "t2", USArrests)
+#' 
+#' dbListTables(con)
+#' 
+#' rs <- dbSendQuery(con, "select * from t1 where UrbanPop >= 80")
+#' dbGetStatement(rs)
+#' dbHasCompleted(rs)
+#' 
+#' info <- dbGetInfo(rs)
+#' names(info)
+#' info$fields
+#' 
+#' fetch(rs, n=2)
+#' dbHasCompleted(rs)
+#' info <- dbGetInfo(rs)
+#' info$fields
+#' dbClearResult(rs)
+#' 
+#' # DBIConnection info
+#' names(dbGetInfo(con))
+#' 
+#' dbDisconnect(con)
+#' @name sqlite-meta
+NULL
+
+#' @export
+#' @rdname sqlite-meta
+setMethod("dbColumnInfo", "SQLiteResult", function(res, ...) {
+  dbGetInfo(res)$fields
+})
+#' @export
+#' @rdname sqlite-meta
+setMethod("dbGetRowsAffected", "SQLiteResult", function(res, ...) {
+  dbGetInfo(res)$rowsAffected
+})
+#' @export
+#' @rdname sqlite-meta
+setMethod("dbGetRowCount", "SQLiteResult", function(res, ...) {
+  dbGetInfo(res)$rowCount
+})
+#' @export
+#' @rdname sqlite-meta
+setMethod("dbHasCompleted", "SQLiteResult", function(res, ...) {
+  out <- dbGetInfo(res)$completed
+  if(out < 0) NA else out == 1L
+})
+#' @rdname sqlite-meta
+#' @export
+setMethod("dbGetStatement", "SQLiteResult", function(res, ...) {
+  dbGetInfo(res)$statement
+})
diff --git a/R/S4R.R b/R/S4R.R
deleted file mode 100644
index ccbe9c0..0000000
--- a/R/S4R.R
+++ /dev/null
@@ -1,19 +0,0 @@
-##
-## $Id$
-##
-## S4/Splus/R compatibility 
-
-usingR <- function(major=0, minor=0){
-  if(is.null(version$language))
-    return(FALSE)
-  if(version$language!="R")
-    return(FALSE)
-  version$major>=major && version$minor>=minor
-}
-
-## constant holding the appropriate error class returned by try() 
-if(usingR()){
-  ErrorClass <- "try-error"
-} else {
-  ErrorClass <- "Error"  
-}
diff --git a/R/SQLite.R b/R/SQLite.R
deleted file mode 100644
index 5b3cab0..0000000
--- a/R/SQLite.R
+++ /dev/null
@@ -1,340 +0,0 @@
-##
-## $Id$
-##
-## Copyright (C) 1999-2003 The Omega Project for Statistical Computing.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser 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
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-##
-## Constants
-##
-
-## these are used to control the mode of new connections
-SQLITE_RWC <- 6L
-SQLITE_RW <- 2L
-SQLITE_RO <- 1L
-
-.SQLitePkgName <- "RSQLite"
-.SQLitePkgRCS <- "$Id$"
-.SQLite.NA.string <- "\\N"  ## on input SQLite interprets \N as NULL (NA)
-
-setOldClass("data.frame")   ## to avoid warnings in setMethod's valueClass arg
-
-## ------------------------------------------------------------------
-## Begin DBI extensions: 
-##
-## generics dbSendPreparedQuery, dbGetPreparedQuery 
-## and dbBeginTransaction
-##
-setGeneric("dbSendPreparedQuery", 
-   def = function(conn, statement, bind.data, ...) 
-           standardGeneric("dbSendPreparedQuery"),
-   valueClass = "DBIResult"
-)
-setGeneric("dbGetPreparedQuery", 
-   def = function(conn, statement, bind.data, ...) 
-           standardGeneric("dbGetPreparedQuery")
-)
-setGeneric("dbBeginTransaction", 
-   def = function(conn, ...)
-           standardGeneric("dbBeginTransaction"),
-   valueClass = "logical"
-)
-##
-## End DBI extensions
-## ------------------------------------------------------------------
-
-
-##
-## Class: SQLiteDriver
-##
-
-setClass("SQLiteObject", representation("DBIObject", "dbObjectId", "VIRTUAL"))
-setClass("SQLiteDriver", representation("DBIDriver", "SQLiteObject"))
-
-"SQLite" <-
-function(max.con = 200L, fetch.default.rec = 500, force.reload = FALSE,
-         shared.cache=FALSE)
-{
-   sqliteInitDriver(max.con, fetch.default.rec, force.reload, shared.cache)
-}
-
-setMethod("dbUnloadDriver", "SQLiteDriver",
-   definition = function(drv, ...) sqliteCloseDriver(drv, ...),
-   valueClass = "logical"
-)
-setMethod("dbGetInfo", "SQLiteDriver",
-   definition = function(dbObj, ...) sqliteDriverInfo(dbObj, ...),
-   valueClass = "list"
-)
-setMethod("dbListConnections", "SQLiteDriver",
-   definition = function(drv, ...) {
-      cons <- dbGetInfo(drv, what = "connectionIds")[[1]]
-      if(!is.null(cons)) cons else list()
-   },
-   valueClass = "list"
-)
-setMethod("summary", "SQLiteDriver",
-   definition = function(object, ...) sqliteDescribeDriver(object, ...)
-)
-
-##
-## Class: SQLiteConnection
-##
-
-setClass("SQLiteConnection", representation("DBIConnection", "SQLiteObject"))
-
-setAs("SQLiteConnection", "SQLiteDriver",
-   def = function(from) new("SQLiteDriver", Id = from at Id)
-)
-setMethod("dbConnect", "SQLiteDriver",
-   definition = function(drv, ...) sqliteNewConnection(drv, ...),
-   valueClass = "SQLiteConnection"
-)
-setMethod("dbConnect", "character",
-   definition = function(drv, ...){
-      d <- dbDriver(drv)
-      dbConnect(d, ...)
-   },
-   valueClass = "SQLiteConnection"
-)
-setMethod("dbConnect", "SQLiteConnection",
-   definition = function(drv, ...){
-      new.id <- .Call("RS_SQLite_cloneConnection", drv at Id, PACKAGE = .SQLitePkgName)
-      new("SQLiteConnection", Id = new.id)
-   },
-   valueClass = "SQLiteConnection"
-)
-setMethod("dbDisconnect", "SQLiteConnection",
-   definition = function(conn, ...) sqliteCloseConnection(conn, ...),
-   valueClass = "logical"
-)
-setMethod("dbGetInfo", "SQLiteConnection",
-   definition = function(dbObj, ...) sqliteConnectionInfo(dbObj, ...),
-   valueClass = "list"
-)
-setMethod("dbGetException", "SQLiteConnection",
-   definition = function(conn, ...){
-       .Call("RS_SQLite_getException", conn at Id, PACKAGE = .SQLitePkgName)
-   },
-   valueClass = "list"    ## TODO: should return a SQLiteException
-)
-setMethod("dbSendQuery",
-   signature = signature(conn = "SQLiteConnection", statement = "character"),
-   definition = function(conn, statement, ...){
-      sqliteExecStatement(conn, statement, ...)
-   },
-   valueClass = "SQLiteResult"
-)
-setMethod("dbSendPreparedQuery", 
-   signature = signature(conn = "SQLiteConnection", statement = "character",
-                   bind.data = "data.frame"),
-   definition = function(conn, statement, bind.data, ...){
-      sqliteExecStatement(conn, statement, bind.data, ...)
-   },
-   valueClass = "SQLiteResult"
-)
-setMethod("dbGetQuery",
-   signature = signature(conn = "SQLiteConnection", statement = "character"),
-   definition = function(conn, statement, ...){
-      sqliteQuickSQL(conn, statement, ...)
-   },
-)
-setMethod("dbGetPreparedQuery", 
-   signature = signature(conn = "SQLiteConnection", statement = "character",
-                   bind.data = "data.frame"),
-   definition = function(conn, statement, bind.data, ...){
-      sqliteQuickSQL(conn, statement, bind.data, ...)
-   },
-   valueClass = "SQLiteResult"
-)
-setMethod("summary", "SQLiteConnection",
-   definition = function(object, ...) sqliteDescribeConnection(object, ...)
-)
-
-setMethod("dbCallProc", "SQLiteConnection",
-   definition = function(conn, ...) .NotYetImplemented()
-)
-
-setMethod("dbCommit", "SQLiteConnection",
-   definition = function(conn, ...) sqliteTransactionStatement(conn, "COMMIT")
-)
-
-setMethod("dbRollback", "SQLiteConnection",
-   definition = function(conn, ...) {
-       rsList <- dbListResults(conn)
-       if (length(rsList))
-         dbClearResult(rsList[[1]])
-       sqliteTransactionStatement(conn, "ROLLBACK")
-   }
-)
-
-setMethod("dbBeginTransaction", "SQLiteConnection",
-   definition = function(conn, ...) sqliteTransactionStatement(conn, "BEGIN")
-)
-
-##
-## Convenience methods
-##
-
-setMethod("dbExistsTable",
-   signature = signature(conn = "SQLiteConnection", name = "character"),
-   definition = function(conn, name, ...){
-      lst <- dbListTables(conn)
-      match(tolower(name), tolower(lst), nomatch = 0) > 0
-   },
-   valueClass = "logical"
-)
-setMethod("dbReadTable",
-   signature = signature(conn = "SQLiteConnection", name = "character"),
-   definition = function(conn, name, ...) sqliteReadTable(conn, name, ...),
-   valueClass = "data.frame"
-)
-setMethod("dbWriteTable",
-   signature = signature(conn = "SQLiteConnection", name = "character",
-                   value="data.frame"),
-   definition = function(conn, name, value, ...)
-      sqliteWriteTable(conn, name, value, ...),
-   valueClass = "logical"
-)
-
-## create/load table from a file via dbWriteTable (the argument
-## value specifies a file name).  TODO, value a connection.
-setMethod("dbWriteTable",
-   signature = signature(conn = "SQLiteConnection", name = "character",
-                   value="character"),
-   definition = function(conn, name, value, ...)
-      sqliteImportFile(conn, name, value, ...),
-   valueClass = "logical"
-)
-setMethod("dbRemoveTable",
-   signature = signature(conn = "SQLiteConnection", name = "character"),
-   definition = function(conn, name, ...){
-      rc <- try(dbGetQuery(conn, paste("drop table", name)))
-      !inherits(rc, ErrorClass)
-   },
-   valueClass = "logical"
-)
-setMethod("dbListResults", "SQLiteConnection",
-   definition = function(conn, ...) {
-      rs <- dbGetInfo(conn, "rsId")[[1]]
-      if(length(rs)>0) rs else list()
-   },
-   valueClass = "list"
-)
-
-##
-## Class: SQLiteResult
-##
-
-setClass("SQLiteResult", representation("DBIResult", "SQLiteObject"))
-
-setAs("SQLiteResult", "SQLiteConnection",
-   def = function(from) new("SQLiteConnection", Id = from at Id)
-)
-setMethod("fetch", "SQLiteResult",
-   definition = function(res, n = 0, ...) sqliteFetch(res, n = n, ...),
-   valueClass = "data.frame"
-)
-setMethod("dbClearResult", "SQLiteResult",
-   definition = function(res, ...) sqliteCloseResult(res, ...),
-   valueClass = "logical"
-)
-setMethod("dbGetInfo", "SQLiteResult",
-   definition = function(dbObj, ...) sqliteResultInfo(dbObj, ...),
-   valueClass = "list"
-)
-setMethod("dbGetStatement", "SQLiteResult",
-   definition = function(res, ...) dbGetInfo(res, "statement")[[1]],
-   valueClass = "character"
-)
-setMethod("dbColumnInfo", "SQLiteResult",
-   definition = function(res, ...){
-      out <- dbGetInfo(res, "fields")[[1]]
-      if(!is.null(out)) out else data.frame(out)
-   },
-   valueClass = "data.frame"
-)
-setMethod("dbGetRowsAffected", "SQLiteResult",
-   definition = function(res, ...) dbGetInfo(res, "rowsAffected")[[1]],
-   valueClass = "integer"
-)
-setMethod("dbGetRowCount", "SQLiteResult",
-   definition = function(res, ...) dbGetInfo(res, "rowCount")[[1]],
-   valueClass = "integer"
-)
-setMethod("dbHasCompleted", "SQLiteResult",
-   definition = function(res, ...){
-      out <- dbGetInfo(res, "completed")[[1]]
-      if(out<0)
-         NA
-      else out == 1L
-   },
-   valueClass = "logical"
-)
-
-setMethod("dbListTables", "SQLiteConnection",
-   definition = function(conn, ...){
-      out <- dbGetQuery(conn,
-         "select name from sqlite_master where type='table' or type='view' order by name",
-         ...)
-      if (is.null(out) || nrow(out) == 0)
-        out <- character(0)
-      else
-        out <- out[, 1]
-      out
-   },
-   valueClass = "character"
-)
-setMethod("dbListFields",
-   signature = signature(conn = "SQLiteConnection", name = "character"),
-   definition = function(conn, name, ...) sqliteTableFields(conn, name, ...),
-   valueClass = "character"
-)
-
-setMethod("summary", "SQLiteResult",
-   definition = function(object, ...) sqliteDescribeResult(object, ...)
-)
-
-##
-## Utilities
-##
-
-setMethod("dbDataType", "SQLiteObject",
-   definition = function(dbObj, obj, ...) sqliteDataType(obj, ...),
-   valueClass = "character"
-)
-
-
-setMethod("make.db.names",
-   signature(dbObj="SQLiteObject", snames = "character"),
-   definition = function(dbObj, snames, keywords, unique, allow.keywords, ...){
-      make.db.names.default(snames, keywords, unique, allow.keywords)
-   },
-   valueClass = "character"
-)
-
-setMethod("SQLKeywords", "SQLiteObject",
-   definition = function(dbObj, ...) .SQL92Keywords,
-   valueClass = "character"
-)
-
-setMethod("isSQLKeyword",
-   signature(dbObj="SQLiteObject", name="character"),
-   definition = function(dbObj, name, keywords, case, ...){
-        isSQLKeyword.default(name, keywords = .SQL92Keywords, case)
-   },
-   valueClass = "character"
-)
diff --git a/R/SQLiteSupport.R b/R/SQLiteSupport.R
deleted file mode 100644
index 26cd00f..0000000
--- a/R/SQLiteSupport.R
+++ /dev/null
@@ -1,724 +0,0 @@
-##
-## $Id$
-##
-## Copyright (C) 1999-2002 The Omega Project for Statistical Computing.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser 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
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-##
-
-"sqliteInitDriver" <-
-function(max.con = 16, fetch.default.rec = 500, force.reload=FALSE,
-         shared.cache=FALSE)
-## return a manager id
-{
-  config.params <- as.integer(c(max.con, fetch.default.rec))
-  force <- as.logical(force.reload)
-  cache <- as.logical(shared.cache)
-  id <- .Call("RS_SQLite_init", config.params, force, cache, PACKAGE = .SQLitePkgName)
-  new("SQLiteDriver", Id = id)
-}
-
-"sqliteCloseDriver" <-
-function(drv, ...)
-{
-  .Call("RS_SQLite_closeManager", drv at Id, PACKAGE = .SQLitePkgName)
-}
-
-"sqliteDescribeDriver" <-
-function(obj, verbose = FALSE, ...)
-## Print out nicely a brief description of the connection Manager
-{
-  if(!isIdCurrent(obj)){
-     show(obj)
-     invisible(return(NULL))
-  }
-  info <- dbGetInfo(obj)
-  show(obj)
-  cat("  Driver name: ", info$drvName, "\n")
-  cat("  Max  connections:", info$length, "\n")
-  cat("  Conn. processed:", info$counter, "\n")
-  cat("  Default records per fetch:", info$"fetch_default_rec", "\n")
-  if(verbose){
-    cat("  SQLite client version: ", info$clientVersion, "\n")
-    cat("  DBI version: ", dbGetDBIVersion(), "\n")
-  }
-  cat("  Open connections:", info$"num_con", "\n")
-  if(verbose && !is.null(info$connectionIds)){
-    for(i in seq(along.with = info$connectionIds)){
-      cat("   ", i, " ")
-      show(info$connectionIds[[i]])
-    }
-  }
-  cat("  Shared Cache:", info$"shared_cache", "\n")
-  invisible(NULL)
-}
-
-"sqliteDriverInfo" <-
-function(obj, what="", ...)
-{
-  if(!isIdCurrent(obj))
-    stop(paste("expired", class(obj)))
-  drvId <- obj at Id
-  info <- .Call("RS_SQLite_managerInfo", drvId, PACKAGE = .SQLitePkgName)
-  info$managerId <- obj
-  ## connection IDs are no longer tracked by the manager.
-  info$connectionIds <- list()
-  if(!missing(what))
-    info[what]
-  else
-    info
-}
-
-## note that dbname may be a database name, an empty string "", or NULL.
-## The distinction between "" and NULL is that "" is interpreted by
-## the SQLite API as the default database (SQLite config specific)
-## while NULL means "no database".
-"sqliteNewConnection"<-
-function(drv, dbname = "", loadable.extensions = TRUE, cache_size = NULL,
-         synchronous = 0, flags = NULL, vfs = NULL)
-{
-  if (is.null(dbname))
-    dbname <- ""
-  ## path.expand converts as.character(NA) => "NA"
-  if (any(is.na(dbname)))
-      stop("'dbname' must not be NA")
-  dbname <- path.expand(dbname)
-  loadable.extensions <- as.logical(loadable.extensions)
-  if (!is.null(vfs)) {
-      if (.Platform[["OS.type"]] == "windows") {
-          warning("vfs customization not available on this platform.",
-                  " Ignoring value: vfs = ", vfs)
-      } else {
-          if (length(vfs) != 1L)
-              stop("'vfs' must be NULL or a character vector of length one")
-          allowed <- c("unix-posix", "unix-afp", "unix-flock", "unix-dotfile",
-                       "unix-none")
-          if (!(vfs %in% allowed)) {
-              stop("'vfs' must be one of ",
-                   paste(allowed, collapse=", "),
-                   ". See http://www.sqlite.org/compile.html")
-          }
-      }
-  }
-  flags <- if (is.null(flags)) SQLITE_RWC else flags
-  drvId <- drv at Id
-  conId <- .Call("RS_SQLite_newConnection", drvId,
-                 dbname, loadable.extensions, flags, vfs, PACKAGE ="RSQLite")
-  con <- new("SQLiteConnection", Id = conId)
-
-  ## experimental PRAGMAs
-  try({
-    if(!is.null(cache_size))
-      dbGetQuery(con, sprintf("PRAGMA cache_size=%d", as.integer(cache_size)))
-    if(is.numeric(synchronous))
-      nsync <- as.integer(synchronous)
-    else if(is.character(synchronous))
-      nsync <-
-        pmatch(tolower(synchronous), c("off", "normal", "full"), nomatch = 1) - 1
-    else nsync <- 0
-    dbGetQuery(con, sprintf("PRAGMA synchronous=%d", as.integer(nsync)))
-   }, silent = TRUE)
-
-  con
-}
-
-"sqliteDescribeConnection" <-
-function(obj, verbose = FALSE, ...)
-{
-  if(!isIdCurrent(obj)){
-     show(obj)
-     invisible(return(NULL))
-  }
-  info <- dbGetInfo(obj)
-  show(obj)
-  cat("  Database name:", info$dbname, "\n")
-  cat("  Loadable extensions:", info$loadableExtensions, "\n")
-  cat("  File open flags:", info$falgs, "\n")
-  cat("  Virtual File System:", info$vfs, "\n")
-  cat("  SQLite engine version: ", info$serverVersion, "\n")
-  cat("  Results Sets:\n")
-  if(length(info$rsId)>0){
-    for(i in seq(along.with = info$rsId)){
-      cat("   ", i, " ")
-      show(info$rsId[[i]])
-    }
-  } else
-    cat("   No open result sets\n")
-  invisible(NULL)
-}
-
-"sqliteCloseConnection" <-
-function(con, ...)
-{
-  if(!isIdCurrent(con)){
-     warning(paste("expired SQLiteConnection"))
-     return(TRUE)
-  }
-  .Call("RS_SQLite_closeConnection", con at Id, PACKAGE = .SQLitePkgName)
-}
-
-"sqliteConnectionInfo" <-
-function(obj, what="", ...)
-{
-  if(!isIdCurrent(obj))
-    stop(paste("expired", class(obj)))
-  id <- obj at Id
-  info <- .Call("RSQLite_connectionInfo", id, PACKAGE = .SQLitePkgName)
-  if(length(info$rsId)){
-    rsId <- vector("list", length = length(info$rsId))
-    for(i in seq(along.with = info$rsId))
-      rsId[[i]] <- new("SQLiteResult",
-                       Id = .Call("DBI_newResultHandle",
-                       id, info$rsId[i], PACKAGE = .SQLitePkgName))
-    info$rsId <- rsId
-  }
-  if(!missing(what))
-    info[what]
-  else
-    info
-}
-
-
-"sqliteQuickColumn" <- function(con, table, column)
-{
-    .Call("RS_SQLite_quick_column", con at Id, as.character(table),
-          as.character(column), PACKAGE="RSQLite")
-}
-
-
-sqliteTransactionStatement <-
-function(con, statement)
-## checks for any open resultsets, and closes them if completed.
-## the statement is then executed on the connection, and returns
-## whether it executed without an error or not.
-{
-  ## are there resultSets pending on con?
-  if(length(dbListResults(con)) > 0){
-    res <- dbListResults(con)[[1]]
-    if(!dbHasCompleted(res)){
-      stop("connection with pending rows, close resultSet before continuing")
-    }
-    dbClearResult(res)
-  }
-
-  rc <- try(dbGetQuery(con, statement), silent = TRUE)
-  !inherits(rc, ErrorClass)
-}
-
-
-"sqliteExecStatement" <-
-function(con, statement, bind.data=NULL)
-## submits the sql statement to SQLite and creates a
-## dbResult object if the SQL operation does not produce
-## output, otherwise it produces a resultSet that can
-## be used for fetching rows.
-{
-  conId <- con at Id
-  statement <- as(statement, "character")
-  if (!is.null(bind.data)) {
-      if (class(bind.data)[1] != "data.frame")
-          bind.data <- as.data.frame(bind.data)
-      if (min(dim(bind.data)) <= 0) {
-          stop("bind.data must have non-zero dimensions")
-      }
-  }
-  rsId <- .Call("RS_SQLite_exec",
-                conId, statement, bind.data,
-                PACKAGE = .SQLitePkgName)
-#  out <- new("SQLitedbResult", Id = rsId)
-#  if(dbGetInfo(out, what="isSelect")
-#    out <- new("SQLiteResultSet", Id = rsId)
-#  out
-  out <- new("SQLiteResult", Id = rsId)
-  out
-}
-
-## helper function: it exec's *and* retrieves a statement. It should
-## be named something else.
-"sqliteQuickSQL" <-
-function(con, statement, bind.data=NULL, ...)
-{
-   rs <- sqliteExecStatement(con, statement, bind.data)
-   if(dbHasCompleted(rs)){
-      dbClearResult(rs)            ## no records to fetch, we're done
-      invisible()
-      return(NULL)
-   }
-   res <- sqliteFetch(rs, n = -1, ...)
-   if(dbHasCompleted(rs))
-      dbClearResult(rs)
-   else
-      warning("pending rows")
-   res
-}
-
-"sqliteFetch" <-
-function(res, n=0, ...)
-## Fetch at most n records from the opened resultSet (n = -1 meanSQLite
-## all records, n=0 means extract as many as "default_fetch_rec",
-## as defined by SQLiteDriver (see summary(drv, TRUE)).
-## The returned object is a data.frame.
-## Note: The method dbHasCompleted() on the resultSet tells you whether
-## or not there are pending records to be fetched.
-##
-## TODO: Make sure we don't exhaust all the memory, or generate
-## an object whose size exceeds option("object.size").  Also,
-## are we sure we want to return a data.frame?
-{
-
-  if(!isIdCurrent(res))
-     stop("invalid result handle")
-  n <- as.integer(n)
-  rsId <- res at Id
-  rel <- .Call("RS_SQLite_fetch", rsId, nrec = n, PACKAGE = .SQLitePkgName)
-  if (is.null(rel)) rel <- list()       # result set is completed
-  ## create running row index as of previous fetch (if any)
-  cnt <- dbGetRowCount(res)
-  nrec <- if (length(rel) > 0L) length(rel[[1L]]) else 0L
-  indx <- seq(from = cnt - nrec + 1L, length.out = nrec)
-  attr(rel, "row.names") <- as.integer(indx)
-  class(rel) <- "data.frame"
-  rel
-}
-
-"sqliteFetchOneColumn" <-
-function(con, statement, n=0, ...)
-{
-    rs <- dbSendQuery(con, statement)
-    on.exit(dbClearResult(rs))
-    n <- as.integer(n)
-    rsId <- rs at Id
-    rel <- .Call("RS_SQLite_fetch", rsId, nrec = n, PACKAGE = .SQLitePkgName)
-    if (length(rel) == 0 || length(rel[[1]]) == 0)
-      return(NULL)
-    rel[[1]]
-}
-
-"sqliteResultInfo" <-
-function(obj, what = "", ...)
-{
-  if(!isIdCurrent(obj))
-    stop(paste("expired", class(obj)))
-   id <- obj at Id
-   info <- .Call("RS_SQLite_resultSetInfo", id, PACKAGE = .SQLitePkgName)
-   flds <- info$fieldDescription[[1]]
-   if(!is.null(flds)){
-       flds$Sclass <- .Call("RS_DBI_SclassNames", flds$Sclass,
-                            PACKAGE = .SQLitePkgName)
-       flds$type <- .Call("RS_SQLite_typeNames", flds$type,
-                            PACKAGE = .SQLitePkgName)
-       ## no factors
-       info$fields <- structure(flds, row.names = paste(seq(along.with=flds$type)),
-                                class="data.frame")
-   }
-   if(!missing(what))
-     info[what]
-   else
-     info
-}
-
-"sqliteDescribeResult" <-
-function(obj, verbose = FALSE, ...)
-{
-  if(!isIdCurrent(obj)){
-    show(obj)
-    invisible(return(NULL))
-  }
-  show(obj)
-  cat("  Statement:", dbGetStatement(obj), "\n")
-  cat("  Has completed?", if(dbHasCompleted(obj)) "yes" else "no", "\n")
-  cat("  Affected rows:", dbGetRowsAffected(obj), "\n")
-  hasOutput <- as.logical(dbGetInfo(obj, "isSelect")[[1]])
-  flds <- dbColumnInfo(obj)
-  if(hasOutput){
-    cat("  Output fields:", nrow(flds), "\n")
-    if(verbose && length(flds)>0){
-       cat("  Fields:\n")
-       out <- print(flds)
-    }
-  }
-  invisible(NULL)
-}
-
-"sqliteCloseResult" <-
-function(res, ...)
-{
-  if(!isIdCurrent(res)){
-     warning(paste("expired SQLiteResult"))
-     return(TRUE)
-  }
-  .Call("RS_SQLite_closeResultSet", res at Id, PACKAGE = .SQLitePkgName)
-}
-
-"sqliteTableFields" <-
-function(con, name, ...)
-{
-   if(length(dbListResults(con))>0){
-      con2 <- dbConnect(con)
-      on.exit(dbDisconnect(con2))
-   }
-   else
-      con2 <- con
-   rs <- dbSendQuery(con2, paste("select * from ", name, "limit 1"))
-   dummy <- fetch(rs, n = 1)
-   dbClearResult(rs)
-   nms <- names(dummy)
-   if(is.null(nms))
-      character()
-   else
-      nms
-}
-## this is exactly the same as ROracle's oraReadTable
-"sqliteReadTable" <-
-function(con, name, row.names = "row_names", check.names = TRUE, ...)
-## Should we also allow row.names to be a character vector (as in read.table)?
-## is it "correct" to set the row.names of output data.frame?
-## Use NULL, "", or 0 as row.names to prevent using any field as row.names.
-{
-   out <- try(dbGetQuery(con, paste("SELECT * from", name)))
-   if(inherits(out, ErrorClass))
-      stop(paste("could not find table", name))
-   if(check.names)
-       names(out) <- make.names(names(out), unique = TRUE)
-   ## should we set the row.names of the output data.frame?
-   nms <- names(out)
-   j <- switch(mode(row.names),
-           character = if(row.names=="") 0 else
-               match(tolower(row.names), tolower(nms),
-                     nomatch = if(missing(row.names)) 0 else -1),
-           numeric=, logical = row.names,
-           NULL = 0,
-           0)
-   if(as.numeric(j)==0)
-      return(out)
-   if(is.logical(j)) ## Must be TRUE
-      j <- match(row.names, tolower(nms), nomatch=0)
-   if(j<1 || j>ncol(out)){
-      warning("row.names not set on output data.frame (non-existing field)")
-      return(out)
-   }
-   rnms <- as.character(out[,j])
-   if(all(!duplicated(rnms))){
-      out <- out[,-j, drop = F]
-      row.names(out) <- rnms
-   } else warning("row.names not set on output (duplicate elements in field)")
-   out
-}
-
-"dbBuildTableDefinition" <-
-function(dbObj, name, value, field.types = NULL, row.names = TRUE, ...)
-{
-  if(!is.data.frame(value))
-    value <- as.data.frame(value)
-  if(!is.null(row.names) && row.names){
-    value  <- cbind(row.names(value), value)  ## can't use row.names= here
-    names(value)[1] <- "row.names"
-  }
-  if(is.null(field.types)){
-    ## the following mapping should be coming from some kind of table
-    ## also, need to use converter functions (for dates, etc.)
-    field.types <- sapply(value, dbDataType, dbObj = dbObj)
-  }
-  i <- match("row.names", names(field.types), nomatch=0)
-  if(i>0) ## did we add a row.names value?  If so, it's a text field.
-    field.types[i] <- dbDataType(dbObj, field.types[["row.names"]])
-  names(field.types) <-
-    make.db.names(dbObj, names(field.types), allow.keywords = FALSE)
-
-  ## need to create a new (empty) table
-  flds <- paste(names(field.types), field.types)
-  paste("CREATE TABLE", name, "\n(", paste(flds, collapse=",\n\t"), "\n)")
-}
-
-"sqliteImportFile" <-
-function(con, name, value, field.types = NULL, overwrite = FALSE,
-  append = FALSE, header, row.names, nrows = 50, sep = ",",
-  eol="\n", skip = 0, ...)
-{
-  if(overwrite && append)
-    stop("overwrite and append cannot both be TRUE")
-
-  ## Do we need to clone the connection (ie., if it is in use)?
-  if(length(dbListResults(con))!=0){
-    new.con <- dbConnect(con)              ## there's pending work, so clone
-    on.exit(dbDisconnect(new.con))
-  }
-  else
-    new.con <- con
-
-  if(dbExistsTable(con,name)){
-    if(overwrite){
-      if(!dbRemoveTable(con, name)){
-        warning(paste("table", name, "couldn't be overwritten"))
-        return(FALSE)
-      }
-    }
-    else if(!append){
-      warning(paste("table", name, "exists in database: aborting dbWriteTable"))
-      return(FALSE)
-    }
-  }
-
-  ## compute full path name (have R expand ~, etc)
-  fn <- file.path(dirname(value), basename(value))
-  if(missing(header) || missing(row.names)){
-    f <- file(fn, open="r")
-    if(skip>0)
-      readLines(f, n=skip)
-    txtcon <- textConnection(readLines(f, n=2))
-    flds <- count.fields.wrapper(file = txtcon, sep = sep, ...)
-    close(txtcon)
-    close(f)
-    nf <- length(unique(flds))
-  }
-  if(missing(header)){
-    header <- nf==2
-  }
-  if(missing(row.names)){
-    if(header)
-      row.names <- if(nf==2) TRUE else FALSE
-    else
-      row.names <- FALSE
-  }
-
-  new.table <- !dbExistsTable(con, name)
-  if(new.table){
-    ## need to init table, say, with the first nrows lines
-    d <- read.table(fn, sep=sep, header=header, skip=skip, nrows=nrows,
-                    na.strings=.SQLite.NA.string,
-                    stringsAsFactors=FALSE, ...)
-    sql <-
-      dbBuildTableDefinition(new.con, name, d, field.types = field.types,
-        row.names = row.names)
-    rs <- try(dbSendQuery(new.con, sql))
-    if(inherits(rs, ErrorClass)){
-      warning("could not create table: aborting sqliteImportFile")
-      return(FALSE)
-    }
-    else
-      dbClearResult(rs)
-  }
-  else if(!append){
-    warning(sprintf("table %s already exists -- use append=TRUE?", name))
-  }
-  rc <-
-      try({
-         skip <- skip + as.integer(header)
-         conId <- con at Id
-         .Call("RS_SQLite_importFile", conId, name, fn, sep, eol,
-            as.integer(skip), PACKAGE = .SQLitePkgName)
-      })
-  if(inherits(rc, ErrorClass)){
-    if(new.table) dbRemoveTable(new.con, name)
-    return(FALSE)
-  }
-  TRUE
-}
-
-## wrapper for count.fields that accepts and ignores additional
-## arguments passed via '...'. Note that this duplicates the default
-## values of count.fields and will need to be updated if that function's
-## defaults change.
-count.fields.wrapper <- function(file, sep = "", quote = "\"'", skip = 0,
-                                 blank.lines.skip = TRUE,
-                                 comment.char = "#", ...)
-{
-
-    count.fields(file, sep, quote, skip, blank.lines.skip, comment.char)
-}
-
-sqliteWriteTable <- function(con, name, value, row.names=TRUE,
-                             overwrite=FALSE, append=FALSE,
-                             field.types=NULL, ...)
-{
-      if (overwrite && append)
-        stop("overwrite and append cannot both be TRUE")
-
-      ## Do we need to clone the connection (ie., if it is in use)?
-      if (length(dbListResults(con))){
-          new.con <- dbConnect(con)              # there's pending work, so clone
-          on.exit(dbDisconnect(new.con))
-      } else {
-          new.con <- con
-      }
-
-      foundTable <- dbExistsTable(con, name)
-      new.table <- !foundTable
-      createTable <- (new.table || foundTable && overwrite)
-      removeTable <- (foundTable && overwrite)
-      success <- dbBeginTransaction(con)
-      if (!success) {
-          warning("unable to begin transaction")
-          return(FALSE)
-      }
-      ## sanity check
-      if (foundTable && !removeTable && !append) {
-          warning(paste("table", name,
-                        "exists in database: aborting dbWriteTable"))
-          success <- FALSE
-      }
-
-      if (removeTable) {
-          success <- tryCatch({
-              if (dbRemoveTable(con, name)) {
-                  TRUE
-              } else {
-                  warning(paste("table", name, "couldn't be overwritten"))
-                  FALSE
-              }
-          }, error=function(e) {
-              warning(conditionMessage(e))
-              FALSE
-          })
-      }
-
-      if (!success) {
-          dbRollback(con)
-          return(FALSE)
-      }
-
-      if (row.names) {
-          ## Need to handle row.names at this level
-          ## for the bind.data to work correctly.
-          ##
-          ## FIXME: for R >= 2.5, we should check
-          ## for numeric row.names and not convert
-          ## to character.
-          value <- cbind(row.names(value), value, stringsAsFactors=FALSE)
-          names(value)[1] <- "row.names"
-      }
-
-      if (createTable) {
-          sql <- dbBuildTableDefinition(new.con, name, value,
-                                        field.types=field.types,
-                                        row.names=FALSE)
-          success <- tryCatch({
-              dbGetQuery(new.con, sql)
-              TRUE
-          }, error=function(e) {
-              warning(conditionMessage(e))
-              FALSE
-          })
-          if (!success) {
-              dbRollback(con)
-              return(FALSE)
-          }
-      }
-
-      valStr <- paste(rep("?", ncol(value)), collapse=",")
-      sql <- sprintf("insert into %s values (%s)",
-                     name, valStr)
-      success <- tryCatch({
-          ## The 'finally' expression will have access to
-          ## this frame, not that of 'error'.  We want ret
-          ## to be defined even if an error occurs.
-          ret <- FALSE
-          rs <- dbSendPreparedQuery(new.con, sql, bind.data=value)
-          ret <- TRUE
-      }, error=function(e) {
-          warning(conditionMessage(e))
-          ret <- FALSE
-      }, finally={
-          if (exists("rs"))
-            dbClearResult(rs)
-          ret
-      })
-      if (!success)
-        dbRollback(con)
-      else {
-          success <- dbCommit(con)
-          if (!success) {
-            warning(dbGetException(con)[["errorMsg"]])
-            dbRollback(con)
-          }
-      }
-      success
-}
-
-## from ROracle, except we don't quote strings here.
-"safe.write" <-
-function(value, file, batch, row.names = TRUE, ...,
-  sep = ',', eol = '\n', quote.string = FALSE)
-## safe.write makes sure write.table don't exceed available memory by batching
-## at most batch rows (but it is still slowww)
-{
-   N <- nrow(value)
-   if(N<1){
-      warning("no rows in data.frame")
-      return(NULL)
-   }
-   if(missing(batch) || is.null(batch))
-      batch <- 10000
-   else if(batch<=0)
-      batch <- N
-   from <- 1
-   to <- min(batch, N)
-   while(from<=N){
-     write.table(value[from:to,, drop=FALSE], file = file,
-        append = from>1,
-        quote = quote.string, sep=sep, na = .SQLite.NA.string,
-        row.names=row.names, col.names=(from==1), eol = eol, ...)
-      from <- to+1
-      to <- min(to+batch, N)
-   }
-   invisible(NULL)
-}
-
-##
-## Utilities
-##
-"sqliteDataType" <- function(obj, ...)
-{
-    rs.class <- data.class(obj)
-    rs.mode <- storage.mode(obj)
-    switch(rs.class,
-           numeric = if (rs.mode=="integer") "INTEGER" else "REAL",
-           character = "TEXT",
-           logical = "INTEGER",
-           factor = "TEXT",
-           ordered = "TEXT",
-           ## list maps to BLOB. Although not checked, the list must
-           ## either be empty or contain only raw vectors or NULLs.
-           list = "BLOB",
-           ## attempt to store obj according to its storage mode if it has
-           ## an unrecognized class.
-           switch(rs.mode,
-                  integer = "INTEGER",
-                  double = "REAL",
-                  ## you'll get this if class is AsIs for a list column
-                  ## within a data.frame
-                  list = if (rs.class == "AsIs") "BLOB" else "TEXT",
-                  "TEXT"))
-}
-
-sqliteCopyDatabase <- function(from, to)
-{
-    if (!is(from, "SQLiteConnection"))
-        stop("'from' must be a SQLiteConnection object")
-    destdb <- to
-    if (!is(to, "SQLiteConnection")) {
-        if (is.character(to) && length(to) == 1L && !is.na(to) && nzchar(to)) {
-            if (":memory:" == to)
-                stop("invalid file name for 'to'.  Use a SQLiteConnection",
-                     " object to copy to an in-memory database")
-            destdb <- dbConnect(SQLite(), dbname = path.expand(to))
-            on.exit(dbDisconnect(destdb))
-        } else {
-            stop("'to' must be SQLiteConnection object or a non-empty string")
-        }
-    }
-    .Call("RS_SQLite_copy_database", from at Id, destdb at Id, PACKAGE = .SQLitePkgName)
-    invisible(NULL)
-}
diff --git a/R/Summary.R b/R/Summary.R
new file mode 100644
index 0000000..9739116
--- /dev/null
+++ b/R/Summary.R
@@ -0,0 +1,78 @@
+#' Summary methods
+#' 
+#' @keywords internal
+#' @name summary
+#' @examples
+#' summary(SQLite())
+#' 
+#' con <- dbConnect(SQLite())
+#' summary(con)
+#' 
+#' dbWriteTable(con, "mtcars", mtcars)
+#' rs <- dbSendQuery(con, "SELECT * FROM mtcars")
+#' summary(rs)
+#' 
+#' dbClearResult(rs)
+#' dbDisconnect(con)
+NULL
+
+setGeneric("summary")
+
+#' @export
+#' 
+#' @param verbose Show extra information.
+#' @rdname summary
+setMethod("summary", "SQLiteDriver", function(object) {
+  cat("<SQLiteDriver>\n")
+  info <- dbGetInfo(object)
+  cat("  Records per fetch: ", info$fetch_default_rec, "\n", sep = "")
+  cat("  SQLite version:    ", info$clientVersion, "\n", sep = "")
+  cat("  DBI version:       ", as.character(packageVersion("DBI")), "\n", sep = "")
+  cat("  Open connections:  ", info$num_con, "\n", sep = "")
+  cat("  Conn. processed:   ", info$counter, "\n", sep = "")
+  cat("  Shared cache:      ", info$shared_cache, "\n", sep = "")
+  invisible(NULL)
+})
+
+#' @export
+#' @rdname summary
+setMethod("summary", "SQLiteConnection", function(object) {
+  cat("<SQLiteConnection>\n")
+  if(!dbIsValid(object)){
+    cat("EXPIRED")
+  } else {
+    info <- dbGetInfo(object)
+    cat("  SQLite version:      ", info$serverVersion, "\n", sep = "")
+    cat("  Database name:       ", info$dbname, "\n", sep = "")
+    cat("  Loadable extensions: ", info$loadableExtensions, "\n", sep = "")
+    cat("  File open flags:     ", info$falgs, "\n", sep = "")
+    cat("  VFS:                 ", info$vfs, "\n", sep = "")
+  }
+
+  invisible(NULL)
+})
+
+#' @export
+#' @rdname summary
+setMethod("summary", "SQLiteResult", function(object) {
+  cat("<SQLiteResult>\n")
+  if(!dbIsValid(object)){
+    cat("EXPIRED")
+  } else {  
+    cat("  Statement:     ", dbGetStatement(object), "\n", sep = "")
+    cat("  Has completed? ", if(dbHasCompleted(object)) "yes" else "no", "\n", sep = "")
+    cat("  Affected rows: ", dbGetRowsAffected(object), "\n", sep = "")
+  }
+  invisible(NULL)  
+})
+
+
+setMethod("show", "SQLiteDriver", function(object) {
+  cat("<SQLiteDriver>\n")
+})
+setMethod("show", "SQLiteConnection", function(object) {
+  cat("<SQLiteConnection>\n")
+})
+setMethod("show", "SQLiteResult", function(object) {
+  cat("<SQLiteResult>\n")
+})
\ No newline at end of file
diff --git a/R/Utils.R b/R/Utils.R
new file mode 100644
index 0000000..5caed22
--- /dev/null
+++ b/R/Utils.R
@@ -0,0 +1,147 @@
+#' Return an entire column from a SQLite database
+#' 
+#' Return an entire column from a table in a SQLite database as an R vector of
+#' the appropriate type.  This function is experimental and subject to change.
+#' 
+#' This function relies upon the SQLite internal \code{ROWID} column to
+#' determine the number of rows in the table.  This may not work depending on
+#' the table schema definition and pattern of update.
+#' 
+#' @param con a \code{SQLiteConnection} object as produced by
+#' \code{sqliteNewConnection}.
+#' @param table a string specifying the name of the table
+#' @param column a string specifying the name of the column in the specified
+#' table to retrieve.
+#' @return an R vector of the appropriate type (based on the type of the column
+#' in the database).
+#' @author Seth Falcon
+#' @keywords interface
+#' @export sqliteQuickColumn
+sqliteQuickColumn <- function(con, table, column) {
+  .Call("RS_SQLite_quick_column", con at Id, as.character(table),
+    as.character(column), PACKAGE="RSQLite")
+}
+
+#' Write a data.frame avoiding exceeding memory limits
+#' 
+#' This function batches calls to \code{write.table} to avoid exceeding memory
+#' limits for very large data.frames.
+#' 
+#' The function has a while loop invoking \code{\link{write.table}} for subsets
+#' of \code{batch} rows of \code{value}.  Since this is a helper function for
+#' \code{\link[RMySQL]{mysqlWriteTable}} has hardcoded other arguments to
+#' \code{write.table}.
+#' 
+#' @param value a data.frame;
+#' @param file a file object (connection, file name, etc).
+#' @param batch maximum number of rows to write at a time.
+#' @param ...,sep,eol,quote.string,row.names 
+#'   arguments are passed to \code{write.table}.
+#' @return \code{NULL}, invisibly.
+#' @note No error checking whatsoever is done.
+#' @seealso \code{\link{write.table}}
+#' @noRd
+safe.write <- function(value, file, batch, row.names = TRUE, ..., sep = ',',
+                       eol = '\n', quote.string = FALSE) {
+  N <- nrow(value)
+  if(N<1){
+    warning("no rows in data.frame")
+    return(NULL)
+  }
+  if(missing(batch) || is.null(batch))
+    batch <- 10000
+  else if(batch<=0)
+    batch <- N
+  from <- 1
+  to <- min(batch, N)
+  while(from<=N){
+    write.table(value[from:to,, drop=FALSE], file = file,
+      append = from>1,
+      quote = quote.string, sep=sep, na = .SQLite.NA.string,
+      row.names=row.names, col.names=(from==1), eol = eol, ...)
+    from <- to+1
+    to <- min(to+batch, N)
+  }
+  invisible(NULL)
+}
+
+
+
+#' Copy a SQLite database
+#' 
+#' This function copies a database connection to a file or to another database
+#' connection.  It can be used to save an in-memory database (created using
+#' \code{dbname = ":memory:"}) to a file or to create an in-memory database as
+#' a copy of anothe database.
+#' 
+#' This function uses SQLite's experimental online backup API to make the copy.
+#' 
+#' @param from A \code{SQLiteConnection} object.  The main database in
+#' \code{from} will be copied to \code{to}.
+#' @param to Either a string specifying the file name where the copy will be
+#' written or a \code{SQLiteConnection} object pointing to an empty database.
+#' If \code{to} specifies an already existing file, it will be overwritten
+#' without a warning.  When \code{to} is a database connection, it is assumed
+#' to point to an empty and unused database; the behavior is undefined
+#' otherwise.
+#' @return Returns \code{NULL}.
+#' @author Seth Falcon
+#' @references \url{http://www.sqlite.org/backup.html}
+#' @examples
+#' 
+#' ## Create an in memory database
+#' db <- dbConnect(SQLite(), dbname = ":memory:")
+#' df <- data.frame(letters=letters[1:4], numbers=1:4, stringsAsFactors = FALSE)
+#' ok <- dbWriteTable(db, "table1", df, row.names = FALSE)
+#' stopifnot(ok)
+#' 
+#' ## Copy the contents of the in memory database to
+#' ## the specified file
+#' backupDbFile <- tempfile()
+#' sqliteCopyDatabase(db, backupDbFile)
+#' diskdb <- dbConnect(SQLite(), dbname = backupDbFile)
+#' stopifnot(identical(df, dbReadTable(diskdb, "table1")))
+#' 
+#' ## Copy from one connection to another
+#' db2 <- dbConnect(SQLite(), dbname = ":memory:")
+#' sqliteCopyDatabase(db, db2)
+#' stopifnot(identical(df, dbReadTable(db2, "table1")))
+#' 
+#' ## cleanup
+#' dbDisconnect(db)
+#' dbDisconnect(diskdb)
+#' dbDisconnect(db2)
+#' unlink(backupDbFile)
+#' 
+#' @export sqliteCopyDatabase
+#' @useDynLib RSQLite RS_SQLite_copy_database
+sqliteCopyDatabase <- function(from, to) {
+  if (!is(from, "SQLiteConnection"))
+    stop("'from' must be a SQLiteConnection object")
+  destdb <- to
+  if (!is(to, "SQLiteConnection")) {
+    if (is.character(to) && length(to) == 1L && !is.na(to) && nzchar(to)) {
+      if (":memory:" == to)
+        stop("invalid file name for 'to'.  Use a SQLiteConnection",
+          " object to copy to an in-memory database")
+      destdb <- dbConnect(SQLite(), dbname = path.expand(to))
+      on.exit(dbDisconnect(destdb))
+    } else {
+      stop("'to' must be SQLiteConnection object or a non-empty string")
+    }
+  }
+  .Call(RS_SQLite_copy_database, from at Id, destdb at Id)
+  invisible(NULL)
+}
+
+
+
+explict_rownames <- function(df, row.names = NA) {
+  if (is.na(row.names)) {
+    row.names <- is.character(attr(df, "row.names"))
+  }
+  if (!row.names) return(df)
+  
+  rn <- data.frame(row_names = row.names(df))
+  cbind(rn, df)
+}
diff --git a/R/datasetsDb.R b/R/datasetsDb.R
new file mode 100644
index 0000000..81d104c
--- /dev/null
+++ b/R/datasetsDb.R
@@ -0,0 +1,17 @@
+#' A sample sqlite database.
+#' 
+#' This database is bundled with the package, and contains all data frames
+#' in the datasets package.
+#' 
+#' @export
+#' @examples
+#' db <- datasetsDb()
+#' dbListTables(db)
+#' 
+#' dbReadTable(db, "CO2")
+#' dbGetQuery(db, "SELECT * FROM CO2 WHERE conc < 100")
+#' 
+#' dbDisconnect(db)
+datasetsDb <- function() {
+  dbConnect(SQLite(), system.file("db", "datasets.sqlite", package = "RSQLite"))
+}
\ No newline at end of file
diff --git a/R/dbGetInfo.R b/R/dbGetInfo.R
new file mode 100644
index 0000000..2aef980
--- /dev/null
+++ b/R/dbGetInfo.R
@@ -0,0 +1,54 @@
+#' Get metadata about a database object.
+#' 
+#' @param dbObj An object of class \code{\linkS4class{SQLiteDriver}},
+#'   \code{\linkS4class{SQLiteConnection}} or 
+#'   \code{\linkS4class{SQLiteResult}}
+#' @name dbGetInfo
+#' @examples
+#' dbGetInfo(SQLite())
+#' 
+#' con <- dbConnect(SQLite())
+#' dbGetInfo(con)
+#' 
+#' dbWriteTable(con, "mtcars", mtcars)
+#' rs <- dbSendQuery(con, "SELECT * FROM mtcars")
+#' dbGetInfo(rs)
+#' dbFetch(rs, 1)
+#' dbGetInfo(rs)
+#' 
+#' dbClearResult(rs)
+#' dbDisconnect(con)
+NULL
+
+#' @rdname dbGetInfo
+#' @export
+#' @useDynLib RSQLite rsqlite_driver_info
+setMethod("dbGetInfo", "SQLiteDriver", function(dbObj) {
+  .Call(rsqlite_driver_info)
+})
+
+#' @rdname dbGetInfo
+#' @export
+#' @useDynLib RSQLite rsqlite_connection_info
+setMethod("dbGetInfo", "SQLiteConnection", function(dbObj) {
+  check_valid(dbObj)
+  info <- .Call(rsqlite_connection_info, dbObj at Id)
+  info
+})
+
+#' @rdname dbGetInfo
+#' @export
+#' @useDynLib RSQLite rsqlite_result_info
+setMethod("dbGetInfo", "SQLiteResult", function(dbObj) {
+  check_valid(dbObj)
+  
+  info <- .Call(rsqlite_result_info, dbObj at Id)
+  flds <- info$fieldDescription[[1]]
+  
+  info$fields <- structure(info$fields, 
+    row.names = .set_row_names(length(info$fields[[1]])),
+    class = "data.frame"
+  )
+  
+  info
+})
diff --git a/R/dbObjectId.R b/R/dbObjectId.R
deleted file mode 100644
index b95352d..0000000
--- a/R/dbObjectId.R
+++ /dev/null
@@ -1,52 +0,0 @@
-##
-## $Id$
-## 
-## Copyright (C) 1999-2002 The Omega Project for Statistical Computing.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser 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
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-##
-
-## Class: dbObjectId
-##
-## This mixin helper class is NOT part of the database interface definition,
-## but it is extended by the Oracle, MySQL, and SQLite implementations to
-## MySQLObject and OracleObject to allow us to conviniently (and portably) 
-## implement all database foreign objects methods (i.e., methods for show(), 
-## print() format() the dbManger, dbConnection, dbResultSet, etc.) 
-## A dbObjectId is an  identifier into an actual remote database objects.  
-## This class and its derived classes <driver-manager>Object need to 
-## be VIRTUAL to avoid coercion (green book, p.293) during method dispatching.
-##
-## TODO: Convert the Id slot to be an external object (as per Luke Tierney's
-## implementation), even at the expense of S-plus compatibility?
-
-setClass("dbObjectId", representation(Id = "externalptr", "VIRTUAL"))
-
-setMethod("show", "dbObjectId",
-   definition = function(object) {
-      expired <- if(isIdCurrent(object)) "" else "Expired "
-      id <- .Call("DBI_handle_to_string", object at Id, PACKAGE = .SQLitePkgName)
-      str <- paste("<", expired, class(object), ": ", id, ">", sep="")
-      cat(str, "\n")
-      invisible(NULL)
-   }
-)
-
-"isIdCurrent" <- 
-function(obj)
-## verify that obj refers to a currently open/loaded database
-{ 
-   .Call("RS_DBI_validHandle", obj at Id, PACKAGE = .SQLitePkgName)
-}
diff --git a/R/extensions.R b/R/extensions.R
new file mode 100644
index 0000000..f1f4dbb
--- /dev/null
+++ b/R/extensions.R
@@ -0,0 +1,36 @@
+#' Add useful extension functions.
+#' 
+#' These extension functions are written by Liam Healy and made available
+#' through the SQLite website (\url{http://www.sqlite.org/contrib}).
+#'
+#' @section Available extension functions:
+#' 
+#' \describe{
+#' \item{Math functions}{acos, acosh, asin, asinh, atan, atan2, atanh, atn2, 
+#'   ceil, cos, cosh, cot, coth, degrees, difference, exp, floor, log, log10, 
+#'   pi, power, radians, sign, sin, sinh, sqrt, square, tan, tanh}
+#' \item{String functions}{charindex, leftstr, ltrim, padc, padl, padr, proper, 
+#'   replace, replicate, reverse, rightstr, rtrim, strfilter, trim}
+#' \item{Aggregate functions}{stdev, variance, mode, median, lower_quartile, 
+#'   upper_quartile}
+#' }
+#' @param db A database to load these extensions.
+#' @export
+#' @examples
+#' db <- dbConnect(SQLite())
+#' initExtension(db)
+#' 
+#' dbWriteTable(db, "mtcars", mtcars)
+#' dbGetQuery(db, "SELECT stdev(mpg) FROM mtcars")
+#' sd(mtcars$mpg)
+initExtension <- function(db) {
+  if (!db at loadable.extensions) {
+    stop("Loadable extensions are not enabled for this db connection", 
+      call. = FALSE)
+  }
+    
+  lib_path <- getLoadedDLLs()[["RSQLite"]][["path"]]
+  res <- dbGetQuery(db, sprintf("SELECT load_extension('%s')", lib_path))
+
+  invisible(TRUE)
+}
diff --git a/R/zzz.R b/R/zzz.R
index 1a6e8a4..17c7b4e 100644
--- a/R/zzz.R
+++ b/R/zzz.R
@@ -1,59 +1,4 @@
 .onUnload <- function(libpath) {
-    library.dynam.unload("RSQLite", libpath)
-}
-
-.test <- function(dir, pattern = ".*_test\\.R$")
-{
-    .failure_details <- function(result) {
-        res <- result[[1L]]
-        if (res$nFail > 0 || res$nErr > 0) {
-            Filter(function(x) length(x) > 0,
-                   lapply(res$sourceFileResults,
-                          function(fileRes) {
-                              names(Filter(function(x) x$kind != "success",
-                                           fileRes))
-                          }))
-        } else list()
-    }
-
-    if (missing(dir)) {
-        dir <- system.file("unitTests", package="RSQLite")
-        if (!nzchar(dir)) {
-            dir <- system.file("UnitTests", package="RSQLite")
-            if (!nzchar(dir))
-                stop("unable to find unit tests, no 'unitTests' dir")
-        }
-    }
-
-    ## Run unit tests from the directory containing the test files.
-    ## This allows tests to refer to data files with relative paths
-    cwd <- getwd()
-    on.exit(setwd(cwd))
-    setwd(dir)
-
-    require("RUnit", quietly=TRUE) || stop("RUnit package not found")
-    RUnit_opts <- getOption("RUnit", list())
-    RUnit_opts$verbose <- 0L
-    RUnit_opts$silent <- TRUE
-    RUnit_opts$verbose_fail_msg <- TRUE
-    options(RUnit = RUnit_opts)
-    suite <- defineTestSuite(name="RSQLite RUnit Tests", dirs=getwd(),
-                             testFileRegexp=pattern,
-                             rngKind="default",
-                             rngNormalKind="default")
-    result <- runTestSuite(suite)
-    cat("\n\n")
-    printTextProtocol(result, showDetails=FALSE)
-    if (length(details <- .failure_details(result)) >0) {
-        cat("\nTest files with failing tests\n")
-        for (i in seq_along(details)) {
-            cat("\n  ", basename(names(details)[[i]]), "\n")
-            for (j in seq_along(details[[i]])) {
-                cat("    ", details[[i]][[j]], "\n")
-            }
-        }
-        cat("\n\n")
-        stop("unit tests failed for package RSQLite")
-    }
-    result
+  gc() # Force garbage collection of connections
+  library.dynam.unload("RSQLite", libpath)
 }
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..68be585
--- /dev/null
+++ b/README.md
@@ -0,0 +1,89 @@
+# RSQLite
+
+[![Build Status](https://travis-ci.org/rstats-db/RSQLite.png?branch=master)](https://travis-ci.org/rstats-db/RSQLite)
+
+RSQLite embeds the SQLite database engine in R, providing a DBI-compliant interface. [SQLite](http://www.sqlite.org) is a public-domain, single-user, very light-weight database engine that implements a decent subset of the SQL 92 standard, including the core table creation, updating, insertion, and selection operations, plus transaction management.
+
+You can install the latest released version from CRAN with:
+
+```R
+install.packages("RSQLite")
+```
+
+Or install the latest development version from github with:
+
+```R
+# install.packages("devtools")
+devtools::install_github("rstats-db/RSQLite")
+```
+
+To install from github, you'll need a [development environment](http://www.rstudio.com/ide/docs/packages/prerequisites).
+
+## Basic usage
+
+```R
+library(DBI)
+# Create an ephemeral in-memory RSQLite database
+con <- dbConnect(RSQLite::SQLite(), ":memory:")
+
+dbListTables(con)
+dbWriteTable(con, "mtcars", mtcars)
+dbListTables(con)
+
+dbListFields(con, "mtcars")
+dbReadTable(con, "mtcars")
+
+# You can fetch all results:
+res <- dbSendQuery(con, "SELECT * FROM mtcars WHERE cyl = 4")
+dbFetch(res)
+dbClearResult(res)
+
+# Or a chunk at a time
+res <- dbSendQuery(con, "SELECT * FROM mtcars WHERE cyl = 4")
+while(!dbHasCompleted(res)){
+  chunk <- dbFetch(res, n = 5)
+  print(nrow(chunk))
+}
+# Clear the result
+dbClearResult(res)
+
+# Disconnect from the database
+dbDisconnect(con)
+```
+
+## Acknowledgements
+
+Many thanks to Doug Bates, Seth Falcon, Detlef Groth, Ronggui Huang, Kurt Hornik, Uwe Ligges, Charles Loboz, Duncan Murdoch, and Brian D. Ripley for comments, suggestions, bug reports, and/or patches.
+
+## Update version of SQLite
+
+1.  Download latest SQLite source
+
+    ```R
+    latest <- "http://sqlite.org/2014/sqlite-amalgamation-3080600.zip"
+    tmp <- tempfile()
+    download.file(latest, tmp)
+    unzip(tmp, exdir = "src/sqlite", junkpaths = TRUE)
+    unlink("src/sqlite/shell.c")
+    ```
+1.  Update `DESCRIPTION` for included version of SQLite
+
+1.  Update `NEWS`
+
+## Update datasets database
+
+RSQLite includes one SQLite database (accessible from `datasetsDb()` that contains all data frames in the datasets package. This is the code that created it.
+
+```R
+tables <- unique(data(package = "datasets")$results[, 3])
+tables <- tables[!grepl("(", tables, fixed = TRUE)]
+
+con <- dbConnect(SQLite(), "inst/db/datasets.sqlite")
+for(table in tables) {
+  df <- getExportedValue("datasets", table)
+  if (!is.data.frame(df)) next
+  
+  message("Creating table: ", table)
+  dbWriteTable(con, table, as.data.frame(df), overwrite = TRUE)
+}
+```
diff --git a/configure b/configure
index 7e75cee..ae2846d 100755
--- a/configure
+++ b/configure
@@ -1,60 +1,81 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
 #
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 # This configure script is free software; the Free Software Foundation
 # gives unlimited permission to copy, distribute and modify it.
-## --------------------- ##
-## M4sh Initialization.  ##
-## --------------------- ##
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
 
 # Be more Bourne compatible
 DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
   emulate sh
   NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
   # is contrary to our usage.  Disable this feature.
   alias -g '${1+"$@"}'='"$@"'
   setopt NO_GLOB_SUBST
 else
-  case `(set -o) 2>/dev/null` in
-  *posix*) set -o posix ;;
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
 esac
-
 fi
 
 
-
-
-# PATH needs CR
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
   else
-    PATH_SEPARATOR=:
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
   fi
-  rm -f conf$$.sh
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
 fi
 
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
 fi
 
 
@@ -63,20 +84,19 @@ fi
 # there to prevent editors from complaining about space-tab.
 # (If _AS_PATH_WALK were called with IFS unset, it would disable word
 # splitting by setting IFS to empty value.)
-as_nl='
-'
 IFS=" ""	$as_nl"
 
 # Find who we are.  Look in the path if we contain no directory separator.
-case $0 in
+as_myself=
+case $0 in #((
   *[\\/]* ) as_myself=$0 ;;
   *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
 IFS=$as_save_IFS
 
      ;;
@@ -87,354 +107,365 @@ if test "x$as_myself" = x; then
   as_myself=$0
 fi
 if test ! -f "$as_myself"; then
-  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
-  { (exit 1); exit 1; }
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
 fi
 
-# Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
 done
 PS1='$ '
 PS2='> '
 PS4='+ '
 
 # NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-	 X"$0" : 'X\(//\)$' \| \
-	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{
-	    s//\1/
-	    q
-	  }
-	  /^X\/\(\/\/\)$/{
-	    s//\1/
-	    q
-	  }
-	  /^X\/\(\/\).*/{
-	    s//\1/
-	    q
-	  }
-	  s/.*/./; q'`
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
 
 # CDPATH.
-$as_unset CDPATH
-
-
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
-  if (eval ":") 2>/dev/null; then
-  as_have_required=yes
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
 else
-  as_have_required=no
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
 fi
-
-  if test $as_have_required = yes && 	 (eval ":
-(as_func_return () {
-  (exit \$1)
-}
-as_func_success () {
-  as_func_return 0
-}
-as_func_failure () {
-  as_func_return 1
-}
-as_func_ret_success () {
-  return 0
-}
-as_func_ret_failure () {
-  return 1
-}
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
 
 exitcode=0
-if as_func_success; then
-  :
-else
-  exitcode=1
-  echo as_func_success failed.
-fi
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
 
-if as_func_failure; then
-  exitcode=1
-  echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
-  :
 else
-  exitcode=1
-  echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
-  exitcode=1
-  echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
-  :
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
 else
-  exitcode=1
-  echo positional parameters were not saved.
+  as_have_required=no
 fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
 
-test \$exitcode = 0) || { (exit 1); exit 1; }
-
-(
-  as_lineno_1=\$LINENO
-  as_lineno_2=\$LINENO
-  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
-  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
-") 2> /dev/null; then
-  :
 else
-  as_candidate_shells=
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
 for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  case $as_dir in
+  as_found=:
+  case $as_dir in #(
 	 /*)
 	   for as_base in sh bash ksh sh5; do
-	     as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
 	   done;;
        esac
+  as_found=false
 done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
 IFS=$as_save_IFS
 
 
-      for as_shell in $as_candidate_shells $SHELL; do
-	 # Try only shells that exist, to save several forks.
-	 if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
-		{ ("$as_shell") 2> /dev/null <<\_ASEOF
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-  setopt NO_GLOB_SUBST
-else
-  case `(set -o) 2>/dev/null` in
-  *posix*) set -o posix ;;
-esac
-
-fi
-
-
-:
-_ASEOF
-}; then
-  CONFIG_SHELL=$as_shell
-	       as_have_required=yes
-	       if { "$as_shell" 2> /dev/null <<\_ASEOF
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-  setopt NO_GLOB_SUBST
-else
-  case `(set -o) 2>/dev/null` in
-  *posix*) set -o posix ;;
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
 esac
-
-fi
-
-
-:
-(as_func_return () {
-  (exit $1)
-}
-as_func_success () {
-  as_func_return 0
-}
-as_func_failure () {
-  as_func_return 1
-}
-as_func_ret_success () {
-  return 0
-}
-as_func_ret_failure () {
-  return 1
-}
-
-exitcode=0
-if as_func_success; then
-  :
-else
-  exitcode=1
-  echo as_func_success failed.
-fi
-
-if as_func_failure; then
-  exitcode=1
-  echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
-  :
-else
-  exitcode=1
-  echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
-  exitcode=1
-  echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = "$1" ); then
-  :
-else
-  exitcode=1
-  echo positional parameters were not saved.
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf at gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
 fi
-
-test $exitcode = 0) || { (exit 1); exit 1; }
-
-(
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
-
-_ASEOF
-}; then
-  break
 fi
-
 fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
 
-      done
-
-      if test "x$CONFIG_SHELL" != x; then
-  for as_var in BASH_ENV ENV
-        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-        done
-        export CONFIG_SHELL
-        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
-fi
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
 
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
 
-    if test $as_have_required = no; then
-  echo This script requires a shell more modern than all the
-      echo shells that I found on your system.  Please install a
-      echo modern shell, or manually run the script under such a
-      echo shell if you do have one.
-      { (exit 1); exit 1; }
-fi
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
 
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
 
-fi
 
-fi
+} # as_fn_mkdir_p
 
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
 
 
-(eval "as_func_return () {
-  (exit \$1)
-}
-as_func_success () {
-  as_func_return 0
-}
-as_func_failure () {
-  as_func_return 1
-}
-as_func_ret_success () {
-  return 0
-}
-as_func_ret_failure () {
-  return 1
-}
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
 
-exitcode=0
-if as_func_success; then
-  :
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
 else
-  exitcode=1
-  echo as_func_success failed.
-fi
-
-if as_func_failure; then
-  exitcode=1
-  echo as_func_failure succeeded.
+  as_expr=false
 fi
 
-if as_func_ret_success; then
-  :
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
 else
-  exitcode=1
-  echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
-  exitcode=1
-  echo as_func_ret_failure succeeded.
+  as_basename=false
 fi
 
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
-  :
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
 else
-  exitcode=1
-  echo positional parameters were not saved.
+  as_dirname=false
 fi
 
-test \$exitcode = 0") || {
-  echo No shell found that supports shell functions.
-  echo Please tell autoconf at gnu.org about your system,
-  echo including any error possibly output before this
-  echo message
-}
-
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
 
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
 
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
 
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line after each line using $LINENO; the second 'sed'
-  # does the real work.  The second script uses 'N' to pair each
-  # line-number line with the line containing $LINENO, and appends
-  # trailing '-' during substitution so that $LINENO is not a special
-  # case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # scripts with optimization help from Paolo Bonzini.  Blame Lee
-  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
   sed -n '
     p
     /[$]LINENO/=
@@ -451,9 +482,12 @@ test \$exitcode = 0") || {
       s/-\n.*//
     ' >$as_me.lineno &&
   chmod +x "$as_me.lineno" ||
-    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
-   { (exit 1); exit 1; }; }
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
 
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
   # original and so on.  Autoconf is especially sensitive to this).
@@ -462,84 +496,55 @@ test \$exitcode = 0") || {
   exit
 }
 
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
-  as_dirname=dirname
-else
-  as_dirname=false
-fi
-
 ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
+case `echo -n x` in #(((((
 -n*)
-  case `echo 'x\c'` in
+  case `echo 'xy\c'` in
   *c*) ECHO_T='	';;	# ECHO_T is single tab character.
-  *)   ECHO_C='\c';;
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
   esac;;
 *)
   ECHO_N='-n';;
 esac
 
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
 rm -f conf$$ conf$$.exe conf$$.file
 if test -d conf$$.dir; then
   rm -f conf$$.dir/conf$$.file
 else
   rm -f conf$$.dir
-  mkdir conf$$.dir
-fi
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s='ln -s'
-  # ... but there are two gotchas:
-  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
-  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-  # In both cases, we have to default to `cp -p'.
-  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-    as_ln_s='cp -p'
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
 
 if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
+  as_mkdir_p='mkdir -p "$as_dir"'
 else
   test -d ./-p && rmdir ./-p
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-        test -d "$1/.";
-      else
-	case $1 in
-        -*)set "./$1";;
-	esac;
-	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
-	???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -548,11 +553,11 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
 
-
-exec 7<&0 </dev/null 6>&1
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
 
 # Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
 # so uname gets run too.
 ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
 
@@ -567,7 +572,6 @@ cross_compiling=no
 subdirs=
 MFLAGS=
 MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
 
 # Identity of this package.
 PACKAGE_NAME=
@@ -575,58 +579,66 @@ PACKAGE_TARNAME=
 PACKAGE_VERSION=
 PACKAGE_STRING=
 PACKAGE_BUGREPORT=
+PACKAGE_URL=
 
-ac_unique_file="src/RS-SQLite.c"
-ac_subst_vars='SHELL
-PATH_SEPARATOR
-PACKAGE_NAME
-PACKAGE_TARNAME
-PACKAGE_VERSION
-PACKAGE_STRING
-PACKAGE_BUGREPORT
-exec_prefix
-prefix
-program_transform_name
-bindir
-sbindir
-libexecdir
-datarootdir
-datadir
-sysconfdir
-sharedstatedir
-localstatedir
-includedir
-oldincludedir
-docdir
-infodir
-htmldir
-dvidir
-pdfdir
-psdir
-libdir
-localedir
-mandir
-DEFS
-ECHO_C
-ECHO_N
-ECHO_T
-LIBS
-build_alias
-host_alias
-target_alias
-CC
-CFLAGS
-LDFLAGS
-CPPFLAGS
-ac_ct_CC
-EXEEXT
-OBJEXT
-CPP
-PKG_CPPFLAGS
-PKG_LIBS
+ac_unique_file="src/rsqlite.h"
+ac_subst_vars='LTLIBOBJS
 LIBOBJS
-LTLIBOBJS'
+PKG_LIBS
+PKG_CPPFLAGS
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
 ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_sqlite_dir
+with_sqlite_lib
+with_sqlite_inc
+'
       ac_precious_vars='build_alias
 host_alias
 target_alias
@@ -641,6 +653,8 @@ CPP'
 # Initialize some variables set by options.
 ac_init_help=
 ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
 # The variables have the same names as the options, with
 # dashes changed to underlines.
 cache_file=/dev/null
@@ -696,8 +710,9 @@ do
   fi
 
   case $ac_option in
-  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
-  *)	ac_optarg=yes ;;
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
   esac
 
   # Accept the important Cygnus configure options, so we can diagnose typos.
@@ -739,13 +754,20 @@ do
     datarootdir=$ac_optarg ;;
 
   -disable-* | --disable-*)
-    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
     # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
-    eval enable_$ac_feature=no ;;
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
 
   -docdir | --docdir | --docdi | --doc | --do)
     ac_prev=docdir ;;
@@ -758,13 +780,20 @@ do
     dvidir=$ac_optarg ;;
 
   -enable-* | --enable-*)
-    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
     # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
-    eval enable_$ac_feature=\$ac_optarg ;;
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
 
   -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
   | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
@@ -955,22 +984,36 @@ do
     ac_init_version=: ;;
 
   -with-* | --with-*)
-    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
     # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
-    eval with_$ac_package=\$ac_optarg ;;
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
 
   -without-* | --without-*)
-    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
     # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
-    eval with_$ac_package=no ;;
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
 
   --x)
     # Obsolete; use --with-x.
@@ -990,26 +1033,26 @@ do
   | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
     x_libraries=$ac_optarg ;;
 
-  -*) { echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
-   { (exit 1); exit 1; }; }
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
     ;;
 
   *=*)
     ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
     # Reject names that are not valid shell variable names.
-    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
-   { (exit 1); exit 1; }; }
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
     eval $ac_envvar=\$ac_optarg
     export $ac_envvar ;;
 
   *)
     # FIXME: should be removed in autoconf 3.0.
-    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
     expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
-    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
     ;;
 
   esac
@@ -1017,23 +1060,36 @@ done
 
 if test -n "$ac_prev"; then
   ac_option=--`echo $ac_prev | sed 's/_/-/g'`
-  { echo "$as_me: error: missing argument to $ac_option" >&2
-   { (exit 1); exit 1; }; }
+  as_fn_error $? "missing argument to $ac_option"
 fi
 
-# Be sure to have absolute directory names.
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
 		libdir localedir mandir
 do
   eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
   case $ac_val in
     [\\/$]* | ?:[\\/]* )  continue;;
     NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
   esac
-  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; }
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
 done
 
 # There might be people who depend on the old broken behavior: `$host'
@@ -1047,8 +1103,6 @@ target=$target_alias
 if test "x$host_alias" != x; then
   if test "x$build_alias" = x; then
     cross_compiling=maybe
-    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used." >&2
   elif test "x$build_alias" != "x$host_alias"; then
     cross_compiling=yes
   fi
@@ -1063,23 +1117,21 @@ test "$silent" = yes && exec 6>/dev/null
 ac_pwd=`pwd` && test -n "$ac_pwd" &&
 ac_ls_di=`ls -di .` &&
 ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
-  { echo "$as_me: error: Working directory cannot be determined" >&2
-   { (exit 1); exit 1; }; }
+  as_fn_error $? "working directory cannot be determined"
 test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
-  { echo "$as_me: error: pwd does not report name of working directory" >&2
-   { (exit 1); exit 1; }; }
+  as_fn_error $? "pwd does not report name of working directory"
 
 
 # Find the source files, if location was not specified.
 if test -z "$srcdir"; then
   ac_srcdir_defaulted=yes
   # Try the directory containing this script, then the parent directory.
-  ac_confdir=`$as_dirname -- "$0" ||
-$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-	 X"$0" : 'X\(//\)[^/]' \| \
-	 X"$0" : 'X\(//\)$' \| \
-	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X"$0" |
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
     sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
 	    s//\1/
 	    q
@@ -1106,13 +1158,11 @@ else
 fi
 if test ! -r "$srcdir/$ac_unique_file"; then
   test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
-  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
-   { (exit 1); exit 1; }; }
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
 fi
 ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
 ac_abs_confdir=`(
-	cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
-   { (exit 1); exit 1; }; }
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
 	pwd)`
 # When building in place, set srcdir=.
 if test "$ac_abs_confdir" = "$ac_pwd"; then
@@ -1152,7 +1202,7 @@ Configuration:
       --help=short        display options specific to this package
       --help=recursive    display the short help of all the included packages
   -V, --version           display version information and exit
-  -q, --quiet, --silent   do not print \`checking...' messages
+  -q, --quiet, --silent   do not print \`checking ...' messages
       --cache-file=FILE   cache test results in FILE [disabled]
   -C, --config-cache      alias for \`--cache-file=config.cache'
   -n, --no-create         do not create output files
@@ -1160,9 +1210,9 @@ Configuration:
 
 Installation directories:
   --prefix=PREFIX         install architecture-independent files in PREFIX
-			  [$ac_default_prefix]
+                          [$ac_default_prefix]
   --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
-			  [PREFIX]
+                          [PREFIX]
 
 By default, \`make install' will install all the files in
 \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
@@ -1172,25 +1222,25 @@ for instance \`--prefix=\$HOME'.
 For better control, use the options below.
 
 Fine tuning of the installation directories:
-  --bindir=DIR           user executables [EPREFIX/bin]
-  --sbindir=DIR          system admin executables [EPREFIX/sbin]
-  --libexecdir=DIR       program executables [EPREFIX/libexec]
-  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
-  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
-  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
-  --libdir=DIR           object code libraries [EPREFIX/lib]
-  --includedir=DIR       C header files [PREFIX/include]
-  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
-  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
-  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
-  --infodir=DIR          info documentation [DATAROOTDIR/info]
-  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
-  --mandir=DIR           man documentation [DATAROOTDIR/man]
-  --docdir=DIR           documentation root [DATAROOTDIR/doc/PACKAGE]
-  --htmldir=DIR          html documentation [DOCDIR]
-  --dvidir=DIR           dvi documentation [DOCDIR]
-  --pdfdir=DIR           pdf documentation [DOCDIR]
-  --psdir=DIR            ps documentation [DOCDIR]
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
 _ACEOF
 
   cat <<\_ACEOF
@@ -1214,13 +1264,14 @@ Some influential environment variables:
   LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
               nonstandard directory <lib dir>
   LIBS        libraries to pass to the linker, e.g. -l<library>
-  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
               you have headers in a nonstandard directory <include dir>
   CPP         C preprocessor
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
 
+Report bugs to the package provider.
 _ACEOF
 ac_status=$?
 fi
@@ -1228,15 +1279,17 @@ fi
 if test "$ac_init_help" = "recursive"; then
   # If there are subdirs, report their specific --help.
   for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
-    test -d "$ac_dir" || continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
     ac_builddir=.
 
 case "$ac_dir" in
 .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
 *)
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
   # A ".." for each directory in $ac_dir_suffix.
-  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
   case $ac_top_builddir_sub in
   "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
   *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1272,7 +1325,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
       echo &&
       $SHELL "$ac_srcdir/configure" --help=recursive
     else
-      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi || ac_status=$?
     cd "$ac_pwd" || { ac_status=$?; break; }
   done
@@ -1282,21 +1335,145 @@ test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
 configure
-generated by GNU Autoconf 2.61
+generated by GNU Autoconf 2.69
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
   exit
 fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
 cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
 It was created by $as_me, which was
-generated by GNU Autoconf 2.61.  Invocation command line was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
 
@@ -1332,8 +1509,8 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  echo "PATH: $as_dir"
-done
+    $as_echo "PATH: $as_dir"
+  done
 IFS=$as_save_IFS
 
 } >&5
@@ -1367,12 +1544,12 @@ do
     | -silent | --silent | --silen | --sile | --sil)
       continue ;;
     *\'*)
-      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
     esac
     case $ac_pass in
-    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
     2)
-      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      as_fn_append ac_configure_args1 " '$ac_arg'"
       if test $ac_must_keep_next = true; then
 	ac_must_keep_next=false # Got value, back to normal.
       else
@@ -1388,13 +1565,13 @@ do
 	  -* ) ac_must_keep_next=true ;;
 	esac
       fi
-      ac_configure_args="$ac_configure_args '$ac_arg'"
+      as_fn_append ac_configure_args " '$ac_arg'"
       ;;
     esac
   done
 done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
 
 # When interrupted or exit'd, cleanup temporary files, and complete
 # config.log.  We remove comments because anyway the quotes in there
@@ -1406,11 +1583,9 @@ trap 'exit_status=$?
   {
     echo
 
-    cat <<\_ASBOX
-## ---------------- ##
+    $as_echo "## ---------------- ##
 ## Cache variables. ##
-## ---------------- ##
-_ASBOX
+## ---------------- ##"
     echo
     # The following way of writing the cache mishandles newlines in values,
 (
@@ -1419,12 +1594,13 @@ _ASBOX
     case $ac_val in #(
     *${as_nl}*)
       case $ac_var in #(
-      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
-echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
       esac
       case $ac_var in #(
       _ | IFS | as_nl) ;; #(
-      *) $as_unset $ac_var ;;
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
       esac ;;
     esac
   done
@@ -1443,128 +1619,136 @@ echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
 )
     echo
 
-    cat <<\_ASBOX
-## ----------------- ##
+    $as_echo "## ----------------- ##
 ## Output variables. ##
-## ----------------- ##
-_ASBOX
+## ----------------- ##"
     echo
     for ac_var in $ac_subst_vars
     do
       eval ac_val=\$$ac_var
       case $ac_val in
-      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
       esac
-      echo "$ac_var='\''$ac_val'\''"
+      $as_echo "$ac_var='\''$ac_val'\''"
     done | sort
     echo
 
     if test -n "$ac_subst_files"; then
-      cat <<\_ASBOX
-## ------------------- ##
+      $as_echo "## ------------------- ##
 ## File substitutions. ##
-## ------------------- ##
-_ASBOX
+## ------------------- ##"
       echo
       for ac_var in $ac_subst_files
       do
 	eval ac_val=\$$ac_var
 	case $ac_val in
-	*\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
 	esac
-	echo "$ac_var='\''$ac_val'\''"
+	$as_echo "$ac_var='\''$ac_val'\''"
       done | sort
       echo
     fi
 
     if test -s confdefs.h; then
-      cat <<\_ASBOX
-## ----------- ##
+      $as_echo "## ----------- ##
 ## confdefs.h. ##
-## ----------- ##
-_ASBOX
+## ----------- ##"
       echo
       cat confdefs.h
       echo
     fi
     test "$ac_signal" != 0 &&
-      echo "$as_me: caught signal $ac_signal"
-    echo "$as_me: exit $exit_status"
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
   } >&5
   rm -f core *.core core.conftest.* &&
     rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
     exit $exit_status
 ' 0
 for ac_signal in 1 2 13 15; do
-  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
 done
 ac_signal=0
 
 # confdefs.h avoids OS command line length limits that DEFS can exceed.
 rm -f -r conftest* confdefs.h
 
+$as_echo "/* confdefs.h */" > confdefs.h
+
 # Predefined preprocessor variables.
 
 cat >>confdefs.h <<_ACEOF
 #define PACKAGE_NAME "$PACKAGE_NAME"
 _ACEOF
 
-
 cat >>confdefs.h <<_ACEOF
 #define PACKAGE_TARNAME "$PACKAGE_TARNAME"
 _ACEOF
 
-
 cat >>confdefs.h <<_ACEOF
 #define PACKAGE_VERSION "$PACKAGE_VERSION"
 _ACEOF
 
-
 cat >>confdefs.h <<_ACEOF
 #define PACKAGE_STRING "$PACKAGE_STRING"
 _ACEOF
 
-
 cat >>confdefs.h <<_ACEOF
 #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
 _ACEOF
 
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
 
 # Let the site file select an alternate cache file if it wants to.
-# Prefer explicitly selected file to automatically selected ones.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
 if test -n "$CONFIG_SITE"; then
-  set x "$CONFIG_SITE"
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
 elif test "x$prefix" != xNONE; then
-  set x "$prefix/share/config.site" "$prefix/etc/config.site"
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
 else
-  set x "$ac_default_prefix/share/config.site" \
-	"$ac_default_prefix/etc/config.site"
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
 fi
-shift
-for ac_site_file
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
 do
-  if test -r "$ac_site_file"; then
-    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
-echo "$as_me: loading site script $ac_site_file" >&6;}
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
     sed 's/^/| /' "$ac_site_file" >&5
-    . "$ac_site_file"
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
   fi
 done
 
 if test -r "$cache_file"; then
-  # Some versions of bash will fail to source /dev/null (special
-  # files actually), so we avoid doing that.
-  if test -f "$cache_file"; then
-    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
-echo "$as_me: loading cache $cache_file" >&6;}
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
     case $cache_file in
       [\\/]* | ?:[\\/]* ) . "$cache_file";;
       *)                      . "./$cache_file";;
     esac
   fi
 else
-  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
-echo "$as_me: creating cache $cache_file" >&6;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
   >$cache_file
 fi
 
@@ -1578,60 +1762,56 @@ for ac_var in $ac_precious_vars; do
   eval ac_new_val=\$ac_env_${ac_var}_value
   case $ac_old_set,$ac_new_set in
     set,)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
       ac_cache_corrupted=: ;;
     ,set)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
       ac_cache_corrupted=: ;;
     ,);;
     *)
       if test "x$ac_old_val" != "x$ac_new_val"; then
-	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
-echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
-	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
-echo "$as_me:   former value:  $ac_old_val" >&2;}
-	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
-echo "$as_me:   current value: $ac_new_val" >&2;}
-	ac_cache_corrupted=:
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
       fi;;
   esac
   # Pass precious variables to config.status.
   if test "$ac_new_set" = set; then
     case $ac_new_val in
-    *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
     *) ac_arg=$ac_var=$ac_new_val ;;
     esac
     case " $ac_configure_args " in
       *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
-      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
     esac
   fi
 done
 if $ac_cache_corrupted; then
-  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
-echo "$as_me: error: changes in the environment can compromise the build" >&2;}
-  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
-   { (exit 1); exit 1; }; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
 fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
 
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -1658,10 +1838,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
 set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -1671,25 +1851,25 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
@@ -1698,10 +1878,10 @@ if test -z "$ac_cv_prog_CC"; then
   ac_ct_CC=$CC
   # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
@@ -1711,25 +1891,25 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
   if test "x$ac_ct_CC" = x; then
@@ -1737,12 +1917,8 @@ fi
   else
     case $cross_compiling:$ac_tool_warned in
 yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
 ac_tool_warned=yes ;;
 esac
     CC=$ac_ct_CC
@@ -1755,10 +1931,10 @@ if test -z "$CC"; then
           if test -n "$ac_tool_prefix"; then
     # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
 set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -1768,25 +1944,25 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
@@ -1795,10 +1971,10 @@ fi
 if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -1809,18 +1985,18 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
      fi
     ac_cv_prog_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 if test $ac_prog_rejected = yes; then
@@ -1839,11 +2015,11 @@ fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
@@ -1854,10 +2030,10 @@ if test -z "$CC"; then
   do
     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -1867,25 +2043,25 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
@@ -1898,10 +2074,10 @@ if test -z "$CC"; then
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
@@ -1911,25 +2087,25 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
@@ -1941,12 +2117,8 @@ done
   else
     case $cross_compiling:$ac_tool_warned in
 yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
 ac_tool_warned=yes ;;
 esac
     CC=$ac_ct_CC
@@ -1956,51 +2128,37 @@ fi
 fi
 
 
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
 
 # Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler --version >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -v >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -V >&5") 2>&5
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
   ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
 
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -2012,42 +2170,38 @@ main ()
 }
 _ACEOF
 ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.exe b.out"
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
 # Try to create an executable without -o first, disregard a.out.
 # It will help us diagnose broken compilers, and finding out an intuition
 # of exeext.
-{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
-ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-#
-# List of possible output files, starting from the most likely.
-# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
-# only as a last resort.  b.out is created by i960 compilers.
-ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
-#
-# The IRIX 6 linker writes into existing files which may not be
-# executable, retaining their permissions.  Remove them first so a
-# subsequent execution test works.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
 ac_rmfiles=
 for ac_file in $ac_files
 do
   case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
     * ) ac_rmfiles="$ac_rmfiles $ac_file";;
   esac
 done
 rm -f $ac_rmfiles
 
-if { (ac_try="$ac_link_default"
+if { { ac_try="$ac_link_default"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
   (eval "$ac_link_default") 2>&5
   ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
   # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
 # So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
 # in a Makefile.  We should not override ac_cv_exeext if it was cached,
@@ -2057,14 +2211,14 @@ for ac_file in $ac_files ''
 do
   test -f "$ac_file" || continue
   case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
 	;;
     [ab].out )
 	# We found the default executable, but exeext='' is most
 	# certainly right.
 	break;;
     *.* )
-        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
 	then :; else
 	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
 	fi
@@ -2083,78 +2237,41 @@ test "$ac_cv_exeext" = no && ac_cv_exeext=
 else
   ac_file=''
 fi
-
-{ echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6; }
-if test -z "$ac_file"; then
-  echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-fi
-
-ac_exeext=$ac_cv_exeext
-
-# Check that the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
-  if { ac_try='./$ac_file'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-    cross_compiling=no
-  else
-    if test "$cross_compiling" = maybe; then
-	cross_compiling=yes
-    else
-	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-    fi
-  fi
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
 fi
-{ echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
 
-rm -f a.out a.exe conftest$ac_cv_exeext b.out
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
 ac_clean_files=$ac_clean_files_save
-# Check that the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
-{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6; }
-
-{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
-if { (ac_try="$ac_link"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
   (eval "$ac_link") 2>&5
   ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
   # If both `conftest.exe' and `conftest' are `present' (well, observable)
 # catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
 # work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -2162,37 +2279,90 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
 for ac_file in conftest.exe conftest conftest.*; do
   test -f "$ac_file" || continue
   case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
     *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
 	  break;;
     * ) break;;
   esac
 done
 else
-  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
 fi
-
-rm -f conftest$ac_cv_exeext
-{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6; }
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
 
 rm -f conftest.$ac_ext
 EXEEXT=$ac_cv_exeext
 ac_exeext=$EXEEXT
-{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
-if test "${ac_cv_objext+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
 _ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -2204,51 +2374,46 @@ main ()
 }
 _ACEOF
 rm -f conftest.o conftest.obj
-if { (ac_try="$ac_compile"
+if { { ac_try="$ac_compile"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
   (eval "$ac_compile") 2>&5
   ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
   for ac_file in conftest.o conftest.obj conftest.*; do
   test -f "$ac_file" || continue;
   case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
     *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
        break;;
   esac
 done
 else
-  echo "$as_me: failed program was:" >&5
+  $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
 fi
-
 rm -f conftest.$ac_cv_objext conftest.$ac_ext
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
 OBJEXT=$ac_cv_objext
 ac_objext=$OBJEXT
-{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -2262,54 +2427,34 @@ main ()
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
   ac_compiler_gnu=yes
 else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_compiler_gnu=no
+  ac_compiler_gnu=no
 fi
-
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 ac_cv_c_compiler_gnu=$ac_compiler_gnu
 
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
-GCC=`test $ac_compiler_gnu = yes && echo yes`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
 ac_test_CFLAGS=${CFLAGS+set}
 ac_save_CFLAGS=$CFLAGS
-{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   ac_save_c_werror_flag=$ac_c_werror_flag
    ac_c_werror_flag=yes
    ac_cv_prog_cc_g=no
    CFLAGS="-g"
-   cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -2320,34 +2465,11 @@ main ()
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
   ac_cv_prog_cc_g=yes
 else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	CFLAGS=""
-      cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -2358,35 +2480,12 @@ main ()
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_compile "$LINENO"; then :
 
-	ac_c_werror_flag=$ac_save_c_werror_flag
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
 	 CFLAGS="-g"
-	 cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -2397,42 +2496,18 @@ main ()
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
   ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
 fi
-
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    ac_c_werror_flag=$ac_save_c_werror_flag
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
 if test "$ac_test_CFLAGS" = set; then
   CFLAGS=$ac_save_CFLAGS
 elif test $ac_cv_prog_cc_g = yes; then
@@ -2448,23 +2523,18 @@ else
     CFLAGS=
   fi
 fi
-{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
-echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   ac_cv_prog_cc_c89=no
 ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -2516,31 +2586,9 @@ for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
 	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
 do
   CC="$ac_save_CC $ac_arg"
-  rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
+  if ac_fn_c_try_compile "$LINENO"; then :
   ac_cv_prog_cc_c89=$ac_arg
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
 fi
-
 rm -f core conftest.err conftest.$ac_objext
   test "x$ac_cv_prog_cc_c89" != "xno" && break
 done
@@ -2551,17 +2599,19 @@ fi
 # AC_CACHE_VAL
 case "x$ac_cv_prog_cc_c89" in
   x)
-    { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
   xno)
-    { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
   *)
     CC="$CC $ac_cv_prog_cc_c89"
-    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
 esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
 
+fi
 
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -2574,15 +2624,15 @@ ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
 fi
 if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
       # Double quotes because CPP needs to be expanded
     for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
@@ -2596,11 +2646,7 @@ do
   # <limits.h> exists even on freestanding compilers.
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp. "Syntax error" is here to catch this case.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #ifdef __STDC__
 # include <limits.h>
@@ -2609,76 +2655,34 @@ cat >>conftest.$ac_ext <<_ACEOF
 #endif
 		     Syntax error
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_cpp "$LINENO"; then :
 
+else
   # Broken: fails on valid input.
 continue
 fi
-
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
 
   # OK, works on sane cases.  Now check whether nonexistent headers
   # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <ac_nonexistent.h>
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
+if ac_fn_c_try_cpp "$LINENO"; then :
   # Broken: success on invalid input.
 continue
 else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
   # Passes both tests.
 ac_preproc_ok=:
 break
 fi
-
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
 
 done
 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
   break
 fi
 
@@ -2690,8 +2694,8 @@ fi
 else
   ac_cv_prog_CPP=$CPP
 fi
-{ echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
 ac_preproc_ok=false
 for ac_c_preproc_warn_flag in '' yes
 do
@@ -2701,11 +2705,7 @@ do
   # <limits.h> exists even on freestanding compilers.
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp. "Syntax error" is here to catch this case.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #ifdef __STDC__
 # include <limits.h>
@@ -2714,83 +2714,40 @@ cat >>conftest.$ac_ext <<_ACEOF
 #endif
 		     Syntax error
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_cpp "$LINENO"; then :
 
+else
   # Broken: fails on valid input.
 continue
 fi
-
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
 
   # OK, works on sane cases.  Now check whether nonexistent headers
   # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <ac_nonexistent.h>
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       }; then
+if ac_fn_c_try_cpp "$LINENO"; then :
   # Broken: success on invalid input.
 continue
 else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
   # Passes both tests.
 ac_preproc_ok=:
 break
 fi
-
-rm -f conftest.err conftest.$ac_ext
+rm -f conftest.err conftest.i conftest.$ac_ext
 
 done
 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  :
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
 else
-  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 
 ac_ext=c
@@ -2807,10 +2764,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
 set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -2820,25 +2777,25 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
@@ -2847,10 +2804,10 @@ if test -z "$ac_cv_prog_CC"; then
   ac_ct_CC=$CC
   # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
@@ -2860,25 +2817,25 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
   if test "x$ac_ct_CC" = x; then
@@ -2886,12 +2843,8 @@ fi
   else
     case $cross_compiling:$ac_tool_warned in
 yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
 ac_tool_warned=yes ;;
 esac
     CC=$ac_ct_CC
@@ -2904,10 +2857,10 @@ if test -z "$CC"; then
           if test -n "$ac_tool_prefix"; then
     # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
 set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -2917,25 +2870,25 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
@@ -2944,10 +2897,10 @@ fi
 if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -2958,18 +2911,18 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
      fi
     ac_cv_prog_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 if test $ac_prog_rejected = yes; then
@@ -2988,11 +2941,11 @@ fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
@@ -3003,10 +2956,10 @@ if test -z "$CC"; then
   do
     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
   ac_cv_prog_CC="$CC" # Let the user override the test.
@@ -3016,25 +2969,25 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  { echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
@@ -3047,10 +3000,10 @@ if test -z "$CC"; then
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
@@ -3060,25 +3013,25 @@ for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
-done
+  done
 IFS=$as_save_IFS
 
 fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
@@ -3090,12 +3043,8 @@ done
   else
     case $cross_compiling:$ac_tool_warned in
 yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf at gnu.org." >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
 ac_tool_warned=yes ;;
 esac
     CC=$ac_ct_CC
@@ -3105,56 +3054,42 @@ fi
 fi
 
 
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
 
 # Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler --version >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -v >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -V >&5") 2>&5
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
   ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
 
-{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -3168,54 +3103,34 @@ main ()
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
   ac_compiler_gnu=yes
 else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_compiler_gnu=no
+  ac_compiler_gnu=no
 fi
-
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 ac_cv_c_compiler_gnu=$ac_compiler_gnu
 
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
-GCC=`test $ac_compiler_gnu = yes && echo yes`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
 ac_test_CFLAGS=${CFLAGS+set}
 ac_save_CFLAGS=$CFLAGS
-{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   ac_save_c_werror_flag=$ac_c_werror_flag
    ac_c_werror_flag=yes
    ac_cv_prog_cc_g=no
    CFLAGS="-g"
-   cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -3226,34 +3141,11 @@ main ()
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
   ac_cv_prog_cc_g=yes
 else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	CFLAGS=""
-      cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -3264,35 +3156,12 @@ main ()
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+if ac_fn_c_try_compile "$LINENO"; then :
 
-	ac_c_werror_flag=$ac_save_c_werror_flag
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
 	 CFLAGS="-g"
-	 cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -3303,42 +3172,18 @@ main ()
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
+if ac_fn_c_try_compile "$LINENO"; then :
   ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
 fi
-
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    ac_c_werror_flag=$ac_save_c_werror_flag
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
 if test "$ac_test_CFLAGS" = set; then
   CFLAGS=$ac_save_CFLAGS
 elif test $ac_cv_prog_cc_g = yes; then
@@ -3354,23 +3199,18 @@ else
     CFLAGS=
   fi
 fi
-{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
-echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   ac_cv_prog_cc_c89=no
 ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -3418,35 +3258,13 @@ return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
   return 0;
 }
 _ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
-	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
-  CC="$ac_save_CC $ac_arg"
-  rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
   ac_cv_prog_cc_c89=$ac_arg
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
 fi
-
 rm -f core conftest.err conftest.$ac_objext
   test "x$ac_cv_prog_cc_c89" != "xno" && break
 done
@@ -3457,17 +3275,19 @@ fi
 # AC_CACHE_VAL
 case "x$ac_cv_prog_cc_c89" in
   x)
-    { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
   xno)
-    { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
   *)
     CC="$CC $ac_cv_prog_cc_c89"
-    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
 esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
 
+fi
 
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -3489,7 +3309,7 @@ test -n "${PKG_CPPFLAGS}" -a -n "${PKG_LIBS}" && FOUND_ALL="yes"
 #
 
 # Check whether --with-sqlite-dir was given.
-if test "${with_sqlite_dir+set}" = set; then
+if test "${with_sqlite_dir+set}" = set; then :
   withval=$with_sqlite_dir; SQLITE_DIR="${with_sqlite_dir}"
 else
   SQLITE_DIR=""
@@ -3497,7 +3317,7 @@ fi
 
 
 # Check whether --with-sqlite-lib was given.
-if test "${with_sqlite_lib+set}" = set; then
+if test "${with_sqlite_lib+set}" = set; then :
   withval=$with_sqlite_lib; SQLITE_LIB="${with_sqlite_lib}"
 else
   SQLITE_LIB=""
@@ -3505,7 +3325,7 @@ fi
 
 
 # Check whether --with-sqlite-inc was given.
-if test "${with_sqlite_inc+set}" = set; then
+if test "${with_sqlite_inc+set}" = set; then :
   withval=$with_sqlite_inc; SQLITE_INC="${with_sqlite_inc}"
 else
   SQLITE_INC=""
@@ -3521,25 +3341,19 @@ fi
 if test "${FOUND_ALL}" = "no"; then
     if test -n "${SQLITE_DIR}" ; then
        test ! -d "${SQLITE_DIR}" && \
-                  { { echo "$as_me:$LINENO: error: dir ${SQLITE_DIR} does not exist" >&5
-echo "$as_me: error: dir ${SQLITE_DIR} does not exist" >&2;}
-   { (exit 1); exit 1; }; }
+                  as_fn_error $? "dir ${SQLITE_DIR} does not exist" "$LINENO" 5
        test -n "${SQLITE_INC}" && \
-                  { echo "$as_me:$LINENO: WARNING: Using sqlite-dir and ignoring sqlite-inc" >&5
-echo "$as_me: WARNING: Using sqlite-dir and ignoring sqlite-inc" >&2;}
+                  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Using sqlite-dir and ignoring sqlite-inc" >&5
+$as_echo "$as_me: WARNING: Using sqlite-dir and ignoring sqlite-inc" >&2;}
        test -n "${SQLITE_LIB}" && \
-                  { echo "$as_me:$LINENO: WARNING: Using sqlite-dir and ignoring sqlite-lib" >&5
-echo "$as_me: WARNING: Using sqlite-dir and ignoring sqlite-lib" >&2;}
+                  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Using sqlite-dir and ignoring sqlite-lib" >&5
+$as_echo "$as_me: WARNING: Using sqlite-dir and ignoring sqlite-lib" >&2;}
        SQLITE_INC="${SQLITE_DIR}/include"
        SQLITE_LIB="${SQLITE_DIR}/lib"
        test ! -d "${SQLITE_INC}" && \
-                  { { echo "$as_me:$LINENO: error: dir ${SQLITE_INC} does not exist" >&5
-echo "$as_me: error: dir ${SQLITE_INC} does not exist" >&2;}
-   { (exit 1); exit 1; }; }
+                  as_fn_error $? "dir ${SQLITE_INC} does not exist" "$LINENO" 5
        test ! -d "${SQLITE_LIB}" && \
-                  { { echo "$as_me:$LINENO: error: dir ${SQLITE_LIB} does not exist" >&5
-echo "$as_me: error: dir ${SQLITE_LIB} does not exist" >&2;}
-   { (exit 1); exit 1; }; }
+                  as_fn_error $? "dir ${SQLITE_LIB} does not exist" "$LINENO" 5
        PKG_LIBS="-L${SQLITE_LIB} -lsqlite3"
        PKG_CPPFLAGS="-I${SQLITE_INC}"
        FOUND_ALL="yes"
@@ -3547,18 +3361,12 @@ echo "$as_me: error: dir ${SQLITE_LIB} does not exist" >&2;}
        if test -n "${SQLITE_INC}" || test -n "${SQLITE_LIB}"; then
           ## must have both
           test -n "${SQLITE_INC}" && test -n "${SQLITE_LIB}" || \
-               { { echo "$as_me:$LINENO: error: must specify sqlite-inc and sqlite-lib" >&5
-echo "$as_me: error: must specify sqlite-inc and sqlite-lib" >&2;}
-   { (exit 1); exit 1; }; }
+               as_fn_error $? "must specify sqlite-inc and sqlite-lib" "$LINENO" 5
           ## must be dirs
           test ! -d "${SQLITE_INC}" && \
-               { { echo "$as_me:$LINENO: error: sqlite-inc dir ${SQLITE_INC} does not exist" >&5
-echo "$as_me: error: sqlite-inc dir ${SQLITE_INC} does not exist" >&2;}
-   { (exit 1); exit 1; }; }
+               as_fn_error $? "sqlite-inc dir ${SQLITE_INC} does not exist" "$LINENO" 5
           test ! -d "${SQLITE_LIB}" && \
-               { { echo "$as_me:$LINENO: error: sqlite-lib dir ${SQLITE_LIB} does not exist" >&5
-echo "$as_me: error: sqlite-lib dir ${SQLITE_LIB} does not exist" >&2;}
-   { (exit 1); exit 1; }; }
+               as_fn_error $? "sqlite-lib dir ${SQLITE_LIB} does not exist" "$LINENO" 5
           PKG_LIBS="-L${SQLITE_LIB} -lsqlite3"
           PKG_CPPFLAGS="-I${SQLITE_INC}"
           FOUND_ALL="yes"
@@ -3579,17 +3387,13 @@ if test "${FOUND_ALL}" = "no" ; then
    PKG_CPPFLAGS="-DRSQLITE_USE_BUNDLED_SQLITE $SQLITE_OPTS"
    PKG_LIBS=""
 
-{ echo "$as_me:$LINENO: checking for library containing fdatasync" >&5
-echo $ECHO_N "checking for library containing fdatasync... $ECHO_C" >&6; }
-if test "${ac_cv_search_fdatasync+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fdatasync" >&5
+$as_echo_n "checking for library containing fdatasync... " >&6; }
+if ${ac_cv_search_fdatasync+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
   ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 /* Override any GCC internal prototype to avoid an error.
@@ -3614,50 +3418,27 @@ for ac_lib in '' rt; do
     ac_res=-l$ac_lib
     LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
   fi
-  rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
+  if ac_fn_c_try_link "$LINENO"; then :
   ac_cv_search_fdatasync=$ac_res
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext
-  if test "${ac_cv_search_fdatasync+set}" = set; then
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_fdatasync+:} false; then :
   break
 fi
 done
-if test "${ac_cv_search_fdatasync+set}" = set; then
-  :
+if ${ac_cv_search_fdatasync+:} false; then :
+
 else
   ac_cv_search_fdatasync=no
 fi
 rm conftest.$ac_ext
 LIBS=$ac_func_search_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_fdatasync" >&5
-echo "${ECHO_T}$ac_cv_search_fdatasync" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fdatasync" >&5
+$as_echo "$ac_cv_search_fdatasync" >&6; }
 ac_res=$ac_cv_search_fdatasync
-if test "$ac_res" != no; then
+if test "$ac_res" != no; then :
   test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
 
 fi
@@ -3698,12 +3479,13 @@ _ACEOF
     case $ac_val in #(
     *${as_nl}*)
       case $ac_var in #(
-      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
-echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
       esac
       case $ac_var in #(
       _ | IFS | as_nl) ;; #(
-      *) $as_unset $ac_var ;;
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
       esac ;;
     esac
   done
@@ -3711,8 +3493,8 @@ echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
   (set) 2>&1 |
     case $as_nl`(ac_space=' '; set) 2>&1` in #(
     *${as_nl}ac_space=\ *)
-      # `set' does not quote correctly, so add quotes (double-quote
-      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
       sed -n \
 	"s/'/'\\\\''/g;
 	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
@@ -3734,13 +3516,24 @@ echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
      :end' >>confcache
 if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
   if test -w "$cache_file"; then
-    test "x$cache_file" != "x/dev/null" &&
-      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
-echo "$as_me: updating cache $cache_file" >&6;}
-    cat confcache >$cache_file
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
   else
-    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
-echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
   fi
 fi
 rm -f confcache
@@ -3757,6 +3550,12 @@ test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
 # take arguments), then branch to the quote section.  Otherwise,
 # look for a macro that doesn't take arguments.
 ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
 t clear
 :clear
 s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
@@ -3783,14 +3582,15 @@ DEFS=`sed -n "$ac_script" confdefs.h`
 
 ac_libobjs=
 ac_ltlibobjs=
+U=
 for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
   # 1. Remove the extension, and $U if already installed.
   ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
-  ac_i=`echo "$ac_i" | sed "$ac_script"`
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
   # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
   #    will be set to the directory where LIBOBJS objects are built.
-  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
-  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
 done
 LIBOBJS=$ac_libobjs
 
@@ -3798,12 +3598,14 @@ LTLIBOBJS=$ac_ltlibobjs
 
 
 
-: ${CONFIG_STATUS=./config.status}
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
 ac_clean_files_save=$ac_clean_files
 ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
-echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
 #! $SHELL
 # Generated by $as_me.
 # Run this file to recreate the current configuration.
@@ -3813,59 +3615,79 @@ cat >$CONFIG_STATUS <<_ACEOF
 debug=false
 ac_cs_recheck=false
 ac_cs_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_ACEOF
 
-cat >>$CONFIG_STATUS <<\_ACEOF
-## --------------------- ##
-## M4sh Initialization.  ##
-## --------------------- ##
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
 
 # Be more Bourne compatible
 DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
   emulate sh
   NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
   # is contrary to our usage.  Disable this feature.
   alias -g '${1+"$@"}'='"$@"'
   setopt NO_GLOB_SUBST
 else
-  case `(set -o) 2>/dev/null` in
-  *posix*) set -o posix ;;
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
 esac
-
 fi
 
 
-
-
-# PATH needs CR
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
   else
-    PATH_SEPARATOR=:
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
   fi
-  rm -f conf$$.sh
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
 fi
 
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
 fi
 
 
@@ -3874,20 +3696,19 @@ fi
 # there to prevent editors from complaining about space-tab.
 # (If _AS_PATH_WALK were called with IFS unset, it would disable word
 # splitting by setting IFS to empty value.)
-as_nl='
-'
 IFS=" ""	$as_nl"
 
 # Find who we are.  Look in the path if we contain no directory separator.
-case $0 in
+as_myself=
+case $0 in #((
   *[\\/]* ) as_myself=$0 ;;
   *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
 IFS=$as_save_IFS
 
      ;;
@@ -3898,32 +3719,111 @@ if test "x$as_myself" = x; then
   as_myself=$0
 fi
 if test ! -f "$as_myself"; then
-  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
-  { (exit 1); exit 1; }
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
 fi
 
-# Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
 done
 PS1='$ '
 PS2='> '
 PS4='+ '
 
 # NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
   fi
-done
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
 
-# Required to use basename.
 if expr a : '\(a\)' >/dev/null 2>&1 &&
    test "X`expr 00001 : '.*\(...\)'`" = X001; then
   as_expr=expr
@@ -3937,13 +3837,17 @@ else
   as_basename=false
 fi
 
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
 
-# Name of the executable.
 as_me=`$as_basename -- "$0" ||
 $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
 	 X"$0" : 'X\(//\)$' \| \
 	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X/"$0" |
+$as_echo X/"$0" |
     sed '/^.*\/\([^/][^/]*\)\/*$/{
 	    s//\1/
 	    q
@@ -3958,131 +3862,118 @@ echo X/"$0" |
 	  }
 	  s/.*/./; q'`
 
-# CDPATH.
-$as_unset CDPATH
-
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line after each line using $LINENO; the second 'sed'
-  # does the real work.  The second script uses 'N' to pair each
-  # line-number line with the line containing $LINENO, and appends
-  # trailing '-' during substitution so that $LINENO is not a special
-  # case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # scripts with optimization help from Paolo Bonzini.  Blame Lee
-  # E. McMahon (1931-1989) for sed's syntax.  :-)
-  sed -n '
-    p
-    /[$]LINENO/=
-  ' <$as_myself |
-    sed '
-      s/[$]LINENO.*/&-/
-      t lineno
-      b
-      :lineno
-      N
-      :loop
-      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
-      t loop
-      s/-\n.*//
-    ' >$as_me.lineno &&
-  chmod +x "$as_me.lineno" ||
-    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
-   { (exit 1); exit 1; }; }
-
-  # Don't try to exec as it changes $[0], causing all sort of problems
-  # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensitive to this).
-  . "./$as_me.lineno"
-  # Exit status is that of the last command.
-  exit
-}
-
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
-  as_dirname=dirname
-else
-  as_dirname=false
-fi
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
 
 ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
+case `echo -n x` in #(((((
 -n*)
-  case `echo 'x\c'` in
+  case `echo 'xy\c'` in
   *c*) ECHO_T='	';;	# ECHO_T is single tab character.
-  *)   ECHO_C='\c';;
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
   esac;;
 *)
   ECHO_N='-n';;
 esac
 
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
 rm -f conf$$ conf$$.exe conf$$.file
 if test -d conf$$.dir; then
   rm -f conf$$.dir/conf$$.file
 else
   rm -f conf$$.dir
-  mkdir conf$$.dir
-fi
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s='ln -s'
-  # ... but there are two gotchas:
-  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
-  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-  # In both cases, we have to default to `cp -p'.
-  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-    as_ln_s='cp -p'
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
 
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
 if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
+  as_mkdir_p='mkdir -p "$as_dir"'
 else
   test -d ./-p && rmdir ./-p
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-        test -d "$1/.";
-      else
-	case $1 in
-        -*)set "./$1";;
-	esac;
-	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
-	???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -4092,13 +3983,19 @@ as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
 
 exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
 
-# Save the log message, to keep $[0] and so on meaningful, and to
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
 This file was extended by $as_me, which was
-generated by GNU Autoconf 2.61.  Invocation command line was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -4111,59 +4008,74 @@ on `(hostname || uname -n) 2>/dev/null | sed 1q`
 
 _ACEOF
 
-cat >>$CONFIG_STATUS <<_ACEOF
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 # Files that config.status was made for.
 config_files="$ac_config_files"
 
 _ACEOF
 
-cat >>$CONFIG_STATUS <<\_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
 
-Usage: $0 [OPTIONS] [FILE]...
+Usage: $0 [OPTION]... [TAG]...
 
   -h, --help       print this help, then exit
   -V, --version    print version number and configuration settings, then exit
-  -q, --quiet      do not print progress messages
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
   -d, --debug      don't remove temporary files
       --recheck    update $as_me by reconfiguring in the same conditions
-  --file=FILE[:TEMPLATE]
-		   instantiate the configuration file FILE
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
 
 Configuration files:
 $config_files
 
-Report bugs to <bug-autoconf at gnu.org>."
+Report bugs to the package provider."
 
 _ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
 config.status
-configured by $0, generated by GNU Autoconf 2.61,
-  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2006 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
 ac_pwd='$ac_pwd'
 srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
 _ACEOF
 
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If no file are specified by the user, then we need to provide default
-# value.  By we need to know if files were specified by the user.
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
 ac_need_defaults=:
 while test $# != 0
 do
   case $1 in
-  --*=*)
+  --*=?*)
     ac_option=`expr "X$1" : 'X\([^=]*\)='`
     ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
     ac_shift=:
     ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
   *)
     ac_option=$1
     ac_optarg=$2
@@ -4176,25 +4088,30 @@ do
   -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
     ac_cs_recheck=: ;;
   --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
-    echo "$ac_cs_version"; exit ;;
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
   --debug | --debu | --deb | --de | --d | -d )
     debug=: ;;
   --file | --fil | --fi | --f )
     $ac_shift
-    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
     ac_need_defaults=false;;
   --he | --h |  --help | --hel | -h )
-    echo "$ac_cs_usage"; exit ;;
+    $as_echo "$ac_cs_usage"; exit ;;
   -q | -quiet | --quiet | --quie | --qui | --qu | --q \
   | -silent | --silent | --silen | --sile | --sil | --si | --s)
     ac_cs_silent=: ;;
 
   # This is an error.
-  -*) { echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2
-   { (exit 1); exit 1; }; } ;;
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
 
-  *) ac_config_targets="$ac_config_targets $1"
+  *) as_fn_append ac_config_targets " $1"
      ac_need_defaults=false ;;
 
   esac
@@ -4209,30 +4126,32 @@ if $ac_cs_silent; then
 fi
 
 _ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 if \$ac_cs_recheck; then
-  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
-  CONFIG_SHELL=$SHELL
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
   export CONFIG_SHELL
-  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  exec "\$@"
 fi
 
 _ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 exec 5>>config.log
 {
   echo
   sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
 ## Running $as_me. ##
 _ASBOX
-  echo "$ac_log"
+  $as_echo "$ac_log"
 } >&5
 
 _ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 _ACEOF
 
-cat >>$CONFIG_STATUS <<\_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 
 # Handling of arguments.
 for ac_config_target in $ac_config_targets
@@ -4240,9 +4159,7 @@ do
   case $ac_config_target in
     "src/Makevars") CONFIG_FILES="$CONFIG_FILES src/Makevars" ;;
 
-  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
-   { (exit 1); exit 1; }; };;
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
 done
 
@@ -4263,160 +4180,194 @@ fi
 # after its creation but before its name has been assigned to `$tmp'.
 $debug ||
 {
-  tmp=
+  tmp= ac_tmp=
   trap 'exit_status=$?
-  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
 ' 0
-  trap '{ (exit 1); exit 1; }' 1 2 13 15
+  trap 'as_fn_exit 1' 1 2 13 15
 }
 # Create a (secure) tmp directory for tmp files.
 
 {
   tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
-  test -n "$tmp" && test -d "$tmp"
+  test -d "$tmp"
 }  ||
 {
   tmp=./conf$$-$RANDOM
   (umask 077 && mkdir "$tmp")
-} ||
-{
-   echo "$me: cannot create a temporary directory in ." >&2
-   { (exit 1); exit 1; }
-}
-
-#
-# Set up the sed scripts for CONFIG_FILES section.
-#
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
 
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
 if test -n "$CONFIG_FILES"; then
 
-_ACEOF
 
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
 
 
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
 ac_delim='%!_!# '
 for ac_last_try in false false false false false :; do
-  cat >conf$$subs.sed <<_ACEOF
-SHELL!$SHELL$ac_delim
-PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
-PACKAGE_NAME!$PACKAGE_NAME$ac_delim
-PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
-PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
-PACKAGE_STRING!$PACKAGE_STRING$ac_delim
-PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
-exec_prefix!$exec_prefix$ac_delim
-prefix!$prefix$ac_delim
-program_transform_name!$program_transform_name$ac_delim
-bindir!$bindir$ac_delim
-sbindir!$sbindir$ac_delim
-libexecdir!$libexecdir$ac_delim
-datarootdir!$datarootdir$ac_delim
-datadir!$datadir$ac_delim
-sysconfdir!$sysconfdir$ac_delim
-sharedstatedir!$sharedstatedir$ac_delim
-localstatedir!$localstatedir$ac_delim
-includedir!$includedir$ac_delim
-oldincludedir!$oldincludedir$ac_delim
-docdir!$docdir$ac_delim
-infodir!$infodir$ac_delim
-htmldir!$htmldir$ac_delim
-dvidir!$dvidir$ac_delim
-pdfdir!$pdfdir$ac_delim
-psdir!$psdir$ac_delim
-libdir!$libdir$ac_delim
-localedir!$localedir$ac_delim
-mandir!$mandir$ac_delim
-DEFS!$DEFS$ac_delim
-ECHO_C!$ECHO_C$ac_delim
-ECHO_N!$ECHO_N$ac_delim
-ECHO_T!$ECHO_T$ac_delim
-LIBS!$LIBS$ac_delim
-build_alias!$build_alias$ac_delim
-host_alias!$host_alias$ac_delim
-target_alias!$target_alias$ac_delim
-CC!$CC$ac_delim
-CFLAGS!$CFLAGS$ac_delim
-LDFLAGS!$LDFLAGS$ac_delim
-CPPFLAGS!$CPPFLAGS$ac_delim
-ac_ct_CC!$ac_ct_CC$ac_delim
-EXEEXT!$EXEEXT$ac_delim
-OBJEXT!$OBJEXT$ac_delim
-CPP!$CPP$ac_delim
-PKG_CPPFLAGS!$PKG_CPPFLAGS$ac_delim
-PKG_LIBS!$PKG_LIBS$ac_delim
-LIBOBJS!$LIBOBJS$ac_delim
-LTLIBOBJS!$LTLIBOBJS$ac_delim
-_ACEOF
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 49; then
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
     break
   elif $ac_last_try; then
-    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
-   { (exit 1); exit 1; }; }
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
   else
     ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
   fi
 done
+rm -f conf$$subs.sh
 
-ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
-if test -n "$ac_eof"; then
-  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
-  ac_eof=`expr $ac_eof + 1`
-fi
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
 
-cat >>$CONFIG_STATUS <<_ACEOF
-cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACAWK
 _ACEOF
-sed '
-s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
-s/^/s,@/; s/!/@,|#_!!_#|/
-:n
-t n
-s/'"$ac_delim"'$/,g/; t
-s/$/\\/; p
-N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
-' >>$CONFIG_STATUS <conf$$subs.sed
-rm -f conf$$subs.sed
-cat >>$CONFIG_STATUS <<_ACEOF
-:end
-s/|#_!!_#|//g
-CEOF$ac_eof
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
 _ACEOF
 
-
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
 # trailing colons and then remove the whole line if VPATH becomes empty
 # (actually we leave an empty line to preserve line numbers).
 if test "x$srcdir" = x.; then
-  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
-s/:*\$(srcdir):*/:/
-s/:*\${srcdir}:*/:/
-s/:*@srcdir@:*/:/
-s/^\([^=]*=[	 ]*\):*/\1/
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
 s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
 s/^[^=]*=[	 ]*$//
 }'
 fi
 
-cat >>$CONFIG_STATUS <<\_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 fi # test -n "$CONFIG_FILES"
 
 
-for ac_tag in  :F $CONFIG_FILES
+eval set X "  :F $CONFIG_FILES      "
+shift
+for ac_tag
 do
   case $ac_tag in
   :[FHLC]) ac_mode=$ac_tag; continue;;
   esac
   case $ac_mode$ac_tag in
   :[FHL]*:*);;
-  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
-echo "$as_me: error: Invalid tag $ac_tag." >&2;}
-   { (exit 1); exit 1; }; };;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
   :[FH]-) ac_tag=-:-;;
   :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
   esac
@@ -4435,7 +4386,7 @@ echo "$as_me: error: Invalid tag $ac_tag." >&2;}
     for ac_f
     do
       case $ac_f in
-      -) ac_f="$tmp/stdin";;
+      -) ac_f="$ac_tmp/stdin";;
       *) # Look for the file first in the build tree, then in the source tree
 	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
 	 # because $ac_f cannot contain `:'.
@@ -4444,26 +4395,34 @@ echo "$as_me: error: Invalid tag $ac_tag." >&2;}
 	   [\\/$]*) false;;
 	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
 	   esac ||
-	   { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
-echo "$as_me: error: cannot find input file: $ac_f" >&2;}
-   { (exit 1); exit 1; }; };;
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
       esac
-      ac_file_inputs="$ac_file_inputs $ac_f"
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
     done
 
     # Let's still pretend it is `configure' which instantiates (i.e., don't
     # use $as_me), people would be surprised to read:
     #    /* config.h.  Generated by config.status.  */
-    configure_input="Generated from "`IFS=:
-	  echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
     if test x"$ac_file" != x-; then
       configure_input="$ac_file.  $configure_input"
-      { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
     fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
 
     case $ac_tag in
-    *:-:* | *:-) cat >"$tmp/stdin";;
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
     esac
     ;;
   esac
@@ -4473,42 +4432,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
 	 X"$ac_file" : 'X\(//\)[^/]' \| \
 	 X"$ac_file" : 'X\(//\)$' \| \
 	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-echo X"$ac_file" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-	    s//\1/
-	    q
-	  }
-	  /^X\(\/\/\)[^/].*/{
-	    s//\1/
-	    q
-	  }
-	  /^X\(\/\/\)$/{
-	    s//\1/
-	    q
-	  }
-	  /^X\(\/\).*/{
-	    s//\1/
-	    q
-	  }
-	  s/.*/./; q'`
-  { as_dir="$ac_dir"
-  case $as_dir in #(
-  -*) as_dir=./$as_dir;;
-  esac
-  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
-    as_dirs=
-    while :; do
-      case $as_dir in #(
-      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
-      *) as_qdir=$as_dir;;
-      esac
-      as_dirs="'$as_qdir' $as_dirs"
-      as_dir=`$as_dirname -- "$as_dir" ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-	 X"$as_dir" : 'X\(//\)[^/]' \| \
-	 X"$as_dir" : 'X\(//\)$' \| \
-	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-echo X"$as_dir" |
+$as_echo X"$ac_file" |
     sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
 	    s//\1/
 	    q
@@ -4526,20 +4450,15 @@ echo X"$as_dir" |
 	    q
 	  }
 	  s/.*/./; q'`
-      test -d "$as_dir" && break
-    done
-    test -z "$as_dirs" || eval "mkdir $as_dirs"
-  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
-echo "$as_me: error: cannot create directory $as_dir" >&2;}
-   { (exit 1); exit 1; }; }; }
+  as_dir="$ac_dir"; as_fn_mkdir_p
   ac_builddir=.
 
 case "$ac_dir" in
 .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
 *)
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
   # A ".." for each directory in $ac_dir_suffix.
-  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
   case $ac_top_builddir_sub in
   "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
   *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -4575,12 +4494,12 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
 
 _ACEOF
 
-cat >>$CONFIG_STATUS <<\_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # If the template does not know about datarootdir, expand it.
 # FIXME: This hack should be removed a few years after 2.60.
 ac_datarootdir_hack=; ac_datarootdir_seen=
-
-case `sed -n '/datarootdir/ {
+ac_sed_dataroot='
+/datarootdir/ {
   p
   q
 }
@@ -4588,36 +4507,37 @@ case `sed -n '/datarootdir/ {
 /@docdir@/p
 /@infodir@/p
 /@localedir@/p
-/@mandir@/p
-' $ac_file_inputs` in
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
 *datarootdir*) ac_datarootdir_seen=yes;;
 *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
-  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
 _ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
   ac_datarootdir_hack='
   s&@datadir@&$datadir&g
   s&@docdir@&$docdir&g
   s&@infodir@&$infodir&g
   s&@localedir@&$localedir&g
   s&@mandir@&$mandir&g
-    s&\\\${datarootdir}&$datarootdir&g' ;;
+  s&\\\${datarootdir}&$datarootdir&g' ;;
 esac
 _ACEOF
 
 # Neutralize VPATH when `$srcdir' = `.'.
 # Shell code in configure.ac might set extrasub.
 # FIXME: do we really want to maintain this feature?
-cat >>$CONFIG_STATUS <<_ACEOF
-  sed "$ac_vpsub
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
 $extrasub
 _ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 :t
 /@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s&@configure_input@&$configure_input&;t t
+s|@configure_input@|$ac_sed_conf_input|;t t
 s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
 s&@srcdir@&$ac_srcdir&;t t
 s&@abs_srcdir@&$ac_abs_srcdir&;t t
 s&@top_srcdir@&$ac_top_srcdir&;t t
@@ -4626,21 +4546,25 @@ s&@builddir@&$ac_builddir&;t t
 s&@abs_builddir@&$ac_abs_builddir&;t t
 s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
 $ac_datarootdir_hack
-" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 
 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
-  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
-  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
-  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined.  Please make sure it is defined." >&5
-echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined.  Please make sure it is defined." >&2;}
-
-  rm -f "$tmp/stdin"
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
   case $ac_file in
-  -) cat "$tmp/out"; rm -f "$tmp/out";;
-  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
-  esac
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
  ;;
 
 
@@ -4650,11 +4574,13 @@ which seems to be undefined.  Please make sure it is defined." >&2;}
 done # for ac_tag
 
 
-{ (exit 0); exit 0; }
+as_fn_exit 0
 _ACEOF
-chmod +x $CONFIG_STATUS
 ac_clean_files=$ac_clean_files_save
 
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
 
 # configure is writing to config.log, and then calls config.status.
 # config.status does its own redirection, appending to config.log.
@@ -4674,7 +4600,11 @@ if test "$no_create" != yes; then
   exec 5>>config.log
   # Use ||, not &&, to avoid exiting from the if with $? = 1, which
   # would make configure fail if this is the last instruction.
-  $ac_cs_success || { (exit 1); exit 1; }
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
 fi
 
 
diff --git a/configure.in b/configure.in
index 5f643de..f0350d3 100644
--- a/configure.in
+++ b/configure.in
@@ -32,7 +32,7 @@ dnl 3. If the user did not specify a SQLite installation, we set a
 dnl    preprocessor define to include the SQLite amalgamation.
 dnl
 
-AC_INIT(src/RS-SQLite.c)
+AC_INIT(src/rsqlite.h)
 
 # As suggested by BDR, I may need to use CFLAGS to compile under 64-bit
 # (I can't test this), but see "Writing R Extensions"
diff --git a/inst/HACKING b/inst/HACKING
deleted file mode 100644
index b80704e..0000000
--- a/inst/HACKING
+++ /dev/null
@@ -1,21 +0,0 @@
-* Updating the included SQLite version
-
-1. Download the sqlite-amalgamatation from
-   http://www.sqlite.org/download.html.  Unzip files to
-   RSQLite/src/sqlite.
-
-2. Change the version in the DESCRIPTION file.
-* Uploading to CRAN
-Here's a curl command example for uploading new versions of packages:
-
-  curl --disable-epsv -T DBI_1.2.3.tar.gz ftp://cran.R-project.org/incoming/
-
-Then send email to: cran at r-project.org
-
-* Running the RUnit unit tests
-
-  cd RSQLite/inst/UnitTests
-  make
-
-If you have already installed the version you want to test, then you
-can run "make test" instead which skips the installation step.
diff --git a/inst/INSTALL b/inst/INSTALL
deleted file mode 100644
index 3b7a896..0000000
--- a/inst/INSTALL
+++ /dev/null
@@ -1,59 +0,0 @@
-
-RSQLite -- Embedding the SQLite engine in R
-
-(The RSQLite package includes a recent copy of the SQLite 
-distribution from http://www.sqlite.org.)
-
-Installation
-------------
-
-There are 3 alternatives for installation:
-
-1. Simple installation:  
-
-      R CMD INSTALL RSQLite-<version>.tar.gz
-
-   the installation automatically detects whether SQLite is 
-   available in any of your system directories;  if it's not 
-   available, it installs the SQLite engine and the R-SQLite 
-   interface under the package directory $R_PACKAGE_DIR/sqlite.
-
-2. If you have SQLite installed in a non-system directory (e.g,
-   in $HOME/sqlite), 
-   
-   a) You can use
-
-      export PKG_LIBS="-L$HOME/sqlite/lib -lsqlite"
-      export PKG_CPPFLAGS="-I$HOME/sqlite/include"
-   
-      R CMD INSTALL RSQLite-<version>.tar.gz
-
-   b) or you can use the --with-sqlite-dir configuration argument
-
-      R CMD INSTALL --configure-args=--with-sqlite-dir=$HOME/sqlite \
-                    RSQLite-<version>.tar.gz
-
-3. If you don't have SQLite but you rather install the version we provide
-   into a directory different than the RSQLite package, for instance,
-   $HOME/app/sqlite, use
-
-      R CMD INSTALL --configure-args=--enable-sqlite=$HOME/app/sqlite \
-                    RSQLite-<version>.tar.gz
-
-Usage
------
-
-Note that if you use an *existing* SQLite library that resides in a 
-non-system directory (e.g., other than /lib, /usr/lib, /usr/local/lib) 
-you may need to include it in our LD_LIBRARY_PATH, prior to invoking R.  
-For instance
-
-    export LD_LIBRARY_PATH=$HOME/sqlite/lib:$LD_LIBRARY_PATH 
-    R
-    > library(help=RSQLite)
-    > library(RSQLite)
-
-(if you use the --enable-sqlite=DIR configuration argument, the SQLite 
-library is statically linked to the RSQLite R package, and you need 
-not worry about setting LD_LIBRARY_PATH.)
-
diff --git a/inst/NEWS b/inst/NEWS
deleted file mode 100644
index 50b33c1..0000000
--- a/inst/NEWS
+++ /dev/null
@@ -1,460 +0,0 @@
-Version 0.11.4
-
-- Upgrade to SQLite 3.7.7
-
-- Fix bug in dbWriteTable preventing use of colClasses argument from
-  being used to control input types.
-
-Version 0.11.3
-
-- Upgrade to SQLite 3.7.16.2
-
-Version 0.11.2
-
-- Upgrade to SQLite 3.7.14
-
-Version 0.11.1
-
-- Prevent RSQLite from crashing R when operations are attempted on
-  expired (closed) connections.
-
-Version 0.11.0
-
-- Enhance type detection in sqliteDataType (dbDataType). The storage
-  mode of a data.frame column is now used as part of the type
-  detection. Prior to this patch, all vectors with class other than
-  numeric or logical were mapped to a TEXT column. This patch uses the
-  output of storage.mode to map to integer and double vectors to
-  INTEGER and REAL columns, respectively.  All other modes are mapped
-  to a TEXT column.
-
-- Detection of BLOBs was narrowed slightly. The code now treats only
-  objects with data.class(obj) == "list" as BLOBs. Previously, is.list
-  was used which could return TRUE for lists of various classes.
-
-- Fix bug in sqliteImportFile (used by dbWriteTable) that prevented a
-  comment character from being specified for the input file.
-
-- Increase compile-time SQLite limits for maximum number of columns in
-  a table to 30000 and maximum number of parameters (?N) in a SELECT
-  to 40000. Use of wide tables is not encouraged. The default values
-  for SQLite are 2000 and 999, respectively. Databases containing
-  tables with more than 2000 columns may not be compatible with
-  versions of SQLite compiled with default settings.
-
-- Upgrade to SQLite 3.7.9.
-
-Version 0.10.0
-
-- Upgrade to SQLite 3.7.8.
-
-Version 0.9-5
-
-- Fix error handling for prepared queries when bind data is missing a
-  named parameter.
-
-Version 0.9-4
-
-- Fix incorrect handling of NA's for character data in the code that
-  binds parameters to a SQL query.  The string "NA" was incorrectly
-  interpretted as a missing value.
-
-Version 0.9-3
-
-- Upgrade SQLite to 3.7.3.  See http://www.sqlite.org/changes.html
-  for release notes for SQLite.
-
-- Enable the sounder(X) function via the SQLITE_SOUNDEX compile time
-  flag.  See http://www.sqlite.org/lang_corefunc.html#soundex for
-  details.
-
-Version 0.9-2
-
-- Fix two missing PROTECTs in RS_SQLite_managerInfo and
-  RS_SQLite_getException, thanks to a patch from Andrew Runnalls
-
-Version 0.9-1
-
-- SQLite header files needed to compile SQLite extension functions are
-  now made available by RSQLite.  Packages can bundle SQLite extension
-  functions and use LinkingTo: RSQLite in the DESCRIPTION file.
-
-- SQLite loadable extensions are now enabled by default for new
-  connections.  If you wish to disallow loadable extensions for a
-  given connection, loadable.extensions=FALSE to dbConnect.
-
-Version 0.9-0
-
-- The SQLite driver handle validation code, is_ValidHandle, no longer
-  requires the driver ID to be equal to the current process ID.
-  SQLite supports multiple processes accessing the same SQLite file
-  via locking (however, results are known to be unreliable on NFS).
-  This change should make using RSQLite with the multicore package
-  easier.  For an example of the issue that the PID check causes see:
-  https://stat.ethz.ch/pipermail/r-sig-hpc/2009-August/000335.html
-
-- Refactor to use external pointers to wrap handle IDs; remove handle
-  ID coerce code (e.g. as(obj at Id, "integer")).  For now, the old
-  scheme of storing handle IDs in an integer vector is mostly
-  maintained only these integer vectors are stored in the protection
-  slot of an external pointer.  Using external pointers will allow the
-  use of finalizer code so that, for example, unreferenced result sets
-  can be cleaned up.
-
-- Upgrade to SQLite 3.6.23.1.
-
-- The memory mangement code for keeping track of database connections
-  was significantly refactored.  Instead of tracking connections in a
-  pre-allocated array attached to the driver manager, connections are
-  now managed dynamically using R's external pointers and finalizers.
-  Consequences of this change are as follows:
-
-    * There is no longer a maximum connection limit (values specified
-      using the max.con argument to SQLite() are now ignored).
-
-    * The dbGetInfo(mgr) method no longer lists open connections and
-      dbListConnections will now always return an empty list.  This
-      functionality was only needed because one needed a reference to
-      a connection in order to finalize the resource via
-      dbDisconnect().  While calling dbDisconnect() is still the
-      recommended approach, database connections that are no longer
-      referenced by any R variables will be finalized by R's garbage
-      collector.
-
-    * The behavior of SQLiteConnection objects now follows typical R
-      semantics.  If no R variables reference a given connection, it
-      will be finalized by R's garbage collector.
-
-- Add support for SQLite BLOBs.  You can now insert and retrieve BLOBs
-  using raw vectors.  For parameterized queries using
-  dbSendPreparedQuery, the BLOB column must be a list.  When a query
-  returns a result set with a BLOB column, that column will be a list
-  of raw vectors.  Lists as columns in data.frames work for simple
-  access, but may break some code that expects columns to be atomic
-  vectors.  A database NULL value is mapped to an R NULL value for
-  BLOBs.  This differs from the mapping of database NULL to NA used
-  for other datatypes (there is no notion of NA for a raw vector).
-
-- The behavior of dbDataType, sqliteDataType, and as a consequence,
-  dbWriteTable has been changed to support BLOBs represented as a
-  column of type list in a data.frame.  Such columns were previously
-  mapped to a TEXT column in SQLite and are not mapped to BLOB.
-
-- RSQLite now depends on R >= 2.10.0.
-
-Version 0.8-4
-
-- Fix a memory leak in bound parameter management and resolve a
-  missing PROTECT bug that caused spurious crashes when performing
-  many prepared queries.
-
-- Improve internal memory handling for prepared queries.  Use
-  R_PreserveObject/R_ReleaseObject instead of the protection stack to
-  manage parameter binding.  Logical vectors are now properly coerced
-  to integer vectors and Rf_asCharacterFactor is used to convert
-  factors in bind data.
-
-- RSQLite now requires DBI >= 0.2-5
-
-- There is now a fairly comprehensive example of using prepared
-  queries in the man page for dbSendQuery-methods.
-
-- Upgrade to SQLite 3.6.21 => 3.6.22 (minor bug fixes).
-
-- Use sqlite3_prepare_v2 throughout, remove workaround code needed for
-  legacy sqlite3_prepare behavior.
-
-- Add name space unload hook to unload RSQLite.so.
-
-- Enable full-text search module by default.  See
-  http://www.sqlite.org/fts3.html for details on this SQLite
-  module.
-
-- Add support for prepared queries that involve a SELECT.  This was
-  previously unsupported.  SELECT queries can now be used with
-  dbSendPreparedQuery.  The return value is the same as rbind'ing the
-  results of the individual queries.  This means that parameters that
-  return no results are ignored in the result.
-
-Version 0.8-3
-
-- Enable RTree module for the Windows build.  The configure script is
-  not run on Windows, options are set directly in src/Makevars.win.
-
-Version 0.8-2
-
-- Changes to support WIN64
-
-Version 0.8-1
-
-- sqliteFetch now returns a data.frame with the expected number of
-  columns when a query returns zero rows.  Before, a 0 x 0 data.frame
-  was returned regardless of the number of columns in the original
-  query.  The change will be seen in calls to fetch and dbGetQuery for
-  queries that return no result rows.
-
-- sqliteCopyDatabase has been refactored to support copying to either
-  a file or an open and empty database connection.  This makes it
-  possible to transfer a disk based database to an in-memory based
-  database.  The changes to sqliteCopyDatabase are NOT BACKWARDS
-  COMPATIBLE: the return value is now NULL (an error is raised if the
-  copying fails) and the argument names have been changed to 'from'
-  and 'to'.  As this was a newly added feature that uses an
-  experimental SQLite API, I decided to disregards compatibility.
-
-- Calling dbSendPreparedQuery with a non-NULL bind.data that has zero
-  rows or zero columns is now an error.
-
-
-Version 0.8-0
-
-- Upgrade to SQLite 3.6.21
-
-- Apply some code and Rd cleanups contributed by Mattias Burger.
-  Avoid partial argument name matching, use TRUE/FALSE not T/F and
-  improve Rd markup.
-
-- Integrate RUnit unit tests so that they run during R CMD check.
-  Small improvements to make the tests run more quietly.  You can run
-  the unit tests by calling RSQLite:::.test_RSQLite() (require latest
-  version of the RUnit package).  Also had to disable some unit tests
-  on Windows.  Investigation of details is on the TODO list.
-
-- Add sqliteCopyDatabase, a function that uses SQLite's online backup
-  API to allow a specified database to be copied to a file.  This can
-  be used to create a file copy of an in memory database.
-
-- Increase the default max connections from 16 to 200 in SQLite().
-  Connections to SQLite are inexpensive and there is no longer any
-  hard-coded limit to the number of connections you can have.
-  However, memory is allocated at driver initialization time based on
-  the maximum, so it is best not to use very large values unless you
-  really need the connections.
-
-- sqliteTransactionStatement, which is used by dbCommit, dbRollback,
-  and dbBeginTransaction, now passes silent=TRUE to try() to suppress
-  error messages.  Without this, code that could otherwise handle a
-  failed commit gracefully had no way to suppress the error message.
-  You can use dbGetException to see the error when
-  sqliteTransactionStatement returns FALSE.
-
-- dbConnect/sqliteNewConnection now throws an error if dbname argument
-  is NA.  Previously, if as.character(NA) was provided, a database
-  with filename "NA" was created.
-
-- dbConnect/sqliteNewConnection now accepts two new arguments:
-
-  flags:
-      provides additional control over connetion details.  For
-      convenience, you can specify one of SQLITE_RWC (default),
-      SQLITE_RW, or SQLITE_RO to obtain a connection in
-      read/write/create, read/write, or read only mode, respectively.
-      See http://sqlite.org/c3ref/open.html for details.
-  vfs:
-      controls the virtual filesystem used by SQLite.  The default,
-      NULL, lets SQLite select the appropriate vfs for the system.
-      You can specify one of "unix-posix", "unix-afp", "unix-flock",
-      "unix-dotfile", or "unix-none".  For details, see
-      http://www.sqlite.org/compile.html.  This functionality is only
-      fully available on OSX.  On non-OSX Unix, you can use
-      unix-dotfile and unix-none.  None of these modules are available
-      on Windows where a non-NULL values of the vfs argument will be
-      ignored with a warning.
-
-
-Version 0.7-3
-
-- Use the default value for SQLITE_MAX_SQL_LENGTH which has now been
-  significantly increased over the value of 2 million that we had set
-  in 2008.
-
-- Fix some Rd cross references in the documentation.
-
-Version 0.7-2
-
-- Fixed some partial argument matching warnings.  Thanks to Matthias
-  Burger for reporting and sending a patch.
-
-- Added dbBuildTableDefinition to exports per user request.
-
-Version 0.7-1
-
-- Upgraded included SQLite from 3.6.0 to 3.6.4
-
-- Old news is now in ONEWS.  Taking a fresh start with this NEWS file
-  to keep better track of changes on a per-release basis.
-
-- Added a HACKING file where we will add notes about how to do
-  development on RSQLite.
-
---------------------
-
-Version 0.4-12
-
-* Fix bug in dbListTables for empty databases
-
-Version 0.4-11
-
-* Implemented dbCommit() and dbRollback(). There is also a new
-  generic method dbBeginTransaction(), which begins a transaction.
-  Note that this is an extension to the DBI interface.
-
-* Update to the SQLite 3 API for fetching records. This means that
-  the records are pulled from the database as required, and not
-  cached in memory as was previously done.
-
-* Added generic methods dbSendPreparedQuery() and dbGetPreparedQuery()
-  which are similiar to dbSendQuery() and dbGetQuery(), but take an
-  extra "bind.data" parameter, which is a data frame. The statement
-  is assumed to contain bind variables. Bind variables are either
-  for a column name (":name" or "@name") or for a column index ("?")
-  in the data frame. See http://sqlite.org/capi3ref.html for more details.
-
-  dbGetPreparedQuery(con, "INSERT INTO table1 VALUES (:col1)",
-                           data.frame(col1=c(1, 2)) )
-
-  Each bind variable in the query has to be bound only once, either via
-  named or positional parameters. If it is not bound or is bound more
-  than once (due to a mix or positional/named parameters) an error is
-  thrown. Any extra columns in the data frame are ignored.
-
-  If you are having a lot of string parameters, use stringsAsFactors=FALSE
-  when creating the bind.data data.frame instance.  You can also use I().
-
-* Added experimental sqliteQuickColumn function that retrieves an entire 
-  column from a specified table as quickly as possible.
-
-* The SQLite driver has a new logical parameter "shared.cache" to
-  enable the shared-cache mode, which allows multiple connections
-  to share a single data and schema cache. See
-  http://www.sqlite.org/sharedcache.html
-
-Version 0.4-9
-
-* Upgraded to SQLite 3.3.8
-
-* Use .SQLitePkgName instead of hard-coding the package name when
-  using .Call
-
-* dbConnect() now has a logical parameter "loadable.extensions"
-  which will allow loading of extensions. See the Loadable
-  Extensions documentation:
-  http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions
-
-Version 0.4-4
-
-* Upgraded to SQLite 3.3.7
-
-* Default when building from source is now to compile the included
-  version of SQLite and link to it statically
-
-* Fixed unclosed textConnections
-
-Version 0.4-1
-
-* Added a method for dbWriteTable to write table from a text file, e.g.,
-  dbWriteTable(con, "tablename", "filename")
-
-* Fixed problems exporting/importing NA's (thanks to Ronngui Huang for
-  a very clear bug report).
-
-* Fixed double free() in the C code, a tiny memory leak, and configure now
-  builds sqlite properly on 64-bit linux (thanks to Seth Falcon for these).
-
-* dbConnect() now accepts values for the "cache_size" and "sychnronous"
-  PRAGMAs ("synchronous" defaults to 0 or "off") to improve
-  performance (thanks to Charles Loboz for pointing these out, see the
-  file "rsqlitePerf.txt").
-
-Version 0.4-0
-
-* First attempt at using the new SQLite Version 3 API.  This version
-  is a bridge to the new API, but it does not make available the new
-  capabilities (e.g., prepared statements, data bindings, etc.) but
-  prepares us for those new features.
-
-* Clean up some installation code (mainly to make it easy to automatically
-  build on Windows, as per Kurt Hornik and Uwe Ligges suggestions).
-
-* Fixed bug that ignored "fetch.default.rec" in SQLite()/dbDriver()
-  (as reported by Duncan Murdoch)
-
-* Fixed bug in dbReadTable() that was not recognizing "row.names" in its
-  default, thus it now re-creates a data.frame that has been exported
-  with dbWriteTable().
-
-* Fixed bug where dbListTables was not listing views (as reported by
-  Doug Bates).
-
-* Added code in "configure.in" to determine CC/CFLAGS used in compiling R
-  (as suggested by Brian D. Ripley to get it to compile on 64-bit machines).
-  As of today, I can't test this myself.
-
-Version 0.3-5
-
-* Documentation typos, trivial packaging changes, as per CRAN maintainer
-  request.
-
-Version 0.3-4
-
-* Fixed documentation typos.
-
-Version 0.3-3
-
-* Minor fixes to accommadate R 1.8.0 changes to data.frame subsetting.
-
-* Updated the documentation to use 1.8.0 new S4-style method documentation.
-
-* Updated to SQLite to the latest 2.8.6 (included with RSQLite).
-
-* Added file NAMESPACE.future to prepare for namespace implementation
-  at some future release.
-
-Version 0.3-2
-
-* Ported to Windows.  It now installs fine under Windows with
-
-    Rcmd INSTALL RSQLite_0.3-2.tar.gz
-
-  (there's also a binary RSQLite_0.3-2.zip)
-
-* Added code to verify that the SQLite library versions used for
-  compilation and at runtime agree.
-
-* Added source sqlite-2.8.3.
-
-* Fixed minor documentation errors and removed the DBI.pdf documentation
-  file, which is included in the required DBI package.
-
-* The package now installs as a binary image by default (use the --no-save
-  argument to R CMD INSTALL to override this).
-
-Version 0.3-1
-
-* Moved the implementation to version 4 style classes, and it now
-  it is fully compliant with the DBI 0.1-3.
-
-* Simplified the core helper R/SQLite functions (w. prefix "sqlite")
-  following the ROracle model.
-
-* Updated to sqlite version 2.7.1 (note that if you have an sqlite
-  database file from a version prior to 2.6 you'll need to update
-  it -- for details see http://www.hwaic.com/sw/sqlite).
-
-Version 0.2-1
-
-* Worked mostly in the configuration;  added the --enable-sqlite and
-  --with-sqlite arguments to have the RSQLite configuration also install
-  SQLite or locate it, respectively.
-
-Version 0.1-1
-
-* First implementation -- used the RS-DBI.[ch] code (which is the core
-  connection/cursor manager) "as is" and modified the RS-MySQL.[hc],
-  (which sits directly on top of the MySQL C API) and replace the
-  MySQL API calls with SQLite API calls.  This was pretty easy, except
-  for the fact that the SQLite API is so minimal (3, yes, 3 C functions)
-  with no support for connections, result set (cursors), data types,
-  meta-data -- nothing.  So I had to simulate all this. (Actually it
-  wasn't too bad).
-
diff --git a/inst/ONEWS b/inst/ONEWS
deleted file mode 100644
index 5273e7b..0000000
--- a/inst/ONEWS
+++ /dev/null
@@ -1,168 +0,0 @@
-Version 0.4-12
-
-* Fix bug in dbListTables for empty databases
-
-Version 0.4-11
-
-* Implemented dbCommit() and dbRollback(). There is also a new
-  generic method dbBeginTransaction(), which begins a transaction.
-  Note that this is an extension to the DBI interface.
-
-* Update to the SQLite 3 API for fetching records. This means that
-  the records are pulled from the database as required, and not
-  cached in memory as was previously done.
-
-* Added generic methods dbSendPreparedQuery() and dbGetPreparedQuery()
-  which are similiar to dbSendQuery() and dbGetQuery(), but take an
-  extra "bind.data" parameter, which is a data frame. The statement
-  is assumed to contain bind variables. Bind variables are either
-  for a column name (":name" or "@name") or for a column index ("?")
-  in the data frame. See http://sqlite.org/capi3ref.html for more details.
-
-  dbGetPreparedQuery(con, "INSERT INTO table1 VALUES (:col1)",
-                           data.frame(col1=c(1, 2)) )
-
-  Each bind variable in the query has to be bound only once, either via
-  named or positional parameters. If it is not bound or is bound more
-  than once (due to a mix or positional/named parameters) an error is
-  thrown. Any extra columns in the data frame are ignored.
-
-  If you are having a lot of string parameters, use stringsAsFactors=FALSE
-  when creating the bind.data data.frame instance.  You can also use I().
-
-* Added experimental sqliteQuickColumn function that retrieves an entire 
-  column from a specified table as quickly as possible.
-
-* The SQLite driver has a new logical parameter "shared.cache" to
-  enable the shared-cache mode, which allows multiple connections
-  to share a single data and schema cache. See
-  http://www.sqlite.org/sharedcache.html
-
-Version 0.4-9
-
-* Upgraded to SQLite 3.3.8
-
-* Use .SQLitePkgName instead of hard-coding the package name when
-  using .Call
-
-* dbConnect() now has a logical parameter "loadable.extensions"
-  which will allow loading of extensions. See the Loadable
-  Extensions documentation:
-  http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions
-
-Version 0.4-4
-
-* Upgraded to SQLite 3.3.7
-
-* Default when building from source is now to compile the included
-  version of SQLite and link to it statically
-
-* Fixed unclosed textConnections
-
-Version 0.4-1
-
-* Added a method for dbWriteTable to write table from a text file, e.g.,
-  dbWriteTable(con, "tablename", "filename")
-
-* Fixed problems exporting/importing NA's (thanks to Ronngui Huang for
-  a very clear bug report).
-
-* Fixed double free() in the C code, a tiny memory leak, and configure now
-  builds sqlite properly on 64-bit linux (thanks to Seth Falcon for these).
-
-* dbConnect() now accepts values for the "cache_size" and "sychnronous"
-  PRAGMAs ("synchronous" defaults to 0 or "off") to improve
-  performance (thanks to Charles Loboz for pointing these out, see the
-  file "rsqlitePerf.txt").
-
-Version 0.4-0
-
-* First attempt at using the new SQLite Version 3 API.  This version
-  is a bridge to the new API, but it does not make available the new
-  capabilities (e.g., prepared statements, data bindings, etc.) but
-  prepares us for those new features.
-
-* Clean up some installation code (mainly to make it easy to automatically
-  build on Windows, as per Kurt Hornik and Uwe Ligges suggestions).
-
-* Fixed bug that ignored "fetch.default.rec" in SQLite()/dbDriver()
-  (as reported by Duncan Murdoch)
-
-* Fixed bug in dbReadTable() that was not recognizing "row.names" in its
-  default, thus it now re-creates a data.frame that has been exported
-  with dbWriteTable().
-
-* Fixed bug where dbListTables was not listing views (as reported by
-  Doug Bates).
-
-* Added code in "configure.in" to determine CC/CFLAGS used in compiling R
-  (as suggested by Brian D. Ripley to get it to compile on 64-bit machines).
-  As of today, I can't test this myself.
-
-Version 0.3-5
-
-* Documentation typos, trivial packaging changes, as per CRAN maintainer
-  request.
-
-Version 0.3-4
-
-* Fixed documentation typos.
-
-Version 0.3-3
-
-* Minor fixes to accommadate R 1.8.0 changes to data.frame subsetting.
-
-* Updated the documentation to use 1.8.0 new S4-style method documentation.
-
-* Updated to SQLite to the latest 2.8.6 (included with RSQLite).
-
-* Added file NAMESPACE.future to prepare for namespace implementation
-  at some future release.
-
-Version 0.3-2
-
-* Ported to Windows.  It now installs fine under Windows with
-
-    Rcmd INSTALL RSQLite_0.3-2.tar.gz
-
-  (there's also a binary RSQLite_0.3-2.zip)
-
-* Added code to verify that the SQLite library versions used for
-  compilation and at runtime agree.
-
-* Added source sqlite-2.8.3.
-
-* Fixed minor documentation errors and removed the DBI.pdf documentation
-  file, which is included in the required DBI package.
-
-* The package now installs as a binary image by default (use the --no-save
-  argument to R CMD INSTALL to override this).
-
-Version 0.3-1
-
-* Moved the implementation to version 4 style classes, and it now
-  it is fully compliant with the DBI 0.1-3.
-
-* Simplified the core helper R/SQLite functions (w. prefix "sqlite")
-  following the ROracle model.
-
-* Updated to sqlite version 2.7.1 (note that if you have an sqlite
-  database file from a version prior to 2.6 you'll need to update
-  it -- for details see http://www.hwaic.com/sw/sqlite).
-
-Version 0.2-1
-
-* Worked mostly in the configuration;  added the --enable-sqlite and
-  --with-sqlite arguments to have the RSQLite configuration also install
-  SQLite or locate it, respectively.
-
-Version 0.1-1
-
-* First implementation -- used the RS-DBI.[ch] code (which is the core
-  connection/cursor manager) "as is" and modified the RS-MySQL.[hc],
-  (which sits directly on top of the MySQL C API) and replace the
-  MySQL API calls with SQLite API calls.  This was pretty easy, except
-  for the fact that the SQLite API is so minimal (3, yes, 3 C functions)
-  with no support for connections, result set (cursors), data types,
-  meta-data -- nothing.  So I had to simulate all this. (Actually it
-  wasn't too bad).
diff --git a/inst/README b/inst/README
deleted file mode 100644
index 8e98e68..0000000
--- a/inst/README
+++ /dev/null
@@ -1,19 +0,0 @@
-RSQLite -- An embedded database engine in R
-
-SQLite (http://www.sqlite.org) is a public-domain,
-single-user, very light-weight database engine that implements
-a decent subset of the SQL 92 standard, including the core
-table creation, updating, insertion, and selection operations,
-plus transaction management.
-
-For those interested, the actual implementation of SQLite
-relies on a simple virtual database machine for dynamically
-translating SQL into executable code, for details see
-www.hwaci.com/sw/sqlite/vdbe.html
-
-RSQLite complies with DBI database interface.
-
-See the file "INSTALL" for details on how to install the package on
-Linux/Unix-like systems.  See INSTALL.windows for instructions on
-how to compile it from source, but notice that there is a Windows
-binary distribution.
diff --git a/inst/THANKS b/inst/THANKS
deleted file mode 100644
index d97da8c..0000000
--- a/inst/THANKS
+++ /dev/null
@@ -1,5 +0,0 @@
-Acknowledgements
-
-Many thanks to Doug Bates, Seth Falcon, Detlef Groth, Ronggui Huang,
-Kurt Hornik, Uwe Ligges, Charles Loboz, Duncan Murdoch, and Brian
-D. Ripley for comments, suggestions, bug reports, and/or patches.
diff --git a/inst/TODO b/inst/TODO
deleted file mode 100644
index 374f519..0000000
--- a/inst/TODO
+++ /dev/null
@@ -1,22 +0,0 @@
-* Need to do a lot more testing.  In particular the actual SQL
-  engine needs vigorous testing -- I've done very simple things
-  with it.
-
-* The actual R SQLite package shares an enormous amount of code
-  with both the RMySQL and ROracle drivers, so that piece should
-  be somewhat stable (he says!).  On the other hand, currently
-  we cannot use both drivers simultaneously (this should be an
-  easy fix).
-
-* Need to add the dbApply(), as in RMySQL.  This is very easy to do
-  here (see RS_SQLite_stdCallback), but shouldn't this be better
-  implemented in the RS-DBI.c to provide this service for all drivers
-  that sit on top of RS-DBI.c?
-
-* It would be nice to hook R as regular SQL functions and aggregations
-  (e.g., select group1, group2, median(x) from FOO group by group1, group2;)
-  Given the modularity in the SQLite C API, this is definitely not hard.
-  How to hook more interesting R function that return objects is not clear
-  at all, though.
-
-* It would be interesting to play with the in-memory db version.
diff --git a/inst/UnitTests/README b/inst/UnitTests/README
deleted file mode 100644
index ed2eade..0000000
--- a/inst/UnitTests/README
+++ /dev/null
@@ -1,22 +0,0 @@
-RSQLite RUnit unit tests
-========================
-
-This directory contains RUnit unit tests for RSQLite.  Test files
-match the glob "*_test.R".
-
-Running the tests
------------------
-
-You can run all tests by checking the package using R CMD check.  This
-will run the unit tests by executing the test script in
-RSQLite/tests/RSQLite_unit_tests.R.  A test failure or error will
-cause check to fail.
-
-You can also run the tests from an R session by calling the
-non-exported function RSQLite:::.test_RSQLite().  You can optionally
-pass a directory argument which should be an absolute path to the unit
-tests.  R's working directory will be set to this directory before
-running the tests so that test code can use relative paths to refer to
-data files.  If not specified, the directory used is the UnitTests
-directory of the installed RSQLite package.
-
diff --git a/inst/UnitTests/basic_type_test.R b/inst/UnitTests/basic_type_test.R
deleted file mode 100644
index c94c1b3..0000000
--- a/inst/UnitTests/basic_type_test.R
+++ /dev/null
@@ -1,148 +0,0 @@
-library("RSQLite")
-
-DATA <- new.env(parent=emptyenv(), hash=TRUE)
-
-.setUp <- function() {
-    DATA$dbfile <- tempfile()
-    DATA$db <- dbConnect(dbDriver("SQLite"), DATA$dbfile)
-}
-
-.tearDown <- function() {
-    lapply(dbListResults(DATA$db), dbClearResult)
-    dbDisconnect(DATA$db)
-    file.remove(DATA$dbfile)
-}
-
-basicDf <- data.frame(name=c("Alice", "Bob", "Carl", "NA", NA),
-                      fldInt=as.integer(c(as.integer(1:4), NA)),
-                      fldDbl=as.double(c(1.1, 2.2, 3.3, 4.4, NA)),
-                      stringsAsFactors=FALSE)
-
-
-testBasicTypeConversion <- function() {
-    db <- DATA$db
-    schema = "create table t1 (name text, fldInt integer, fldDbl float)"
-    dbGetQuery(db, schema)
-    dbBeginTransaction(db)
-    dbGetPreparedQuery(db, "insert into t1 values (?, ?, ?)", bind.data=basicDf)
-    dbCommit(db)
-    expected_types <- c(name="character", fldInt="integer", fldDbl="double")
-    gotdf <- dbGetQuery(db, "select * from t1")
-
-    checkEquals(dim(basicDf), dim(gotdf))
-    checkEquals(expected_types, sapply(gotdf, typeof))
-    expect_na <- c(rep(FALSE, 4), TRUE)
-    for (j in ncol(gotdf)) {
-        checkEquals(expect_na, is.na(gotdf[, j]))
-    }
-}
-
-testNAInFirstRow <- function() {
-    db <- DATA$db
-    basicDf <- data.frame(name=c(NA, "Alice", "Bob", "Cody", NA),
-                          id=as.integer(c(NA, 10:12, NA)),
-                          rate=c(NA, 1:3 * pi, NA), stringsAsFactors=FALSE)
-    basicTableSql <- ('create table t1 (name text, id integer, rate real)')
-    values <- c("(:name, :id, :rate)")
-    dbGetQuery(db, basicTableSql)
-    sql <- paste("insert into t1 values", values)
-    tryCatch({
-        dbBeginTransaction(db)
-        rs <- dbSendPreparedQuery(db, sql, bind.data=basicDf)
-        dbClearResult(rs)
-    }, error=function(e) {
-        dbRollBack(db)
-        signalCondition(e)
-    })
-    dbCommit(db)
-    got <- dbGetQuery(db, "select * from t1")
-    checkEquals(basicDf, got)
-}
-
-testUnitFetch <- function() {
-    db <- DATA$db
-    ## Create table by hand
-    schema = "create table t1 (name text, fldInt integer, fldDbl float)"
-    dbGetQuery(db, schema)
-    dbBeginTransaction(db)
-    dbGetPreparedQuery(db, "insert into t1 values (?, ?, ?)", bind.data=basicDf)
-    dbCommit(db)
-    expected_types <- c(name="character", fldInt="integer", fldDbl="double")
-    rs <- dbSendQuery(db, "select * from t1")
-    on.exit(dbClearResult(rs))
-    for (i in seq_len(nrow(basicDf))) {
-        gotdf <- fetch(rs, n=1)
-        checkEquals(1:1, nrow(gotdf))
-        checkEquals(ncol(basicDf), ncol(gotdf))
-        checkEquals(expected_types, sapply(gotdf, typeof))
-        checkEquals(basicDf[i, ], gotdf)
-    }
-    ## In this case, you can't know there are no more records:
-    checkTrue(!dbHasCompleted(rs))
-    checkEquals(0, nrow(fetch(rs, n=1)))
-    checkTrue(dbHasCompleted(rs))
-}
-
-testFetchByTwo <- function() {
-    db <- DATA$db
-    ## Create table by hand
-    schema = "create table t1 (name text, fldInt integer, fldDbl float)"
-    dbGetQuery(db, schema)
-    dbBeginTransaction(db)
-    dbGetPreparedQuery(db, "insert into t1 values (?, ?, ?)", bind.data=basicDf)
-    dbCommit(db)
-    expected_types <- c(name="character", fldInt="integer", fldDbl="double")
-    rs <- dbSendQuery(db, "select * from t1")
-    on.exit(dbClearResult(rs))
-    N <- nrow(basicDf)
-    if (N %% 2 != 0)
-      N <- N + 1
-    N <- N / 2
-    for (i in seq(1, N)) {
-        gotdf <- fetch(rs, n=2)
-        checkEquals(ncol(basicDf), ncol(gotdf))
-        checkEquals(expected_types, sapply(gotdf, typeof))
-        if (i < 3) {
-            checkEquals(2, nrow(gotdf))
-        }
-    }
-    checkTrue(dbHasCompleted(rs))
-}
-
-
-testWriteTableBasicTypeConversion <- function() {
-    db <- DATA$db
-    dbWriteTable(db, "t1", basicDf, row.names=FALSE)
-
-    expected_types <- c(name="character", fldInt="integer", fldDbl="double")
-    gotdf <- dbGetQuery(db, "select * from t1")
-
-    checkEquals(dim(basicDf), dim(gotdf))
-    checkEquals(expected_types, sapply(gotdf, typeof))
-    checkTrue(all(is.na(gotdf[5, ])))
-}
-
-testFirstResultRowIsNull <- function() {
-    db <- DATA$db
-    data(USArrests)
-    dbWriteTable(db, "t1", USArrests)
-    a1 <- dbGetQuery(db, "select Murder/(Murder - 8.1) from t1 limit 10")
-    checkEquals("double", typeof(a1[[1]]))
-    ## This isn't ideal, but for now, if the first row of a result set
-    ## contains a NULL, then that column is forced to be character.
-    a2 <- dbGetQuery(db,
-                     "select Murder/(Murder - 8.1) from t1 limit 10 offset 2")
-    checkEquals("character", typeof(a2[[1]]))
-}
-
-test_no_rows_preserves_column_count <- function()
-{
-    db <- DATA$db
-    want_dim <- c(1L, 2L)
-    ans <- dbGetQuery(db, "select 1 as a, 2 as b where 1")
-    checkEquals(want_dim, dim(ans))
-
-    want_dim <- c(0L, 2L)
-    ans <- dbGetQuery(db, "select 1 as a, 2 as b where 0")
-    checkEquals(want_dim, dim(ans))
-}
diff --git a/inst/UnitTests/bind_data_test.R b/inst/UnitTests/bind_data_test.R
deleted file mode 100644
index cc330ae..0000000
--- a/inst/UnitTests/bind_data_test.R
+++ /dev/null
@@ -1,198 +0,0 @@
-library("RSQLite")
-
-DATA <- new.env(parent=emptyenv(), hash=TRUE)
-
-.setUp <- function() {
-    DATA$dbfile <- tempfile()
-    DATA$db <- dbConnect(dbDriver("SQLite"), DATA$dbfile)
-}
-
-.tearDown <- function() {
-    lapply(dbListResults(DATA$db), dbClearResult)
-    dbDisconnect(DATA$db)
-    file.remove(DATA$dbfile)
-}
-
-basicTableSql <- ('
-create table t1 (name text, id integer, rate real)
-')
-
-basicDf <- data.frame(name=c("Alice", "Bob", "Cody", NA),
-                      id=as.integer(c(10:12, NA)),
-                      rate=c(1:3 * pi, NA), stringsAsFactors=FALSE)
-
-testSimpleBindPositional <- function() {
-    db <- DATA$db
-    dbGetQuery(db, basicTableSql)
-    values <- "(?, ?, ?)"
-    sql <- paste("insert into t1 values", values)
-    dbBeginTransaction(db)
-    rs <- dbSendPreparedQuery(db, sql, bind.data=basicDf)
-    dbClearResult(rs)
-    dbCommit(db)
-
-    got <- dbGetQuery(db, "select * from t1")
-    checkEquals(basicDf, got)
-}
-
-testSimpleBindNamed <- function() {
-    db <- DATA$db
-    dbGetQuery(db, basicTableSql)
-    values <- "(:name, :id, :rate)"
-    sql <- paste("insert into t1 values", values)
-    rs <- dbSendPreparedQuery(db, sql, bind.data=basicDf)
-    dbClearResult(rs)
-    got <- dbGetQuery(db, "select * from t1")
-    checkEquals(basicDf, got)
-}
-
-testBindNamedMissing <- function() {
-    db <- DATA$db
-    dbGetQuery(db, basicTableSql)
-    values <- "(:name, :id, :rate)"
-    sql <- paste("insert into t1 values", values)
-    colnames(basicDf)[2] <- "garbled"
-    Got <- tryCatch({
-        dbSendPreparedQuery(db, sql, bind.data=basicDf)
-        FALSE
-    },
-             error = function(e) {
-                 checkTrue(grepl("unable to bind data for parameter",
-                                 conditionMessage(e)))
-                 TRUE
-             })
-    checkTrue(Got)                      # verify exception
-}
-
-testBindNamedReordered <- function() {
-    db <- DATA$db
-    dbGetQuery(db, basicTableSql)
-    values <- "(:name, :id, :rate)"
-    sql <- paste("insert into t1 values", values)
-    newOrd <- c("id", "rate", "name")
-    basicDf <- basicDf[ , newOrd]
-    rs <- dbSendPreparedQuery(db, sql, bind.data=basicDf)
-    dbClearResult(rs)
-    got <- dbGetQuery(db, "select * from t1")
-    checkEquals(basicDf, got[ , newOrd])
-}
-
-testBindNamedReorderExtraCols <- function() {
-    db <- DATA$db
-    dbGetQuery(db, basicTableSql)
-    values <- "(:name, :id, :rate)"
-    sql <- paste("insert into t1 values", values)
-    basicDf$foo <- 1:1
-    basicDf$bar <- 0:0
-    basicDf$baz <- "a"
-    newOrd <- c("foo", "id", "bar", "rate", "name", "baz")
-    basicDf <- basicDf[ , newOrd]
-
-    ## This raises the following error:
-##     Error in sqliteExecStatement(conn, statement, bind.data, ...) :
-## 	RS-DBI driver: (attempted to re-bind column [name] to positional
-## 	parameter 1)
-
-    rs <- dbSendPreparedQuery(db, sql, bind.data=basicDf)
-    dbClearResult(rs)
-
-    got <- dbGetQuery(db, "select * from t1")
-    checkEquals(basicDf[ , c("name", "id", "rate")], got)
-}
-
-test_bind_data_has_zero_dim <- function()
-{
-    db <- DATA$db
-    dbGetQuery(db, basicTableSql)
-    values <- "(:name, :id, :rate)"
-    sql <- paste("insert into t1 values", values)
-    df <- basicDf[0, ]
-    checkException(dbSendPreparedQuery(db, sql, bind.data = df))
-}
-
-bind_select_setup <- function(db) {
-    df <- data.frame(id = letters[1:5],
-                     score = 1:5,
-                     size = c(1L, 1L, 2L, 2L, 3L),
-                     stringsAsFactors = FALSE)
-
-    dbWriteTable(db, "t1", df, row.names = FALSE)
-    df
-}
-
-test_bind_select_one_per <- function()
-{
-    db <- DATA$db
-    df <- bind_select_setup(db)
-    q <- "select * from t1 where id = ?"
-    got <- dbGetPreparedQuery(db, q, data.frame(id = c("e", "a", "c")))
-    checkEquals(c("e", "a", "c"), got$id)
-    checkEquals(c(5L, 1L, 3L), got$score)
-
-    res <- dbSendPreparedQuery(db, q, data.frame(id = c("e", "a", "c")))
-    checkEquals("e", fetch(res, n = 1)[["id"]])
-    checkEquals("a", fetch(res, n = 1)[["id"]])
-    checkEquals("c", fetch(res, n = 1)[["id"]])
-    checkEquals(0L, nrow(fetch(res, n = 1)))
-    checkTrue(dbGetInfo(res)$completed == 1L)
-    dbClearResult(res)
-}
-
-test_bind_select_no_matches <- function()
-{
-    db <- DATA$db
-    df <- bind_select_setup(db)
-    q <- "select * from t1 where id = ?"
-
-    ## no result 1
-    got <- dbGetPreparedQuery(db, q, data.frame(id = "X"))
-    checkEquals(c(0L, 3L), dim(got))
-    checkEquals(names(df), names(got))
-
-    ## no result many
-    got <- dbGetPreparedQuery(db, q, data.frame(id = c("X", "Y", "Z")))
-    checkEquals(c(0L, 3L), dim(got))
-    checkEquals(names(df), names(got))
-
-    # no results when mixed in
-    got <- dbGetPreparedQuery(db, q,
-                              data.frame(id = c("X", "b", "e", "Y", "a")))
-    checkEquals(c("b", "e", "a"), got$id)
-}
-
-test_bind_select_multi_match <- function()
-{
-    db <- DATA$db
-    df <- bind_select_setup(db)
-    q <- "select * from t1 where size = ?"
-
-    got <- dbGetPreparedQuery(db, q,
-                              data.frame(size=c(1L, 2L, 3L)))
-    checkEquals(df, got)
-
-    ## with non-match
-    got <- dbGetPreparedQuery(db, q,
-                              data.frame(size=c(1L, -100L, 2L, 3L)))
-    checkEquals(df, got)
-
-    ## as result set using incremental fetch
-    res <- dbSendPreparedQuery(db, q,
-                               data.frame(size=c(3L, 2L)))
-    checkEquals("e", fetch(res, n = 1L)[["id"]])
-    checkEquals("c", fetch(res, n = 1L)[["id"]])
-    checkEquals("d", fetch(res, n = 1L)[["id"]])
-    checkEquals(c(0L, 3L), dim(fetch(res, n = 1L)))
-    checkTrue(dbGetInfo(res)$completed == 1L)
-}
-
-test_bind_select_NA <- function()
-{
-    db <- DATA$db
-    df <- bind_select_setup(db)
-    dbGetQuery(db, "insert into t1 values ('x', NULL, NULL)")
-
-    got <- dbGetPreparedQuery(db, "select id from t1 where score is :v",
-                              data.frame(v=as.integer(NA)))
-    checkEquals(c(1L, 1L), dim(got))
-    checkEquals("x", got$id)
-}
diff --git a/inst/UnitTests/blob_test.R b/inst/UnitTests/blob_test.R
deleted file mode 100644
index 49f6a47..0000000
--- a/inst/UnitTests/blob_test.R
+++ /dev/null
@@ -1,93 +0,0 @@
-set.seed(0x977)
-
-mk_df <- function()
-{
-    mk_blob <- function(n) as.raw(sample(0:255, n, replace = TRUE))
-    name <- letters[1:10]
-    data <- lapply(1:10, function(x) mk_blob(sample(10:256, 1)))
-    score <- rnorm(10)
-    count <- sample(1:10)
-    df <- data.frame(name = name, score = score, count = count,
-                     data = I(data),
-                     stringsAsFactors = FALSE)
-}
-
-mk_db <- function(df)
-{
-    db <- dbConnect(SQLite(), dbname = ":memory:")
-    dbGetQuery(db, "create table t (name text, score float,
-                    count integer, data blob)")
-    dbGetPreparedQuery(db, "insert into t values (?, ?, ?, ?)", df)
-    db
-}
-
-do_column_test <- function(colName)
-{
-    df <- mk_df()
-    db <- mk_db(df)
-    ans <- dbGetQuery(db, sprintf("select %s from t", colName))[[1]]
-    ## for list valued columns, there will be an AsIs class attr
-    want <- df[[colName]]
-    if (is.list(want)) class(want) <- NULL
-    checkEquals(want, ans)
-    dbDisconnect(db)
-}
-
-test_column_access <- function()
-{
-    for (cn in names(mk_df())) {
-        do_column_test(cn)
-    }
-}
-
-test_simple_blob_column <- function()
-{
-    db <- dbConnect(SQLite(), dbname = ":memory:")
-    dbGetQuery(db, "CREATE TABLE t1 (name TEXT, data BLOB)")
-
-    z <- paste("hello", 1:10)
-    df <- data.frame(a = letters[1:10],
-                     z = I(lapply(z, charToRaw)))
-    dbGetPreparedQuery(db, "insert into t1 values (:a, :z)", df)
-    a <- dbGetQuery(db, "select name from t1")
-    checkEquals(10, nrow(a))
-    a <- dbGetQuery(db, "select data from t1")
-    checkEquals(10, nrow(a))
-    a <- dbGetQuery(db, "select * from t1")
-    checkEquals(10, nrow(a))
-    checkEquals(2, ncol(a))
-
-    checkEquals(z, sapply(a$data, rawToChar))
-    dbDisconnect(db)
-}
-
-test_null_valued_blobs <- function()
-{
-    db <- dbConnect(SQLite(), ":memory:")
-    df <- data.frame(ii=1:3, aa=letters[1:3])
-    df$blob <- list(NULL, raw(3), raw(0))
-
-    ## verify that you can insert BLOB NULL.  This makes use of
-    ## dbSendPreparedQuery so we are testing that interface here.
-    checkEquals(TRUE, dbWriteTable(db, "t3", df, row.names=FALSE))
-
-    ## db NULL => R NULL
-    ans <- dbGetQuery(db, "SELECT * FROM t3 WHERE blob IS NULL")
-    checkEquals(1, ans[["ii"]])
-    checkEquals("a", ans[["aa"]])
-    checkTrue(is.list(ans[["blob"]]))
-    checkEquals(1, length(ans[["blob"]]))
-    checkTrue(is.null(ans[["blob"]][[1]]))
-
-    ## zero-length BLOBs map correctly
-    ans <- dbGetQuery(db, "SELECT * FROM t3 WHERE blob=x''")
-    checkEquals(3, ans[["ii"]])
-    checkEquals("c", ans[["aa"]])
-    checkEquals(raw(0), ans[["blob"]][[1]])
-
-    ## no rows returned, types inferred correctly
-    ans <- dbGetQuery(db, "SELECT * FROM t3 WHERE 0")
-    checkEquals(0, nrow(ans))
-    wantedTypes <- c("integer", "character", "list")
-    checkEquals(wantedTypes, as.character(sapply(ans, typeof)))
-}
diff --git a/inst/UnitTests/connection_gc_test.R b/inst/UnitTests/connection_gc_test.R
deleted file mode 100644
index 79f14e7..0000000
--- a/inst/UnitTests/connection_gc_test.R
+++ /dev/null
@@ -1,25 +0,0 @@
-test_connections_are_finalized <- function()
-{
-    drv <- SQLite()
-    dbs <- lapply(1:50, function(x) {
-        dbConnect(drv, dbname = ":memory:")
-    })
-    checkEquals(50L, dbGetInfo(SQLite())$num_con)
-    rm(dbs)
-    gc(verbose = FALSE)
-    checkEquals(0L, dbGetInfo(SQLite())$num_con)
-}
-
-test_connections_are_held_by_result_set <- function()
-{
-    db <- dbConnect(SQLite(), dbname = ":memory:")
-    res <- dbSendQuery(db, "create table t1 (a text, b text)")
-    rm(db)
-    gc(verbose = FALSE)
-    checkEquals(1L, dbGetInfo(SQLite())$num_con)
-    dbClearResult(res)
-    ## clearing a result set means that result set no loner
-    ## protects the connection
-    gc(verbose = FALSE)
-    checkEquals(0L, dbGetInfo(SQLite())$num_con)
-}
diff --git a/inst/UnitTests/dat2.txt b/inst/UnitTests/dat2.txt
deleted file mode 100644
index f641fa7..0000000
--- a/inst/UnitTests/dat2.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-a|b
-1|x
-2|y
-3|z
-\N|E
-
diff --git a/inst/UnitTests/dat4.txt b/inst/UnitTests/dat4.txt
deleted file mode 100644
index 1a9942c..0000000
--- a/inst/UnitTests/dat4.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-a|b
-1|x
-2|y
-3|z
-\N|E
diff --git a/inst/UnitTests/dbConnect_test.R b/inst/UnitTests/dbConnect_test.R
deleted file mode 100644
index da07fe4..0000000
--- a/inst/UnitTests/dbConnect_test.R
+++ /dev/null
@@ -1,90 +0,0 @@
-.getOS <- function()
-{
-    ostype <- .Platform[["OS.type"]]
-    if (ostype == "windows") return("windows")
-    if (grepl("darwin", R.Version()$os)) return("osx")
-    ostype
-}
-
-test_NULL_dbname <- function() {
-    for (i in 1:20) {
-        db <- dbConnect(SQLite(), dbname=NULL)
-        checkTrue(dbDisconnect(db))
-    }
-}
-
-test_invalid_dbname_is_caught <- function()
-{
-    drv <- SQLite()
-    checkException(dbConnect(drv, dbname = 1:3))
-    checkException(dbConnect(drv, dbname = c("a", "b")))
-    checkException(dbConnect(drv, dbname = NA))
-    checkException(dbConnect(drv, dbname = as.character(NA)))
-}
-
-test_invalid_vfs_is_caught <- function()
-{
-    if (.getOS() == "windows") {
-        cat("Skipping test: vfs customization not available on Windows\n")
-        return(TRUE)
-    }
-    drv <- SQLite()
-    checkException(dbConnect(drv, dbname = "", vfs = ""))
-    checkException(dbConnect(drv, dbname = "", vfs = "notvfs"))
-    checkException(dbConnect(drv, dbname = "", vfs = NA))
-    checkException(dbConnect(drv, dbname = "", vfs = as.character(NA)))
-    checkException(dbConnect(drv, dbname = "", vfs = 1L))
-    checkException(dbConnect(drv, dbname = "",
-                             vfs = c("unix-none", "unix-posix")))
-}
-
-test_valid_vfs <- function()
-{
-    allowed <- switch(.getOS(),
-                      osx = c("unix-posix", "unix-afp", "unix-flock",
-                              "unix-dotfile", "unix-none"),
-                      unix = c("unix-dotfile", "unix-none"),
-                      windows = character(0),
-                      character(0))
-    drv <- SQLite()
-    checkVfs <- function(v)
-    {
-        db <- dbConnect(drv, dbname = "", vfs = v)
-        on.exit(dbDisconnect(db))
-        checkEquals(v, dbGetInfo(db)[["vfs"]])
-    }
-    for (v in allowed) checkVfs(v)
-}
-
-test_open_flags <- function()
-{
-    drv <- SQLite()
-    tmpFile <- tempfile()
-    on.exit(file.remove(tmpFile))
-
-    ## error if file does not exist
-    checkException(dbConnect(drv, dbname = tmpFile, flags = SQLITE_RO))
-    checkException(dbConnect(drv, dbname = tmpFile, flags = SQLITE_RW))
-
-    dbrw <- dbConnect(drv, dbname = tmpFile, flags = SQLITE_RWC)
-    df <- data.frame(a=letters, b=runif(26L), stringsAsFactors=FALSE)
-    checkTrue(dbWriteTable(dbrw, "t1", df))
-
-    dbro <- dbConnect(drv, dbname = tmpFile, flags = SQLITE_RO)
-    checkTrue(!suppressWarnings(dbWriteTable(dbro, "t2", df)))
-
-    dbrw2 <- dbConnect(drv, dbname = tmpFile, flags = SQLITE_RW)
-    checkTrue(dbWriteTable(dbrw2, "t2", df))
-
-    dbDisconnect(dbrw)
-    dbDisconnect(dbro)
-    dbDisconnect(dbrw2)
-}
-
-test_query_closed_connection <- function()
-{
-    db <- dbConnect(SQLite(), dbname = ":memory:")
-    dbDisconnect(db)
-    checkException(dbGetQuery(db, "select * from foo"))
-}
-
diff --git a/inst/UnitTests/dbDataType_test.R b/inst/UnitTests/dbDataType_test.R
deleted file mode 100644
index 798022b..0000000
--- a/inst/UnitTests/dbDataType_test.R
+++ /dev/null
@@ -1,76 +0,0 @@
-test_integer <- function()
-{
-    checkEquals("INTEGER", sqliteDataType(1L))
-    checkEquals("INTEGER", sqliteDataType(FALSE))
-    checkEquals("INTEGER", sqliteDataType(TRUE))
-    checkEquals("INTEGER", sqliteDataType(NA))
-}
-
-test_real <- function()
-{
-    checkEquals("REAL", sqliteDataType(1.0))
-}
-
-test_text <- function()
-{
-    checkEquals("TEXT", sqliteDataType("a"))
-    checkEquals("TEXT", sqliteDataType(factor(letters)))
-    checkEquals("TEXT", sqliteDataType(factor(letters, ordered = TRUE)))
-}
-
-test_blob <- function()
-{
-    checkEquals("BLOB", sqliteDataType(list(raw(1))))
-    checkEquals("BLOB", sqliteDataType(list()))
-    checkEquals("BLOB", sqliteDataType(list(a=NULL)))
-}
-
-test_I_AsIs <- function()
-{
-    df <- data.frame(a=I(1:2),
-                     b=I(c("x", "y")),
-                     c=I(list(raw(3), raw(1))),
-                     d=I(c(1.1, 2.2)))
-    got <- sapply(df, sqliteDataType)
-    expect <- c(a="INTEGER", b="TEXT", c="BLOB", d="REAL")
-    checkEquals(expect, got)
-}
-
-test_classes <- function()
-{
-    ## unhandled classes default to storage.mode and finally to TEXT.
-    checkEquals("REAL", sqliteDataType(Sys.Date()))
-    checkEquals("REAL", sqliteDataType(Sys.time()))
-
-    intClass <- structure(1L, class="unknown1")
-    checkEquals("INTEGER", sqliteDataType(intClass))
-
-    dblClass <- structure(3.14, class="unknown1")
-    checkEquals("REAL", sqliteDataType(dblClass))
-
-    strClass <- structure("abc", class="unknown1")
-    checkEquals("TEXT", sqliteDataType(strClass))
-}
-
-test_sqliteDataType <- function()
-{
-    input_list <- list(a=c(1L, 2L, 3L),
-                       b=c(1.2, 2.2, 3.3),
-                       c=c(TRUE, FALSE),
-                       d=c("a", "b"),
-                       e=factor(c("a", "a", "b")),
-                       f=factor(c("a", "a", "b"), ordered = TRUE),
-                       g=1+2i)
-
-    expect_list <- list(a="INTEGER",
-                        b="REAL",
-                        c="INTEGER",
-                        d="TEXT",
-                        e="TEXT",
-                        f="TEXT",
-                        g="TEXT")
-
-    mapply(function(input, expect) checkEquals(expect,
-                                               sqliteDataType(input)),
-           input_list, expect_list)
-}
diff --git a/inst/UnitTests/dbGetInfo_test.R b/inst/UnitTests/dbGetInfo_test.R
deleted file mode 100644
index b38078f..0000000
--- a/inst/UnitTests/dbGetInfo_test.R
+++ /dev/null
@@ -1,35 +0,0 @@
-test_dbGetInfo_connection <- function()
-{
-    db <- dbConnect(SQLite(), dbname = ":memory:")
-    on.exit(dbDisconnect(db))
-
-    info <- dbGetInfo(db)
-    checkEquals(6L, length(info))
-    checkEquals(":memory:", info[["dbname"]])
-    checkEquals("3.7.17", info[["serverVersion"]])
-    checkEquals(integer(0), info[["rsId"]])
-    checkEquals("on", info[["loadableExtensions"]])
-    checkEquals(SQLITE_RWC, info[["flags"]])
-    checkEquals("", info[["vfs"]])
-}
-
-test_dbGetInfo_connection_vfs <- function()
-{
-    if (.Platform[["OS.type"]] == "windows") {
-        cat("Skipping test: vfs customization not available on Windows\n")
-        return(TRUE)
-    }
-    db <- dbConnect(SQLite(), dbname = "", vfs = "unix-none")
-    on.exit(dbDisconnect(db))
-    info <- dbGetInfo(db)
-    checkEquals("", info[["dbname"]])
-    checkEquals("unix-none", info[["vfs"]])
-}
-
-test_dbGetInfo_extensions <- function()
-{
-    db <- dbConnect(SQLite(), dbname = "", loadable.extensions = FALSE)
-    on.exit(dbDisconnect(db))
-    info <- dbGetInfo(db)
-    checkEquals("off", info[["loadableExtensions"]])
-}
diff --git a/inst/UnitTests/dbWriteTable_test.R b/inst/UnitTests/dbWriteTable_test.R
deleted file mode 100644
index ddf8d05..0000000
--- a/inst/UnitTests/dbWriteTable_test.R
+++ /dev/null
@@ -1,194 +0,0 @@
-library("RSQLite")
-
-DATA <- new.env(parent=emptyenv(), hash=TRUE)
-
-.setUp <- function() {
-    DATA$dbfile <- tempfile()
-    DATA$db <- dbConnect(dbDriver("SQLite"), dbname=DATA$dbfile)
-}
-
-.tearDown <- function() {
-    lapply(dbListResults(DATA$db), dbClearResult)
-    dbDisconnect(DATA$db)
-    file.remove(DATA$dbfile)
-}
-
-
-testWithRowNames <- function() {
-    df <- data.frame(a=1:10, b=pi*1:10, c=LETTERS[1:10],
-                     stringsAsFactors=FALSE)
-    rn <- paste(letters[1:10], 1:10, sep="")
-    row.names(df) <- rn
-    dbWriteTable(DATA$db, "t1rn", df)
-
-    expect <- df
-    row.names(expect) <- 1:nrow(df)
-    expect <- cbind(rn, expect, stringsAsFactors=FALSE)
-    names(expect)[1] <- "row_names"
-    got <- dbGetQuery(DATA$db, "select * from t1rn")
-    colTypes <- c("character", "integer", "double", "character")
-    names(colTypes) <- names(expect)
-    checkEquals(colTypes, sapply(expect, typeof))
-    checkEquals(colTypes, sapply(got, typeof))
-    checkEquals(dim(expect), dim(got))
-    checkEquals(expect, got)
-}
-
-testOverwriteAndAppend <- function() {
-    df <- data.frame(a=1:10, b=pi*1:10, c=LETTERS[1:10],
-                     stringsAsFactors=FALSE)
-    dbWriteTable(DATA$db, "t1", df, row.names=FALSE)
-    ## The default is overwrite=FALSE, append
-    checkTrue(!suppressWarnings(dbWriteTable(DATA$db, "t1",
-                                             df, row.names=FALSE)))
-    checkTrue(dbWriteTable(DATA$db, "t1", df, row.names=FALSE,
-                           append=TRUE))
-    checkTrue(dbWriteTable(DATA$db, "t1", df, row.names=FALSE,
-                           overwrite=TRUE))
-    ## you can't overwrite and append
-    checkException(dbWriteTable(DATA$db, "t1", df, row.names=FALSE,
-                                overwrite=TRUE, append=TRUE),
-                   silent=TRUE)
-}
-
-
-testCanCloseAfterFailedWriteTable <- function() {
-    ## handle DB connection manually since we want
-    ## to explicitly check dbDisconnect is error free.
-    tf <- tempfile()
-    con <- dbConnect(dbDriver("SQLite"), dbname=tf)
-
-    x <- data.frame(col1=1:10, col2=letters[1:10])
-
-    dbWriteTable(con, "t1", x)
-    dbGetQuery(con, "create unique index t1_c1_c2_idx on t1(col1, col2)")
-
-    ## uniqueness constraint error/failure
-    checkEquals(FALSE,
-                suppressWarnings(dbWriteTable(con,"t1", x, append=TRUE)))
-
-    ## this used to cause an error
-    checkEquals(TRUE, dbDisconnect(con))
-    file.remove(tf)
-}
-
-
-testCommasInDataFrame <- function() {
-    ## From: "Clarkson, Brian" <brian.clarkson at credit-suisse.com>
-    ## Subject: RE: improper use of sqlite3_prepare() API?
-    ## Date: Mon Dec  4 20:27:06 2006 -0800
-
-    ## Oh and while I am talking to you, there are two more problems that I
-    ## was able to hack the R to get around and hence wasn't as urgent...
-
-    ## You cannot write data.frames that contain commas in its character
-    ## string data to a database. The problem was that the sqliteWriteTable
-    ## function internally uses comma-delimited files without properly
-    ## quoting the text columns. Here is an example:
-
-    df <- data.frame(company=c("ABC, Inc.","DEF Holdings"),
-                     layoffs=c(1000,2000),
-                     country=c("JP","HK"),
-                     stringsAsFactors=FALSE)
-    dbWriteTable(DATA$db, "t1", df, row.names=FALSE)
-    got <- dbGetQuery(DATA$db, "select * from t1")
-    checkEquals(df, got)
-}
-
-
-##  con <- dbConnect(drv,dbname="test.db") blah2 <-
-##  dbGetQuery(con,"select * from blah") dbDisconnect(con)
-## [1] TRUE blah2
-##        company layoffs country 1 ABC, Inc.  1000 JP\r 2 DEF Holdings
-## 2000 HK\r
-
-
-## If I read back the results that I just wrote, we can see that the last
-## column has '\r' appended to each row. I traced this to assumption in
-## sqliteImportFile that the eol character is assumed in the code to be
-## \n' which is not true for Windows. Specifying the eol character in the
-## dbWriteTable call fixes this problem:
-
-## dbWriteTable(con,"blah",blah,eol="\r\n")
-
-## tests for importing a file using dbWriteTable
-
-testImportViaWriteTable <- function() {
-    expect <- data.frame(a=c(1:3, NA), b=c("x", "y", "z", "E"),
-                         stringsAsFactors=FALSE)
-    checkTrue(dbWriteTable(DATA$db, "dat", "dat1.txt", sep="|", eol="\n",
-                           header=TRUE, overwrite=TRUE))
-    got <- dbGetQuery(DATA$db, "select * from dat")
-    checkEquals(expect, got)
-
-    checkTrue(dbWriteTable(DATA$db, "dat", "dat2.txt", sep="|", eol="\n",
-                           header=TRUE, overwrite=TRUE))
-    got <- dbGetQuery(DATA$db, "select * from dat")
-    checkEquals(expect, got)
-
-    checkTrue(dbWriteTable(DATA$db, "dat", "dat3.txt", sep="|", eol="\r\n",
-                           header=TRUE, overwrite=TRUE))
-    got <- dbGetQuery(DATA$db, "select * from dat")
-    checkEquals(expect, got)
-
-    checkTrue(dbWriteTable(DATA$db, "dat", "dat4.txt", sep="|", eol="\r\n",
-                           header=TRUE, overwrite=TRUE))
-    got <- dbGetQuery(DATA$db, "select * from dat")
-    checkEquals(expect, got)
-
-}
-
-
-testFactorWithNA <- function() {
-    df <- data.frame(x=1:10,y=factor(LETTERS[1:10]))
-    df$y[4] <- NA
-
-    dbWriteTable(DATA$db, "bad_table", df)
-
-    got <- dbGetQuery(DATA$db, "select * from bad_table")
-
-    checkEquals(df$x, got$x)
-    checkEquals(as.character(df$y), got$y)
-}
-
-testLogicalTreatedAsInt <- function() {
-    df <- data.frame(x=1:3, y=c(NA, TRUE, FALSE))
-
-    dbWriteTable(DATA$db, "t1", df)
-
-    got <- dbGetQuery(DATA$db, "select * from t1")
-
-    checkEquals("integer", typeof(got$y))
-    checkEquals(as.integer(NA), got$y[1])
-    checkEquals(1L, got$y[2])
-    checkEquals(0L, got$y[3])
-}
-
-testCommentCharIsRespected <- function()
-{
-    tmp_file <- tempfile()
-    on.exit(file.remove(tmp_file))
-    cat('A,B,C\n11,2#2,33\n', file = tmp_file)
-    ## default comment.char is '#'
-    checkException(dbWriteTable(DATA$db, "t1", tmp_file,
-                                header = TRUE, sep = ","),
-                   silent = TRUE)
-
-    ## specifying a comment.char works
-    dbWriteTable(DATA$db, "t1", tmp_file, header = TRUE, sep = ",",
-                 comment.char = "")
-    got <- as.character(dbGetQuery(DATA$db, "select B from t1"))
-    checkEquals("2#2", got)
-}
-
-testColClasses <- function()
-{
-    tmp_file <- tempfile()
-    on.exit(file.remove(tmp_file))
-    cat('A,B,C\n1,2,3\n4,5,6\na,7,8\n', file = tmp_file)
-    dbWriteTable(DATA$db, "t1", tmp_file, header = TRUE, sep = ",",
-                 colClasses=c("character", "integer", "double"))
-    got <- dbGetQuery(DATA$db, "select * from t1")
-    checkEquals(c(A="character", B="integer", C="numeric"),
-                sapply(got, class))
-}
diff --git a/inst/UnitTests/multiple_cons_test.R b/inst/UnitTests/multiple_cons_test.R
deleted file mode 100644
index 99c9fde..0000000
--- a/inst/UnitTests/multiple_cons_test.R
+++ /dev/null
@@ -1,113 +0,0 @@
-library("RSQLite")
-
-DATA <- new.env(parent=emptyenv(), hash=TRUE)
-
-.setUp <- function() {
-    DATA$dbfile <- tempfile()
-    DATA$db1 <- dbConnect(dbDriver("SQLite"), dbname = DATA$dbfile)
-    DATA$db2 <- dbConnect(dbDriver("SQLite"), dbname = DATA$dbfile)
-    DATA$df <- data.frame(a=letters, b=LETTERS, c=1:26,
-                          stringsAsFactors=FALSE)
-    dbGetQuery(DATA$db1, "create table t1 (a text, b text, c integer)")
-    rs <- dbSendPreparedQuery(DATA$db1,
-                              "insert into t1 values (:a, :b, :c)",
-                              DATA$df)
-    dbClearResult(rs)
-}
-
-.tearDown <- function() {
-    lapply(dbListResults(DATA$db1), dbClearResult)
-    lapply(dbListResults(DATA$db2), dbClearResult)
-    dbDisconnect(DATA$db1)
-    dbDisconnect(DATA$db2)
-    file.remove(DATA$dbfile)
-}
-
-testSchemaChangeDuringQuery <- function() {
-    rs1 <- dbSendQuery(DATA$db1, "select * from t1")
-    junk <- fetch(rs1, n=1)
-    checkEquals("a", junk[["a"]])
-    ## This should cause an error because the DB is locked
-    ## by the active select.
-    checkException(dbGetQuery(DATA$db2,
-                              "create table t2 (x text, y integer)"),
-                   silent=TRUE)
-    dbClearResult(rs1)
-
-    ## if we haven't started fetching, it is ok on unix,
-    ## but not on Windows
-    ## rs1 <- dbSendQuery(DATA$db1, "select * from t1")
-    ## dbGetQuery(DATA$db2,
-    ##            "create table t2 (x text, y integer)")
-    ## junk <- fetch(rs1, n=2)
-    ## checkEquals(c("a", "b"), junk[["a"]])
-}
-
-testSimultaneousSelects <- function() {
-    dbfile <- tempfile()
-    db1 <- dbConnect(dbDriver("SQLite"), dbfile)
-    df <- data.frame(a=letters, b=LETTERS, c=1:26,
-                     stringsAsFactors=FALSE)
-    dbGetQuery(db1, "create table t1 (a text, b text, c integer)")
-    rs <- dbSendPreparedQuery(db1,
-                              "insert into t1 values (:a, :b, :c)", df)
-    dbClearResult(rs)
-    ## here we wait to open the 2nd con till after table created
-    db2 <- dbConnect(dbDriver("SQLite"), dbfile)
-    rs1 <- dbSendQuery(db1, "select * from t1")
-    rs2 <- dbSendQuery(db2, "select a, c from t1")
-    junk <- fetch(rs1, n=1)
-    junk <- fetch(rs2, n=1)
-    dbClearResult(rs1)
-    dbClearResult(rs2)
-    dbDisconnect(db1)
-    dbDisconnect(db2)
-}
-
-
-testSimultaneousSelects2 <- function() {
-    dbfile <- tempfile()
-    db1 <- dbConnect(dbDriver("SQLite"), dbfile)
-    db2 <- dbConnect(dbDriver("SQLite"), dbfile)
-    df <- data.frame(a=letters, b=LETTERS, c=1:26,
-                     stringsAsFactors=FALSE)
-    dbGetQuery(db1, "create table t1 (a text, b text, c integer)")
-    rs <- dbSendPreparedQuery(db1,
-                              "insert into t1 values (:a, :b, :c)", df)
-    dbClearResult(rs)
-
-    ## TODO: investigate why this works on Unix and fails on Windows
-    if (.Platform[["OS.type"]] == "windows") {
-        cat("skipping test, simultaneous selects not working on Windows\n")
-        return(TRUE)
-    }
-    rs1 <- dbSendQuery(db1, "select * from t1")
-    rs2 <- dbSendQuery(db2, "select a, c from t1")
-    junk <- fetch(rs1, n=1)
-    junk <- fetch(rs2, n=1)
-    dbClearResult(rs1)
-    dbClearResult(rs2)
-    dbDisconnect(db1)
-    dbDisconnect(db2)
-}
-
-testSchemaChangeDuringWriteTable <- function() {
-    if (.Platform[["OS.type"]] == "windows") {
-        cat("skipping test, schema change on write table on Windows\n")
-        return(TRUE)
-    }
-    rs1 <- dbSendQuery(DATA$db1, "select * from t1")
-    junk <- fetch(rs1, n=1)
-    checkEquals("a", junk[["a"]])
-    x <- data.frame(col1=1:10, col2=letters[1:10])
-    ## This fails because the active select locks the DB
-    checkEquals(FALSE,
-                suppressWarnings(dbWriteTable(DATA$db2, "tablex", x)))
-    dbClearResult(rs1)
-    checkEquals(TRUE, dbWriteTable(DATA$db2, "tablex", x))
-    checkTrue("tablex" %in% dbListTables(DATA$db2))
-
-    dbGetQuery(DATA$db1, "create table foobar (a text)")
-    dbWriteTable(DATA$db2, "tabley", x)
-    checkTrue("tabley" %in% dbListTables(DATA$db2))
-}
diff --git a/inst/UnitTests/result_set_closing_test.R b/inst/UnitTests/result_set_closing_test.R
deleted file mode 100644
index 4bd7cd1..0000000
--- a/inst/UnitTests/result_set_closing_test.R
+++ /dev/null
@@ -1,63 +0,0 @@
-library("RSQLite")
-
-DATA <- new.env(parent=emptyenv(), hash=TRUE)
-
-.setUp <- function() {
-    DATA$p1 <- tempfile()
-    DATA$p2 <- tempfile()
-    db1 <- dbConnect(SQLite(), DATA$p1)
-    data(USArrests)
-    dbWriteTable(db1, "ua", USArrests, row.names=FALSE)
-    dbDisconnect(db1)
-}
-
-.tearDown <- function() {
-    f <- c(DATA$p1, DATA$p2)
-    file.remove(f[file.exists(f)])
-}
-
-test_dbGetQuery_auto_close <- function() {
-    db <- dbConnect(SQLite(), DATA$p2)
-    res <- dbSendQuery(db, "CREATE TABLE t1 (b integer, bb text)")
-
-    checkEquals(TRUE, dbHasCompleted(res))
-
-    sql <- sprintf("ATTACH '%s' AS db1", DATA$p1)
-    checkEquals(NULL, dbGetQuery(db, sql))
-    df <- dbGetQuery(db, "select * from db1.ua limit 3")
-    checkEquals(3, nrow(df))
-    dbDisconnect(db)
-}
-
-test_dbGetQuery_error_on_incomplete_open_result_set <- function() {
-    db <- dbConnect(SQLite(), DATA$p2)
-    res <- dbSendQuery(db, "CREATE TABLE t1 (b integer, bb text)")
-    dbClearResult(res)
-    res <- dbSendQuery(db, "SELECT * from t1")
-    checkEquals(FALSE, dbHasCompleted(res))
-    ans <- tryCatch({
-        dbGetQuery(db, "CREATE TABLE t2 (foo text)")
-        FALSE
-        }, error=function(w) {
-                 TRUE
-             })
-    checkEquals(TRUE, ans)
-    dbClearResult(res)
-    dbDisconnect(db)
-}
-
-test_accessing_cleared_result_set <- function()
-{
-    db = dbConnect(SQLite(), ":memory:")
-    res = dbSendQuery(db, "create table t1 (a, b)")
-    rm(db)
-    gc(verbose = FALSE)
-    ## result set keeps connection protected
-    checkEquals(1L, dbGetInfo(SQLite())$num_con)
-    ## clearing a result set no longer protects connection
-    dbClearResult(res)
-    gc(verbose = FALSE)
-    checkEquals(0L, dbGetInfo(SQLite())$num_con)
-    checkEquals(FALSE, isIdCurrent(res))
-    checkException(dbGetInfo(res))
-}
diff --git a/inst/UnitTests/sqliteCopyDatabase_test.R b/inst/UnitTests/sqliteCopyDatabase_test.R
deleted file mode 100644
index 0e235bb..0000000
--- a/inst/UnitTests/sqliteCopyDatabase_test.R
+++ /dev/null
@@ -1,55 +0,0 @@
-require("RSQLite") || stop("unable to load RSQLite")
-
-DATA <- new.env(parent=emptyenv())
-
-.setUp <- function() {
-    DATA$db <- dbConnect(dbDriver("SQLite"), dbname=":memory:")
-}
-
-.tearDown <- function() {
-    lapply(dbListResults(DATA$db), dbClearResult)
-    dbDisconnect(DATA$db)
-}
-
-testBadFilenameArg <- function()
-{
-    tmpfiles <- tempfile(letters[1:3])
-    badFilenameArgs <- list(
-                            1:5,
-                            character(0),
-                            as.character(NA),
-                            "",
-                            tmpfiles)
-    for (badFile in badFilenameArgs) {
-        checkException(sqliteCopyDatabase(DATA$db, badFile))
-    }
-    for (f in tmpfiles) checkTrue(!file.exists(f))
-}
-
-test_backup_to_file <- function()
-{
-    backup <- tempfile()
-    checkTrue(!file.exists(backup))
-    df <- data.frame(foo=1:5, bar=letters[1:5], stringsAsFactors = FALSE)
-    checkTrue(dbWriteTable(DATA$db, "t1", df, row.names = FALSE))
-    sqliteCopyDatabase(DATA$db, backup)
-    checkTrue(file.exists(backup))
-    db2 <- dbConnect(SQLite(), dbname = backup)
-    on.exit(dbDisconnect(db2))
-    on.exit(unlink(backup), add = TRUE)
-    backupDf <- dbReadTable(db2, "t1")
-    checkEquals(df, backupDf)
-}
-
-test_backup_to_connection <- function()
-{
-    df <- data.frame(foo=1:5, bar=letters[1:5], stringsAsFactors = FALSE)
-    checkTrue(dbWriteTable(DATA$db, "t1", df, row.names = FALSE))
-
-    db2 <- dbConnect(SQLite(), dbname = ":memory:")
-    on.exit(dbDisconnect(db2))
-
-    sqliteCopyDatabase(DATA$db, db2)
-    got <- dbReadTable(db2, "t1")
-    checkEquals(df, got)
-}
diff --git a/inst/UnitTests/sqliteQuickColumn_test.R b/inst/UnitTests/sqliteQuickColumn_test.R
deleted file mode 100644
index 39f1e93..0000000
--- a/inst/UnitTests/sqliteQuickColumn_test.R
+++ /dev/null
@@ -1,42 +0,0 @@
-set.seed(0x977)
-
-mk_df <- function()
-{
-    mk_blob <- function(n) as.raw(sample(0:255, n, replace = TRUE))
-    name <- letters[1:10]
-    data <- lapply(1:10, function(x) mk_blob(sample(10:256, 1)))
-    score <- rnorm(10)
-    count <- sample(1:10)
-    df <- data.frame(name = name, score = score, count = count,
-                     data = I(data),
-                     stringsAsFactors = FALSE)
-}
-
-mk_db <- function(df)
-{
-    db <- dbConnect(SQLite(), dbname = ":memory:")
-    dbGetQuery(db, "create table t (name text, score float,
-                    count integer, data blob)")
-    dbGetPreparedQuery(db, "insert into t values (?, ?, ?, ?)", df)
-    db
-}
-
-do_column_test <- function(colName)
-{
-    df <- mk_df()
-    db <- mk_db(df)
-    ans <- RSQLite:::sqliteQuickColumn(db, "t", colName)
-    ## for list valued columns, there will be an AsIs class attr
-    want <- df[[colName]]
-    if (is.list(want)) class(want) <- NULL
-    checkEquals(want, ans)
-    dbDisconnect(db)
-}
-
-test_column_access <- function()
-{
-    for (cn in names(mk_df())) {
-        do_column_test(cn)
-    }
-}
-
diff --git a/inst/announce b/inst/announce
deleted file mode 100644
index 6fa2ab3..0000000
--- a/inst/announce
+++ /dev/null
@@ -1,22 +0,0 @@
-Version 0.4-1 of the RSQLite package has been uploaded to CRAN
-(RSQLite embeds the SQLite (www.sqlite.org) database engine in R.)
-
-Changes include:
-
-* Fixed problems exporting/importing NA's 
-
-* An experimental new dbWriteTable() method to create SQLite tables
-  from simple files (delimited fields) without creating intermediate 
-  data.frames (useful for handling reasonably large amounts of data), 
-  e.g., 
-     > dbWriteTable(con, "tablename", "filename", header = TRUE, 
-     +              sep = ",", eol = "\n", skip = 0)
-     > methods?dbWriteTable           ## see full documentation
-  
-* dbConnect() now accepts values for the "cache_size" and "synchronous" 
-  PRAGMAs (synchronous is set to 0 or "off") to improve SQLite 
-  performance.
-     > methods?dbConnect              ## see full documentation
-
-Thanks to Seth Falcon, Ronggui Huang, and Charles Loboz for their
-patches, bug reports, suggestions, and testing.
diff --git a/inst/db/datasets.sqlite b/inst/db/datasets.sqlite
new file mode 100644
index 0000000..a63cb4a
Binary files /dev/null and b/inst/db/datasets.sqlite differ
diff --git a/inst/include/sqlite3.h b/inst/include/sqlite3.h
index 28a500d..9879f80 100644
--- a/inst/include/sqlite3.h
+++ b/inst/include/sqlite3.h
@@ -107,9 +107,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.7.8"
-#define SQLITE_VERSION_NUMBER 3007008
-#define SQLITE_SOURCE_ID      "2011-09-19 14:49:19 3e0da808d2f5b4d12046e05980ca04578f581177"
+#define SQLITE_VERSION        "3.8.6"
+#define SQLITE_VERSION_NUMBER 3008006
+#define SQLITE_SOURCE_ID      "2014-08-15 11:46:33 9491ba7d738528f168657adb43a198238abde19e"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -177,7 +177,7 @@ SQLITE_API const char *sqlite3_compileoption_get(int N);
 ** CAPI3REF: Test To See If The Library Is Threadsafe
 **
 ** ^The sqlite3_threadsafe() function returns zero if and only if
-** SQLite was compiled mutexing code omitted due to the
+** SQLite was compiled with mutexing code omitted due to the
 ** [SQLITE_THREADSAFE] compile-time option being set to 0.
 **
 ** SQLite can be compiled with or without mutexes.  When
@@ -219,7 +219,8 @@ SQLITE_API int sqlite3_threadsafe(void);
 ** the opaque structure named "sqlite3".  It is useful to think of an sqlite3
 ** pointer as an object.  The [sqlite3_open()], [sqlite3_open16()], and
 ** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]
-** is its destructor.  There are many other interfaces (such as
+** and [sqlite3_close_v2()] are its destructors.  There are many other
+** interfaces (such as
 ** [sqlite3_prepare_v2()], [sqlite3_create_function()], and
 ** [sqlite3_busy_timeout()] to name but three) that are methods on an
 ** sqlite3 object.
@@ -266,28 +267,46 @@ typedef sqlite_uint64 sqlite3_uint64;
 /*
 ** CAPI3REF: Closing A Database Connection
 **
-** ^The sqlite3_close() routine is the destructor for the [sqlite3] object.
-** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is
-** successfully destroyed and all associated resources are deallocated.
-**
-** Applications must [sqlite3_finalize | finalize] all [prepared statements]
-** and [sqlite3_blob_close | close] all [BLOB handles] associated with
-** the [sqlite3] object prior to attempting to close the object.  ^If
-** sqlite3_close() is called on a [database connection] that still has
-** outstanding [prepared statements] or [BLOB handles], then it returns
-** SQLITE_BUSY.
-**
-** ^If [sqlite3_close()] is invoked while a transaction is open,
+** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
+** for the [sqlite3] object.
+** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
+** the [sqlite3] object is successfully destroyed and all associated
+** resources are deallocated.
+**
+** ^If the database connection is associated with unfinalized prepared
+** statements or unfinished sqlite3_backup objects then sqlite3_close()
+** will leave the database connection open and return [SQLITE_BUSY].
+** ^If sqlite3_close_v2() is called with unfinalized prepared statements
+** and/or unfinished sqlite3_backups, then the database connection becomes
+** an unusable "zombie" which will automatically be deallocated when the
+** last prepared statement is finalized or the last sqlite3_backup is
+** finished.  The sqlite3_close_v2() interface is intended for use with
+** host languages that are garbage collected, and where the order in which
+** destructors are called is arbitrary.
+**
+** Applications should [sqlite3_finalize | finalize] all [prepared statements],
+** [sqlite3_blob_close | close] all [BLOB handles], and 
+** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
+** with the [sqlite3] object prior to attempting to close the object.  ^If
+** sqlite3_close_v2() is called on a [database connection] that still has
+** outstanding [prepared statements], [BLOB handles], and/or
+** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
+** of resources is deferred until all [prepared statements], [BLOB handles],
+** and [sqlite3_backup] objects are also destroyed.
+**
+** ^If an [sqlite3] object is destroyed while a transaction is open,
 ** the transaction is automatically rolled back.
 **
-** The C parameter to [sqlite3_close(C)] must be either a NULL
+** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
+** must be either a NULL
 ** pointer or an [sqlite3] object pointer obtained
 ** from [sqlite3_open()], [sqlite3_open16()], or
 ** [sqlite3_open_v2()], and not previously closed.
-** ^Calling sqlite3_close() with a NULL pointer argument is a 
-** harmless no-op.
+** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
+** argument is a harmless no-op.
 */
-SQLITE_API int sqlite3_close(sqlite3 *);
+SQLITE_API int sqlite3_close(sqlite3*);
+SQLITE_API int sqlite3_close_v2(sqlite3*);
 
 /*
 ** The type for a callback function.
@@ -351,7 +370,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 ** <ul>
 ** <li> The application must insure that the 1st parameter to sqlite3_exec()
 **      is a valid and open [database connection].
-** <li> The application must not close [database connection] specified by
+** <li> The application must not close the [database connection] specified by
 **      the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
 ** <li> The application must not modify the SQL statement text passed into
 **      the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
@@ -367,16 +386,14 @@ SQLITE_API int sqlite3_exec(
 
 /*
 ** CAPI3REF: Result Codes
-** KEYWORDS: SQLITE_OK {error code} {error codes}
-** KEYWORDS: {result code} {result codes}
+** KEYWORDS: {result code definitions}
 **
 ** Many SQLite functions return an integer result code from the set shown
-** here in order to indicates success or failure.
+** here in order to indicate success or failure.
 **
 ** New error codes may be added in future versions of SQLite.
 **
-** See also: [SQLITE_IOERR_READ | extended result codes],
-** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
+** See also: [extended result code definitions]
 */
 #define SQLITE_OK           0   /* Successful result */
 /* beginning-of-error-codes */
@@ -406,32 +423,27 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_FORMAT      24   /* Auxiliary database format error */
 #define SQLITE_RANGE       25   /* 2nd parameter to sqlite3_bind out of range */
 #define SQLITE_NOTADB      26   /* File opened that is not a database file */
+#define SQLITE_NOTICE      27   /* Notifications from sqlite3_log() */
+#define SQLITE_WARNING     28   /* Warnings from sqlite3_log() */
 #define SQLITE_ROW         100  /* sqlite3_step() has another row ready */
 #define SQLITE_DONE        101  /* sqlite3_step() has finished executing */
 /* end-of-error-codes */
 
 /*
 ** CAPI3REF: Extended Result Codes
-** KEYWORDS: {extended error code} {extended error codes}
-** KEYWORDS: {extended result code} {extended result codes}
+** KEYWORDS: {extended result code definitions}
 **
-** In its default configuration, SQLite API routines return one of 26 integer
-** [SQLITE_OK | result codes].  However, experience has shown that many of
+** In its default configuration, SQLite API routines return one of 30 integer
+** [result codes].  However, experience has shown that many of
 ** these result codes are too coarse-grained.  They do not provide as
 ** much information about problems as programmers might like.  In an effort to
 ** address this, newer versions of SQLite (version 3.3.8 and later) include
 ** support for additional result codes that provide more detailed information
-** about errors. The extended result codes are enabled or disabled
+** about errors. These [extended result codes] are enabled or disabled
 ** on a per database connection basis using the
-** [sqlite3_extended_result_codes()] API.
-**
-** Some of the available extended result codes are listed here.
-** One may expect the number of extended result codes will be expand
-** over time.  Software that uses extended result codes should expect
-** to see new result codes in future releases of SQLite.
-**
-** The SQLITE_OK result code will never be extended.  It will always
-** be exactly zero.
+** [sqlite3_extended_result_codes()] API.  Or, the extended code for
+** the most recent error can be obtained using
+** [sqlite3_extended_errcode()].
 */
 #define SQLITE_IOERR_READ              (SQLITE_IOERR | (1<<8))
 #define SQLITE_IOERR_SHORT_READ        (SQLITE_IOERR | (2<<8))
@@ -455,12 +467,36 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
 #define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
 #define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
+#define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
+#define SQLITE_IOERR_MMAP              (SQLITE_IOERR | (24<<8))
+#define SQLITE_IOERR_GETTEMPPATH       (SQLITE_IOERR | (25<<8))
+#define SQLITE_IOERR_CONVPATH          (SQLITE_IOERR | (26<<8))
 #define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
 #define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
+#define SQLITE_BUSY_SNAPSHOT           (SQLITE_BUSY   |  (2<<8))
 #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
+#define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
+#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
+#define SQLITE_CANTOPEN_CONVPATH       (SQLITE_CANTOPEN | (4<<8))
 #define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
 #define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
 #define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
+#define SQLITE_READONLY_ROLLBACK       (SQLITE_READONLY | (3<<8))
+#define SQLITE_READONLY_DBMOVED        (SQLITE_READONLY | (4<<8))
+#define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
+#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
+#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
+#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
+#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
+#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
+#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
+#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
+#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
+#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
+#define SQLITE_CONSTRAINT_ROWID        (SQLITE_CONSTRAINT |(10<<8))
+#define SQLITE_NOTICE_RECOVER_WAL      (SQLITE_NOTICE | (1<<8))
+#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
+#define SQLITE_WARNING_AUTOINDEX       (SQLITE_WARNING | (1<<8))
 
 /*
 ** CAPI3REF: Flags For File Open Operations
@@ -476,6 +512,7 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_OPEN_EXCLUSIVE        0x00000010  /* VFS only */
 #define SQLITE_OPEN_AUTOPROXY        0x00000020  /* VFS only */
 #define SQLITE_OPEN_URI              0x00000040  /* Ok for sqlite3_open_v2() */
+#define SQLITE_OPEN_MEMORY           0x00000080  /* Ok for sqlite3_open_v2() */
 #define SQLITE_OPEN_MAIN_DB          0x00000100  /* VFS only */
 #define SQLITE_OPEN_TEMP_DB          0x00000200  /* VFS only */
 #define SQLITE_OPEN_TRANSIENT_DB     0x00000400  /* VFS only */
@@ -495,7 +532,7 @@ SQLITE_API int sqlite3_exec(
 ** CAPI3REF: Device Characteristics
 **
 ** The xDeviceCharacteristics method of the [sqlite3_io_methods]
-** object returns an integer which is a vector of the these
+** object returns an integer which is a vector of these
 ** bit values expressing I/O characteristics of the mass storage
 ** device that holds the file that the [sqlite3_io_methods]
 ** refers to.
@@ -509,7 +546,15 @@ SQLITE_API int sqlite3_exec(
 ** first then the size of the file is extended, never the other
 ** way around.  The SQLITE_IOCAP_SEQUENTIAL property means that
 ** information is written to disk in the same order as calls
-** to xWrite().
+** to xWrite().  The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that
+** after reboot following a crash or power loss, the only bytes in a
+** file that were written at the application level might have changed
+** and that adjacent bytes, even bytes within the same sector are
+** guaranteed to be unchanged.  The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
+** flag indicate that a file cannot be deleted when open.  The
+** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
+** read-only media and cannot be changed even by processes with
+** elevated privileges.
 */
 #define SQLITE_IOCAP_ATOMIC                 0x00000001
 #define SQLITE_IOCAP_ATOMIC512              0x00000002
@@ -523,6 +568,8 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_IOCAP_SAFE_APPEND            0x00000200
 #define SQLITE_IOCAP_SEQUENTIAL             0x00000400
 #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN  0x00000800
+#define SQLITE_IOCAP_POWERSAFE_OVERWRITE    0x00001000
+#define SQLITE_IOCAP_IMMUTABLE              0x00002000
 
 /*
 ** CAPI3REF: File Locking Levels
@@ -629,7 +676,7 @@ struct sqlite3_file {
 ** locking strategy (for example to use dot-file locks), to inquire
 ** about the status of a lock, or to break stale locks.  The SQLite
 ** core reserves all opcodes less than 100 for its own use.
-** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
+** A [file control opcodes | list of opcodes] less than 100 is available.
 ** Applications that define a custom xFileControl method should use opcodes
 ** greater than 100 to avoid conflicts.  VFS implementations should
 ** return [SQLITE_NOTFOUND] for file control opcodes that they do not
@@ -694,11 +741,15 @@ struct sqlite3_io_methods {
   void (*xShmBarrier)(sqlite3_file*);
   int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
   /* Methods above are valid for version 2 */
+  int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
+  int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
+  /* Methods above are valid for version 3 */
   /* Additional methods may be added in future releases */
 };
 
 /*
 ** CAPI3REF: Standard File Control Opcodes
+** KEYWORDS: {file control opcodes} {file control opcode}
 **
 ** These integer constants are opcodes for the xFileControl method
 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
@@ -711,7 +762,8 @@ struct sqlite3_io_methods {
 ** into an integer that the pArg argument points to. This capability
 ** is used during testing and only needs to be supported when SQLITE_TEST
 ** is defined.
-**
+** <ul>
+** <li>[[SQLITE_FCNTL_SIZE_HINT]]
 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
 ** layer a hint of how large the database file will grow to be during the
 ** current transaction.  This hint is not guaranteed to be accurate but it
@@ -719,6 +771,7 @@ struct sqlite3_io_methods {
 ** file space based on this hint in order to help writes to the database
 ** file run faster.
 **
+** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
 ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
 ** extends and truncates the database file in chunks of a size specified
 ** by the user. The fourth argument to [sqlite3_file_control()] should 
@@ -727,29 +780,46 @@ struct sqlite3_io_methods {
 ** chunks (say 1MB at a time), may reduce file-system fragmentation and
 ** improve performance on some systems.
 **
+** <li>[[SQLITE_FCNTL_FILE_POINTER]]
 ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
 ** to the [sqlite3_file] object associated with a particular database
 ** connection.  See the [sqlite3_file_control()] documentation for
 ** additional information.
 **
-** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
-** SQLite and sent to all VFSes in place of a call to the xSync method
-** when the database connection has [PRAGMA synchronous] set to OFF.)^
-** Some specialized VFSes need this signal in order to operate correctly
-** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
-** VFSes do not need this signal and should silently ignore this opcode.
-** Applications should not call [sqlite3_file_control()] with this
-** opcode as doing so may disrupt the operation of the specialized VFSes
-** that do require it.  
-**
+** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
+** No longer in use.
+**
+** <li>[[SQLITE_FCNTL_SYNC]]
+** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
+** sent to the VFS immediately before the xSync method is invoked on a
+** database file descriptor. Or, if the xSync method is not invoked 
+** because the user has configured SQLite with 
+** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place 
+** of the xSync method. In most cases, the pointer argument passed with
+** this file-control is NULL. However, if the database file is being synced
+** as part of a multi-database commit, the argument points to a nul-terminated
+** string containing the transactions master-journal file name. VFSes that 
+** do not need this signal should silently ignore this opcode. Applications 
+** should not call [sqlite3_file_control()] with this opcode as doing so may 
+** disrupt the operation of the specialized VFSes that do require it.  
+**
+** <li>[[SQLITE_FCNTL_COMMIT_PHASETWO]]
+** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite
+** and sent to the VFS after a transaction has been committed immediately
+** but before the database is unlocked. VFSes that do not need this signal
+** should silently ignore this opcode. Applications should not call
+** [sqlite3_file_control()] with this opcode as doing so may disrupt the 
+** operation of the specialized VFSes that do require it.  
+**
+** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
 ** retry counts and intervals for certain disk I/O operations for the
-** windows [VFS] in order to work to provide robustness against
+** windows [VFS] in order to provide robustness in the presence of
 ** anti-virus programs.  By default, the windows VFS will retry file read,
-** file write, and file delete opertions up to 10 times, with a delay
+** file write, and file delete operations up to 10 times, with a delay
 ** of 25 milliseconds before the first retry and with the delay increasing
 ** by an additional 25 milliseconds with each subsequent retry.  This
-** opcode allows those to values (10 retries and 25 milliseconds of delay)
+** opcode allows these two values (10 retries and 25 milliseconds of delay)
 ** to be adjusted.  The values are changed for all database connections
 ** within the same process.  The argument is a pointer to an array of two
 ** integers where the first integer i the new retry count and the second
@@ -758,8 +828,9 @@ struct sqlite3_io_methods {
 ** into the array entry, allowing the current retry settings to be
 ** interrogated.  The zDbName parameter is ignored.
 **
+** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
 ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
-** persistent [WAL | Write AHead Log] setting.  By default, the auxiliary
+** persistent [WAL | Write Ahead Log] setting.  By default, the auxiliary
 ** write ahead log and shared memory files used for transaction control
 ** are automatically deleted when the latest connection to the database
 ** closes.  Setting persistent WAL mode causes those files to persist after
@@ -771,18 +842,133 @@ struct sqlite3_io_methods {
 ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
 ** WAL mode.  If the integer is -1, then it is overwritten with the current
 ** WAL persistence setting.
-** 
+**
+** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]]
+** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
+** persistent "powersafe-overwrite" or "PSOW" setting.  The PSOW setting
+** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
+** xDeviceCharacteristics methods. The fourth parameter to
+** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
+** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
+** mode.  If the integer is -1, then it is overwritten with the current
+** zero-damage mode setting.
+**
+** <li>[[SQLITE_FCNTL_OVERWRITE]]
+** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
+** a write transaction to indicate that, unless it is rolled back for some
+** reason, the entire database file will be overwritten by the current 
+** transaction. This is used by VACUUM operations.
+**
+** <li>[[SQLITE_FCNTL_VFSNAME]]
+** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
+** all [VFSes] in the VFS stack.  The names are of all VFS shims and the
+** final bottom-level VFS are written into memory obtained from 
+** [sqlite3_malloc()] and the result is stored in the char* variable
+** that the fourth parameter of [sqlite3_file_control()] points to.
+** The caller is responsible for freeing the memory when done.  As with
+** all file-control actions, there is no guarantee that this will actually
+** do anything.  Callers should initialize the char* variable to a NULL
+** pointer in case this file-control is not implemented.  This file-control
+** is intended for diagnostic use only.
+**
+** <li>[[SQLITE_FCNTL_PRAGMA]]
+** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] 
+** file control is sent to the open [sqlite3_file] object corresponding
+** to the database file to which the pragma statement refers. ^The argument
+** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
+** pointers to strings (char**) in which the second element of the array
+** is the name of the pragma and the third element is the argument to the
+** pragma or NULL if the pragma has no argument.  ^The handler for an
+** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element
+** of the char** argument point to a string obtained from [sqlite3_mprintf()]
+** or the equivalent and that string will become the result of the pragma or
+** the error message if the pragma fails. ^If the
+** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal 
+** [PRAGMA] processing continues.  ^If the [SQLITE_FCNTL_PRAGMA]
+** file control returns [SQLITE_OK], then the parser assumes that the
+** VFS has handled the PRAGMA itself and the parser generates a no-op
+** prepared statement.  ^If the [SQLITE_FCNTL_PRAGMA] file control returns
+** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
+** that the VFS encountered an error while handling the [PRAGMA] and the
+** compilation of the PRAGMA fails with an error.  ^The [SQLITE_FCNTL_PRAGMA]
+** file control occurs at the beginning of pragma statement analysis and so
+** it is able to override built-in [PRAGMA] statements.
+**
+** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
+** ^The [SQLITE_FCNTL_BUSYHANDLER]
+** file-control may be invoked by SQLite on the database file handle
+** shortly after it is opened in order to provide a custom VFS with access
+** to the connections busy-handler callback. The argument is of type (void **)
+** - an array of two (void *) values. The first (void *) actually points
+** to a function of type (int (*)(void *)). In order to invoke the connections
+** busy-handler, this function should be invoked with the second (void *) in
+** the array as the only argument. If it returns non-zero, then the operation
+** should be retried. If it returns zero, the custom VFS should abandon the
+** current operation.
+**
+** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
+** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
+** to have SQLite generate a
+** temporary filename using the same algorithm that is followed to generate
+** temporary filenames for TEMP tables and other internal uses.  The
+** argument should be a char** which will be filled with the filename
+** written into memory obtained from [sqlite3_malloc()].  The caller should
+** invoke [sqlite3_free()] on the result to avoid a memory leak.
+**
+** <li>[[SQLITE_FCNTL_MMAP_SIZE]]
+** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the
+** maximum number of bytes that will be used for memory-mapped I/O.
+** The argument is a pointer to a value of type sqlite3_int64 that
+** is an advisory maximum number of bytes in the file to memory map.  The
+** pointer is overwritten with the old value.  The limit is not changed if
+** the value originally pointed to is negative, and so the current limit 
+** can be queried by passing in a pointer to a negative number.  This
+** file-control is used internally to implement [PRAGMA mmap_size].
+**
+** <li>[[SQLITE_FCNTL_TRACE]]
+** The [SQLITE_FCNTL_TRACE] file control provides advisory information
+** to the VFS about what the higher layers of the SQLite stack are doing.
+** This file control is used by some VFS activity tracing [shims].
+** The argument is a zero-terminated string.  Higher layers in the
+** SQLite stack may generate instances of this file control if
+** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled.
+**
+** <li>[[SQLITE_FCNTL_HAS_MOVED]]
+** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
+** pointer to an integer and it writes a boolean into that integer depending
+** on whether or not the file has been renamed, moved, or deleted since it
+** was first opened.
+**
+** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
+** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging.  This
+** opcode causes the xFileControl method to swap the file handle with the one
+** pointed to by the pArg argument.  This capability is used during testing
+** and only needs to be supported when SQLITE_TEST is defined.
+**
+** </ul>
 */
-#define SQLITE_FCNTL_LOCKSTATE        1
-#define SQLITE_GET_LOCKPROXYFILE      2
-#define SQLITE_SET_LOCKPROXYFILE      3
-#define SQLITE_LAST_ERRNO             4
-#define SQLITE_FCNTL_SIZE_HINT        5
-#define SQLITE_FCNTL_CHUNK_SIZE       6
-#define SQLITE_FCNTL_FILE_POINTER     7
-#define SQLITE_FCNTL_SYNC_OMITTED     8
-#define SQLITE_FCNTL_WIN32_AV_RETRY   9
-#define SQLITE_FCNTL_PERSIST_WAL     10
+#define SQLITE_FCNTL_LOCKSTATE               1
+#define SQLITE_GET_LOCKPROXYFILE             2
+#define SQLITE_SET_LOCKPROXYFILE             3
+#define SQLITE_LAST_ERRNO                    4
+#define SQLITE_FCNTL_SIZE_HINT               5
+#define SQLITE_FCNTL_CHUNK_SIZE              6
+#define SQLITE_FCNTL_FILE_POINTER            7
+#define SQLITE_FCNTL_SYNC_OMITTED            8
+#define SQLITE_FCNTL_WIN32_AV_RETRY          9
+#define SQLITE_FCNTL_PERSIST_WAL            10
+#define SQLITE_FCNTL_OVERWRITE              11
+#define SQLITE_FCNTL_VFSNAME                12
+#define SQLITE_FCNTL_POWERSAFE_OVERWRITE    13
+#define SQLITE_FCNTL_PRAGMA                 14
+#define SQLITE_FCNTL_BUSYHANDLER            15
+#define SQLITE_FCNTL_TEMPFILENAME           16
+#define SQLITE_FCNTL_MMAP_SIZE              18
+#define SQLITE_FCNTL_TRACE                  19
+#define SQLITE_FCNTL_HAS_MOVED              20
+#define SQLITE_FCNTL_SYNC                   21
+#define SQLITE_FCNTL_COMMIT_PHASETWO        22
+#define SQLITE_FCNTL_WIN32_SET_HANDLE       23
 
 /*
 ** CAPI3REF: Mutex Handle
@@ -837,7 +1023,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
 ** from xFullPathname() with an optional suffix added.
 ** ^If a suffix is added to the zFilename parameter, it will
 ** consist of a single "-" character followed by no more than
-** 10 alphanumeric and/or "-" characters.
+** 11 alphanumeric and/or "-" characters.
 ** ^SQLite further guarantees that
 ** the string will be valid and unchanged until xClose() is
 ** called. Because of the previous sentence,
@@ -1227,7 +1413,7 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
 ** or [sqlite3_realloc()] first calls xRoundup.  If xRoundup returns 0, 
 ** that causes the corresponding memory allocation to fail.
 **
-** The xInit method initializes the memory allocator.  (For example,
+** The xInit method initializes the memory allocator.  For example,
 ** it might allocate any require mutexes or initialize internal data
 ** structures.  The xShutdown method is invoked (indirectly) by
 ** [sqlite3_shutdown()] and should deallocate any resources acquired
@@ -1368,7 +1554,7 @@ struct sqlite3_mem_methods {
 ** <dd> ^This option specifies a static memory buffer that SQLite can use for
 ** the database page cache with the default page cache implementation.  
 ** This configuration should not be used if an application-define page
-** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
+** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option.
 ** There are three arguments to this option: A pointer to 8-byte aligned
 ** memory, the size of each page buffer (sz), and the number of pages (N).
 ** The sz argument should be the size of the largest database page
@@ -1399,8 +1585,8 @@ struct sqlite3_mem_methods {
 ** allocator is engaged to handle all of SQLites memory allocation needs.
 ** The first pointer (the memory pointer) must be aligned to an 8-byte
 ** boundary or subsequent behavior of SQLite will be undefined.
-** The minimum allocation size is capped at 2^12. Reasonable values
-** for the minimum allocation size are 2^5 through 2^8.</dd>
+** The minimum allocation size is capped at 2**12. Reasonable values
+** for the minimum allocation size are 2**5 through 2**8.</dd>
 **
 ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
 ** <dd> ^(This option takes a single argument which is a pointer to an
@@ -1437,19 +1623,21 @@ struct sqlite3_mem_methods {
 ** verb to [sqlite3_db_config()] can be used to change the lookaside
 ** configuration on individual connections.)^ </dd>
 **
-** [[SQLITE_CONFIG_PCACHE]] <dt>SQLITE_CONFIG_PCACHE</dt>
+** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt>
 ** <dd> ^(This option takes a single argument which is a pointer to
-** an [sqlite3_pcache_methods] object.  This object specifies the interface
+** an [sqlite3_pcache_methods2] object.  This object specifies the interface
 ** to a custom page cache implementation.)^  ^SQLite makes a copy of the
 ** object and uses it for page cache memory allocations.</dd>
 **
-** [[SQLITE_CONFIG_GETPCACHE]] <dt>SQLITE_CONFIG_GETPCACHE</dt>
+** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt>
 ** <dd> ^(This option takes a single argument which is a pointer to an
-** [sqlite3_pcache_methods] object.  SQLite copies of the current
+** [sqlite3_pcache_methods2] object.  SQLite copies of the current
 ** page cache implementation into that object.)^ </dd>
 **
 ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
-** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
+** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite
+** global [error log].
+** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
 ** function with a call signature of void(*)(void*,int,const char*), 
 ** and a pointer to void. ^If the function pointer is not NULL, it is
 ** invoked by [sqlite3_log()] to process each logging event.  ^If the
@@ -1467,17 +1655,73 @@ struct sqlite3_mem_methods {
 ** function must be threadsafe. </dd>
 **
 ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
-** <dd> This option takes a single argument of type int. If non-zero, then
+** <dd>^(This option takes a single argument of type int. If non-zero, then
 ** URI handling is globally enabled. If the parameter is zero, then URI handling
-** is globally disabled. If URI handling is globally enabled, all filenames
+** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
 ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
 ** specified as part of [ATTACH] commands are interpreted as URIs, regardless
 ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
-** connection is opened. If it is globally disabled, filenames are
+** connection is opened. ^If it is globally disabled, filenames are
 ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
-** database connection is opened. By default, URI handling is globally
+** database connection is opened. ^(By default, URI handling is globally
 ** disabled. The default value may be changed by compiling with the
-** [SQLITE_USE_URI] symbol defined.
+** [SQLITE_USE_URI] symbol defined.)^
+**
+** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
+** <dd>^This option takes a single integer argument which is interpreted as
+** a boolean in order to enable or disable the use of covering indices for
+** full table scans in the query optimizer.  ^The default setting is determined
+** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
+** if that compile-time option is omitted.
+** The ability to disable the use of covering indices for full table scans
+** is because some incorrectly coded legacy applications might malfunction
+** when the optimization is enabled.  Providing the ability to
+** disable the optimization allows the older, buggy application code to work
+** without change even with newer versions of SQLite.
+**
+** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
+** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
+** <dd> These options are obsolete and should not be used by new code.
+** They are retained for backwards compatibility but are now no-ops.
+** </dd>
+**
+** [[SQLITE_CONFIG_SQLLOG]]
+** <dt>SQLITE_CONFIG_SQLLOG
+** <dd>This option is only available if sqlite is compiled with the
+** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should
+** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
+** The second should be of type (void*). The callback is invoked by the library
+** in three separate circumstances, identified by the value passed as the
+** fourth parameter. If the fourth parameter is 0, then the database connection
+** passed as the second argument has just been opened. The third argument
+** points to a buffer containing the name of the main database file. If the
+** fourth parameter is 1, then the SQL statement that the third parameter
+** points to has just been executed. Or, if the fourth parameter is 2, then
+** the connection being passed as the second parameter is being closed. The
+** third parameter is passed NULL In this case.  An example of using this
+** configuration option can be seen in the "test_sqllog.c" source file in
+** the canonical SQLite source tree.</dd>
+**
+** [[SQLITE_CONFIG_MMAP_SIZE]]
+** <dt>SQLITE_CONFIG_MMAP_SIZE
+** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
+** that are the default mmap size limit (the default setting for
+** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
+** ^The default setting can be overridden by each database connection using
+** either the [PRAGMA mmap_size] command, or by using the
+** [SQLITE_FCNTL_MMAP_SIZE] file control.  ^(The maximum allowed mmap size
+** cannot be changed at run-time.  Nor may the maximum allowed mmap size
+** exceed the compile-time maximum mmap size set by the
+** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
+** ^If either argument to this option is negative, then that argument is
+** changed to its compile-time default.
+**
+** [[SQLITE_CONFIG_WIN32_HEAPSIZE]]
+** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
+** <dd>^This option is only available if SQLite is compiled for Windows
+** with the [SQLITE_WIN32_MALLOC] pre-processor macro defined.
+** SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
+** that specifies the maximum size of the created heap.
 ** </dl>
 */
 #define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
@@ -1493,10 +1737,16 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */
 /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ 
 #define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
-#define SQLITE_CONFIG_PCACHE       14  /* sqlite3_pcache_methods* */
-#define SQLITE_CONFIG_GETPCACHE    15  /* sqlite3_pcache_methods* */
+#define SQLITE_CONFIG_PCACHE       14  /* no-op */
+#define SQLITE_CONFIG_GETPCACHE    15  /* no-op */
 #define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
 #define SQLITE_CONFIG_URI          17  /* int */
+#define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
+#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
+#define SQLITE_CONFIG_MMAP_SIZE    22  /* sqlite3_int64, sqlite3_int64 */
+#define SQLITE_CONFIG_WIN32_HEAPSIZE      23  /* int nByte */
 
 /*
 ** CAPI3REF: Database Connection Configuration Options
@@ -1573,19 +1823,21 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
 /*
 ** CAPI3REF: Last Insert Rowid
 **
-** ^Each entry in an SQLite table has a unique 64-bit signed
+** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables)
+** has a unique 64-bit signed
 ** integer key called the [ROWID | "rowid"]. ^The rowid is always available
 ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
 ** names are not also used by explicitly declared columns. ^If
 ** the table has a column of type [INTEGER PRIMARY KEY] then that column
 ** is another alias for the rowid.
 **
-** ^This routine returns the [rowid] of the most recent
-** successful [INSERT] into the database from the [database connection]
-** in the first argument.  ^As of SQLite version 3.7.7, this routines
-** records the last insert rowid of both ordinary tables and [virtual tables].
-** ^If no successful [INSERT]s
-** have ever occurred on that database connection, zero is returned.
+** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the 
+** most recent successful [INSERT] into a rowid table or [virtual table]
+** on database connection D.
+** ^Inserts into [WITHOUT ROWID] tables are not recorded.
+** ^If no successful [INSERT]s into rowid tables
+** have ever occurred on the database connection D, 
+** then sqlite3_last_insert_rowid(D) returns zero.
 **
 ** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
 ** method, then this routine will return the [rowid] of the inserted
@@ -1777,27 +2029,33 @@ SQLITE_API int sqlite3_complete16(const void *sql);
 /*
 ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
 **
-** ^This routine sets a callback function that might be invoked whenever
-** an attempt is made to open a database table that another thread
-** or process has locked.
+** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
+** that might be invoked with argument P whenever
+** an attempt is made to access a database table associated with
+** [database connection] D when another thread
+** or process has the table locked.
+** The sqlite3_busy_handler() interface is used to implement
+** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
 **
-** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
+** ^If the busy callback is NULL, then [SQLITE_BUSY]
 ** is returned immediately upon encountering the lock.  ^If the busy callback
 ** is not NULL, then the callback might be invoked with two arguments.
 **
 ** ^The first argument to the busy handler is a copy of the void* pointer which
 ** is the third argument to sqlite3_busy_handler().  ^The second argument to
 ** the busy handler callback is the number of times that the busy handler has
-** been invoked for this locking event.  ^If the
+** been invoked for the same locking event.  ^If the
 ** busy callback returns 0, then no additional attempts are made to
-** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
+** access the database and [SQLITE_BUSY] is returned
+** to the application.
 ** ^If the callback returns non-zero, then another attempt
-** is made to open the database for reading and the cycle repeats.
+** is made to access the database and the cycle repeats.
 **
 ** The presence of a busy handler does not guarantee that it will be invoked
 ** when there is lock contention. ^If SQLite determines that invoking the busy
 ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
-** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
+** to the application instead of invoking the 
+** busy handler.
 ** Consider a scenario where one process is holding a read lock that
 ** it is trying to promote to a reserved lock and
 ** a second process is holding a reserved lock that it is trying
@@ -1811,28 +2069,15 @@ SQLITE_API int sqlite3_complete16(const void *sql);
 **
 ** ^The default busy callback is NULL.
 **
-** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
-** when SQLite is in the middle of a large transaction where all the
-** changes will not fit into the in-memory cache.  SQLite will
-** already hold a RESERVED lock on the database file, but it needs
-** to promote this lock to EXCLUSIVE so that it can spill cache
-** pages into the database file without harm to concurrent
-** readers.  ^If it is unable to promote the lock, then the in-memory
-** cache will be left in an inconsistent state and so the error
-** code is promoted from the relatively benign [SQLITE_BUSY] to
-** the more severe [SQLITE_IOERR_BLOCKED].  ^This error code promotion
-** forces an automatic rollback of the changes.  See the
-** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
-** CorruptionFollowingBusyError</a> wiki page for a discussion of why
-** this is important.
-**
 ** ^(There can only be a single busy handler defined for each
 ** [database connection].  Setting a new busy handler clears any
 ** previously set handler.)^  ^Note that calling [sqlite3_busy_timeout()]
-** will also set or clear the busy handler.
+** or evaluating [PRAGMA busy_timeout=N] will change the
+** busy handler and thus clear any previously set busy handler.
 **
 ** The busy callback should not take any actions which modify the
-** database connection that invoked the busy handler.  Any such actions
+** database connection that invoked the busy handler.  In other words,
+** the busy handler is not reentrant.  Any such actions
 ** result in undefined behavior.
 ** 
 ** A busy handler must not close the database connection
@@ -1848,7 +2093,7 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
 ** will sleep multiple times until at least "ms" milliseconds of sleeping
 ** have accumulated.  ^After at least "ms" milliseconds of sleeping,
 ** the handler returns 0 which causes [sqlite3_step()] to return
-** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
+** [SQLITE_BUSY].
 **
 ** ^Calling this routine with an argument less than or equal to zero
 ** turns off all busy handlers.
@@ -1857,6 +2102,8 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
 ** [database connection] any any given moment.  If another busy handler
 ** was defined  (using [sqlite3_busy_handler()]) prior to calling
 ** this routine, that other busy handler is cleared.)^
+**
+** See also:  [PRAGMA busy_timeout]
 */
 SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
 
@@ -1981,7 +2228,7 @@ SQLITE_API void sqlite3_free_table(char **result);
 ** All of the usual printf() formatting options apply.  In addition, there
 ** is are "%q", "%Q", and "%z" options.
 **
-** ^(The %q option works like %s in that it substitutes a null-terminated
+** ^(The %q option works like %s in that it substitutes a nul-terminated
 ** string from the argument list.  But %q also doubles every '\'' character.
 ** %q is designed for use inside a string literal.)^  By doubling each '\''
 ** character it escapes that character and allows it to be inserted into
@@ -2094,12 +2341,12 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
 ** implementation of these routines to be omitted.  That capability
 ** is no longer provided.  Only built-in memory allocators can be used.
 **
-** The Windows OS interface layer calls
+** Prior to SQLite version 3.7.10, the Windows OS interface layer called
 ** the system malloc() and free() directly when converting
 ** filenames between the UTF-8 encoding used by SQLite
 ** and whatever filename encoding is used by the particular Windows
-** installation.  Memory allocation errors are detected, but
-** they are reported back as [SQLITE_CANTOPEN] or
+** installation.  Memory allocation errors were detected, but
+** they were reported back as [SQLITE_CANTOPEN] or
 ** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
 **
 ** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
@@ -2151,11 +2398,13 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
 ** applications to access the same PRNG for other purposes.
 **
 ** ^A call to this routine stores N bytes of randomness into buffer P.
+** ^If N is less than one, then P can be a NULL pointer.
 **
-** ^The first time this routine is invoked (either internally or by
-** the application) the PRNG is seeded using randomness obtained
-** from the xRandomness method of the default [sqlite3_vfs] object.
-** ^On all subsequent invocations, the pseudo-randomness is generated
+** ^If this routine has not been previously called or if the previous
+** call had N less than one, then the PRNG is seeded using randomness
+** obtained from the xRandomness method of the default [sqlite3_vfs] object.
+** ^If the previous call to this routine had an N of 1 or more then
+** the pseudo-randomness is generated
 ** internally and without recourse to the [sqlite3_vfs] xRandomness
 ** method.
 */
@@ -2256,8 +2505,8 @@ SQLITE_API int sqlite3_set_authorizer(
 ** [sqlite3_set_authorizer | authorizer documentation] for additional
 ** information.
 **
-** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
-** from the [sqlite3_vtab_on_conflict()] interface.
+** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
+** returned from the [sqlite3_vtab_on_conflict()] interface.
 */
 #define SQLITE_DENY   1   /* Abort the SQL statement with an error */
 #define SQLITE_IGNORE 2   /* Don't allow access, but don't generate an error */
@@ -2315,6 +2564,7 @@ SQLITE_API int sqlite3_set_authorizer(
 #define SQLITE_FUNCTION             31   /* NULL            Function Name   */
 #define SQLITE_SAVEPOINT            32   /* Operation       Savepoint Name  */
 #define SQLITE_COPY                  0   /* No longer used */
+#define SQLITE_RECURSIVE            33   /* NULL            NULL            */
 
 /*
 ** CAPI3REF: Tracing And Profiling Functions
@@ -2330,6 +2580,9 @@ SQLITE_API int sqlite3_set_authorizer(
 ** as each triggered subprogram is entered.  The callbacks for triggers
 ** contain a UTF-8 SQL comment that identifies the trigger.)^
 **
+** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit
+** the length of [bound parameter] expansion in the output of sqlite3_trace().
+**
 ** ^The callback function registered by sqlite3_profile() is invoked
 ** as each SQL statement finishes.  ^The profile callback contains
 ** the original statement text and an estimate of wall-clock time
@@ -2355,9 +2608,10 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
 ** interface is to keep a GUI updated during a large query.
 **
 ** ^The parameter P is passed through as the only parameter to the 
-** callback function X.  ^The parameter N is the number of 
+** callback function X.  ^The parameter N is the approximate number of 
 ** [virtual machine instructions] that are evaluated between successive
-** invocations of the callback X.
+** invocations of the callback X.  ^If N is less than one then the progress
+** handler is disabled.
 **
 ** ^Only a single progress handler may be defined at one time per
 ** [database connection]; setting a new progress handler cancels the
@@ -2500,18 +2754,20 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     present, then the VFS specified by the option takes precedence over
 **     the value passed as the fourth parameter to sqlite3_open_v2().
 **
-**   <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
-**     "rwc". Attempting to set it to any other value is an error)^. 
+**   <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw",
+**     "rwc", or "memory". Attempting to set it to any other value is
+**     an error)^. 
 **     ^If "ro" is specified, then the database is opened for read-only 
 **     access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the 
-**     third argument to sqlite3_prepare_v2(). ^If the mode option is set to 
+**     third argument to sqlite3_open_v2(). ^If the mode option is set to 
 **     "rw", then the database is opened for read-write (but not create) 
 **     access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had 
 **     been set. ^Value "rwc" is equivalent to setting both 
-**     SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is 
-**     used, it is an error to specify a value for the mode parameter that is 
-**     less restrictive than that specified by the flags passed as the third 
-**     parameter.
+**     SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.  ^If the mode option is
+**     set to "memory" then a pure [in-memory database] that never reads
+**     or writes from disk is used. ^It is an error to specify a value for
+**     the mode parameter that is less restrictive than that specified by
+**     the flags passed in the third parameter to sqlite3_open_v2().
 **
 **   <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
 **     "private". ^Setting it to "shared" is equivalent to setting the
@@ -2519,8 +2775,32 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
 **     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
 **     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
-**     a URI filename, its value overrides any behaviour requested by setting
+**     a URI filename, its value overrides any behavior requested by setting
 **     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
+**
+**  <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
+**     "1") or "false" (or "off" or "no" or "0") to indicate that the
+**     [powersafe overwrite] property does or does not apply to the
+**     storage media on which the database file resides.  ^The psow query
+**     parameter only works for the built-in unix and Windows VFSes.
+**
+**  <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
+**     which if set disables file locking in rollback journal modes.  This
+**     is useful for accessing a database on a filesystem that does not
+**     support locking.  Caution:  Database corruption might result if two
+**     or more processes write to the same database and any one of those
+**     processes uses nolock=1.
+**
+**  <li> <b>immutable</b>: ^The immutable parameter is a boolean query
+**     parameter that indicates that the database file is stored on
+**     read-only media.  ^When immutable is set, SQLite assumes that the
+**     database file cannot be changed, even by a process with higher
+**     privilege, and so the database is opened read-only and all locking
+**     and change detection is disabled.  Caution: Setting the immutable
+**     property on a database file that does in fact change can result
+**     in incorrect query results and/or [SQLITE_CORRUPT] errors.
+**     See also: [SQLITE_IOCAP_IMMUTABLE].
+**       
 ** </ul>
 **
 ** ^Specifying an unknown parameter in the query component of a URI is not an
@@ -2550,8 +2830,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **          Open file "data.db" in the current directory for read-only access.
 **          Regardless of whether or not shared-cache mode is enabled by
 **          default, use a private cache.
-** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
-**          Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
+** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
+**          Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
+**          that uses dot-files in place of posix advisory locking.
 ** <tr><td> file:data.db?mode=readonly <td> 
 **          An error. "readonly" is not a valid option for the "mode" parameter.
 ** </table>
@@ -2570,6 +2851,12 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 ** codepage is currently defined.  Filenames containing international
 ** characters must be converted to UTF-8 prior to passing them into
 ** sqlite3_open() or sqlite3_open_v2().
+**
+** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
+** prior to calling sqlite3_open() or sqlite3_open_v2().  Otherwise, various
+** features that require the use of temporary files may fail.
+**
+** See also: [sqlite3_temp_directory]
 */
 SQLITE_API int sqlite3_open(
   const char *filename,   /* Database filename (UTF-8) */
@@ -2589,21 +2876,45 @@ SQLITE_API int sqlite3_open_v2(
 /*
 ** CAPI3REF: Obtain Values For URI Parameters
 **
-** This is a utility routine, useful to VFS implementations, that checks
+** These are utility routines, useful to VFS implementations, that check
 ** to see if a database file was a URI that contained a specific query 
-** parameter, and if so obtains the value of the query parameter.
-**
-** The zFilename argument is the filename pointer passed into the xOpen()
-** method of a VFS implementation.  The zParam argument is the name of the
-** query parameter we seek.  This routine returns the value of the zParam
-** parameter if it exists.  If the parameter does not exist, this routine
-** returns a NULL pointer.
-**
-** If the zFilename argument to this function is not a pointer that SQLite
-** passed into the xOpen VFS method, then the behavior of this routine
-** is undefined and probably undesirable.
+** parameter, and if so obtains the value of that query parameter.
+**
+** If F is the database filename pointer passed into the xOpen() method of 
+** a VFS implementation when the flags parameter to xOpen() has one or 
+** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
+** P is the name of the query parameter, then
+** sqlite3_uri_parameter(F,P) returns the value of the P
+** parameter if it exists or a NULL pointer if P does not appear as a 
+** query parameter on F.  If P is a query parameter of F
+** has no explicit value, then sqlite3_uri_parameter(F,P) returns
+** a pointer to an empty string.
+**
+** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean
+** parameter and returns true (1) or false (0) according to the value
+** of P.  The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the
+** value of query parameter P is one of "yes", "true", or "on" in any
+** case or if the value begins with a non-zero number.  The 
+** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
+** query parameter P is one of "no", "false", or "off" in any case or
+** if the value begins with a numeric zero.  If P is not a query
+** parameter on F or if the value of P is does not match any of the
+** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
+**
+** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
+** 64-bit signed integer and returns that integer, or D if P does not
+** exist.  If the value of P is something other than an integer, then
+** zero is returned.
+** 
+** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
+** sqlite3_uri_boolean(F,P,B) returns B.  If F is not a NULL pointer and
+** is not a database file pathname pointer that SQLite passed into the xOpen
+** VFS method, then the behavior of this routine is undefined and probably
+** undesirable.
 */
 SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
+SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
+SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
 
 
 /*
@@ -2625,6 +2936,11 @@ SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *
 ** However, the error string might be overwritten or deallocated by
 ** subsequent calls to other SQLite interface functions.)^
 **
+** ^The sqlite3_errstr() interface returns the English-language text
+** that describes the [result code], as UTF-8.
+** ^(Memory to hold the error message string is managed internally
+** and must not be freed by the application)^.
+**
 ** When the serialized [threading mode] is in use, it might be the
 ** case that a second error occurs on a separate thread in between
 ** the time of the first error and the call to these interfaces.
@@ -2643,6 +2959,7 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db);
 SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
 SQLITE_API const char *sqlite3_errmsg(sqlite3*);
 SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *sqlite3_errstr(int);
 
 /*
 ** CAPI3REF: SQL Statement Object
@@ -2799,7 +3116,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
 ** that the supplied string is nul-terminated, then there is a small
 ** performance advantage to be gained by passing an nByte parameter that
 ** is equal to the number of bytes in the input string <i>including</i>
-** the nul-terminator bytes.
+** the nul-terminator bytes as this saves SQLite from having to
+** make a copy of the input string.
 **
 ** ^If pzTail is not NULL then *pzTail is made to point to the first byte
 ** past the end of the first SQL statement in zSql.  These routines only
@@ -2829,7 +3147,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
 ** <li>
 ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it
 ** always used to do, [sqlite3_step()] will automatically recompile the SQL
-** statement and try to run it again.
+** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY]
+** retries will occur before sqlite3_step() gives up and returns an error.
 ** </li>
 **
 ** <li>
@@ -2850,8 +3169,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
 ** ^The specific value of WHERE-clause [parameter] might influence the 
 ** choice of query plan if the parameter is the left-hand side of a [LIKE]
 ** or [GLOB] operator or if the parameter is compared to an indexed column
-** and the [SQLITE_ENABLE_STAT2] compile-time option is enabled.
-** the 
+** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
 ** </li>
 ** </ol>
 */
@@ -2925,6 +3243,25 @@ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
 SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
 
 /*
+** CAPI3REF: Determine If A Prepared Statement Has Been Reset
+**
+** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
+** [prepared statement] S has been stepped at least once using 
+** [sqlite3_step(S)] but has not run to completion and/or has not 
+** been reset using [sqlite3_reset(S)].  ^The sqlite3_stmt_busy(S)
+** interface returns false if S is a NULL pointer.  If S is not a 
+** NULL pointer and is not a pointer to a valid [prepared statement]
+** object, then the behavior is undefined and probably undesirable.
+**
+** This interface can be used in combination [sqlite3_next_stmt()]
+** to locate all prepared statements associated with a database 
+** connection that are in need of being reset.  This can be used,
+** for example, in diagnostic routines to search for prepared 
+** statements that are holding a transaction open.
+*/
+SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
+
+/*
 ** CAPI3REF: Dynamically Typed Value Object
 ** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
 **
@@ -3014,12 +3351,25 @@ typedef struct sqlite3_context sqlite3_context;
 ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
 **
 ** ^The third argument is the value to bind to the parameter.
+** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
+** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
+** is ignored and the end result is the same as sqlite3_bind_null().
 **
 ** ^(In those routines that have a fourth argument, its value is the
 ** number of bytes in the parameter.  To be clear: the value is the
 ** number of <u>bytes</u> in the value, not the number of characters.)^
-** ^If the fourth parameter is negative, the length of the string is
+** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
+** is negative, then the length of the string is
 ** the number of bytes up to the first zero terminator.
+** If the fourth parameter to sqlite3_bind_blob() is negative, then
+** the behavior is undefined.
+** If a non-negative fourth parameter is provided to sqlite3_bind_text()
+** or sqlite3_bind_text16() then that parameter must be the byte offset
+** where the NUL terminator would occur assuming the string were NUL
+** terminated.  If any NUL characters occur at byte offsets less than 
+** the value of the fourth parameter then the resulting string value will
+** contain embedded NULs.  The result of expressions involving strings
+** with embedded NULs is undefined.
 **
 ** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
 ** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
@@ -3353,6 +3703,12 @@ SQLITE_API int sqlite3_step(sqlite3_stmt*);
 ** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
 ** interfaces) then sqlite3_data_count(P) returns 0.
 ** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
+** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
+** [sqlite3_step](P) returned [SQLITE_DONE].  ^The sqlite3_data_count(P)
+** will return non-zero if previous call to [sqlite3_step](P) returned
+** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum]
+** where it always returns zero since each step of that multi-step
+** pragma returns 0 columns of data.
 **
 ** See also: [sqlite3_column_count()]
 */
@@ -3452,7 +3808,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
 ** bytes in the string, not the number of characters.
 **
 ** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(),
-** even empty strings, are always zero terminated.  ^The return
+** even empty strings, are always zero-terminated.  ^The return
 ** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
 **
 ** ^The object returned by [sqlite3_column_value()] is an
@@ -3475,19 +3831,19 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
 **
 ** <tr><td>  NULL    <td> INTEGER   <td> Result is 0
 ** <tr><td>  NULL    <td>  FLOAT    <td> Result is 0.0
-** <tr><td>  NULL    <td>   TEXT    <td> Result is NULL pointer
-** <tr><td>  NULL    <td>   BLOB    <td> Result is NULL pointer
+** <tr><td>  NULL    <td>   TEXT    <td> Result is a NULL pointer
+** <tr><td>  NULL    <td>   BLOB    <td> Result is a NULL pointer
 ** <tr><td> INTEGER  <td>  FLOAT    <td> Convert from integer to float
 ** <tr><td> INTEGER  <td>   TEXT    <td> ASCII rendering of the integer
 ** <tr><td> INTEGER  <td>   BLOB    <td> Same as INTEGER->TEXT
-** <tr><td>  FLOAT   <td> INTEGER   <td> Convert from float to integer
+** <tr><td>  FLOAT   <td> INTEGER   <td> [CAST] to INTEGER
 ** <tr><td>  FLOAT   <td>   TEXT    <td> ASCII rendering of the float
-** <tr><td>  FLOAT   <td>   BLOB    <td> Same as FLOAT->TEXT
-** <tr><td>  TEXT    <td> INTEGER   <td> Use atoi()
-** <tr><td>  TEXT    <td>  FLOAT    <td> Use atof()
+** <tr><td>  FLOAT   <td>   BLOB    <td> [CAST] to BLOB
+** <tr><td>  TEXT    <td> INTEGER   <td> [CAST] to INTEGER
+** <tr><td>  TEXT    <td>  FLOAT    <td> [CAST] to REAL
 ** <tr><td>  TEXT    <td>   BLOB    <td> No change
-** <tr><td>  BLOB    <td> INTEGER   <td> Convert to TEXT then use atoi()
-** <tr><td>  BLOB    <td>  FLOAT    <td> Convert to TEXT then use atof()
+** <tr><td>  BLOB    <td> INTEGER   <td> [CAST] to INTEGER
+** <tr><td>  BLOB    <td>  FLOAT    <td> [CAST] to REAL
 ** <tr><td>  BLOB    <td>   TEXT    <td> Add a zero terminator if needed
 ** </table>
 ** </blockquote>)^
@@ -3543,7 +3899,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
 ** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
 ** [sqlite3_finalize()] is called.  ^The memory space used to hold strings
 ** and BLOBs is freed automatically.  Do <b>not</b> pass the pointers returned
-** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
+** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
 ** [sqlite3_free()].
 **
 ** ^(If a memory allocation error occurs during the evaluation of any
@@ -3652,15 +4008,24 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
 **
 ** ^The fourth parameter, eTextRep, specifies what
 ** [SQLITE_UTF8 | text encoding] this SQL function prefers for
-** its parameters.  Every SQL function implementation must be able to work
-** with UTF-8, UTF-16le, or UTF-16be.  But some implementations may be
-** more efficient with one encoding than another.  ^An application may
-** invoke sqlite3_create_function() or sqlite3_create_function16() multiple
-** times with the same function but with different values of eTextRep.
+** its parameters.  The application should set this parameter to
+** [SQLITE_UTF16LE] if the function implementation invokes 
+** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the
+** implementation invokes [sqlite3_value_text16be()] on an input, or
+** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8]
+** otherwise.  ^The same SQL function may be registered multiple times using
+** different preferred text encodings, with different implementations for
+** each encoding.
 ** ^When multiple implementations of the same function are available, SQLite
 ** will pick the one that involves the least amount of data conversion.
-** If there is only a single implementation which does not care what text
-** encoding is used, then the fourth argument should be [SQLITE_ANY].
+**
+** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC]
+** to signal that the function will always return the same result given
+** the same inputs within a single SQL statement.  Most SQL functions are
+** deterministic.  The built-in [random()] SQL function is an example of a
+** function that is not deterministic.  The SQLite query planner is able to
+** perform additional optimizations on deterministic functions, so use
+** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
 **
 ** ^(The fifth parameter is an arbitrary pointer.  The implementation of the
 ** function can gain access to this pointer using [sqlite3_user_data()].)^
@@ -3746,10 +4111,20 @@ SQLITE_API int sqlite3_create_function_v2(
 #define SQLITE_UTF16LE        2
 #define SQLITE_UTF16BE        3
 #define SQLITE_UTF16          4    /* Use native byte order */
-#define SQLITE_ANY            5    /* sqlite3_create_function only */
+#define SQLITE_ANY            5    /* Deprecated */
 #define SQLITE_UTF16_ALIGNED  8    /* sqlite3_create_collation only */
 
 /*
+** CAPI3REF: Function Flags
+**
+** These constants may be ORed together with the 
+** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
+** to [sqlite3_create_function()], [sqlite3_create_function16()], or
+** [sqlite3_create_function_v2()].
+*/
+#define SQLITE_DETERMINISTIC    0x800
+
+/*
 ** CAPI3REF: Deprecated Functions
 ** DEPRECATED
 **
@@ -3765,7 +4140,8 @@ 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);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
+                      void*,sqlite3_int64);
 #endif
 
 /*
@@ -3845,14 +4221,17 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
 ** In those cases, sqlite3_aggregate_context() might be called for the
 ** first time from within xFinal().)^
 **
-** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer if N is
-** less than or equal to zero or if a memory allocate error occurs.
+** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer 
+** when first called if N is less than or equal to zero or if a memory
+** allocate error occurs.
 **
 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
 ** determined by the N parameter on first successful call.  Changing the
 ** value of N in subsequent call to sqlite3_aggregate_context() within
 ** the same aggregate function instance will not resize the memory
-** allocation.)^
+** allocation.)^  Within the xFinal callback, it is customary to set
+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no 
+** pointless memory allocations occur.
 **
 ** ^SQLite automatically frees the memory allocated by 
 ** sqlite3_aggregate_context() when the aggregate query concludes.
@@ -3895,41 +4274,49 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
 /*
 ** CAPI3REF: Function Auxiliary Data
 **
-** The following two functions may be used by scalar SQL functions to
+** These functions may be used by (non-aggregate) SQL functions to
 ** associate metadata with argument values. If the same value is passed to
 ** multiple invocations of the same SQL function during query execution, under
-** some circumstances the associated metadata may be preserved. This may
-** be used, for example, to add a regular-expression matching scalar
-** function. The compiled version of the regular expression is stored as
-** metadata associated with the SQL value passed as the regular expression
-** pattern.  The compiled regular expression can be reused on multiple
-** invocations of the same function so that the original pattern string
-** does not need to be recompiled on each invocation.
+** some circumstances the associated metadata may be preserved.  An example
+** of where this might be useful is in a regular-expression matching
+** function. The compiled version of the regular expression can be stored as
+** metadata associated with the pattern string.  
+** Then as long as the pattern string remains the same,
+** the compiled regular expression can be reused on multiple
+** invocations of the same function.
 **
 ** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
 ** associated by the sqlite3_set_auxdata() function with the Nth argument
-** value to the application-defined function. ^If no metadata has been ever
-** been set for the Nth argument of the function, or if the corresponding
-** function parameter has changed since the meta-data was set,
-** then sqlite3_get_auxdata() returns a NULL pointer.
-**
-** ^The sqlite3_set_auxdata() interface saves the metadata
-** pointed to by its 3rd parameter as the metadata for the N-th
-** argument of the application-defined function.  Subsequent
-** calls to sqlite3_get_auxdata() might return this data, if it has
-** not been destroyed.
-** ^If it is not NULL, SQLite will invoke the destructor
-** function given by the 4th parameter to sqlite3_set_auxdata() on
-** the metadata when the corresponding function parameter changes
-** or when the SQL statement completes, whichever comes first.
-**
-** SQLite is free to call the destructor and drop metadata on any
-** parameter of any function at any time.  ^The only guarantee is that
-** the destructor will be called before the metadata is dropped.
+** value to the application-defined function. ^If there is no metadata
+** associated with the function argument, this sqlite3_get_auxdata() interface
+** returns a NULL pointer.
+**
+** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
+** argument of the application-defined function.  ^Subsequent
+** calls to sqlite3_get_auxdata(C,N) return P from the most recent
+** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
+** NULL if the metadata has been discarded.
+** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
+** SQLite will invoke the destructor function X with parameter P exactly
+** once, when the metadata is discarded.
+** SQLite is free to discard the metadata at any time, including: <ul>
+** <li> when the corresponding function parameter changes, or
+** <li> when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
+**      SQL statement, or
+** <li> when sqlite3_set_auxdata() is invoked again on the same parameter, or
+** <li> during the original sqlite3_set_auxdata() call when a memory 
+**      allocation error occurs. </ul>)^
+**
+** Note the last bullet in particular.  The destructor X in 
+** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
+** sqlite3_set_auxdata() interface even returns.  Hence sqlite3_set_auxdata()
+** should be called near the end of the function implementation and the
+** function implementation should not make any use of P after
+** sqlite3_set_auxdata() has been called.
 **
 ** ^(In practice, metadata is preserved between function calls for
-** expressions that are constant at compile time. This includes literal
-** values and [parameters].)^
+** function parameters that are compile-time constants, including literal
+** values and [parameters] and expressions composed from the same.)^
 **
 ** These routines must be called from the same thread in which
 ** the SQL function is running.
@@ -3950,7 +4337,7 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi
 ** the content before returning.
 **
 ** The typedef is necessary to work around problems in certain
-** C++ compilers.  See ticket #2191.
+** C++ compilers.
 */
 typedef void (*sqlite3_destructor_type)(void*);
 #define SQLITE_STATIC      ((sqlite3_destructor_type)0)
@@ -4003,11 +4390,11 @@ typedef void (*sqlite3_destructor_type)(void*);
 ** the error code is SQLITE_ERROR.  ^A subsequent call to sqlite3_result_error()
 ** or sqlite3_result_error16() resets the error code to SQLITE_ERROR.
 **
-** ^The sqlite3_result_toobig() interface causes SQLite to throw an error
-** indicating that a string or BLOB is too long to represent.
+** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an
+** error indicating that a string or BLOB is too long to represent.
 **
-** ^The sqlite3_result_nomem() interface causes SQLite to throw an error
-** indicating that a memory allocation failed.
+** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an
+** error indicating that a memory allocation failed.
 **
 ** ^The sqlite3_result_int() interface sets the return value
 ** of the application-defined function to be the 32-bit signed integer
@@ -4032,7 +4419,12 @@ typedef void (*sqlite3_destructor_type)(void*);
 ** ^If the 3rd parameter to the sqlite3_result_text* interfaces
 ** is non-negative, then as many bytes (not characters) of the text
 ** pointed to by the 2nd parameter are taken as the application-defined
-** function result.
+** function result.  If the 3rd parameter is non-negative, then it
+** must be the byte offset into the string where the NUL terminator would
+** appear if the string where NUL terminated.  If any NUL characters occur
+** in the string at a byte offset that is less than the value of the 3rd
+** parameter, then the resulting string will contain embedded NULs and the
+** result of expressions operating on strings with embedded NULs is undefined.
 ** ^If the 4th parameter to the sqlite3_result_text* interfaces
 ** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that
 ** function as the destructor on the text or BLOB result when it has
@@ -4229,6 +4621,11 @@ SQLITE_API int sqlite3_key(
   sqlite3 *db,                   /* Database to be rekeyed */
   const void *pKey, int nKey     /* The key */
 );
+SQLITE_API int sqlite3_key_v2(
+  sqlite3 *db,                   /* Database to be rekeyed */
+  const char *zDbName,           /* Name of the database */
+  const void *pKey, int nKey     /* The key */
+);
 
 /*
 ** Change the key on an open database.  If the current database is not
@@ -4242,6 +4639,11 @@ SQLITE_API int sqlite3_rekey(
   sqlite3 *db,                   /* Database to be rekeyed */
   const void *pKey, int nKey     /* The new key */
 );
+SQLITE_API int sqlite3_rekey_v2(
+  sqlite3 *db,                   /* Database to be rekeyed */
+  const char *zDbName,           /* Name of the database */
+  const void *pKey, int nKey     /* The new key */
+);
 
 /*
 ** Specify the activation key for a SEE database.  Unless 
@@ -4291,6 +4693,13 @@ SQLITE_API int sqlite3_sleep(int);
 ** is a NULL pointer, then SQLite performs a search for an appropriate
 ** temporary file directory.
 **
+** Applications are strongly discouraged from using this global variable.
+** It is required to set a temporary folder on Windows Runtime (WinRT).
+** But for all other platforms, it is highly recommended that applications
+** neither read nor write this variable.  This global variable is a relic
+** that exists for backwards compatibility of legacy applications and should
+** be avoided in new projects.
+**
 ** It is not safe to read or modify this variable in more than one
 ** thread at a time.  It is not safe to read or modify this variable
 ** if a [database connection] is being used at the same time in a separate
@@ -4309,10 +4718,67 @@ SQLITE_API int sqlite3_sleep(int);
 ** Hence, if this variable is modified directly, either it should be
 ** made NULL or made to point to memory obtained from [sqlite3_malloc]
 ** or else the use of the [temp_store_directory pragma] should be avoided.
+** Except when requested by the [temp_store_directory pragma], SQLite
+** does not free the memory that sqlite3_temp_directory points to.  If
+** the application wants that memory to be freed, it must do
+** so itself, taking care to only do so after all [database connection]
+** objects have been destroyed.
+**
+** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
+** prior to calling [sqlite3_open] or [sqlite3_open_v2].  Otherwise, various
+** features that require the use of temporary files may fail.  Here is an
+** example of how to do this using C++ with the Windows Runtime:
+**
+** <blockquote><pre>
+** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
+**       TemporaryFolder->Path->Data();
+** char zPathBuf[MAX_PATH + 1];
+** memset(zPathBuf, 0, sizeof(zPathBuf));
+** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
+**       NULL, NULL);
+** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
+** </pre></blockquote>
 */
 SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory;
 
 /*
+** CAPI3REF: Name Of The Folder Holding Database Files
+**
+** ^(If this global variable is made to point to a string which is
+** the name of a folder (a.k.a. directory), then all database files
+** specified with a relative pathname and created or accessed by
+** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed
+** to be relative to that directory.)^ ^If this variable is a NULL
+** pointer, then SQLite assumes that all database files specified
+** with a relative pathname are relative to the current directory
+** for the process.  Only the windows VFS makes use of this global
+** variable; it is ignored by the unix VFS.
+**
+** Changing the value of this variable while a database connection is
+** open can result in a corrupt database.
+**
+** It is not safe to read or modify this variable in more than one
+** thread at a time.  It is not safe to read or modify this variable
+** if a [database connection] is being used at the same time in a separate
+** thread.
+** It is intended that this variable be set once
+** as part of process initialization and before any SQLite interface
+** routines have been called and that this variable remain unchanged
+** thereafter.
+**
+** ^The [data_store_directory pragma] may modify this variable and cause
+** it to point to memory obtained from [sqlite3_malloc].  ^Furthermore,
+** the [data_store_directory pragma] always assumes that any string
+** that this variable points to is held in memory obtained from 
+** [sqlite3_malloc] and the pragma may attempt to free that memory
+** using [sqlite3_free].
+** Hence, if this variable is modified directly, either it should be
+** made NULL or made to point to memory obtained from [sqlite3_malloc]
+** or else the use of the [data_store_directory pragma] should be avoided.
+*/
+SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory;
+
+/*
 ** CAPI3REF: Test For Auto-Commit Mode
 ** KEYWORDS: {autocommit mode}
 **
@@ -4348,6 +4814,31 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3*);
 SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
 
 /*
+** CAPI3REF: Return The Filename For A Database Connection
+**
+** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
+** associated with database N of connection D.  ^The main database file
+** has the name "main".  If there is no attached database N on the database
+** connection D, or if database N is a temporary or in-memory database, then
+** a NULL pointer is returned.
+**
+** ^The filename returned by this function is the output of the
+** xFullPathname method of the [VFS].  ^In other words, the filename
+** will be an absolute pathname, even if the filename used
+** to open the database originally was a URI or relative pathname.
+*/
+SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
+
+/*
+** CAPI3REF: Determine if a database is read-only
+**
+** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
+** of connection D is read-only, 0 if it is read/write, or -1 if N is not
+** the name of a database on connection D.
+*/
+SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
+
+/*
 ** CAPI3REF: Find the next prepared statement
 **
 ** ^This interface returns a pointer to the next [prepared statement] after
@@ -4382,13 +4873,15 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
 ** on the same [database connection] D, or NULL for
 ** the first call for each function on D.
 **
+** The commit and rollback hook callbacks are not reentrant.
 ** The callback implementation must not do anything that will modify
 ** the database connection that invoked the callback.  Any actions
 ** to modify the database connection must be deferred until after the
 ** completion of the [sqlite3_step()] call that triggered the commit
 ** or rollback hook in the first place.
-** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
-** database connections for the meaning of "modify" in this paragraph.
+** Note that running any other SQL statements, including SELECT statements,
+** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify
+** the database connections for the meaning of "modify" in this paragraph.
 **
 ** ^Registering a NULL function disables the callback.
 **
@@ -4414,12 +4907,13 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
 **
 ** ^The sqlite3_update_hook() interface registers a callback function
 ** with the [database connection] identified by the first argument
-** to be invoked whenever a row is updated, inserted or deleted.
+** to be invoked whenever a row is updated, inserted or deleted in
+** a rowid table.
 ** ^Any callback set by a previous call to this function
 ** for the same database connection is overridden.
 **
 ** ^The second argument is a pointer to the function to invoke when a
-** row is updated, inserted or deleted.
+** row is updated, inserted or deleted in a rowid table.
 ** ^The first argument to the callback is a copy of the third argument
 ** to sqlite3_update_hook().
 ** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
@@ -4432,6 +4926,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
 **
 ** ^(The update hook is not invoked when internal system tables are
 ** modified (i.e. sqlite_master and sqlite_sequence).)^
+** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
 **
 ** ^In the current implementation, the update hook
 ** is not invoked when duplication rows are deleted because of an
@@ -4463,7 +4958,6 @@ SQLITE_API void *sqlite3_update_hook(
 
 /*
 ** CAPI3REF: Enable Or Disable Shared Pager Cache
-** KEYWORDS: {shared cache}
 **
 ** ^(This routine enables or disables the sharing of the database cache
 ** and schema data structures between [database connection | connections]
@@ -4486,6 +4980,9 @@ SQLITE_API void *sqlite3_update_hook(
 ** future releases of SQLite.  Applications that care about shared
 ** cache setting should set it explicitly.
 **
+** This interface is threadsafe on processors where writing a
+** 32-bit integer is atomic.
+**
 ** See Also:  [SQLite Shared-Cache Mode]
 */
 SQLITE_API int sqlite3_enable_shared_cache(int);
@@ -4501,10 +4998,25 @@ SQLITE_API int sqlite3_enable_shared_cache(int);
 ** which might be more or less than the amount requested.
 ** ^The sqlite3_release_memory() routine is a no-op returning zero
 ** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT].
+**
+** See also: [sqlite3_db_release_memory()]
 */
 SQLITE_API int sqlite3_release_memory(int);
 
 /*
+** CAPI3REF: Free Memory Used By A Database Connection
+**
+** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
+** memory as possible from database connection D. Unlike the
+** [sqlite3_release_memory()] interface, this interface is in effect even
+** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
+** omitted.
+**
+** See also: [sqlite3_release_memory()]
+*/
+SQLITE_API int sqlite3_db_release_memory(sqlite3*);
+
+/*
 ** CAPI3REF: Impose A Limit On Heap Size
 **
 ** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
@@ -4518,7 +5030,8 @@ SQLITE_API int sqlite3_release_memory(int);
 ** is advisory only.
 **
 ** ^The return value from sqlite3_soft_heap_limit64() is the size of
-** the soft heap limit prior to the call.  ^If the argument N is negative
+** the soft heap limit prior to the call, or negative in the case of an
+** error.  ^If the argument N is negative
 ** then no change is made to the soft heap limit.  Hence, the current
 ** size of the soft heap limit can be determined by invoking
 ** sqlite3_soft_heap_limit64() with a negative argument.
@@ -4534,7 +5047,7 @@ SQLITE_API int sqlite3_release_memory(int);
 **      [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
 **      the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
 ** <li> An alternative page cache implementation is specified using
-**      [sqlite3_config]([SQLITE_CONFIG_PCACHE],...).
+**      [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...).
 ** <li> The page cache allocates from its own memory pool supplied
 **      by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than
 **      from the heap.
@@ -4647,11 +5160,20 @@ SQLITE_API int sqlite3_table_column_metadata(
 ** ^This interface loads an SQLite extension library from the named file.
 **
 ** ^The sqlite3_load_extension() interface attempts to load an
-** SQLite extension library contained in the file zFile.
+** [SQLite extension] library contained in the file zFile.  If
+** the file cannot be loaded directly, attempts are made to load
+** with various operating-system specific extensions added.
+** So for example, if "samplelib" cannot be loaded, then names like
+** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
+** be tried also.
 **
 ** ^The entry point is zProc.
-** ^zProc may be 0, in which case the name of the entry point
-** defaults to "sqlite3_extension_init".
+** ^(zProc may be 0, in which case SQLite will try to come up with an
+** entry point name on its own.  It first tries "sqlite3_extension_init".
+** If that does not work, it constructs a name "sqlite3_X_init" where the
+** X is consists of the lower-case equivalent of all ASCII alphabetic
+** characters in the filename from the last "/" to the first following
+** "." and omitting any initial "lib".)^
 ** ^The sqlite3_load_extension() interface returns
 ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
 ** ^If an error occurs and pzErrMsg is not 0, then the
@@ -4677,11 +5199,11 @@ SQLITE_API int sqlite3_load_extension(
 ** CAPI3REF: Enable Or Disable Extension Loading
 **
 ** ^So as not to open security holes in older applications that are
-** unprepared to deal with extension loading, and as a means of disabling
-** extension loading while evaluating user-entered SQL, the following API
+** unprepared to deal with [extension loading], and as a means of disabling
+** [extension loading] while evaluating user-entered SQL, the following API
 ** is provided to turn the [sqlite3_load_extension()] mechanism on and off.
 **
-** ^Extension loading is off by default. See ticket #1863.
+** ^Extension loading is off by default.
 ** ^Call the sqlite3_enable_load_extension() routine with onoff==1
 ** to turn extension loading on and call it with onoff==0 to turn
 ** it back off again.
@@ -4693,7 +5215,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
 **
 ** ^This interface causes the xEntryPoint() function to be invoked for
 ** each new [database connection] that is created.  The idea here is that
-** xEntryPoint() is the entry point for a statically linked SQLite extension
+** xEntryPoint() is the entry point for a statically linked [SQLite extension]
 ** that is to be automatically loaded into all new database connections.
 **
 ** ^(Even though the function prototype shows that xEntryPoint() takes
@@ -4721,11 +5243,24 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
 ** on the list of automatic extensions is a harmless no-op. ^No entry point
 ** will be called more than once for each database connection that is opened.
 **
-** See also: [sqlite3_reset_auto_extension()].
+** See also: [sqlite3_reset_auto_extension()]
+** and [sqlite3_cancel_auto_extension()]
 */
 SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
 
 /*
+** CAPI3REF: Cancel Automatic Extension Loading
+**
+** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
+** initialization routine X that was registered using a prior call to
+** [sqlite3_auto_extension(X)].  ^The [sqlite3_cancel_auto_extension(X)]
+** routine returns 1 if initialization routine X was successfully 
+** unregistered and it returns 0 if X was not on the list of initialization
+** routines.
+*/
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
+
+/*
 ** CAPI3REF: Reset Automatic Extension Loading
 **
 ** ^This interface disables all automatic extensions previously
@@ -4849,10 +5384,22 @@ struct sqlite3_module {
 ** the correct order to satisfy the ORDER BY clause so that no separate
 ** sorting step is required.
 **
-** ^The estimatedCost value is an estimate of the cost of doing the
-** particular lookup.  A full scan of a table with N entries should have
-** a cost of N.  A binary search of a table of N entries should have a
-** cost of approximately log(N).
+** ^The estimatedCost value is an estimate of the cost of a particular
+** strategy. A cost of N indicates that the cost of the strategy is similar
+** to a linear scan of an SQLite table with N rows. A cost of log(N) 
+** indicates that the expense of the operation is similar to that of a
+** binary search on a unique indexed field of an SQLite table with N rows.
+**
+** ^The estimatedRows value is an estimate of the number of rows that
+** will be returned by the strategy.
+**
+** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
+** structure for SQLite version 3.8.2. If a virtual table extension is
+** used with an SQLite version earlier than 3.8.2, the results of attempting 
+** to read or write the estimatedRows field are undefined (but are likely 
+** to included crashing the application). The estimatedRows field should
+** therefore only be used if [sqlite3_libversion_number()] returns a
+** value greater than or equal to 3008002.
 */
 struct sqlite3_index_info {
   /* Inputs */
@@ -4877,7 +5424,9 @@ struct sqlite3_index_info {
   char *idxStr;              /* String, possibly obtained from sqlite3_malloc */
   int needToFreeIdxStr;      /* Free idxStr using sqlite3_free() if true */
   int orderByConsumed;       /* True if output is already ordered */
-  double estimatedCost;      /* Estimated cost of using this index */
+  double estimatedCost;           /* Estimated cost of using this index */
+  /* Fields below are only available in SQLite 3.8.2 and later */
+  sqlite3_int64 estimatedRows;    /* Estimated number of rows returned */
 };
 
 /*
@@ -5081,6 +5630,9 @@ typedef struct sqlite3_blob sqlite3_blob;
 ** interface.  Use the [UPDATE] SQL command to change the size of a
 ** blob.
 **
+** ^The [sqlite3_blob_open()] interface will fail for a [WITHOUT ROWID]
+** table.  Incremental BLOB I/O is not possible on [WITHOUT ROWID] tables.
+**
 ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
 ** and the built-in [zeroblob] SQL function can be used, if desired,
 ** to create an empty, zero-filled blob in which to read or write using
@@ -5275,17 +5827,16 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
 ** implementations are available in the SQLite core:
 **
 ** <ul>
-** <li>   SQLITE_MUTEX_OS2
-** <li>   SQLITE_MUTEX_PTHREAD
+** <li>   SQLITE_MUTEX_PTHREADS
 ** <li>   SQLITE_MUTEX_W32
 ** <li>   SQLITE_MUTEX_NOOP
 ** </ul>)^
 **
 ** ^The SQLITE_MUTEX_NOOP implementation is a set of routines
 ** that does no real locking and is appropriate for use in
-** a single-threaded application.  ^The SQLITE_MUTEX_OS2,
-** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations
-** are appropriate for use on OS/2, Unix, and Windows.
+** a single-threaded application.  ^The SQLITE_MUTEX_PTHREADS and
+** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix
+** and Windows.
 **
 ** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
 ** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
@@ -5306,10 +5857,12 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
 ** <li>  SQLITE_MUTEX_RECURSIVE
 ** <li>  SQLITE_MUTEX_STATIC_MASTER
 ** <li>  SQLITE_MUTEX_STATIC_MEM
-** <li>  SQLITE_MUTEX_STATIC_MEM2
+** <li>  SQLITE_MUTEX_STATIC_OPEN
 ** <li>  SQLITE_MUTEX_STATIC_PRNG
 ** <li>  SQLITE_MUTEX_STATIC_LRU
-** <li>  SQLITE_MUTEX_STATIC_LRU2
+** <li>  SQLITE_MUTEX_STATIC_PMEM
+** <li>  SQLITE_MUTEX_STATIC_APP1
+** <li>  SQLITE_MUTEX_STATIC_APP2
 ** </ul>)^
 **
 ** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
@@ -5474,7 +6027,7 @@ struct sqlite3_mutex_methods {
 ** ^These routines should return true if the mutex in their argument
 ** is held or not held, respectively, by the calling thread.
 **
-** ^The implementation is not required to provided versions of these
+** ^The implementation is not required to provide versions of these
 ** routines that actually work. If the implementation does not provide working
 ** versions of these routines, it should at least provide stubs that always
 ** return true so that one does not get spurious assertion failures.
@@ -5513,6 +6066,9 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
 #define SQLITE_MUTEX_STATIC_LRU       6  /* lru page list */
 #define SQLITE_MUTEX_STATIC_LRU2      7  /* NOT USED */
 #define SQLITE_MUTEX_STATIC_PMEM      7  /* sqlite3PageMalloc() */
+#define SQLITE_MUTEX_STATIC_APP1      8  /* For use by application */
+#define SQLITE_MUTEX_STATIC_APP2      9  /* For use by application */
+#define SQLITE_MUTEX_STATIC_APP3     10  /* For use by application */
 
 /*
 ** CAPI3REF: Retrieve the mutex for a database connection
@@ -5602,10 +6158,14 @@ SQLITE_API int sqlite3_test_control(int op, ...);
 #define SQLITE_TESTCTRL_RESERVE                 14
 #define SQLITE_TESTCTRL_OPTIMIZATIONS           15
 #define SQLITE_TESTCTRL_ISKEYWORD               16
-#define SQLITE_TESTCTRL_PGHDRSZ                 17
-#define SQLITE_TESTCTRL_SCRATCHMALLOC           18
-#define SQLITE_TESTCTRL_LOCALTIME_FAULT         19
-#define SQLITE_TESTCTRL_LAST                    19
+#define SQLITE_TESTCTRL_SCRATCHMALLOC           17
+#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
+#define SQLITE_TESTCTRL_EXPLAIN_STMT            19
+#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
+#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
+#define SQLITE_TESTCTRL_BYTEORDER               22
+#define SQLITE_TESTCTRL_ISINIT                  23
+#define SQLITE_TESTCTRL_LAST                    23
 
 /*
 ** CAPI3REF: SQLite Runtime Status
@@ -5815,6 +6375,35 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 ** the database connection.)^
 ** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
 ** </dd>
+**
+** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt>
+** <dd>This parameter returns the number of pager cache hits that have
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT 
+** is always 0.
+** </dd>
+**
+** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
+** <dd>This parameter returns the number of pager cache misses that have
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS 
+** is always 0.
+** </dd>
+**
+** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(<dt>SQLITE_DBSTATUS_CACHE_WRITE</dt>
+** <dd>This parameter returns the number of dirty cache entries that have
+** been written to disk. Specifically, the number of pages written to the
+** wal file in wal mode databases, or the number of pages written to the
+** database file in rollback mode databases. Any pages written as part of
+** transaction rollback or database recovery operations are not included.
+** If an IO or other error occurs while writing a page to disk, the effect
+** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
+** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
+** </dd>
+**
+** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
+** <dd>This parameter returns zero for the current value if and only if
+** all foreign key constraints (deferred or immediate) have been
+** resolved.)^  ^The highwater mark is always 0.
+** </dd>
 ** </dl>
 */
 #define SQLITE_DBSTATUS_LOOKASIDE_USED       0
@@ -5824,7 +6413,11 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 #define SQLITE_DBSTATUS_LOOKASIDE_HIT        4
 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE  5
 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL  6
-#define SQLITE_DBSTATUS_MAX                  6   /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_CACHE_HIT            7
+#define SQLITE_DBSTATUS_CACHE_MISS           8
+#define SQLITE_DBSTATUS_CACHE_WRITE          9
+#define SQLITE_DBSTATUS_DEFERRED_FKS        10
+#define SQLITE_DBSTATUS_MAX                 10   /* Largest defined DBSTATUS */
 
 
 /*
@@ -5879,11 +6472,20 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
 ** improvement performance by adding permanent indices that do not
 ** need to be reinitialized each time the statement is run.</dd>
 **
+** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
+** <dd>^This is the number of virtual machine operations executed
+** by the prepared statement if that number is less than or equal
+** to 2147483647.  The number of virtual machine operations can be 
+** used as a proxy for the total work done by the prepared statement.
+** If the number of virtual machine operations exceeds 2147483647
+** then the value returned by this statement status code is undefined.
+** </dd>
 ** </dl>
 */
 #define SQLITE_STMTSTATUS_FULLSCAN_STEP     1
 #define SQLITE_STMTSTATUS_SORT              2
 #define SQLITE_STMTSTATUS_AUTOINDEX         3
+#define SQLITE_STMTSTATUS_VM_STEP           4
 
 /*
 ** CAPI3REF: Custom Page Cache Object
@@ -5894,17 +6496,33 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
 ** sqlite3_pcache object except by holding and passing pointers
 ** to the object.
 **
-** See [sqlite3_pcache_methods] for additional information.
+** See [sqlite3_pcache_methods2] for additional information.
 */
 typedef struct sqlite3_pcache sqlite3_pcache;
 
 /*
+** CAPI3REF: Custom Page Cache Object
+**
+** The sqlite3_pcache_page object represents a single page in the
+** page cache.  The page cache will allocate instances of this
+** object.  Various methods of the page cache use pointers to instances
+** of this object as parameters or as their return value.
+**
+** See [sqlite3_pcache_methods2] for additional information.
+*/
+typedef struct sqlite3_pcache_page sqlite3_pcache_page;
+struct sqlite3_pcache_page {
+  void *pBuf;        /* The content of the page */
+  void *pExtra;      /* Extra information associated with the page */
+};
+
+/*
 ** CAPI3REF: Application Defined Page Cache.
 ** KEYWORDS: {page cache}
 **
-** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can
+** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can
 ** register an alternative page cache implementation by passing in an 
-** instance of the sqlite3_pcache_methods structure.)^
+** instance of the sqlite3_pcache_methods2 structure.)^
 ** In many applications, most of the heap memory allocated by 
 ** SQLite is used for the page cache.
 ** By implementing a 
@@ -5918,7 +6536,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
 ** extreme measure that is only needed by the most demanding applications.
 ** The built-in page cache is recommended for most uses.
 **
-** ^(The contents of the sqlite3_pcache_methods structure are copied to an
+** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an
 ** internal buffer by SQLite within the call to [sqlite3_config].  Hence
 ** the application may discard the parameter after the call to
 ** [sqlite3_config()] returns.)^
@@ -5927,7 +6545,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
 ** ^(The xInit() method is called once for each effective 
 ** call to [sqlite3_initialize()])^
 ** (usually only once during the lifetime of the process). ^(The xInit()
-** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^
+** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^
 ** The intent of the xInit() method is to set up global data structures 
 ** required by the custom page cache implementation. 
 ** ^(If the xInit() method is NULL, then the 
@@ -5954,17 +6572,15 @@ typedef struct sqlite3_pcache sqlite3_pcache;
 ** SQLite will typically create one cache instance for each open database file,
 ** though this is not guaranteed. ^The
 ** first parameter, szPage, is the size in bytes of the pages that must
-** be allocated by the cache.  ^szPage will not be a power of two.  ^szPage
-** will the page size of the database file that is to be cached plus an
-** increment (here called "R") of less than 250.  SQLite will use the
-** extra R bytes on each page to store metadata about the underlying
-** database page on disk.  The value of R depends
+** be allocated by the cache.  ^szPage will always a power of two.  ^The
+** second parameter szExtra is a number of bytes of extra storage 
+** associated with each page cache entry.  ^The szExtra parameter will
+** a number less than 250.  SQLite will use the
+** extra szExtra bytes on each page to store metadata about the underlying
+** database page on disk.  The value passed into szExtra depends
 ** on the SQLite version, the target platform, and how SQLite was compiled.
-** ^(R is constant for a particular build of SQLite. Except, there are two
-** distinct values of R when SQLite is compiled with the proprietary
-** ZIPVFS extension.)^  ^The second argument to
-** xCreate(), bPurgeable, is true if the cache being created will
-** be used to cache database pages of a file stored on disk, or
+** ^The third argument to xCreate(), bPurgeable, is true if the cache being
+** created will be used to cache database pages of a file stored on disk, or
 ** false if it is used for an in-memory database. The cache implementation
 ** does not have to do anything special based with the value of bPurgeable;
 ** it is purely advisory.  ^On a cache where bPurgeable is false, SQLite will
@@ -5988,11 +6604,16 @@ typedef struct sqlite3_pcache sqlite3_pcache;
 ** 
 ** [[the xFetch() page cache methods]]
 ** The xFetch() method locates a page in the cache and returns a pointer to 
-** the page, or a NULL pointer.
-** A "page", in this context, means a buffer of szPage bytes aligned at an
-** 8-byte boundary. The page to be fetched is determined by the key. ^The
-** minimum key value is 1.  After it has been retrieved using xFetch, the page 
-** is considered to be "pinned".
+** an sqlite3_pcache_page object associated with that page, or a NULL pointer.
+** The pBuf element of the returned sqlite3_pcache_page object will be a
+** pointer to a buffer of szPage bytes used to store the content of a 
+** single database page.  The pExtra element of sqlite3_pcache_page will be
+** a pointer to the szExtra bytes of extra storage that SQLite has requested
+** for each entry in the page cache.
+**
+** The page to be fetched is determined by the key. ^The minimum key value
+** is 1.  After it has been retrieved using xFetch, the page is considered
+** to be "pinned".
 **
 ** If the requested page is already in the page cache, then the page cache
 ** implementation must return a pointer to the page buffer with its content
@@ -6001,7 +6622,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
 ** parameter to help it determined what action to take:
 **
 ** <table border=1 width=85% align=center>
-** <tr><th> createFlag <th> Behaviour when page is not already in cache
+** <tr><th> createFlag <th> Behavior when page is not already in cache
 ** <tr><td> 0 <td> Do not allocate a new page.  Return NULL.
 ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
 **                 Otherwise return NULL.
@@ -6045,8 +6666,37 @@ typedef struct sqlite3_pcache sqlite3_pcache;
 ** ^The xDestroy() method is used to delete a cache allocated by xCreate().
 ** All resources associated with the specified cache should be freed. ^After
 ** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
-** handle invalid, and will not use it with any other sqlite3_pcache_methods
+** handle invalid, and will not use it with any other sqlite3_pcache_methods2
 ** functions.
+**
+** [[the xShrink() page cache method]]
+** ^SQLite invokes the xShrink() method when it wants the page cache to
+** free up as much of heap memory as possible.  The page cache implementation
+** is not obligated to free any memory, but well-behaved implementations should
+** do their best.
+*/
+typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
+struct sqlite3_pcache_methods2 {
+  int iVersion;
+  void *pArg;
+  int (*xInit)(void*);
+  void (*xShutdown)(void*);
+  sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
+  void (*xCachesize)(sqlite3_pcache*, int nCachesize);
+  int (*xPagecount)(sqlite3_pcache*);
+  sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
+  void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
+  void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, 
+      unsigned oldKey, unsigned newKey);
+  void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
+  void (*xDestroy)(sqlite3_pcache*);
+  void (*xShrink)(sqlite3_pcache*);
+};
+
+/*
+** This is the obsolete pcache_methods object that has now been replaced
+** by sqlite3_pcache_methods2.  This object is not used by SQLite.  It is
+** retained in the header file for backwards compatibility only.
 */
 typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
 struct sqlite3_pcache_methods {
@@ -6063,6 +6713,7 @@ struct sqlite3_pcache_methods {
   void (*xDestroy)(sqlite3_pcache*);
 };
 
+
 /*
 ** CAPI3REF: Online Backup Object
 **
@@ -6392,17 +7043,33 @@ SQLITE_API int sqlite3_unlock_notify(
 /*
 ** CAPI3REF: String Comparison
 **
-** ^The [sqlite3_strnicmp()] API allows applications and extensions to
-** compare the contents of two buffers containing UTF-8 strings in a
-** case-independent fashion, using the same definition of case independence 
-** that SQLite uses internally when comparing identifiers.
+** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications
+** and extensions to compare the contents of two buffers containing UTF-8
+** strings in a case-independent fashion, using the same definition of "case
+** independence" that SQLite uses internally when comparing identifiers.
 */
+SQLITE_API int sqlite3_stricmp(const char *, const char *);
 SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
 
 /*
+** CAPI3REF: String Globbing
+*
+** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches
+** the glob pattern P, and it returns non-zero if string X does not match
+** the glob pattern P.  ^The definition of glob pattern matching used in
+** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the
+** SQL dialect used by SQLite.  ^The sqlite3_strglob(P,X) function is case
+** sensitive.
+**
+** Note that this routine returns zero on a match and non-zero if the strings
+** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
+*/
+SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr);
+
+/*
 ** CAPI3REF: Error Logging Interface
 **
-** ^The [sqlite3_log()] interface writes a message into the error log
+** ^The [sqlite3_log()] interface writes a message into the [error log]
 ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
 ** ^If logging is enabled, the zFormat string and subsequent arguments are
 ** used with [sqlite3_snprintf()] to generate the final output string.
@@ -6482,6 +7149,9 @@ SQLITE_API void *sqlite3_wal_hook(
 ** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
 ** from SQL.
 **
+** ^Checkpoints initiated by this mechanism are
+** [sqlite3_wal_checkpoint_v2|PASSIVE].
+**
 ** ^Every new [database connection] defaults to having the auto-checkpoint
 ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
 ** pages.  The use of this interface
@@ -6498,6 +7168,10 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
 ** empty string, then a checkpoint is run on all databases of
 ** connection D.  ^If the database connection D is not in
 ** [WAL | write-ahead log mode] then this interface is a harmless no-op.
+** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
+** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
+** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
+** or RESET checkpoint.
 **
 ** ^The [wal_checkpoint pragma] can be used to invoke this interface
 ** from SQL.  ^The [sqlite3_wal_autocheckpoint()] interface and the
@@ -6520,10 +7194,12 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
 **   Checkpoint as many frames as possible without waiting for any database 
 **   readers or writers to finish. Sync the db file if all frames in the log
 **   are checkpointed. This mode is the same as calling 
-**   sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
+**   sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
+**   is never invoked.
 **
 ** <dt>SQLITE_CHECKPOINT_FULL<dd>
-**   This mode blocks (calls the busy-handler callback) until there is no
+**   This mode blocks (it invokes the
+**   [sqlite3_busy_handler|busy-handler callback]) until there is no
 **   database writer and all readers are reading from the most recent database
 **   snapshot. It then checkpoints all frames in the log file and syncs the
 **   database file. This call blocks database writers while it is running,
@@ -6531,7 +7207,8 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
 **
 ** <dt>SQLITE_CHECKPOINT_RESTART<dd>
 **   This mode works the same way as SQLITE_CHECKPOINT_FULL, except after 
-**   checkpointing the log file it blocks (calls the busy-handler callback)
+**   checkpointing the log file it blocks (calls the 
+**   [sqlite3_busy_handler|busy-handler callback])
 **   until all readers are reading from the database file only. This ensures 
 **   that the next client to write to the database file restarts the log file 
 **   from the beginning. This call blocks database writers while it is running,
@@ -6669,6 +7346,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
 
 /*
 ** CAPI3REF: Conflict resolution modes
+** KEYWORDS: {conflict resolution mode}
 **
 ** These constants are returned by [sqlite3_vtab_on_conflict()] to
 ** inform a [virtual table] implementation what the [ON CONFLICT] mode
@@ -6697,7 +7375,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
 #ifdef __cplusplus
 }  /* End of the 'extern "C"' block */
 #endif
-#endif
+#endif /* _SQLITE3_H_ */
 
 /*
 ** 2010 August 30
@@ -6721,6 +7399,16 @@ extern "C" {
 #endif
 
 typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
+typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
+
+/* The double-precision datatype used by RTree depends on the
+** SQLITE_RTREE_INT_ONLY compile-time option.
+*/
+#ifdef SQLITE_RTREE_INT_ONLY
+  typedef sqlite3_int64 sqlite3_rtree_dbl;
+#else
+  typedef double sqlite3_rtree_dbl;
+#endif
 
 /*
 ** Register a geometry callback named zGeom that can be used as part of an
@@ -6731,7 +7419,7 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
 SQLITE_API int sqlite3_rtree_geometry_callback(
   sqlite3 *db,
   const char *zGeom,
-  int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes),
+  int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
   void *pContext
 );
 
@@ -6743,11 +7431,60 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
 struct sqlite3_rtree_geometry {
   void *pContext;                 /* Copy of pContext passed to s_r_g_c() */
   int nParam;                     /* Size of array aParam[] */
-  double *aParam;                 /* Parameters passed to SQL geom function */
+  sqlite3_rtree_dbl *aParam;      /* Parameters passed to SQL geom function */
   void *pUser;                    /* Callback implementation user data */
   void (*xDelUser)(void *);       /* Called by SQLite to clean up pUser */
 };
 
+/*
+** Register a 2nd-generation geometry callback named zScore that can be 
+** used as part of an R-Tree geometry query as follows:
+**
+**   SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
+*/
+SQLITE_API int sqlite3_rtree_query_callback(
+  sqlite3 *db,
+  const char *zQueryFunc,
+  int (*xQueryFunc)(sqlite3_rtree_query_info*),
+  void *pContext,
+  void (*xDestructor)(void*)
+);
+
+
+/*
+** A pointer to a structure of the following type is passed as the 
+** argument to scored geometry callback registered using
+** sqlite3_rtree_query_callback().
+**
+** Note that the first 5 fields of this structure are identical to
+** sqlite3_rtree_geometry.  This structure is a subclass of
+** sqlite3_rtree_geometry.
+*/
+struct sqlite3_rtree_query_info {
+  void *pContext;                   /* pContext from when function registered */
+  int nParam;                       /* Number of function parameters */
+  sqlite3_rtree_dbl *aParam;        /* value of function parameters */
+  void *pUser;                      /* callback can use this, if desired */
+  void (*xDelUser)(void*);          /* function to free pUser */
+  sqlite3_rtree_dbl *aCoord;        /* Coordinates of node or entry to check */
+  unsigned int *anQueue;            /* Number of pending entries in the queue */
+  int nCoord;                       /* Number of coordinates */
+  int iLevel;                       /* Level of current node or entry */
+  int mxLevel;                      /* The largest iLevel value in the tree */
+  sqlite3_int64 iRowid;             /* Rowid for current entry */
+  sqlite3_rtree_dbl rParentScore;   /* Score of parent node */
+  int eParentWithin;                /* Visibility of parent node */
+  int eWithin;                      /* OUT: Visiblity */
+  sqlite3_rtree_dbl rScore;         /* OUT: Write the score here */
+};
+
+/*
+** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
+*/
+#define NOT_WITHIN       0   /* Object completely outside of query region */
+#define PARTLY_WITHIN    1   /* Object partially overlaps query region */
+#define FULLY_WITHIN     2   /* Object fully contained within query region */
+
 
 #ifdef __cplusplus
 }  /* end of the 'extern "C"' block */
diff --git a/inst/include/sqlite3ext.h b/inst/include/sqlite3ext.h
index 50dd5b6..ecf93f6 100644
--- a/inst/include/sqlite3ext.h
+++ b/inst/include/sqlite3ext.h
@@ -49,8 +49,10 @@ struct sqlite3_api_routines {
   int  (*busy_timeout)(sqlite3*,int ms);
   int  (*changes)(sqlite3*);
   int  (*close)(sqlite3*);
-  int  (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*));
-  int  (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*));
+  int  (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
+                           int eTextRep,const char*));
+  int  (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
+                             int eTextRep,const void*));
   const void * (*column_blob)(sqlite3_stmt*,int iCol);
   int  (*column_bytes)(sqlite3_stmt*,int iCol);
   int  (*column_bytes16)(sqlite3_stmt*,int iCol);
@@ -75,10 +77,18 @@ struct sqlite3_api_routines {
   void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
   int  (*complete)(const char*sql);
   int  (*complete16)(const void*sql);
-  int  (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*));
-  int  (*create_collation16)(sqlite3*,const void*,int,void*,int(*)(void*,int,const void*,int,const void*));
-  int  (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
-  int  (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
+  int  (*create_collation)(sqlite3*,const char*,int,void*,
+                           int(*)(void*,int,const void*,int,const void*));
+  int  (*create_collation16)(sqlite3*,const void*,int,void*,
+                             int(*)(void*,int,const void*,int,const void*));
+  int  (*create_function)(sqlite3*,const char*,int,int,void*,
+                          void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+                          void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+                          void (*xFinal)(sqlite3_context*));
+  int  (*create_function16)(sqlite3*,const void*,int,int,void*,
+                            void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+                            void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+                            void (*xFinal)(sqlite3_context*));
   int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
   int  (*data_count)(sqlite3_stmt*pStmt);
   sqlite3 * (*db_handle)(sqlite3_stmt*);
@@ -123,16 +133,19 @@ struct sqlite3_api_routines {
   void  (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
   void  (*result_value)(sqlite3_context*,sqlite3_value*);
   void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
-  int  (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*);
+  int  (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
+                         const char*,const char*),void*);
   void  (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
   char * (*snprintf)(int,char*,const char*,...);
   int  (*step)(sqlite3_stmt*);
-  int  (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*);
+  int  (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
+                                char const**,char const**,int*,int*,int*);
   void  (*thread_cleanup)(void);
   int  (*total_changes)(sqlite3*);
   void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
   int  (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
-  void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*);
+  void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
+                                         sqlite_int64),void*);
   void * (*user_data)(sqlite3_context*);
   const void * (*value_blob)(sqlite3_value*);
   int  (*value_bytes)(sqlite3_value*);
@@ -154,15 +167,19 @@ struct sqlite3_api_routines {
   int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
   int (*clear_bindings)(sqlite3_stmt*);
   /* Added by 3.4.1 */
-  int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,void (*xDestroy)(void *));
+  int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
+                          void (*xDestroy)(void *));
   /* Added by 3.5.0 */
   int (*bind_zeroblob)(sqlite3_stmt*,int,int);
   int (*blob_bytes)(sqlite3_blob*);
   int (*blob_close)(sqlite3_blob*);
-  int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,int,sqlite3_blob**);
+  int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
+                   int,sqlite3_blob**);
   int (*blob_read)(sqlite3_blob*,void*,int,int);
   int (*blob_write)(sqlite3_blob*,const void*,int,int);
-  int (*create_collation_v2)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*),void(*)(void*));
+  int (*create_collation_v2)(sqlite3*,const char*,int,void*,
+                             int(*)(void*,int,const void*,int,const void*),
+                             void(*)(void*));
   int (*file_control)(sqlite3*,const char*,int,void*);
   sqlite3_int64 (*memory_highwater)(int);
   sqlite3_int64 (*memory_used)(void);
@@ -198,7 +215,11 @@ struct sqlite3_api_routines {
   int (*backup_step)(sqlite3_backup*,int);
   const char *(*compileoption_get)(int);
   int (*compileoption_used)(const char*);
-  int (*create_function_v2)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*),void(*xDestroy)(void*));
+  int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
+                            void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+                            void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+                            void (*xFinal)(sqlite3_context*),
+                            void(*xDestroy)(void*));
   int (*db_config)(sqlite3*,int,...);
   sqlite3_mutex *(*db_mutex)(sqlite3*);
   int (*db_status)(sqlite3*,int,int*,int*,int);
@@ -215,6 +236,20 @@ struct sqlite3_api_routines {
   int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
   int (*vtab_config)(sqlite3*,int op,...);
   int (*vtab_on_conflict)(sqlite3*);
+  /* Version 3.7.16 and later */
+  int (*close_v2)(sqlite3*);
+  const char *(*db_filename)(sqlite3*,const char*);
+  int (*db_readonly)(sqlite3*,const char*);
+  int (*db_release_memory)(sqlite3*);
+  const char *(*errstr)(int);
+  int (*stmt_busy)(sqlite3_stmt*);
+  int (*stmt_readonly)(sqlite3_stmt*);
+  int (*stricmp)(const char*,const char*);
+  int (*uri_boolean)(const char*,const char*,int);
+  sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
+  const char *(*uri_parameter)(const char*,const char*);
+  char *(*vsnprintf)(int,char*,const char*,va_list);
+  int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
 };
 
 /*
@@ -418,9 +453,35 @@ struct sqlite3_api_routines {
 #define sqlite3_blob_reopen            sqlite3_api->blob_reopen
 #define sqlite3_vtab_config            sqlite3_api->vtab_config
 #define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict
+/* Version 3.7.16 and later */
+#define sqlite3_close_v2               sqlite3_api->close_v2
+#define sqlite3_db_filename            sqlite3_api->db_filename
+#define sqlite3_db_readonly            sqlite3_api->db_readonly
+#define sqlite3_db_release_memory      sqlite3_api->db_release_memory
+#define sqlite3_errstr                 sqlite3_api->errstr
+#define sqlite3_stmt_busy              sqlite3_api->stmt_busy
+#define sqlite3_stmt_readonly          sqlite3_api->stmt_readonly
+#define sqlite3_stricmp                sqlite3_api->stricmp
+#define sqlite3_uri_boolean            sqlite3_api->uri_boolean
+#define sqlite3_uri_int64              sqlite3_api->uri_int64
+#define sqlite3_uri_parameter          sqlite3_api->uri_parameter
+#define sqlite3_uri_vsnprintf          sqlite3_api->vsnprintf
+#define sqlite3_wal_checkpoint_v2      sqlite3_api->wal_checkpoint_v2
 #endif /* SQLITE_CORE */
 
-#define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
-#define SQLITE_EXTENSION_INIT2(v)  sqlite3_api = v;
+#ifndef SQLITE_CORE
+  /* This case when the file really is being compiled as a loadable 
+  ** extension */
+# define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
+# define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;
+# define SQLITE_EXTENSION_INIT3     \
+    extern const sqlite3_api_routines *sqlite3_api;
+#else
+  /* This case when the file is being statically linked into the 
+  ** application */
+# define SQLITE_EXTENSION_INIT1     /*no-op*/
+# define SQLITE_EXTENSION_INIT2(v)  (void)v; /* unused parameter */
+# define SQLITE_EXTENSION_INIT3     /*no-op*/
+#endif
 
 #endif /* _SQLITE3EXT_H_ */
diff --git a/inst/rsqlitePerf.txt b/inst/rsqlitePerf.txt
deleted file mode 100644
index 727f0fd..0000000
--- a/inst/rsqlitePerf.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-From Charles Loboz (edited to remove bug reports that have been fixed):
-
-I think that the following remarks can be usefule for R users working
-with SQLite. They were collected while testing my own computations on
-Windows version of R and SQL, under XP home and W2K professional. They
-may apply - or not - to other platforms
-
-
-        Cache size
-
-Default cache size is 2000 pages, default page size is 1kb. That means
-that the default cache size is only two megabytes (!) That is the single
-factor creating most slowdown. It may not matter much if the main usage
-mode is just dbReadTable/dbWriteTable, but it will slow down most
-dbGetQuery. Since SQLite does not use cache unnecessarily, it may be
-safer to declare larges caches. Even on a 128mb computer I was running
-my calculations with 32mb cache size quite comfortably.
-
-Suggested: after opening the database
-execute immediately pragma cache_size=32000 (or greater)
-
-
-            Page size
-
-It seems that it cannot be set when creating databases from R, though it
-can be set when creating the database from sqlite3 utility. The default
-is 1024. Changing it to 4096 does not seem to change performance much.
-So - unless some evidence to the contrary is available - that should not
-be tinkered with.
-
-
-        Synchronization
-
-Default synchronization for SQLite database (pragma synchronous) is
-level 2 (FULL). That is good for transaction processing environments,
-but hardly likely to be necessary in a typical R usage.
-
-Suggested: after opening the database execute immediately pragma
-synchronous 0. Computations storing small dataframes multiple times will
-be running several times faster.
-
-
-        Column names when storing tables
-
-
-Be aware that some column names are silently changed when dbWriteTable
-is performed - and dbReadTable does not restore them. I observed that in
-particular column names like FROM etc are extended with __1.
-
diff --git a/man/S4R.Rd b/man/S4R.Rd
deleted file mode 100644
index 28a912a..0000000
--- a/man/S4R.Rd
+++ /dev/null
@@ -1,16 +0,0 @@
-% $Id$
-\name{S4R}
-\alias{ErrorClass}
-\alias{usingR}
-
-\title{R compatibility with S version 4/S-Plus 5+ support functions}
-\description{
-  These objects ease the task of porting functions into R
-  from S Version 4 and S-Plus 5.0 and later.  See the documentation
-  of the lower-case functions there. May be obsolete in the future.
-}
-\usage{
-usingR(major, minor)
-}
-\keyword{internal}
-% vim:syntax=tex
diff --git a/man/SQLite.Rd b/man/SQLite.Rd
deleted file mode 100644
index 77121bc..0000000
--- a/man/SQLite.Rd
+++ /dev/null
@@ -1,143 +0,0 @@
-% $Id$
-\name{SQLite}
-\alias{SQLite}
-\alias{SQLiteDriver}
-\title{
-  Initialize the SQLite engine for the current R session.
-}
-\description{
-This function initializes the SQLite engine.
-It returns an object that allows you to connect to the SQLite engine
-embedded in R.
-}
-\usage{
-SQLite(max.con = 200, fetch.default.rec = 500, force.reload = FALSE, 
-       shared.cache=FALSE)
-}
-\arguments{
-\item{max.con}{
-  IGNORED.  As of RSQLite 0.9.0, connections are managed dynamically and
-  there is no predefined limit to the number of connections you can have
-  in a given R session.
-  }
-\item{fetch.default.rec}{
-  default number of records to fetch at one time from the database.
-  The \code{fetch} method will use this number as a default, but
-  individual calls can override it.
-  }
-\item{force.reload}{
-  should the package code be reloaded (reinitialized)?
-  Setting this to \code{TRUE} allows you to change
-  default settings.  Notice that all connections should be closed
-  before re-loading.
-  }
-\item{shared.cache}{
-  logical describing whether shared-cache mode should be enabled on the SQLite
-  driver. The default is \code{FALSE}.
-  }
-}
-\value{
-An object of class \code{SQLiteDriver} which extends 
-\code{dbDriver} and \code{dbObjectId}.
-This object is needed to create connections
-to the embedded SQLite database.
-There can be many SQLite database instances running
-simultaneously.
-}
-\section{Side Effects}{
-The R client part of the database communication is initialized,
-but note that connecting to database instances needs to be done through
-calls to \code{dbConnect}.
-}
-\details{
-This object is a singleton, that is, on subsequent invocations
-it returns the same initialized object. 
-
-This implementation allows the R embedded SQLite engine
-to work with multiple database instances through multiple connections 
-simultaneously.
-
-SQLite keeps each database instance in one single file. The name
-of the database \emph{is} the file name, thus database names
-should be legal file names in the running platform.
-}
-\section{User authentication}{
-SQLite is a single-user database engine, so no authentication
-is required.
-}
-\author{David A. James}
-\section{References}{
-See the Omega Project for Statistical Computing
-\url{http://stat.bell-labs.com/RS-DBI}
-for more details on the R database interface.
-
-See the Adobe PDF file \code{DBI.pdf} under the \code{doc}
-subdirectory of the DBI package, i.e., 
-\code{system.file("doc", "DBI.pdf", package = "DBI")}
-
-See the documentation at the SQLite Web site
-\url{http://www.sqlite.org} for details.
-}
-\seealso{
-On database drivers:
-
-\code{\link[DBI]{dbDriver}},
-\code{\link[DBI]{dbUnloadDriver}},
-\code{\link[DBI]{dbListConnections}}.
-
-On connections, SQL statements and resultSets:
-
-\code{\link[DBI]{dbConnect}},
-\code{\link[DBI]{dbDisconnect}},
-\code{\link[DBI]{dbSendQuery}},
-\code{\link[DBI]{dbGetQuery}},
-\code{\link[DBI]{fetch}},
-\code{\link[DBI]{dbListResults}}.
-
-On transaction management:
-
-\code{\link[DBI]{dbCommit}}, 
-\code{\link[DBI]{dbRollback}}.
-
-On meta-data:
-
-\code{\link{summary}},
-\code{\link[DBI]{dbGetInfo}},
-\code{\link[DBI]{dbListTables}},
-\code{\link[DBI]{dbListFields}},
-\code{\link[DBI]{dbColumnInfo}},
-\code{\link[DBI]{dbGetException}},
-\code{\link[DBI]{dbGetStatement}},
-\code{\link[DBI]{dbHasCompleted}},
-\code{\link[DBI]{dbGetRowCount}},
-\code{\link[DBI]{dbGetRowsAffected}}.
-}
-\examples{
-   # create a SQLite instance and create one connection.
-   m <- dbDriver("SQLite")
-   
-   # initialize a new database to a tempfile and copy some data.frame
-   # from the base package into it
-   tfile <- tempfile()
-   con <- dbConnect(m, dbname = tfile)
-   data(USArrests)
-   dbWriteTable(con, "USArrests", USArrests)
-   
-   # query
-   rs <- dbSendQuery(con, "select * from USArrests")
-   d1 <- fetch(rs, n = 10)      # extract data in chunks of 10 rows
-   dbHasCompleted(rs)
-   d2 <- fetch(rs, n = -1)      # extract all remaining data
-   dbHasCompleted(rs)
-   dbClearResult(rs)
-   dbListTables(con)
-
-   # clean up
-   dbDisconnect(con)
-   file.info(tfile)
-   file.remove(tfile)
-}
-\keyword{interface}
-\keyword{database}
-% docclass is function
-%  vim: syntax=tex
diff --git a/man/SQLiteConnection-class.Rd b/man/SQLiteConnection-class.Rd
index eb3eb2d..ba3df12 100644
--- a/man/SQLiteConnection-class.Rd
+++ b/man/SQLiteConnection-class.Rd
@@ -1,63 +1,14 @@
-% $Id$
-\name{SQLiteConnection-class}
+% Generated by roxygen2 (4.0.2): do not edit by hand
 \docType{class}
+\name{SQLiteConnection-class}
 \alias{SQLiteConnection-class}
-\title{Class SQLiteConnection}
-\description{SQLite connection class.}
-\section{Generators}{
-    The method \code{\link[DBI]{dbConnect}} is the main generator.
-}
-\section{Extends}{
-Class \code{"DBIConnection"}, directly.
-Class \code{"SQLiteObject"}, directly.
-Class \code{"DBIObject"}, by class "DBIConnection".
-Class \code{"dbObjectId"}, by class "SQLiteObject".
-}
-\section{Methods}{
-  \describe{
-    \item{\link{coerce}}{\code{signature(from = "SQLiteConnection", to = "SQLiteResult")}: ... }
-    \item{\link[DBI]{dbCallProc}}{\code{signature(conn = "SQLiteConnection")}: ... }
-    \item{\link[DBI]{dbCommit}}{\code{signature(conn = "SQLiteConnection")}: ... }
-    \item{\link[DBI]{dbConnect}}{\code{signature(drv = "SQLiteConnection")}: ... }
-    \item{\link[DBI]{dbDisconnect}}{\code{signature(conn = "SQLiteConnection")}: ... }
-    \item{\link[DBI]{dbExistsTable}}{\code{signature(conn = "SQLiteConnection", name = "character")}: ... }
-    \item{\link[DBI]{dbGetException}}{\code{signature(conn = "SQLiteConnection")}: ... }
-    \item{\link[DBI]{dbGetInfo}}{\code{signature(dbObj = "SQLiteConnection")}: ... }
-    \item{\link[DBI]{dbGetQuery}}{\code{signature(conn = "SQLiteConnection", statement = "character")}: ... }
-    \item{\link[DBI]{dbListFields}}{\code{signature(conn = "SQLiteConnection", name = "character")}: ... }
-    \item{\link[DBI]{dbListResults}}{\code{signature(conn = "SQLiteConnection")}: ... }
-    \item{\link[DBI]{dbListTables}}{\code{signature(conn = "SQLiteConnection")}: ... }
-    \item{\link[DBI]{dbReadTable}}{\code{signature(conn = "SQLiteConnection", name = "character")}: ... }
-    \item{\link[DBI]{dbRemoveTable}}{\code{signature(conn = "SQLiteConnection", name = "character")}: ... }
-    \item{\link[DBI]{dbRollback}}{\code{signature(conn = "SQLiteConnection")}: ... }
-    \item{\link[DBI]{dbSendQuery}}{\code{signature(conn = "SQLiteConnection", statement = "character")}: ... }
-    \item{\link[DBI]{dbWriteTable}}{\code{signature(conn = "SQLiteConnection", name = "character", value = "data.frame")}: ... }
-    \item{summary}{\code{signature(object = "SQLiteConnection")}: ... }
-  }
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
+\title{Class SQLiteConnection.}
+\description{
+\code{SQLiteConnection} objects are usually created by
+\code{\link[DBI]{dbConnect}}
 }
-\author{R-SIG-DB}
-
-\seealso{
- DBI classes:
- \code{\link{SQLiteObject-class}}
- \code{\link{SQLiteDriver-class}}
- \code{\link{SQLiteConnection-class}}
- \code{\link{SQLiteResult-class}}
-}
-
 \examples{
-drv <- dbDriver("SQLite")
-tfile <- tempfile()
-con <- dbConnect(drv, dbname = tfile)
+con <- dbConnect(SQLite(), dbname = tempfile())
 dbDisconnect(con)
-dbUnloadDriver(drv)
 }
-\keyword{database}
-\keyword{interface}
-\keyword{classes}
-% vim: syntax=tex
+
diff --git a/man/SQLiteDriver-class.Rd b/man/SQLiteDriver-class.Rd
index b88c220..ffbbd1a 100644
--- a/man/SQLiteDriver-class.Rd
+++ b/man/SQLiteDriver-class.Rd
@@ -1,52 +1,60 @@
-% $Id$
-\name{SQLiteDriver-class}
+% Generated by roxygen2 (4.0.2): do not edit by hand
 \docType{class}
+\name{SQLiteDriver-class}
+\alias{SQLite}
 \alias{SQLiteDriver-class}
-\title{Class SQLiteDriver}
-\description{
-   An SQLite driver implementing the R/S-Plus database (DBI) API.
+\title{Class SQLiteDriver with constructor SQLite.}
+\usage{
+SQLite(max.con = 200L, fetch.default.rec = 500, force.reload = FALSE,
+  shared.cache = FALSE)
 }
-\section{Generators}{
-   The main generators are \code{\link[DBI]{dbDriver}} and 
-   \code{\link{SQLite}}.
-}
-\section{Extends}{
-Class \code{"DBIDriver"}, directly.
-Class \code{"SQLiteObject"}, directly.
-Class \code{"DBIObject"}, by class "DBIDriver".
-Class \code{"dbObjectId"}, by class "SQLiteObject".
-}
-\section{Methods}{
-  \describe{
-    \item{\link{coerce}}{\code{signature(from = "SQLiteObject", to = "SQLiteDriver")}: ... }
-    \item{\link[DBI]{dbConnect}}{\code{signature(drv = "SQLiteDriver")}: ... }
-    \item{\link[DBI]{dbGetInfo}}{\code{signature(dbObj = "SQLiteDriver")}: ... }
-    \item{\link[DBI]{dbListConnections}}{\code{signature(drv = "SQLiteDriver")}: ... }
-    \item{\link[DBI]{dbUnloadDriver}}{\code{signature(drv = "SQLiteDriver")}: ... }
-    \item{\link{summary}}{\code{signature(object = "SQLiteDriver")}: ... }
-  }
+\arguments{
+\item{max.con,force.reload}{Ignored and deprecated.}
+
+\item{fetch.default.rec}{default number of records to fetch at one time from
+the database.  The \code{fetch} method will use this number as a default,
+but individual calls can override it.}
+
+\item{shared.cache}{logical describing whether shared-cache mode should be
+enabled on the SQLite driver. The default is \code{FALSE}.}
 }
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
+\value{
+An object of class \code{SQLiteDriver} which extends \code{dbDriver}
+  and \code{dbObjectId}. This object is needed to create connections to the
+  embedded SQLite database. There can be many SQLite database instances
+  running simultaneously.
 }
-\author{R-SIG-DB}
+\description{
+An SQLite driver implementing the R/S-Plus database (DBI) API.
+This class should always be initializes with the \code{SQLite()} function.
+It returns a singleton object that allows you to connect to the SQLite
+engine embedded in R.
+}
+\details{
+This implementation allows the R embedded SQLite engine to work with
+multiple database instances through multiple connections simultaneously.
 
-\seealso{
- DBI classes:
- \code{\link{SQLiteObject-class}}
- \code{\link{SQLiteDriver-class}}
- \code{\link{SQLiteConnection-class}}
- \code{\link{SQLiteResult-class}}
-}
+SQLite keeps each database instance in one single file. The name of the
+database \emph{is} the file name, thus database names should be legal file
+names in the running platform.
+}
+\examples{
+# initialize a new database to a tempfile and copy some data.frame
+# from the base package into it
+con <- dbConnect(SQLite(), ":memory:")
+data(USArrests)
+dbWriteTable(con, "USArrests", USArrests)
 
-\examples{\dontrun{
-drv <- dbDriver("SQLite")
-con <- dbConnect(drv, dbname="path/to/dbfile")
-}
+# query
+rs <- dbSendQuery(con, "select * from USArrests")
+d1 <- fetch(rs, n = 10)      # extract data in chunks of 10 rows
+dbHasCompleted(rs)
+d2 <- fetch(rs, n = -1)      # extract all remaining data
+dbHasCompleted(rs)
+dbClearResult(rs)
+dbListTables(con)
+
+# clean up
+dbDisconnect(con)
 }
-\keyword{database}
-\keyword{interface}
-\keyword{classes}
-% vim: syntax=tex
+
diff --git a/man/SQLiteObject-class.Rd b/man/SQLiteObject-class.Rd
deleted file mode 100644
index 2fdd3e4..0000000
--- a/man/SQLiteObject-class.Rd
+++ /dev/null
@@ -1,48 +0,0 @@
-% $Id$
-\name{SQLiteObject-class}
-\docType{class}
-\alias{SQLiteObject-class}
-\title{Class SQLiteObject}
-\description{
-   Base class for all SQLite-specific DBI classes
-}
-\section{Objects from the Class}{
-   A virtual Class: No objects may be created from it.
-}
-\section{Extends}{
-Class \code{"DBIObject"}, directly.
-Class \code{"dbObjectId"}, directly.
-}
-\section{Methods}{
-  \describe{
-    \item{\link{coerce}}{\code{signature(from = "SQLiteObject", to = "SQLiteDriver")}: ... }
-    \item{\link[DBI]{dbDataType}}{\code{signature(dbObj = "SQLiteObject")}: ... }
-    \item{\link[DBI]{isSQLKeyword}}{\code{signature(dbObj = "SQLiteObject", name = "character")}: ... }
-    \item{\link[DBI]{make.db.names}}{\code{signature(dbObj = "SQLiteObject", snames = "character")}: ... }
-    \item{\link[DBI]{SQLKeywords}}{\code{signature(dbObj = "SQLiteObject")}: ... }
-  }
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\author{R-SIG-DB}
-
-\seealso{
- DBI classes:
- \code{\link{SQLiteObject-class}}
- \code{\link{SQLiteDriver-class}}
- \code{\link{SQLiteConnection-class}}
- \code{\link{SQLiteResult-class}}
-}
-
-\examples{\dontrun{
-drv <- dbDriver("SQLite")
-con <- dbConnect(drv, dbname = "rsdbi.db")
-}
-}
-\keyword{database}
-\keyword{interface}
-\keyword{classes}
-% vim: syntax=tex
diff --git a/man/SQLiteResult-class.Rd b/man/SQLiteResult-class.Rd
index 92e8e79..3e94d34 100644
--- a/man/SQLiteResult-class.Rd
+++ b/man/SQLiteResult-class.Rd
@@ -1,54 +1,10 @@
-% $Id$
-\name{SQLiteResult-class}
+% Generated by roxygen2 (4.0.2): do not edit by hand
 \docType{class}
+\name{SQLiteResult-class}
 \alias{SQLiteResult-class}
 \title{Class SQLiteResult}
 \description{
-   SQLite's query results class.  This classes encapsulates the
-   result of an SQL statement (either \code{select} or not).
-}
-\section{Generators}{
-   The main generator is \code{\link[DBI]{dbSendQuery}}.
-}
-\section{Extends}{
-Class \code{"DBIResult"}, directly.
-Class \code{"SQLiteObject"}, directly.
-Class \code{"DBIObject"}, by class "DBIResult".
-Class \code{"dbObjectId"}, by class "SQLiteObject".
-}
-\section{Methods}{
-  \describe{
-    \item{\link{coerce}}{\code{signature(from = "SQLiteConnection", to = "SQLiteResult")}: ... }
-    \item{\link[DBI]{dbClearResult}}{\code{signature(res = "SQLiteResult")}: ... }
-    \item{\link[DBI]{dbColumnInfo}}{\code{signature(res = "SQLiteResult")}: ... }
-    \item{\link[DBI]{dbGetException}}{\code{signature(conn = "SQLiteResult")}: ... }
-    \item{\link[DBI]{dbGetInfo}}{\code{signature(dbObj = "SQLiteResult")}: ... }
-    \item{\link[DBI]{dbGetRowCount}}{\code{signature(res = "SQLiteResult")}: ... }
-    \item{\link[DBI]{dbGetRowsAffected}}{\code{signature(res = "SQLiteResult")}: ... }
-    \item{\link[DBI]{dbGetStatement}}{\code{signature(res = "SQLiteResult")}: ... }
-    \item{\link[DBI]{dbHasCompleted}}{\code{signature(res = "SQLiteResult")}: ... }
-    \item{\link[DBI]{dbListFields}}{\code{signature(conn = "SQLiteResult", name = "missing")}: ... }
-    \item{\link[DBI]{fetch}}{\code{signature(res = "SQLiteResult", n = "numeric")}: ... }
-    \item{\link[DBI]{fetch}}{\code{signature(res = "SQLiteResult", n = "missing")}: ... }
-    \item{\link{summary}}{\code{signature(object = "SQLiteResult")}: ... }
-  }
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\author{R-SIG-DB}
-
-\seealso{
- DBI classes:
- \code{\link{SQLiteObject-class}}
- \code{\link{SQLiteDriver-class}}
- \code{\link{SQLiteConnection-class}}
- \code{\link{SQLiteResult-class}}
+SQLite's query results class.  This classes encapsulates the result of an
+SQL statement (either \code{select} or not).
 }
 
-\keyword{database}
-\keyword{interface}
-\keyword{classes}
-% vim: syntax=tex
diff --git a/man/datasetsDb.Rd b/man/datasetsDb.Rd
new file mode 100644
index 0000000..14365c4
--- /dev/null
+++ b/man/datasetsDb.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\name{datasetsDb}
+\alias{datasetsDb}
+\title{A sample sqlite database.}
+\usage{
+datasetsDb()
+}
+\description{
+This database is bundled with the package, and contains all data frames
+in the datasets package.
+}
+\examples{
+db <- datasetsDb()
+dbListTables(db)
+
+dbReadTable(db, "CO2")
+dbGetQuery(db, "SELECT * FROM CO2 WHERE conc < 100")
+
+dbDisconnect(db)
+}
+
diff --git a/man/dbBeginTransaction.Rd b/man/dbBeginTransaction.Rd
new file mode 100644
index 0000000..3753fdf
--- /dev/null
+++ b/man/dbBeginTransaction.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\name{dbBeginTransaction}
+\alias{dbBeginTransaction}
+\title{Generic for creating a new transaction.}
+\usage{
+dbBeginTransaction(conn, ...)
+}
+\arguments{
+\item{conn}{An \code{DBIConnection} object.}
+
+\item{...}{Other arguments used by methods}
+}
+\description{
+See method documentation for details.
+}
+\keyword{internal}
+
diff --git a/man/dbBuildTableDefinition.Rd b/man/dbBuildTableDefinition.Rd
deleted file mode 100644
index 1737fcd..0000000
--- a/man/dbBuildTableDefinition.Rd
+++ /dev/null
@@ -1,47 +0,0 @@
-\name{dbBuildTableDefinition}
-\alias{dbBuildTableDefinition}
-\title{Build the SQL CREATE TABLE definition as a string}
-\description{
-   Build the SQL CREATE TABLE definition as a string for the
-   input data.frame
-}
-\usage{
-dbBuildTableDefinition(dbObj, name, value, field.types = NULL, row.names = TRUE, ...)
-}
-\arguments{
-  \item{dbObj}{any DBI object (used only to dispatch according to the 
-    engine (e.g., MySQL, SQLite, Oracle) }
-  \item{name}{name of the new SQL table}
-  \item{value}{data.frame for which we want to create a table}
-  \item{field.types}{optional named list of the types for each field 
-    in \code{value}} 
-  \item{row.names}{logical, should row.name of \code{value} be exported
-    as a \code{row\_names} field? Default is \code{TRUE}}
-  \item{\dots}{reserved for future use}
-}
-\details{
-  The output SQL statement is a simple \code{CREATE TABLE} with
-  suitable for \code{dbGetQuery}
-}
-\value{
-  An SQL string
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link{SQLite}},
-  \code{\link[DBI]{dbConnect}},
-  \code{\link[DBI]{dbSendQuery}},
-  \code{\link[DBI]{dbGetQuery}},
-  \code{\link[DBI]{fetch}},
-  \code{\link[DBI]{dbCommit}},
-  \code{\link[DBI]{dbGetInfo}},
-  \code{\link[DBI]{dbReadTable}}.
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-%% vim: syntax=tex
diff --git a/man/dbCallProc-methods.Rd b/man/dbCallProc-methods.Rd
deleted file mode 100644
index 83ea529..0000000
--- a/man/dbCallProc-methods.Rd
+++ /dev/null
@@ -1,39 +0,0 @@
-% $Id$
-\name{dbCallProc-methods}
-\docType{methods}
-\alias{dbCallProc-methods}
-\alias{dbCallProc,SQLiteConnection-method}
-\title{
-  Call an SQL stored procedure
-}
-\description{
-  Not yet implemented.
-}
-\section{Methods}{\describe{
-\item{conn}{
-  a \code{SQLiteConnection} object.
-  }
-\item{\dots }{
-  additional arguments are passed to the implementing method.
-  }
-}
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-   \code{\link{SQLite}},
-   \code{\link[DBI]{dbConnect}},
-   \code{\link[DBI]{dbSendQuery}},
-   \code{\link[DBI]{dbGetQuery}},
-   \code{\link[DBI]{fetch}},
-   \code{\link[DBI]{dbCommit}},
-   \code{\link[DBI]{dbGetInfo}},
-   \code{\link[DBI]{dbReadTable}}.
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/dbCommit-methods.Rd b/man/dbCommit-methods.Rd
deleted file mode 100644
index 9657f9e..0000000
--- a/man/dbCommit-methods.Rd
+++ /dev/null
@@ -1,75 +0,0 @@
-% $Id$
-\name{dbCommit-methods}
-\docType{methods}
-\alias{dbBeginTransaction}
-\alias{dbBeginTransaction-methods}
-\alias{dbCommit-methods}
-\alias{dbRollback-methods}
-\alias{dbBeginTransaction,SQLiteConnection-method}
-\alias{dbCommit,SQLiteConnection-method}
-\alias{dbRollback,SQLiteConnection-method}
-\title{
-  DBMS Transaction Management
-}
-\description{
-  By default, SQLite is in auto-commit mode. \code{dbBeginTransaction}
-  starts a SQLite transaction and turns auto-commit
-  off. \code{dbCommit} and \code{dbRollback} commit and rollback the
-  transaction, respectively and turn auto-commit on.
-
-}
-\section{Methods}{\describe{
-\item{conn}{
-  a \code{SQLiteConnection} object, as produced by the function 
-  \code{dbConnect}.
-  }
-\item{\dots }{
-  any database-specific arguments.
-  }
-}
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or
-  \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-   \code{\link{SQLite}},
-   \code{\link[DBI]{dbConnect}},
-   \code{\link[DBI]{dbSendQuery}},
-   \code{\link[DBI]{dbGetQuery}},
-   \code{\link[DBI]{fetch}},
-   \code{\link[DBI]{dbCommit}},
-   \code{\link[DBI]{dbGetInfo}},
-   \code{\link[DBI]{dbReadTable}}.
-}
-\examples{
-drv <- dbDriver("SQLite")
-tfile <- tempfile()
-con <- dbConnect(drv, dbname = tfile)
-data(USArrests)
-dbWriteTable(con, "arrests", USArrests)
-dbGetQuery(con, "select count(*) from arrests")[1, ]
-
-dbBeginTransaction(con)
-rs <- dbSendQuery(con, "DELETE from arrests WHERE Murder > 1")
-do_commit <- if (dbGetInfo(rs)[["rowsAffected"]] > 40) FALSE else TRUE
-dbClearResult(rs)
-dbGetQuery(con, "select count(*) from arrests")[1, ]
-if (!do_commit)
-    dbRollback(con)
-dbGetQuery(con, "select count(*) from arrests")[1, ]
-
-dbBeginTransaction(con)
-rs <- dbSendQuery(con, "DELETE from arrests WHERE Murder > 5")
-dbClearResult(rs)
-dbCommit(con)
-dbGetQuery(con, "select count(*) from arrests")[1, ]
-
-dbDisconnect(con)
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/dbConnect-SQLiteDriver-method.Rd b/man/dbConnect-SQLiteDriver-method.Rd
new file mode 100644
index 0000000..fee03ce
--- /dev/null
+++ b/man/dbConnect-SQLiteDriver-method.Rd
@@ -0,0 +1,76 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbConnect,SQLiteDriver-method}
+\alias{SQLITE_RO}
+\alias{SQLITE_RW}
+\alias{SQLITE_RWC}
+\alias{dbConnect,SQLiteConnection-method}
+\alias{dbConnect,SQLiteDriver-method}
+\alias{dbDisconnect,SQLiteConnection-method}
+\title{Connect to/disconnect from a SQLite database.}
+\usage{
+\S4method{dbConnect}{SQLiteDriver}(drv, dbname = "",
+  loadable.extensions = TRUE, cache_size = NULL, synchronous = "off",
+  flags = SQLITE_RWC, vfs = NULL)
+
+\S4method{dbConnect}{SQLiteConnection}(drv)
+
+\S4method{dbDisconnect}{SQLiteConnection}(conn)
+}
+\arguments{
+\item{drv,conn}{An objected generated by \code{\link{SQLite}}, or an existing
+\code{\linkS4class{SQLiteConnection}}. If an connection, the connection
+will be cloned.}
+
+\item{dbname}{The path to the database file. There are two special values:
+
+  \itemize{
+  \item \code{""}: creates a temporary on-disk database The file will be
+     deleted when the connection is closed.
+  \item \code{":memory:"}: create a temporary in-memory database.
+  }}
+
+\item{loadable.extensions}{When \code{TRUE} (default) SQLite3
+loadable extensions are enabled. Setting this value to \code{FALSE}
+prevents extensions from being loaded.}
+
+\item{cache_size}{Advanced option. A positive integer to change the maximum
+number of disk pages that SQLite holds in memory (SQLite's default is
+2000 pages). See \url{http://www.sqlite.org/pragma.html#pragma_cache_size}
+for details.}
+
+\item{synchronous}{Advanced options. Possible values for \code{synchronous}
+are "off" (the default), "normal", or  "full".  Users have reported
+significant speed ups using \code{sychronous = "off"}, and the SQLite
+documentation itself implies considerable improved performance at the very
+modest risk of database corruption in the unlikely case of the operating
+system (\emph{not} the R application) crashing. See
+\url{http://www.sqlite.org/pragma.html#pragma_synchronous} for details.}
+
+\item{flags}{\code{SQLITE_RWC}: open the database in read/write mode
+and create the database file if it does not already exist;
+\code{SQLITE_RW}: open the database in read/write mode. Raise an error
+if the file does not already exist; \code{SQLITE_RO}: open the database in
+read only mode.  Raise an error if the file does not already exist}
+
+\item{vfs}{Select the SQLite3 OS interface. See
+\url{http://www.sqlite.org/vfs.html} for details. Allowed values are
+\code{"unix-posix"}, \code{"unix-unix-afp"},
+\code{"unix-unix-flock"}, \code{"unix-dotfile"}, and
+\code{"unix-none"}.}
+}
+\description{
+Connect to/disconnect from a SQLite database.
+}
+\examples{
+# Create temporary in-memory db
+tmp <- dbConnect(SQLite(), ":memory:")
+summary(tmp)
+dbDisconnect(tmp)
+
+# Create temporary on-disk db with bigger cache and safer synchronisation
+tmp <- dbConnect(SQLite(), "", cache_size = 5000, synchronous = "full")
+summary(tmp)
+dbDisconnect(tmp)
+}
+
diff --git a/man/dbConnect-methods.Rd b/man/dbConnect-methods.Rd
deleted file mode 100644
index 52abeef..0000000
--- a/man/dbConnect-methods.Rd
+++ /dev/null
@@ -1,74 +0,0 @@
-% $Id$
-\name{dbConnect-methods}
-\docType{methods}
-\alias{dbDisconnect-methods}
-\alias{dbConnect-methods}
-\alias{dbDisconnect,SQLiteConnection-method}
-\alias{dbConnect,SQLiteDriver-method}
-\alias{dbConnect,SQLiteConnection-method}
-\alias{dbConnect,character-method}
-\title{
-  Create a connection object to an SQLite DBMS
-}
-\description{
-   These methods are straight-forward implementations of the corresponding
-   generic functions.
-}
-\section{Methods}{\describe{
-\item{drv}{
-  an object of class \code{SQLiteDriver}, or
-  the character string "SQLite" or an \code{SQLiteConnection}.
-  }
-\item{conn}{
-  an \code{SQLiteConnection} object as produced by \code{dbConnect}.
-  }
-\item{\dots }{
-  As of RSQLite 0.4-1 you may specify values for the two \code{PRAGMAs}
-  \code{cache\_size} and \code{synchronous} when initializing a new
-  connection (this does not apply when cloning an existing
-  connection).
-
-  RSQLite defaults \code{synchronous} to 0 (or "OFF"),
-  although SQLite's default as of 3.2.8 is 2 (FULL).
-  Possible values for \code{synchronous} are 0, 1, or 2 or the 
-  corresponding strings "OFF", "NORMAL", or "FULL".
-  Users have reported significant speed ups using \code{sychronous=0},
-  and the SQLite documentation itself implies considerable improved
-  performance at the very modest risk of database corruption in the
-  unlikely case of the operating system (\emph{not} the R application) 
-  crashing. See the SQLite documentation for the full details of this
-  \code{PRAGMA}.
-  
-  \code{cache\_size} can be a positive integer to change
-   the maximum number of disk pages that SQLite holds in
-   memory (SQLite's default is 2000 pages). }
-}
-}
-\section{Side Effects}{
-  A connection between R/S-Plus and the embeddable SQLite server is 
-  established.  Note that since the SQLite is embedded in R/S-Plus,
-  connections are not too resource hungry.
-
-  SQLite connections only require the file name where the SQLite
-  database reside.  For details see \code{\link{SQLite}}.
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link{SQLite}},
-  \code{\link[DBI]{dbConnect}},
-  \code{\link[DBI]{dbSendQuery}},
-  \code{\link[DBI]{dbGetQuery}},
-  \code{\link[DBI]{fetch}},
-  \code{\link[DBI]{dbCommit}},
-  \code{\link[DBI]{dbGetInfo}},
-  \code{\link[DBI]{dbReadTable}}.
-}
-
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/dbDataType-SQLiteConnection-method.Rd b/man/dbDataType-SQLiteConnection-method.Rd
new file mode 100644
index 0000000..7663f07
--- /dev/null
+++ b/man/dbDataType-SQLiteConnection-method.Rd
@@ -0,0 +1,34 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbDataType,SQLiteConnection-method}
+\alias{dbDataType,SQLiteConnection-method}
+\alias{dbDataType,SQLiteDriver-method}
+\title{Determine the SQL Data Type of an R object.}
+\usage{
+\S4method{dbDataType}{SQLiteConnection}(dbObj, obj, ...)
+
+\S4method{dbDataType}{SQLiteDriver}(dbObj, obj, ...)
+}
+\arguments{
+\item{dbObj}{a \code{SQLiteDriver} object,}
+
+\item{obj}{an R object whose SQL type we want to determine.}
+
+\item{...}{Needed for compatibility with generic. Otherwise ignored.}
+}
+\description{
+This method is a straight-forward implementation of the corresponding
+generic function.
+}
+\examples{
+data(quakes)
+drv <- SQLite()
+
+sapply(quakes, function(x) dbDataType(drv, x))
+
+dbDataType(drv, 1)
+dbDataType(drv, as.integer(1))
+dbDataType(drv, "1")
+dbDataType(drv, charToRaw("1"))
+}
+
diff --git a/man/dbDataType-methods.Rd b/man/dbDataType-methods.Rd
deleted file mode 100644
index e6932a2..0000000
--- a/man/dbDataType-methods.Rd
+++ /dev/null
@@ -1,51 +0,0 @@
-% $Id$
-\name{dbDataType-methods}
-\docType{methods}
-\alias{dbDataType-methods}
-\alias{dbDataType,SQLiteObject-method}
-\title{
-  Determine the SQL Data Type of an S object
-}
-\description{
-   This method is a straight-forward implementation of the corresponding
-   generic function.
-}
-\section{Methods}{\describe{
-\item{dbObj}{
-  a \code{SQLiteDriver} object, e.g., \code{ODBCDriver},
-  \code{OracleDriver}.
-  }
-\item{obj}{
-  R/S-Plus object whose SQL type we want to determine.
-  }
-\item{\dots }{
-  any other parameters that individual methods may need.
-  }
-}
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link[DBI]{isSQLKeyword}}
-  \code{\link[DBI]{make.db.names}}
-}
-\examples{
-data(quakes)
-drv <- dbDriver("SQLite")
-sapply(quakes, function(x) dbDataType(drv, x))
-
-dbDataType(drv, 1)
-dbDataType(drv, as.integer(1))
-dbDataType(drv, "1")
-dbDataType(drv, charToRaw("1"))
-
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% docclass is function
-% Converted by Sd2Rd version 1.15.2.1.
-% vim: syntax=tex
diff --git a/man/dbDriver-methods.Rd b/man/dbDriver-methods.Rd
deleted file mode 100644
index 8755806..0000000
--- a/man/dbDriver-methods.Rd
+++ /dev/null
@@ -1,64 +0,0 @@
-% $Id$
-\name{dbDriver-methods}
-\docType{methods}
-\alias{dbDriver-methods}
-\alias{dbUnloadDriver-methods}
-\alias{dbDriver,character-method}
-\alias{dbUnloadDriver,SQLiteDriver-method}
-\title{
-  SQLite implementation of the Database Interface (DBI) classes 
-  and drivers 
-}
-\description{
-  SQLite driver initialization and closing
-}
-\section{Methods}{\describe{
-\item{drvName}{
-  character name of the driver to instantiate.
-  }
-\item{drv}{
-  an object that inherits from \code{SQLiteDriver} as created by
-  \code{dbDriver}.
-}
-\item{\dots}{
-  any other arguments are passed to the driver \code{drvName}.
-  }
-}
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or
-  \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link{SQLite}},
-  \code{\link[DBI]{dbConnect}},
-  \code{\link[DBI]{dbSendQuery}},
-  \code{\link[DBI]{dbGetQuery}},
-  \code{\link[DBI]{fetch}},
-  \code{\link[DBI]{dbCommit}},
-  \code{\link[DBI]{dbGetInfo}},
-  \code{\link[DBI]{dbListTables}},
-  \code{\link[DBI]{dbReadTable}}.
-}
-\examples{\dontrun{
-# create an SQLite instance for capacity of up to 25 simultaneous
-# connections.
-m <- dbDriver("SQLite", max.con = 25)
-
-con <- dbConnect(m, dbname="sqlite.db")
-rs <- dbSubmitQuery(con, 
-         "select * from HTTP_ACCESS where IP_ADDRESS = '127.0.0.1'")
-df <- fetch(rs, n = 50)
-df2 <- fetch(rs, n = -1)
-dbClearResult(rs)
-
-pcon <- dbConnect(p, "user", "password", "dbname")
-dbListTables(pcon)
-}
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/dbExistsTable-SQLiteConnection-character-method.Rd b/man/dbExistsTable-SQLiteConnection-character-method.Rd
new file mode 100644
index 0000000..c38dabe
--- /dev/null
+++ b/man/dbExistsTable-SQLiteConnection-character-method.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbExistsTable,SQLiteConnection,character-method}
+\alias{dbExistsTable,SQLiteConnection,character-method}
+\title{Does the table exist?}
+\usage{
+\S4method{dbExistsTable}{SQLiteConnection,character}(conn, name)
+}
+\arguments{
+\item{conn}{An existing \code{\linkS4class{SQLiteConnection}}}
+
+\item{name}{String, name of table. Match is case insensitive.}
+}
+\description{
+Does the table exist?
+}
+
diff --git a/man/dbGetException-SQLiteConnection-method.Rd b/man/dbGetException-SQLiteConnection-method.Rd
new file mode 100644
index 0000000..61a1e83
--- /dev/null
+++ b/man/dbGetException-SQLiteConnection-method.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbGetException,SQLiteConnection-method}
+\alias{dbGetException,SQLiteConnection-method}
+\title{Get the last exception from the connection.}
+\usage{
+\S4method{dbGetException}{SQLiteConnection}(conn)
+}
+\arguments{
+\item{conn}{an object of class \code{\linkS4class{SQLiteConnection}}}
+}
+\description{
+Get the last exception from the connection.
+}
+\keyword{internal}
+
diff --git a/man/dbGetInfo-methods.Rd b/man/dbGetInfo-methods.Rd
deleted file mode 100644
index 82c3676..0000000
--- a/man/dbGetInfo-methods.Rd
+++ /dev/null
@@ -1,89 +0,0 @@
-% $Id$
-\name{dbGetInfo-methods}
-\docType{methods}
-\alias{dbGetInfo}
-\alias{dbGetDBIVersion-methods}
-\alias{dbGetStatement-methods}
-\alias{dbGetRowCount-methods}
-\alias{dbGetRowsAffected-methods}
-\alias{dbColumnInfo-methods}
-\alias{dbHasCompleted-methods}
-\alias{dbGetInfo,SQLiteObject-method}
-\alias{dbGetInfo,SQLiteDriver-method}        % BUG: this is not needed
-\alias{dbGetInfo,SQLiteConnection-method}        % BUG: this is not needed
-\alias{dbGetInfo,SQLiteResult-method}        % BUG: this is not needed
-\alias{dbGetStatement,SQLiteResult-method}
-\alias{dbGetRowCount,SQLiteResult-method}
-\alias{dbGetRowsAffected,SQLiteResult-method}
-\alias{dbColumnInfo,SQLiteResult-method}
-\alias{dbHasCompleted,SQLiteResult-method}
-\title{
-  Database interface meta-data
-}
-\description{
-   These methods are straight-forward implementations of the corresponding
-   generic functions.
-}
-\section{Methods}{\describe{
-\item{dbObj}{
-  any object that implements some functionality in the R/S-Plus
-  interface to databases (a driver, a connection or a result set).
-  }
-%\item{drv}{an \code{SQLiteDriver}.}
-%\item{conn}{an \code{SQLiteConnection}.}
-\item{res}{ an \code{SQLiteResult}.}
-\item{\dots}{currently not being used.}
-}
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link{SQLite}},
-  \code{\link[DBI]{dbDriver}},
-  \code{\link[DBI]{dbConnect}},
-  \code{\link[DBI]{dbSendQuery}},
-  \code{\link[DBI]{dbGetQuery}},
-  \code{\link[DBI]{fetch}},
-  \code{\link[DBI]{dbCommit}},
-  \code{\link[DBI]{dbGetInfo}},
-  \code{\link[DBI]{dbListTables}},
-  \code{\link[DBI]{dbReadTable}}.
-}
-\examples{
-data(USArrests)
-drv <- dbDriver("SQLite")
-con <- dbConnect(drv, dbname=":memory:")
-dbWriteTable(con, "t1", USArrests)
-dbWriteTable(con, "t2", USArrests)
-
-dbListTables(con)
-
-rs <- dbSendQuery(con, "select * from t1 where UrbanPop >= 80")
-dbGetStatement(rs)
-dbHasCompleted(rs)
-
-info <- dbGetInfo(rs)
-names(info)
-info$fields
-
-fetch(rs, n=2)
-dbHasCompleted(rs)
-info <- dbGetInfo(rs)
-info$fields
-dbClearResult(rs)
-
-names(dbGetInfo(drv))  
-
-# DBIConnection info
-names(dbGetInfo(con))
-
-dbDisconnect(con)
-}
-
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/dbGetInfo.Rd b/man/dbGetInfo.Rd
new file mode 100644
index 0000000..8aaf09a
--- /dev/null
+++ b/man/dbGetInfo.Rd
@@ -0,0 +1,39 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbGetInfo}
+\alias{dbGetInfo}
+\alias{dbGetInfo,SQLiteConnection-method}
+\alias{dbGetInfo,SQLiteDriver-method}
+\alias{dbGetInfo,SQLiteResult-method}
+\title{Get metadata about a database object.}
+\usage{
+\S4method{dbGetInfo}{SQLiteDriver}(dbObj)
+
+\S4method{dbGetInfo}{SQLiteConnection}(dbObj)
+
+\S4method{dbGetInfo}{SQLiteResult}(dbObj)
+}
+\arguments{
+\item{dbObj}{An object of class \code{\linkS4class{SQLiteDriver}},
+\code{\linkS4class{SQLiteConnection}} or
+\code{\linkS4class{SQLiteResult}}}
+}
+\description{
+Get metadata about a database object.
+}
+\examples{
+dbGetInfo(SQLite())
+
+con <- dbConnect(SQLite())
+dbGetInfo(con)
+
+dbWriteTable(con, "mtcars", mtcars)
+rs <- dbSendQuery(con, "SELECT * FROM mtcars")
+dbGetInfo(rs)
+dbFetch(rs, 1)
+dbGetInfo(rs)
+
+dbClearResult(rs)
+dbDisconnect(con)
+}
+
diff --git a/man/dbIsValid.Rd b/man/dbIsValid.Rd
new file mode 100644
index 0000000..f86b8bd
--- /dev/null
+++ b/man/dbIsValid.Rd
@@ -0,0 +1,38 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbIsValid}
+\alias{dbIsValid}
+\alias{dbIsValid,SQLiteConnection-method}
+\alias{dbIsValid,SQLiteDriver-method}
+\alias{dbIsValid,SQLiteResult-method}
+\alias{isIdCurrent}
+\title{Check whether an SQLite object is valid or not.}
+\usage{
+\S4method{dbIsValid}{SQLiteDriver}(dbObj)
+
+\S4method{dbIsValid}{SQLiteConnection}(dbObj)
+
+\S4method{dbIsValid}{SQLiteResult}(dbObj)
+
+isIdCurrent(obj)
+}
+\arguments{
+\item{dbObj,obj}{A driver, connection or result.}
+}
+\value{
+A logical scalar.
+}
+\description{
+Support function that verifies that the holding a reference to a
+foreign object is still valid for communicating with the RDBMS
+}
+\examples{
+dbIsValid(SQLite())
+
+con <- dbConnect(SQLite())
+dbIsValid(con)
+
+dbDisconnect(con)
+dbIsValid(con)
+}
+
diff --git a/man/dbListFields-SQLiteConnection-character-method.Rd b/man/dbListFields-SQLiteConnection-character-method.Rd
new file mode 100644
index 0000000..9054952
--- /dev/null
+++ b/man/dbListFields-SQLiteConnection-character-method.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbListFields,SQLiteConnection,character-method}
+\alias{dbListFields,SQLiteConnection,character-method}
+\title{List fields in specified table.}
+\usage{
+\S4method{dbListFields}{SQLiteConnection,character}(conn, name)
+}
+\arguments{
+\item{conn}{An existing \code{\linkS4class{SQLiteConnection}}}
+
+\item{name}{a length 1 character vector giving the name of a table.}
+}
+\description{
+List fields in specified table.
+}
+\examples{
+con <- dbConnect(SQLite())
+dbWriteTable(con, "iris", iris)
+dbListFields(con, "iris")
+dbDisconnect(con)
+}
+
diff --git a/man/dbListTables-SQLiteConnection-method.Rd b/man/dbListTables-SQLiteConnection-method.Rd
new file mode 100644
index 0000000..185305e
--- /dev/null
+++ b/man/dbListTables-SQLiteConnection-method.Rd
@@ -0,0 +1,15 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbListTables,SQLiteConnection-method}
+\alias{dbListTables,SQLiteConnection-method}
+\title{List available SQLite tables.}
+\usage{
+\S4method{dbListTables}{SQLiteConnection}(conn)
+}
+\arguments{
+\item{conn}{An existing \code{\linkS4class{SQLiteConnection}}}
+}
+\description{
+List available SQLite tables.
+}
+
diff --git a/man/dbListTables-methods.Rd b/man/dbListTables-methods.Rd
deleted file mode 100644
index 0deb812..0000000
--- a/man/dbListTables-methods.Rd
+++ /dev/null
@@ -1,52 +0,0 @@
-% $Id$
-\name{dbListTables-methods}
-\docType{methods}
-\alias{dbListTables-methods}
-\alias{dbListFields-methods}
-\alias{dbListConnections-methods}
-\alias{dbListResults-methods}
-\alias{dbListTables,SQLiteConnection-method}
-\alias{dbListFields,SQLiteConnection,character-method}
-\alias{dbListConnections,SQLiteDriver-method}
-\alias{dbListResults,SQLiteConnection-method}
-\title{
-  List items from an SQLite DBMS and from objects 
-}
-\description{
-   These methods are straight-forward implementations of the corresponding
-   generic functions.
-}
-\section{Methods}{\describe{
-  \item{drv}{an \code{SQLiteDriver}.}
-  \item{conn}{an \code{SQLiteConnection}.}
-  \item{name}{a character string with the table name.}
-  \item{\dots}{currently not used.}
-}
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or
-  \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link{SQLite}},
-  \code{\link[DBI]{dbGetInfo}},
-  \code{\link[DBI]{dbColumnInfo}},
-  \code{\link[DBI]{dbDriver}},
-  \code{\link[DBI]{dbConnect}},
-  \code{\link[DBI]{dbSendQuery}}
-}
-
-\examples{\dontrun{
-drv <- dbDriver("SQLite")
-# after working awhile...
-for(con in dbListConnections(odbc)){
-   dbGetStatement(dbListResults(con))
-}
-}
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/dbObjectId-class.Rd b/man/dbObjectId-class.Rd
deleted file mode 100644
index 9dab031..0000000
--- a/man/dbObjectId-class.Rd
+++ /dev/null
@@ -1,44 +0,0 @@
-% $Id$
-\name{dbObjectId-class}
-\docType{class}
-\alias{dbObjectId-class}
-\title{Class dbObjectId}
-\description{  
-   A helper (mixin) class to provide external references in
-   an R/S-Plus portable way.
-}
-\section{Objects from the Class}{A virtual Class: No objects may be created from it.}
-\section{Slots}{
-  \describe{
-    \item{\code{Id}:}{Object of class \code{"integer"} 
-    this is an integer vector holding an opaque reference into a C struct
-    (may or may not be a C pointer, may or may not have length one).
-    }
-  }
-}
-
-\section{Methods}{
-  \describe{
-    \item{\link{coerce}}{\code{signature(from = "dbObjectId", to = "integer")}: ... }
-    \item{\link{coerce}}{\code{signature(from = "dbObjectId", to = "numeric")}: ... }
-    \item{\link{coerce}}{\code{signature(from = "dbObjectId", to = "character")}: ... }
-    \item{\link{format}}{\code{signature(x = "dbObjectId")}: ... }
-    \item{\link{print}}{\code{signature(x = "dbObjectId")}: ... }
-    \item{\link{show}}{\code{signature(object = "dbObjectId")}: ... }
-  }
-}
-
-\note{A cleaner mechanism would use external references, but
-historically this class has existed mainly for R/S-Plus portability.}
-
-\examples{
-  sqlite <- dbDriver("SQLite")
-  con <- dbConnect(sqlite, ":memory:")
-  is(sqlite, "dbObjectId")   ## True
-  is(con, "dbObjectId")  ## True
-  isIdCurrent(con)       ## True
-  dbDisconnect(con)
-  isIdCurrent(con)       ## False
-}
-\keyword{classes}
-% vim: syntax=tex
diff --git a/man/dbReadTable-SQLiteConnection-character-method.Rd b/man/dbReadTable-SQLiteConnection-character-method.Rd
new file mode 100644
index 0000000..1497f6c
--- /dev/null
+++ b/man/dbReadTable-SQLiteConnection-character-method.Rd
@@ -0,0 +1,53 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbReadTable,SQLiteConnection,character-method}
+\alias{dbReadTable,SQLiteConnection,character-method}
+\title{Convenience functions for importing/exporting DBMS tables}
+\usage{
+\S4method{dbReadTable}{SQLiteConnection,character}(conn, name, row.names,
+  check.names = TRUE, select.cols = "*")
+}
+\arguments{
+\item{conn}{a \code{\linkS4class{SQLiteConnection}} object, produced by
+\code{\link[DBI]{dbConnect}}}
+
+\item{name}{a character string specifying a table name. SQLite table names
+are \emph{not} case sensitive, e.g., table names \code{ABC} and \code{abc}
+are considered equal.}
+
+\item{row.names}{A string or an index specifying the column in the DBMS table
+to use as \code{row.names} in the output data.frame. Defaults to using the
+\code{row_names} column if present. Set to \code{NULL} to never use
+row names.}
+
+\item{check.names}{If \code{TRUE}, the default, column names will be
+converted to valid R identifiers.}
+
+\item{select.cols}{A SQL statement (in the form of a character vector of
+length 1) giving the columns to select. E.g. "*" selects all columns,
+"x,y,z" selects three columns named as listed.}
+}
+\value{
+A data.frame in the case of \code{dbReadTable}; otherwise a logical
+indicating whether the operation was successful.
+}
+\description{
+These functions mimic their R/S-Plus counterpart \code{get}, \code{assign},
+\code{exists}, \code{remove}, and \code{objects}, except that they generate
+code that gets remotely executed in a database engine.
+}
+\note{
+Note that the data.frame returned by \code{dbReadTable} only has
+primitive data, e.g., it does not coerce character data to factors.
+}
+\examples{
+con <- dbConnect(SQLite())
+dbWriteTable(con, "mtcars", mtcars)
+dbReadTable(con, "mtcars")
+
+# Supress row names
+dbReadTable(con, "mtcars", row.names = FALSE)
+
+dbDisconnect(con)
+}
+
diff --git a/man/dbReadTable-methods.Rd b/man/dbReadTable-methods.Rd
deleted file mode 100644
index 3b38c73..0000000
--- a/man/dbReadTable-methods.Rd
+++ /dev/null
@@ -1,147 +0,0 @@
-% $Id$
-\name{dbReadTable-methods}
-\docType{methods}
-\alias{dbReadTable-methods}
-\alias{dbWriteTable-methods}
-\alias{dbExistsTable-methods}
-\alias{dbRemoveTable-methods}
-\alias{dbReadTable,SQLiteConnection,character-method}
-\alias{dbWriteTable,SQLiteConnection,character,data.frame-method}
-\alias{dbWriteTable,SQLiteConnection,character,character-method}
-\alias{dbExistsTable,SQLiteConnection,character-method}
-\alias{dbRemoveTable,SQLiteConnection,character-method}
-\title{
-  Convenience functions for Importing/Exporting DBMS tables
-}
-\description{
-  These functions mimic their R/S-Plus counterpart 
-  \code{get},
-  \code{assign},
-  \code{exists}, 
-  \code{remove}, and
-  \code{objects},
-  except that they generate code that gets remotely executed
-  in a database engine.
-}
-\section{Methods}{\describe{
-\item{conn}{
-  an \code{SQLiteConnection} database connection object.
-  }
-\item{name}{
-  a character string specifying a table name.
-  }
-\item{value}{
-  a data.frame (or coercible to data.frame) object 
-  or a file name (character).  In the first case, the data.frame
-  is written to a temporary file and then imported to SQLite;
-  when \code{value} is a character, it is interpreted as a
-  file name and its contents imported to SQLite.
-  }
-\item{row.names}{
-  in the case of \code{dbReadTable}, this argument can be a string or
-  an index specifying the column in the DBMS table to be used as 
-  \code{row.names} in the output data.frame (a \code{NULL}, \code{""}, or 0 
-  specifies that no column should be used as \code{row.names} in the output).
-
-  In the case of \code{dbWriteTable}, this argument should be a logical
-  specifying whether the \code{row.names} should be output to the
-  output DBMS table; if \code{TRUE}, an extra field whose name will be 
-  whatever the R/S-Plus identifier \code{"row.names"} maps to the DBMS
-  (see \code{\link[DBI]{make.db.names}}).
-  }
-\item{overwrite}{
-  a logical specifying whether to overwrite an existing table
-  or not.  Its default is \code{FALSE}.  (See the BUGS section below).
-  }
-\item{append}{
-  a logical specifying whether to append to an existing table
-  in the DBMS.  Its default is \code{FALSE}.
-  }
-\item{\dots }{
-  optional arguments.
-
-  When \code{dbWriteTable} is used to import data from a file, 
-  you may optionally specify \code{header=}, \code{row.names=},
-  \code{col.names=}, \code{sep=}, \code{eol=}, \code{field.types=}, 
-  and \code{skip=}.
-
-  \code{header} is a logical indicating whether the first data line
-  (but see \code{skip}) has a header or not.  If missing, it value
-  is determined following \code{\link{read.table}} convention,
-  namely, it is set to TRUE if and only if the first row has one
-  fewer field that the number of columns.
-
-  \code{row.names} is a logical to specify whether the first column
-  is a set of row names.  If missing its defualt follows the 
-  \code{\link{read.table}} convention.
-  
-  \code{col.names} a character vector with column names (these names
-  will be filtered with \code{\link[DBI]{make.db.names}} to 
-  ensure valid SQL identifiers. (See also \code{field.types} below.)
-
-  The field separator \code{sep=} defaults to \code{','}.
-
-  The end-of-line delimiter \code{eol} defaults to \code{'\n'}.
-
-  \code{skip} specifies number of lines to skip before reading the data
-  and it defaults to 0. 
-
-  \code{field.types} is a list of named field SQL types where 
-  \code{names(field.types)} provide the new table's column names 
-  (if missing, field types are inferred using \code{\link[DBI]{dbDataType}}).
- }
-}
-}
-
-\value{
-   A data.frame in the case of \code{dbReadTable}; otherwise a logical 
-   indicating whether the operation was successful.  
-}
-\section{BUGS}{
-  These RSQLite methods do not use transactions, thus it is dangerous 
-  to specify \code{overwrite=TRUE} in \code{dbWriteTable} (the
-  table is first removed and in case the data exporting fails
-  the original table is lost forever).
-}
-\note{
-   Note that the data.frame returned by \code{dbReadTable} only has
-   primitive data, e.g., it does not coerce character data to factors.
-
-   SQLite table names are \emph{not} case sensitive, e.g., table
-   names \code{ABC} and \code{abc} are considered equal.
-}
-\references{
-   See the Database Interface definition document
-   \code{DBI.pdf} in the base directory of this package
-   or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link{sqliteImportFile}},
-  \code{\link{SQLite}},
-  \code{\link[DBI]{dbDriver}},
-  \code{\link[DBI]{dbConnect}},
-  \code{\link[DBI]{dbSendQuery}},
-  \code{\link[DBI]{dbGetQuery}},
-  \code{\link[DBI]{fetch}},
-  \code{\link[DBI]{dbCommit}},
-  \code{\link[DBI]{dbGetInfo}},
-  \code{\link[DBI]{dbListTables}},
-  \code{\link[DBI]{dbReadTable}}.
-}
-\examples{\dontrun{
-conn <- dbConnect("SQLite", dbname = "sqlite.db")
-if(dbExistsTable(con, "fuel_frame")){
-   dbRemoveTable(conn, "fuel_frame")
-   dbWriteTable(conn, "fuel_frame", fuel.frame)
-}
-if(dbExistsTable(conn, "RESULTS")){
-   dbWriteTable(conn, "RESULTS", results2000, append = TRUE)
-else
-   dbWriteTable(conn, "RESULTS", results2000)
-}
-}
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/dbRemoveTable-SQLiteConnection-character-method.Rd b/man/dbRemoveTable-SQLiteConnection-character-method.Rd
new file mode 100644
index 0000000..fd5e535
--- /dev/null
+++ b/man/dbRemoveTable-SQLiteConnection-character-method.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbRemoveTable,SQLiteConnection,character-method}
+\alias{dbRemoveTable,SQLiteConnection,character-method}
+\title{Remove a table from the database.}
+\usage{
+\S4method{dbRemoveTable}{SQLiteConnection,character}(conn, name)
+}
+\arguments{
+\item{conn}{An existing \code{\linkS4class{SQLiteConnection}}}
+
+\item{name}{character vector of length 1 giving name of table to remove}
+}
+\description{
+Executes the SQL \code{DROP TABLE}.
+}
+
diff --git a/man/dbSendPreparedQuery.Rd b/man/dbSendPreparedQuery.Rd
new file mode 100644
index 0000000..5113f77
--- /dev/null
+++ b/man/dbSendPreparedQuery.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\name{dbSendPreparedQuery}
+\alias{dbGetPreparedQuery}
+\alias{dbSendPreparedQuery}
+\title{Generics for getting and sending prepared queries.}
+\usage{
+dbSendPreparedQuery(conn, statement, bind.data, ...)
+
+dbGetPreparedQuery(conn, statement, bind.data, ...)
+}
+\arguments{
+\item{conn}{An \code{DBIConnection} object.}
+
+\item{statement}{A SQL string}
+
+\item{bind.data}{A data frame}
+
+\item{...}{Other arguments used by methods}
+}
+\description{
+Generics for getting and sending prepared queries.
+}
+
diff --git a/man/dbSendQuery-methods.Rd b/man/dbSendQuery-methods.Rd
deleted file mode 100644
index b3fc8ef..0000000
--- a/man/dbSendQuery-methods.Rd
+++ /dev/null
@@ -1,130 +0,0 @@
-\name{dbSendQuery-methods}
-\docType{methods}
-\alias{dbSendQuery-methods}
-\alias{dbGetQuery-methods}
-\alias{dbSendPreparedQuery}
-\alias{dbGetPreparedQuery}
-\alias{dbSendPreparedQuery-methods}
-\alias{dbGetPreparedQuery-methods}
-\alias{dbGetException-methods}
-\alias{dbSendQuery,SQLiteConnection,character-method}
-\alias{dbGetQuery,SQLiteConnection,character-method}
-\alias{dbSendPreparedQuery,SQLiteConnection,character,data.frame-method}
-\alias{dbGetPreparedQuery,SQLiteConnection,character,data.frame-method}
-\alias{dbClearResult,SQLiteResult-method}
-\alias{dbGetException,SQLiteConnection-method}
-\title{
-  Execute a SQL statement on a database connection
-}
-\description{
-   These are the primary methods for interacting with a database via SQL
-   queries.
-}
-\section{Methods}{\describe{
-\item{conn}{a \code{SQLiteConnection} object.}
-\item{statement}{a character vector of length one specifying the SQL
-statement that should be executed.  Only a single SQL statment should be
-provided.}
-\item{res}{a \code{SQLiteResult} object.}
-\item{\dots }{additional parameters.}
-}
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link{SQLite}},
-  \code{\link[DBI]{dbDriver}},
-  \code{\link[DBI]{dbConnect}},
-  \code{\link[DBI]{fetch}},
-  \code{\link[DBI]{dbCommit}},
-  \code{\link[DBI]{dbGetInfo}},
-  \code{\link[DBI]{dbReadTable}}.
-}
-\examples{
-con <- dbConnect(SQLite(), ":memory:")
-data(USArrests)
-dbWriteTable(con, "arrests", USArrests)
-
-res <- dbSendQuery(con, "SELECT * from arrests")
-data <- fetch(res, n = 2)
-data
-dbClearResult(res)
-
-dbGetQuery(con, "SELECT * from arrests limit 3")
-
-tryCatch(dbGetQuery(con, "SELECT * FROM tableDoesNotExist"),
-         error=function(e) { print("caught") })
-dbGetException(con)
-
-## The following example demonstrates the use of
-## transactions and bound parameters in prepared
-## statements.
-
-set.seed(0x4554)
-
-make_data <- function(n)
-{
-    alpha <- c(letters, as.character(0:9))
-    make_key <- function(n)
-    {
-        paste(sample(alpha, n, replace = TRUE), collapse = "")
-    }
-    keys <- sapply(sample(1:5, replace=TRUE), function(x) make_key(x))
-    counts <- sample(seq_len(1e4), n, replace = TRUE)
-    data.frame(key = keys, count = counts, stringsAsFactors = FALSE)
-}
-
-key_counts <- make_data(100)
-
-
-db <- dbConnect(SQLite(), dbname = ":memory:")
-
-sql <- "
-create table keys (key text, count integer)
-"
-
-dbGetQuery(db, sql)
-
-bulk_insert <- function(sql, key_counts)
-{
-    dbBeginTransaction(db)
-    dbGetPreparedQuery(db, sql, bind.data = key_counts)
-    dbCommit(db)
-    dbGetQuery(db, "select count(*) from keys")[[1]]
-}
-
-##  for all styles, you can have up to 999 parameters
-
-## anonymous
-sql <- "insert into keys values (?, ?)"
-bulk_insert(sql, key_counts)
-
-
-## named w/ :, $, @
-## names are matched against column names of bind.data
-
-sql <- "insert into keys values (:key, :count)"
-bulk_insert(sql, key_counts[ , 2:1])
-
-sql <- "insert into keys values ($key, $count)"
-bulk_insert(sql, key_counts)
-
-sql <- "insert into keys values (@key, @count)"
-bulk_insert(sql, key_counts)
-
-## indexed (NOT CURRENTLY SUPPORTED)
-## sql <- "insert into keys values (?1, ?2)"
-## bulk_insert(sql)
-
-sql <- "select * from keys where count = :cc"
-dbGetPreparedQuery(db, sql, data.frame(cc = c(95, 403)))
-
-dbDisconnect(db)
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/dbSetDataMappings-methods.Rd b/man/dbSetDataMappings-methods.Rd
deleted file mode 100644
index 9e418b6..0000000
--- a/man/dbSetDataMappings-methods.Rd
+++ /dev/null
@@ -1,53 +0,0 @@
-% $Id$
-\name{dbSetDataMappings-methods}
-\docType{methods}
-\alias{dbSetDataMappings-methods}
-\alias{dbSetDataMappings,SQLiteResult,data.frame-method}
-\title{
-  Set data mappings between SQLite and R/S-Plus
-}
-\description{
-  Not yet implemented
-}
-\section{Methods}{\describe{
-\item{res}{
-  a \code{SQLiteResult} object as returned by \code{dbSendQuery}.
-  }
-\item{flds}{
-  a data.frame with field descriptions as returned by 
-  \code{\link[DBI]{dbColumnInfo}}.
-  }
-\item{\dots }{
-  any additional arguments are passed to the implementing method.
-  }
-}
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link{SQLite}},
-  \code{\link[DBI]{dbSendQuery}},
-  \code{\link[DBI]{fetch}},
-  \code{\link[DBI]{dbColumnInfo}}.
-}
-\examples{\dontrun{
-makeImage <- function(x) {
-  .C("make_Image", as.integer(x), length(x))
-}
-
-res <- dbSendQuery(con, statement)
-flds <- dbColumnInfo(res)
-flds[3, "Sclass"] <- makeImage
-
-dbSetDataMappings(rs, flds)
-
-im <- fetch(rs, n = -1)
-}
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/dbUnloadDriver-SQLiteDriver-method.Rd b/man/dbUnloadDriver-SQLiteDriver-method.Rd
new file mode 100644
index 0000000..f05b063
--- /dev/null
+++ b/man/dbUnloadDriver-SQLiteDriver-method.Rd
@@ -0,0 +1,26 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbUnloadDriver,SQLiteDriver-method}
+\alias{dbUnloadDriver,SQLiteDriver-method}
+\title{Unload SQLite driver.}
+\usage{
+\S4method{dbUnloadDriver}{SQLiteDriver}(drv, ...)
+}
+\arguments{
+\item{drv}{Object created by \code{\link{SQLite}}}
+
+\item{...}{Ignored. Needed for compatibility with generic.}
+}
+\value{
+A logical indicating whether the operation succeeded or not.
+}
+\description{
+Unload SQLite driver.
+}
+\examples{
+\dontrun{
+db <- SQLite()
+dbUnloadDriver(db)
+}
+}
+
diff --git a/man/dbWriteTable.Rd b/man/dbWriteTable.Rd
new file mode 100644
index 0000000..11a5eab
--- /dev/null
+++ b/man/dbWriteTable.Rd
@@ -0,0 +1,77 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{dbWriteTable,SQLiteConnection,character,data.frame-method}
+\alias{dbWriteTable,SQLiteConnection,character,character-method}
+\alias{dbWriteTable,SQLiteConnection,character,data.frame-method}
+\title{Write a local data frame or file to the database.}
+\usage{
+\S4method{dbWriteTable}{SQLiteConnection,character,data.frame}(conn, name,
+  value, row.names = NA, overwrite = FALSE, append = FALSE,
+  field.types = NULL)
+
+\S4method{dbWriteTable}{SQLiteConnection,character,character}(conn, name, value,
+  field.types = NULL, overwrite = FALSE, append = FALSE, header = TRUE,
+  colClasses = NA, row.names = FALSE, nrows = 50, sep = ",",
+  eol = "\\n", skip = 0)
+}
+\arguments{
+\item{conn}{a \code{\linkS4class{SQLiteConnection}} object, produced by
+\code{\link[DBI]{dbConnect}}}
+
+\item{name}{a character string specifying a table name. SQLite table names
+are \emph{not} case sensitive, e.g., table names \code{ABC} and \code{abc}
+are considered equal.}
+
+\item{value}{a data.frame (or coercible to data.frame) object or a
+file name (character).  In the first case, the data.frame is
+written to a temporary file and then imported to SQLite; when \code{value}
+is a character, it is interpreted as a file name and its contents imported
+to SQLite.}
+
+\item{row.names}{A logical specifying whether the \code{row.names} should be
+output to the output DBMS table; if \code{TRUE}, an extra field whose name
+will be whatever the R identifier \code{"row.names"} maps to the DBMS (see
+\code{\link[DBI]{make.db.names}}). If \code{NA} will add rows names if
+they are characters, otherwise will ignore.}
+
+\item{overwrite}{a logical specifying whether to overwrite an existing table
+or not. Its default is \code{FALSE}. (See the BUGS section below)}
+
+\item{append}{a logical specifying whether to append to an existing table
+in the DBMS.  Its default is \code{FALSE}.}
+
+\item{field.types}{character vector of named  SQL field types where
+the names are the names of new table's columns. If missing, types inferred
+with \code{\link[DBI]{dbDataType}}).}
+
+\item{header}{is a logical indicating whether the first data line (but see
+\code{skip}) has a header or not.  If missing, it value is determined
+following \code{\link{read.table}} convention, namely, it is set to TRUE if
+and only if the first row has one fewer field that the number of columns.}
+
+\item{colClasses}{Character vector of R type names, used to override
+defaults when imputing classes from on-disk file.}
+
+\item{nrows}{Number of rows to read to determine types.}
+
+\item{sep}{The field separator, defaults to \code{','}.}
+
+\item{eol}{The end-of-line delimiter, defaults to \code{'\n'}.}
+
+\item{skip}{number of lines to skip before reading the data. Defaults to 0.}
+}
+\description{
+Write a local data frame or file to the database.
+}
+\examples{
+con <- dbConnect(SQLite())
+dbWriteTable(con, "mtcars", mtcars)
+dbReadTable(con, "mtcars")
+
+# A zero row data frame just creates a table definition.
+dbWriteTable(con, "mtcars2", mtcars[0, ])
+dbReadTable(con, "mtcars2")
+
+dbDisconnect(con)
+}
+
diff --git a/man/fetch-methods.Rd b/man/fetch-methods.Rd
deleted file mode 100644
index b9bfe55..0000000
--- a/man/fetch-methods.Rd
+++ /dev/null
@@ -1,76 +0,0 @@
-% $Id$
-\name{fetch-methods}
-\docType{methods}
-\alias{fetch-methods}
-\alias{fetch,SQLiteResult,numeric-method}
-\alias{fetch,SQLiteResult-method}
-\title{
-  Fetch records from a previously executed query
-}
-\description{
-   This method is a straight-forward implementation of the corresponding
-   generic function.
-}
-\section{Methods}{\describe{
-
-\item{res}{
-  an \code{SQLiteResult} object.
-  }
-\item{n}{
-  maximum number of records to retrieve per fetch.
-  Use \code{n = -1} to retrieve all pending records;
-  use a value of \code{n = 0} for fetching the default number 
-  of rows \code{fetch.default.rec} defined in the 
-  \code{\link{SQLite}} initialization invocation.
-  }
-\item{\dots }{currently not used.}
-}
-}
-\details{
-  The \code{RSQLite} implementations retrieves all records into a 
-  buffer internally managed by the RSQLite driver (thus this memory
-  in not managed by R but its part of the R process), and
-  \code{fetch} simple returns records from this internal buffer.
-}
-\references{
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link{SQLite}},
-  \code{\link[DBI]{dbConnect}},
-  \code{\link[DBI]{dbSendQuery}},
-  \code{\link[DBI]{dbGetQuery}},
-  \code{\link[DBI]{dbClearResult}},
-  \code{\link[DBI]{dbCommit}},
-  \code{\link[DBI]{dbGetInfo}},
-  \code{\link[DBI]{dbReadTable}}.
-}
-\examples{
-drv <- dbDriver("SQLite")
-tfile <- tempfile()
-con <- dbConnect(drv, dbname = tfile)
-data(USJudgeRatings)
-dbWriteTable(con, "jratings", USJudgeRatings)
-
-res <- dbSendQuery(con, statement = paste(
-                      "SELECT row_names, ORAL, DILG, FAMI",
-                      "FROM jratings"))
-
-# we now fetch the first 10 records from the resultSet into a data.frame
-data1 <- fetch(res, n = 10)   
-dim(data1)
-
-dbHasCompleted(res)
-
-# let's get all remaining records
-data2 <- fetch(res, n = -1)
-
-dbClearResult(res)
-dbDisconnect(con)
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/initExtension.Rd b/man/initExtension.Rd
new file mode 100644
index 0000000..aa05a72
--- /dev/null
+++ b/man/initExtension.Rd
@@ -0,0 +1,36 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\name{initExtension}
+\alias{initExtension}
+\title{Add useful extension functions.}
+\usage{
+initExtension(db)
+}
+\arguments{
+\item{db}{A database to load these extensions.}
+}
+\description{
+These extension functions are written by Liam Healy and made available
+through the SQLite website (\url{http://www.sqlite.org/contrib}).
+}
+\section{Available extension functions}{
+
+
+\describe{
+\item{Math functions}{acos, acosh, asin, asinh, atan, atan2, atanh, atn2,
+  ceil, cos, cosh, cot, coth, degrees, difference, exp, floor, log, log10,
+  pi, power, radians, sign, sin, sinh, sqrt, square, tan, tanh}
+\item{String functions}{charindex, leftstr, ltrim, padc, padl, padr, proper,
+  replace, replicate, reverse, rightstr, rtrim, strfilter, trim}
+\item{Aggregate functions}{stdev, variance, mode, median, lower_quartile,
+  upper_quartile}
+}
+}
+\examples{
+db <- dbConnect(SQLite())
+initExtension(db)
+
+dbWriteTable(db, "mtcars", mtcars)
+dbGetQuery(db, "SELECT stdev(mpg) FROM mtcars")
+sd(mtcars$mpg)
+}
+
diff --git a/man/isIdCurrent.Rd b/man/isIdCurrent.Rd
deleted file mode 100644
index 74f8898..0000000
--- a/man/isIdCurrent.Rd
+++ /dev/null
@@ -1,44 +0,0 @@
-% $Id$
-\name{isIdCurrent}
-\alias{isIdCurrent}
-\title{
-  Check whether an dbObjectId handle object is valid or not
-}
-\description{
-Support function that verifies that an dbObjectId holding a reference
-to a foreign object is still valid for communicating with the RDBMS
-}
-\usage{
-isIdCurrent(obj)
-}
-\arguments{
-\item{obj}{
-any \code{dbObjectId} (e.g., \code{dbDriver},
-\code{dbConnection}, \code{dbResult}).
-}
-}
-\value{
-a logical scalar.
-}
-\details{
-\code{dbObjectId} are R/S-Plus remote references to foreign (C code) objects.
-This introduces differences to the object's semantics such as
-persistence (e.g., connections may be closed unexpectedly),
-thus this function provides a minimal verification to ensure 
-that the foreign object being referenced can be contacted.
-}
-\seealso{
-\code{\link[DBI]{dbDriver}}
-\code{\link[DBI]{dbConnect}}
-\code{\link[DBI]{dbSendQuery}}
-\code{\link[DBI]{dbGetQuery}}
-\code{\link[DBI]{fetch}}
-}
-\examples{\dontrun{
-cursor <- dbSendQuery(con, sql.statement)
-isIdCurrent(cursor)
-}
-}
-\keyword{interface}
-\keyword{database}
-% vim:syntax=tex
diff --git a/man/make.db.names-SQLiteConnection-character-method.Rd b/man/make.db.names-SQLiteConnection-character-method.Rd
new file mode 100644
index 0000000..21d9577
--- /dev/null
+++ b/man/make.db.names-SQLiteConnection-character-method.Rd
@@ -0,0 +1,61 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{make.db.names,SQLiteConnection,character-method}
+\alias{SQLKeywords,SQLiteConnection-method}
+\alias{isSQLKeyword,SQLiteConnection,character-method}
+\alias{make.db.names,SQLiteConnection,character-method}
+\title{Make R/S-Plus identifiers into legal SQL identifiers}
+\usage{
+\S4method{make.db.names}{SQLiteConnection,character}(dbObj, snames,
+  keywords = .SQL92Keywords, unique = TRUE, allow.keywords = TRUE, ...)
+
+\S4method{SQLKeywords}{SQLiteConnection}(dbObj, ...)
+
+\S4method{isSQLKeyword}{SQLiteConnection,character}(dbObj, name,
+  keywords = .SQL92Keywords, case = c("lower", "upper", "any")[3], ...)
+}
+\arguments{
+\item{dbObj}{any SQLite object (e.g., \code{SQLiteDriver}).}
+
+\item{snames}{a character vector of R identifiers (symbols) from which to
+make SQL identifiers.}
+
+\item{keywords}{a character vector with SQL keywords, namely
+\code{.SQL92Keywords} defined in the \code{DBI} package.}
+
+\item{unique}{logical describing whether the resulting set of SQL names
+should be unique.  The default is \code{TRUE}. Following the SQL 92
+standard, uniqueness of SQL identifiers is determined regardless of whether
+letters are upper or lower case.}
+
+\item{allow.keywords}{logical describing whether SQL keywords should be
+allowed in the resulting set of SQL names.  The default is \code{TRUE}.}
+
+\item{...}{Not used. Included for compatiblity with generic.}
+
+\item{name}{a character vector of SQL identifiers we want to check against
+keywords from the DBMS.}
+
+\item{case}{a character string specifying whether to make the comparison
+as lower case, upper case, or any of the two.  it defaults to \code{"any"}.}
+}
+\description{
+These methods are straight-forward implementations of the corresponding
+generic functions.
+}
+\examples{
+\dontrun{
+# This example shows how we could export a bunch of data.frames
+# into tables on a remote database.
+
+con <- dbConnect("SQLite", dbname = "sqlite.db")
+
+export <- c("trantime.email", "trantime.print", "round.trip.time.email")
+tabs <- make.db.names(con, export, unique = TRUE, allow.keywords = TRUE)
+
+for(i in seq_along(export) )
+   dbWriteTable(con, name = tabs[i],  get(export[i]))
+}
+}
+\keyword{internal}
+
diff --git a/man/make.db.names-methods.Rd b/man/make.db.names-methods.Rd
deleted file mode 100644
index d45a6f8..0000000
--- a/man/make.db.names-methods.Rd
+++ /dev/null
@@ -1,87 +0,0 @@
-% $Id$
-\name{make.db.names-methods}
-\docType{methods}
-\alias{SQLKeywords-methods}
-\alias{isSQLKeyword-methods}
-\alias{make.db.names,SQLiteObject,character-method}
-\alias{SQLKeywords,SQLiteObject-method}
-\alias{SQLKeywords,missing-method}
-\alias{isSQLKeyword,SQLiteObject,character-method}
-\title{
-  Make R/S-Plus identifiers into legal SQL identifiers
-}
-\description{
-   These methods are straight-forward implementations of the corresponding
-   generic functions.
-}
-\section{Methods}{\describe{
-\item{dbObj}{
-  any SQLite object (e.g., \code{SQLiteDriver}).
-  }
-\item{snames}{
-  a character vector of R/S-Plus identifiers (symbols) from which
-  we need to make SQL identifiers.
-  }
-\item{name}{
-  a character vector of SQL identifiers we want to check against
-  keywords from the DBMS.
-}
-\item{unique}{
-  logical describing whether the resulting set of SQL names should
-  be unique.  Its default is \code{TRUE}.  Following the SQL 92
-  standard, uniqueness of SQL identifiers is determined regardless
-  of whether letters are upper or lower case.
-  }
-\item{allow.keywords }{
-  logical describing whether SQL keywords should be allowed in the
-  resulting set of SQL names.  Its default is \code{TRUE}
-  }
-\item{keywords}{
-  a character vector with SQL keywords, namely 
-  \code{.SQL92Keywords} defined in the \code{DBI} package.
-  }
-\item{case}{
-  a character string specifying whether to make the comparison
-  as lower case, upper case, or any of the two.
-  it defaults to \code{any}.
-  }
-\item{\dots}{currently not used.}
-}
-}
-\references{
-  The set of SQL keywords is stored in the character vector
-  \code{.SQL92Keywords} and reflects the SQL ANSI/ISO standard as
-  documented in "X/Open SQL and RDA", 1994, ISBN 1-872630-68-8.
-  Users can easily override or update this vector.
-
-  SQLite does not add keywords to the SQL 92 standard.
-
-  See the Database Interface definition document
-  \code{DBI.pdf} in the base directory of this package
-  or \url{http://stat.bell-labs.com/RS-DBI}.
-}
-\seealso{
-  \code{\link{SQLite}},
-  \code{\link[DBI]{dbReadTable}},
-  \code{\link[DBI]{dbWriteTable}},
-  \code{\link[DBI]{dbExistsTable}},
-  \code{\link[DBI]{dbRemoveTable}},
-  \code{\link[DBI]{dbListTables}}.
-}
-\examples{\dontrun{
-# This example shows how we could export a bunch of data.frames
-# into tables on a remote database.
-
-con <- dbConnect("SQLite", dbname = "sqlite.db")
-
-export <- c("trantime.email", "trantime.print", "round.trip.time.email")
-tabs <- make.db.names(con, export, unique = TRUE, allow.keywords = TRUE)
-
-for(i in seq_along(export) )
-   dbWriteTable(con, name = tabs[i],  get(export[i]))
-}
-}
-\keyword{methods}
-\keyword{interface}
-\keyword{database}
-% vim: syntax=tex
diff --git a/man/query.Rd b/man/query.Rd
new file mode 100644
index 0000000..526c3f7
--- /dev/null
+++ b/man/query.Rd
@@ -0,0 +1,83 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{query}
+\alias{dbClearResult,SQLiteConnection-method}
+\alias{dbClearResult,SQLiteResult-method}
+\alias{dbFetch,SQLiteResult-method}
+\alias{dbGetPreparedQuery,SQLiteConnection,character,data.frame-method}
+\alias{dbGetQuery,SQLiteConnection,character-method}
+\alias{dbListResults,SQLiteConnection-method}
+\alias{dbSendPreparedQuery,SQLiteConnection,character,data.frame-method}
+\alias{dbSendQuery,SQLiteConnection,character-method}
+\alias{fetch,SQLiteResult-method}
+\alias{query}
+\title{Execute a SQL statement on a database connection}
+\usage{
+\S4method{dbSendQuery}{SQLiteConnection,character}(conn, statement)
+
+\S4method{dbSendPreparedQuery}{SQLiteConnection,character,data.frame}(conn,
+  statement, bind.data)
+
+\S4method{dbFetch}{SQLiteResult}(res, n = 0)
+
+\S4method{fetch}{SQLiteResult}(res, n = 0)
+
+\S4method{dbClearResult}{SQLiteResult}(res, ...)
+
+\S4method{dbClearResult}{SQLiteConnection}(res, ...)
+
+\S4method{dbListResults}{SQLiteConnection}(conn, ...)
+
+\S4method{dbGetQuery}{SQLiteConnection,character}(conn, statement)
+
+\S4method{dbGetPreparedQuery}{SQLiteConnection,character,data.frame}(conn,
+  statement, bind.data)
+}
+\arguments{
+\item{conn}{an \code{\linkS4class{SQLiteConnection}} object.}
+
+\item{statement}{a character vector of length one specifying the SQL
+statement that should be executed.  Only a single SQL statment should be
+provided.}
+
+\item{bind.data}{A data frame of data to be bound.}
+
+\item{res}{an \code{\linkS4class{SQLiteResult}} object.}
+
+\item{n}{maximum number of records to retrieve per fetch. Use \code{-1} to
+retrieve all pending records; use \code{0} for to fetch the default
+number of rows as defined in \code{\link{SQLite}}}
+
+\item{...}{Unused. Needed for compatibility with generic.}
+}
+\description{
+To retrieve results a chunk at a time, use \code{dbSendQuery},
+\code{dbFetch}, then \code{ClearResult}. Alternatively, if you want all the
+results (and they'll fit in memory) use \code{dbGetQuery} which sends,
+fetches and clears for you.
+}
+\examples{
+con <- dbConnect(SQLite(), ":memory:")
+dbWriteTable(con, "arrests", datasets::USArrests)
+
+# Run query to get results as dataframe
+dbGetQuery(con, "SELECT * FROM arrests limit 3")
+
+# Send query to pull requests in batches
+res <- dbSendQuery(con, "SELECT * FROM arrests")
+data <- fetch(res, n = 2)
+data
+dbHasCompleted(res)
+
+dbListResults(con)
+dbClearResult(res)
+
+# Use dbSendPreparedQuery/dbGetPreparedQuery for "prepared" queries
+dbGetPreparedQuery(con, "SELECT * FROM arrests WHERE Murder < ?",
+   data.frame(x = 3))
+dbGetPreparedQuery(con, "SELECT * FROM arrests WHERE Murder < (:x)",
+   data.frame(x = 3))
+
+dbDisconnect(con)
+}
+
diff --git a/man/safe.write.Rd b/man/safe.write.Rd
deleted file mode 100644
index fc894d4..0000000
--- a/man/safe.write.Rd
+++ /dev/null
@@ -1,41 +0,0 @@
-% $Id$
-\name{safe.write}
-\alias{safe.write}
-\title{Write a data.frame avoiding exceeding memory limits}
-\description{
-   This function batches calls to \code{write.table} to avoid
-   exceeding memory limits for very large data.frames.
-}
-\usage{
-safe.write(value, file, batch, row.names = TRUE, ..., sep = ',', 
-  eol = '\n', quote.string=FALSE)
-}
-\arguments{
-  \item{value}{a data.frame;}
-  \item{file}{a file object (connection, file name, etc).}
-  \item{batch}{maximum number of rows to write at a time.}
-  \item{\dots}{any other arguments are passed to \code{write.table}.}
-  \item{sep}{field separator passed to \code{write.table}.}
-  \item{eol}{end of line character passed to \code{write.table}.}
-  \item{quote.string}{logical value passed to \code{write.table}.}
-}
-\details{
-   The function has a while loop invoking \code{\link{write.table}}
-   for subsets of \code{batch} rows of \code{value}.  Since this is
-   a helper function for \code{\link[RMySQL]{mysqlWriteTable}} has hardcoded
-   other arguments to \code{write.table}.
-}
-\value{
-    \code{NULL}, invisibly.
-}
-\note{No error checking whatsoever is done.}
-
-\seealso{\code{\link{write.table}}}
-
-\examples{\dontrun{
-   ctr.file <- file("dump.sqloader", "w")
-   safe.write(big.data, file = ctr.file, batch = 25000)
-}
-}
-\keyword{internal}
-%% vim: syntax=tex
diff --git a/man/sqlite-meta.Rd b/man/sqlite-meta.Rd
new file mode 100644
index 0000000..c15c47a
--- /dev/null
+++ b/man/sqlite-meta.Rd
@@ -0,0 +1,57 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{sqlite-meta}
+\alias{dbColumnInfo,SQLiteResult-method}
+\alias{dbGetRowCount,SQLiteResult-method}
+\alias{dbGetRowsAffected,SQLiteResult-method}
+\alias{dbGetStatement,SQLiteResult-method}
+\alias{dbHasCompleted,SQLiteResult-method}
+\alias{sqlite-meta}
+\title{Database interface meta-data.}
+\usage{
+\S4method{dbColumnInfo}{SQLiteResult}(res, ...)
+
+\S4method{dbGetRowsAffected}{SQLiteResult}(res, ...)
+
+\S4method{dbGetRowCount}{SQLiteResult}(res, ...)
+
+\S4method{dbHasCompleted}{SQLiteResult}(res, ...)
+
+\S4method{dbGetStatement}{SQLiteResult}(res, ...)
+}
+\arguments{
+\item{res}{An object of class \code{\linkS4class{SQLiteResult}}}
+
+\item{...}{Ignored. Needed for compatibility with generic}
+}
+\description{
+See documentation of generics for more details.
+}
+\examples{
+data(USArrests)
+con <- dbConnect(SQLite(), dbname=":memory:")
+dbWriteTable(con, "t1", USArrests)
+dbWriteTable(con, "t2", USArrests)
+
+dbListTables(con)
+
+rs <- dbSendQuery(con, "select * from t1 where UrbanPop >= 80")
+dbGetStatement(rs)
+dbHasCompleted(rs)
+
+info <- dbGetInfo(rs)
+names(info)
+info$fields
+
+fetch(rs, n=2)
+dbHasCompleted(rs)
+info <- dbGetInfo(rs)
+info$fields
+dbClearResult(rs)
+
+# DBIConnection info
+names(dbGetInfo(con))
+
+dbDisconnect(con)
+}
+
diff --git a/man/sqliteBuildTableDefinition.Rd b/man/sqliteBuildTableDefinition.Rd
new file mode 100644
index 0000000..e468b2d
--- /dev/null
+++ b/man/sqliteBuildTableDefinition.Rd
@@ -0,0 +1,31 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\name{sqliteBuildTableDefinition}
+\alias{dbBuildTableDefinition}
+\alias{sqliteBuildTableDefinition}
+\title{Build the SQL CREATE TABLE definition as a string}
+\usage{
+sqliteBuildTableDefinition(con, name, value, field.types = NULL,
+  row.names = NA)
+}
+\arguments{
+\item{name}{Name of the new SQL table}
+
+\item{value}{A data.frame, for which we want to create a table.}
+
+\item{field.types}{Optional, named character vector of the types for each
+field in \code{value}}
+
+\item{row.names}{Logical. Should row.name of \code{value} be exported as a
+\code{row\_names} field? Default is \code{TRUE}}
+
+\item{conn}{A database connection.}
+}
+\value{
+An SQL string
+}
+\description{
+The output SQL statement is a simple \code{CREATE TABLE} with suitable for
+\code{dbGetQuery}
+}
+\keyword{internal}
+
diff --git a/man/sqliteCopyDatabase.Rd b/man/sqliteCopyDatabase.Rd
index 68d7158..486306a 100644
--- a/man/sqliteCopyDatabase.Rd
+++ b/man/sqliteCopyDatabase.Rd
@@ -1,56 +1,33 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
 \name{sqliteCopyDatabase}
 \alias{sqliteCopyDatabase}
-
-\title{
-Copy a SQLite database
-}
-
-\description{
-  This function copies a database connection to a file or to another
-  database connection.  It can be used to save an in-memory database
-  (created using \code{dbname = ":memory:"}) to a file or to create an
-  in-memory database as a copy of anothe database.
-}
-
+\title{Copy a SQLite database}
 \usage{
 sqliteCopyDatabase(from, to)
 }
-
 \arguments{
-  \item{from}{
-    A \code{SQLiteConnection} object.  The main database in \code{from}
-    will be copied to \code{to}.
-  }
-  
-  \item{to}{
-    Either a string specifying the file name where the copy will be
-    written or a \code{SQLiteConnection} object pointing to an empty
-    database.  If \code{to} specifies an already existing
-    file, it will be overwritten without a warning.  When \code{to} is a
-    database connection, it is assumed to point to an empty and unused
-    database; the behavior is undefined otherwise.
-  }
-
-}
-
- \details{
-  This function uses SQLite's experimental online backup API to make the
-  copy.  
+\item{from}{A \code{SQLiteConnection} object.  The main database in
+\code{from} will be copied to \code{to}.}
 
+\item{to}{Either a string specifying the file name where the copy will be
+written or a \code{SQLiteConnection} object pointing to an empty database.
+If \code{to} specifies an already existing file, it will be overwritten
+without a warning.  When \code{to} is a database connection, it is assumed
+to point to an empty and unused database; the behavior is undefined
+otherwise.}
 }
-
 \value{
-  Returns \code{NULL}.
+Returns \code{NULL}.
 }
-
-\references{
-  \url{http://www.sqlite.org/backup.html}
+\description{
+This function copies a database connection to a file or to another database
+connection.  It can be used to save an in-memory database (created using
+\code{dbname = ":memory:"}) to a file or to create an in-memory database as
+a copy of anothe database.
 }
-
-\author{
-Seth Falcon
+\details{
+This function uses SQLite's experimental online backup API to make the copy.
 }
-
 \examples{
 ## Create an in memory database
 db <- dbConnect(SQLite(), dbname = ":memory:")
@@ -76,5 +53,10 @@ dbDisconnect(diskdb)
 dbDisconnect(db2)
 unlink(backupDbFile)
 }
+\author{
+Seth Falcon
+}
+\references{
+\url{http://www.sqlite.org/backup.html}
+}
 
-\keyword{database}
diff --git a/man/sqliteQuickColumn.Rd b/man/sqliteQuickColumn.Rd
index 9fb1c9f..647500a 100644
--- a/man/sqliteQuickColumn.Rd
+++ b/man/sqliteQuickColumn.Rd
@@ -1,35 +1,34 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
 \name{sqliteQuickColumn}
 \alias{sqliteQuickColumn}
-
 \title{Return an entire column from a SQLite database}
-\description{
-  Return an entire column from a table in a SQLite database as an R
-  vector of the appropriate type.  This function is experimental and
-  subject to change.
-}
-
 \usage{
 sqliteQuickColumn(con, table, column)
 }
-%- maybe also 'usage' for other objects documented here.
 \arguments{
-\item{con}{ a \code{SQLiteConnection} object as produced by
-    \code{sqliteNewConnection}.}
-  \item{table}{a string specifying the name of the table}
-  \item{column}{a string specifying the name of the column in the
-      specified table to retrieve.}
+\item{con}{a \code{SQLiteConnection} object as produced by
+\code{sqliteNewConnection}.}
+
+\item{table}{a string specifying the name of the table}
+
+\item{column}{a string specifying the name of the column in the specified
+table to retrieve.}
+}
+\value{
+an R vector of the appropriate type (based on the type of the column
+in the database).
+}
+\description{
+Return an entire column from a table in a SQLite database as an R vector of
+the appropriate type.  This function is experimental and subject to change.
 }
 \details{
-  This function relies upon the SQLite internal \code{ROWID} column to
-  determine the number of rows in the table.  This may not work
-  depending on the table schema definition and pattern of update.
+This function relies upon the SQLite internal \code{ROWID} column to
+determine the number of rows in the table.  This may not work depending on
+the table schema definition and pattern of update.
 }
-\value{
-  an R vector of the appropriate type (based on the type of the column
-  in the database).
+\author{
+Seth Falcon
 }
-
-\author{Seth Falcon}
-
 \keyword{interface}
 
diff --git a/man/sqliteSupport.Rd b/man/sqliteSupport.Rd
deleted file mode 100644
index d1661f5..0000000
--- a/man/sqliteSupport.Rd
+++ /dev/null
@@ -1,317 +0,0 @@
-\name{sqliteSupport}                % adapted from ROracle
-\alias{sqliteInitDriver}            % driver-related function
-\alias{sqliteDriverInfo}
-\alias{sqliteDescribeDriver}
-\alias{sqliteCloseDriver}           % connection-related
-\alias{sqliteNewConnection}
-\alias{sqliteConnectionInfo}
-\alias{sqliteDescribeConnection}
-\alias{sqliteCloseConnection}
-\alias{sqliteExecStatement}         % result-related
-\alias{sqliteFetch}
-\alias{sqliteQuickSQL}
-\alias{sqliteTransactionStatement}
-\alias{sqliteResultInfo}
-\alias{sqliteDescribeResult}
-\alias{sqliteCloseResult}
-\alias{sqliteReadTable}
-\alias{sqliteWriteTable}            % convenience functions
-\alias{sqliteImportFile}
-\alias{sqliteTableFields}
-\alias{sqliteDataType}
-\alias{sqliteFetchOneColumn}
-\alias{.SQLitePkgName}              % constants
-\alias{.SQLitePkgVersion}
-\alias{.SQLitePkgRCS}
-\alias{.SQLite.NA.string}
-\alias{SQLITE_RWC}
-\alias{SQLITE_RW}
-\alias{SQLITE_RO}
-\alias{last.warning}
-%\alias{.SQLiteSQLKeywords}
-\alias{.conflicts.OK}
-%\non_function{}
-\title{Support Functions}
-\description{
-   These functions are the workhorses behind the RSQLite package, but
-   users need not invoke these directly.
-}
-\usage{
-   ## SQLiteDriver-related
-   sqliteInitDriver(max.con=16, fetch.default.rec = 500, force.reload=FALSE,
-                    shared.cache=FALSE)
-   sqliteDriverInfo(obj, what, ...)
-   sqliteDescribeDriver(obj, verbose = FALSE, ...)
-   sqliteCloseDriver(drv, ...)
-
-   ## SQLiteConnection-related
-   sqliteNewConnection(drv, dbname, loadable.extensions=TRUE, cache_size=NULL,
-                       synchronous=0, flags = NULL, vfs = NULL)
-   sqliteConnectionInfo(obj, what, ...)
-   sqliteDescribeConnection(obj, verbose = FALSE, ...)
-   sqliteCloseConnection(con, ...)
-
-   ## SQLiteResult-related
-   sqliteExecStatement(con, statement, bind.data=NULL)
-   sqliteTransactionStatement(con, statement)
-   sqliteFetch(res, n=0, ...)
-   sqliteQuickSQL(con, statement, bind.data=NULL, ...)
-   sqliteResultInfo(obj, what, ...)
-   sqliteDescribeResult(obj, verbose = FALSE, ...)
-   sqliteCloseResult(res, ...)
-
-   ## data mappings and convenience functions
-   sqliteDataType(obj, ...)
-   sqliteReadTable(con, name, row.names = "row_names", check.names = TRUE, ...)
-   sqliteImportFile(con, name, value, field.types, overwrite=FALSE,
-      append=FALSE, header, row.names, nrows=50, sep=",", eol="\n",
-      skip = 0, ...)
-   sqliteWriteTable(con, name, value, row.names = TRUE,
-                    overwrite = FALSE, append = FALSE,
-                    field.types = NULL, ...)
-   sqliteTableFields(con, name, ...)
-}
-\arguments{
-\item{max.con}{
-   positive integer specifying maximum number of open connections.
-   The default is 10.  Note that since SQLite is embedded in R/S-Plus
-   connections are simple, very efficient direct C calls.
-}
-\item{fetch.default.rec}{
-   default number of rows to fetch (move to R/S-Plus).  This default is
-   used in \code{sqliteFetch}.
-   The default is 500.
-}
-\item{force.reload}{
-   logical indicating whether to re-initialize the driver.  This may be
-   useful if you want to change the defaults (e.g., \code{fetch.default.rec}).
-   Note that the driver is a singleton (subsequent inits just returned the
-   previously initialized driver, thus this argument).
-}
-\item{obj}{
-   any of the SQLite DBI objects (e.g., \code{SQLiteConnection},
-   \code{SQLiteResult}).
-}
-\item{what}{
-   character vector of metadata to extract, e.g., "version", "statement",
-   "isSelect".
-}
-\item{verbose}{
-   logical controlling how much information to display.
-   Defaults to \code{FALSE}.
-}
-\item{drv}{
-   an \code{SQLiteDriver} object as produced by \code{sqliteInit}.
-}
-\item{con}{
-   an \code{SQLiteConnection} object as produced by \code{sqliteNewConnection}.
-}
-\item{res}{
-   an \code{SQLiteResult} object as produced by by \code{sqliteExecStatement}.
-}
-\item{dbname}{
-   character string with the SQLite database file name (SQLite, like
-   Microsoft's Access, stores an entire database in one file).
-}
-\item{loadable.extensions}{
-   logical describing whether loadable extensions will be enabled for this
-   connection. The default is FALSE.
- }
-\item{flags}{
-   An integer that will be interpretted as a collection of flags by the
-   SQLite API.  If \code{NULL}, the flags will default to
-   \code{SQLITE_RWC} which will open the file in read/write mode and
-   create the file if it does not exist.  You can use \code{SQLITE_RW}
-   to open in read/write mode and \code{SQLITE_RO} to open in read only
-   mode.  In both cases, an error is raised if the database file does
-   not already exist.  See \url{http://sqlite.org/c3ref/open.html} for
-   more details.
- }
-\item{shared.cache}{
-   logical describing whether shared-cache mode should be enabled on the SQLite
-   driver. The default is FALSE.
-}
-\item{bind.data}{
-   a data frame which will be used to bind variables in the statement.
-}
-\item{cache_size}{
-   positive integer to pass to the \code{PRAGMA cache_size};  this
-   changes the maximum number of disk pages that SQLite will hold in
-   memory (SQLite's default is 2000 pages).
-}
-\item{synchronous}{
-  values the \code{PRAGMA synchronous} flag, possible values are
-  0, 1, or 2 or the corresponding strings "OFF", "NORMAL", or "FULL".
-  The \code{RSQLite} package uses a default of 0 (OFF), although
-  SQLite's default is 2 (FULL) as of version 3.2.8.
-  Users have reported significant speed ups using \code{sychronous="OFF"},
-  and the SQLite documentation itself implies considerably improved
-  performance at the very modest risk of database corruption in the
-  unlikely case of the operating system (\emph{not} the R application)
-  crashing.
-}
-
-\item{vfs}{
-  The name of the SQLite virtual filesystem module to use.  If
-  \code{NULL}, the default module will be used.  Module availability
-  depends on your operating as summarized by the following table:
-
-\tabular{rlll}{
-  module          \tab OSX \tab Unix (not OSX) \tab Windows\cr
-  "unix-none"     \tab Y   \tab Y              \tab N\cr
-  "unix-dotfile"  \tab Y   \tab Y              \tab N\cr
-  "unix-flock"    \tab Y   \tab N              \tab N\cr
-  "unix-afp"      \tab Y   \tab N              \tab N\cr
-  "unix-posix"    \tab Y   \tab N              \tab N\cr
-}
-See \url{http://www.sqlite.org/compile.html} for details.
-}
-
-
-%\item{max.results}{
-%   positive integer indicating the maximum number of results that
-%   SQLite connections will hold open.  The current default of 1
-%   is hardcoded in the C code.
-%}
-\item{force}{
-   logical indicating whether to close a connection that has open
-   result sets.  The default is \code{FALSE}.
-}
-\item{statement}{
-   character string holding SQL statements.
-}
-\item{n}{
-   number of rows to fetch from the given result set. A value of -1
-   indicates to retrieve all the rows.  The default of 0 specifies
-   to extract whatever the \code{fetch.default.rec} was specified
-   during driver initialization \code{sqliteInit}.
-}
-\item{name}{
-   character vector of names (table names, fields, keywords).
-}
-\item{value}{
-   a data.frame.
-}
-\item{field.types}{
-   a list specifying the mapping from R/S-Plus fields in the data.frame
-   \code{value} to SQL data types.  The default is
-   \code{sapply(value,SQLDataType)}, see \code{SQLiteSQLType}.
-}
-\item{row.names}{
-   a logical specifying whether to prepend the \code{value} data.frame
-   row names or not.  The default is \code{TRUE}.
-}
-\item{check.names}{
-   a logical specifying whether to convert DBMS field names into
-   legal S names. Default is \code{TRUE}.
-}
-\item{overwrite}{
-   logical indicating whether to replace the table \code{name} with
-   the contents of the data.frame \code{value}.
-   The defauls is \code{FALSE}.
-}
-\item{append}{
-   logical indicating whether to append \code{value} to the existing
-   table \code{name}.
-}
-\item{header}{
-  logical, does the input file have a header line?  Default is the
-  same heuristic used by \code{read.table}, i.e., TRUE if the first
-  line has one fewer column that the second line.
-}
-\item{nrows}{
-   number of lines to rows to import using \code{read.table} from the
-  input file to create the proper table definition. Default is 50.
-}
-\item{sep}{field separator character.}
-\item{eol}{end-of-line separator.}
-\item{skip}{
-   number of lines to skip before reading data in the input file.
-}
-\item{\dots}{
-   placeholder for future use.
-}
-}
-\value{
-   \code{sqliteInitDriver} returns an \code{SQLiteDriver} object.
-
-   \code{sqliteDriverInfo} returns a list of name-value metadata pairs.
-
-   \code{sqliteDescribeDriver} returns \code{NULL} (displays the object's
-   metadata).
-
-   \code{sqliteCloseDriver} returns a logical indicating whether the
-   operation succeeded or not.
-
-   \code{sqliteNewConnection} returns an \code{SQLiteConnection} object.
-
-   \code{sqliteConnectionInfo}returns a list of name-value metadata pairs.
-
-   \code{sqliteDescribeConnection} returns \code{NULL} (displays the
-   object's metadata).
-
-   \code{sqliteCloseConnection} returns a logical indicating whether the
-   operation succeeded or not.
-
-   \code{sqliteExecStatement} returns an \code{SQLiteResult} object.
-
-   \code{sqliteFetch} returns a data.frame.
-
-   \code{sqliteQuickSQL} returns either a data.frame if the \code{statement} is
-   a \code{select}-like or NULL otherwise.
-
-   \code{sqliteDescribeResult} returns \code{NULL} (displays the object's
-   metadata).
-
-   \code{sqliteCloseResult} returns a logical indicating whether the
-   operation succeeded or not.
-
-   \code{sqliteReadTable}  returns a data.frame with the contents of the
-   DBMS table.
-
-   \code{sqliteWriteTable}  returns a logical indicating whether the
-   operation succeeded or not.
-
-   \code{sqliteImportFile}  returns a logical indicating whether the
-   operation succeeded or not.
-
-   \code{sqliteTableFields} returns a character vector with the
-   table \code{name} field names.
-
-   \code{sqliteDataType} retuns a character string with the closest
-   SQL data type.  Note that SQLite is typeless, so this is mostly for
-   creating table that are compatible across RDBMS.
-
-   \code{sqliteResultInfo} returns a list of name-value metadata pairs.
-}
-
-\section{Constants}{
-  \code{.SQLitePkgName} (currently \code{"RSQLite"}),
-  \code{.SQLitePkgVersion} (the R package version),
-  \code{.SQLitePkgRCS} (the RCS revision),
-  \code{.SQLitecle.NA.string} (character that SQLite uses to
-  denote \code{NULL} on input),
-  \code{.conflicts.OK}.
-  
-  The following constants can be used as the value of the \code{flags}
-  argument to \code{sqliteNewConnection} to control the mode of the
-  databse connection:
-  
-  \describe{
-    \item{\code{SQLITE_RWC}}{
-      open the database in read/write mode and create the database file if
-      it does not already exist}
-    
-    \item{\code{SQLITE_RW}}{open the database in read/write mode.
-      Raise an error if the file does not already exist}
-    
-    \item{\code{SQLITE_RO}}{open the database in read only mode.
-      Raise an error if the file does not already exist}
-  }
-}
-
-\keyword{datasets}
-\keyword{interface}
-\keyword{database}
-%\keyword{internal}
-% vim:syntax=tex
diff --git a/man/summary-methods.Rd b/man/summary-methods.Rd
deleted file mode 100644
index ebeb903..0000000
--- a/man/summary-methods.Rd
+++ /dev/null
@@ -1,40 +0,0 @@
-% $Id$
-\name{summary-methods}
-\docType{methods}
-\alias{coerce-methods}
-\alias{summary-methods}
-\alias{format-methods}
-\alias{show-methods}
-\alias{coerce,dbObjectId,integer-method}
-\alias{coerce,dbObjectId,numeric-method}
-\alias{coerce,dbObjectId,character-method}
-\alias{coerce,SQLiteConnection,SQLiteDriver-method}
-\alias{coerce,SQLiteResult,SQLiteConnection-method}
-\alias{format,dbObjectId-method}
-\alias{print,dbObjectId-method}
-\alias{show,dbObjectId-method}
-\alias{summary,SQLiteObject-method}
-\alias{summary,SQLiteDriver-method}
-\alias{summary,SQLiteConnection-method}
-\alias{summary,SQLiteResult-method}
-\title{Summarize an SQLite object}
-\description{
-   These methods are straight-forward implementations of the corresponding
-   generic functions.
-}
-\section{Methods}{\describe{
-
-\item{object = "DBIObject"}{
-   Provides relevant metadata information on \code{object}, 
-   for instance, the SQLite server file, the
-   SQL statement associated with a result set, etc.  
-   }
-\item{from}{object to be coerced}
-\item{to}{coercion class}
-\item{x}{object to \code{format} or \code{print} or \code{show}}
-}
-}
-\keyword{methods}
-\keyword{database}
-\keyword{interface}
-% vim: syntax=tex
diff --git a/man/summary.Rd b/man/summary.Rd
new file mode 100644
index 0000000..07a8134
--- /dev/null
+++ b/man/summary.Rd
@@ -0,0 +1,36 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{summary}
+\alias{summary}
+\alias{summary,SQLiteConnection-method}
+\alias{summary,SQLiteDriver-method}
+\alias{summary,SQLiteResult-method}
+\title{Summary methods}
+\usage{
+\S4method{summary}{SQLiteDriver}(object)
+
+\S4method{summary}{SQLiteConnection}(object)
+
+\S4method{summary}{SQLiteResult}(object)
+}
+\arguments{
+\item{verbose}{Show extra information.}
+}
+\description{
+Summary methods
+}
+\examples{
+summary(SQLite())
+
+con <- dbConnect(SQLite())
+summary(con)
+
+dbWriteTable(con, "mtcars", mtcars)
+rs <- dbSendQuery(con, "SELECT * FROM mtcars")
+summary(rs)
+
+dbClearResult(rs)
+dbDisconnect(con)
+}
+\keyword{internal}
+
diff --git a/man/transactions.Rd b/man/transactions.Rd
new file mode 100644
index 0000000..a5799bb
--- /dev/null
+++ b/man/transactions.Rd
@@ -0,0 +1,61 @@
+% Generated by roxygen2 (4.0.2): do not edit by hand
+\docType{methods}
+\name{transactions}
+\alias{dbBegin,SQLiteConnection-method}
+\alias{dbCommit,SQLiteConnection-method}
+\alias{dbRollback,SQLiteConnection-method}
+\alias{transactions}
+\title{SQLite transaction management.}
+\usage{
+\S4method{dbBegin}{SQLiteConnection}(conn, name = NULL)
+
+\S4method{dbCommit}{SQLiteConnection}(conn, name = NULL)
+
+\S4method{dbRollback}{SQLiteConnection}(conn, name = NULL)
+}
+\arguments{
+\item{conn}{a \code{\linkS4class{SQLiteConnection}} object, produced by
+\code{\link[DBI]{dbConnect}}}
+
+\item{name}{Supply a name to use a named savepoint. This allows you to
+nest multiple transaction}
+}
+\value{
+A boolean, indicating success or failure.
+}
+\description{
+By default, SQLite is in auto-commit mode. \code{dbBegin} starts
+a SQLite transaction and turns auto-commit off. \code{dbCommit} and
+\code{dbRollback} commit and rollback the transaction, respectively and turn
+auto-commit on.
+}
+\examples{
+con <- dbConnect(SQLite(), ":memory:")
+dbWriteTable(con, "arrests", datasets::USArrests)
+dbGetQuery(con, "select count(*) from arrests")
+
+dbBegin(con)
+rs <- dbSendQuery(con, "DELETE from arrests WHERE Murder > 1")
+dbGetRowsAffected(rs)
+dbClearResult(rs)
+
+dbGetQuery(con, "select count(*) from arrests")
+
+dbRollback(con)
+dbGetQuery(con, "select count(*) from arrests")[1, ]
+
+dbBegin(con)
+rs <- dbSendQuery(con, "DELETE FROM arrests WHERE Murder > 5")
+dbClearResult(rs)
+dbCommit(con)
+dbGetQuery(con, "SELECT count(*) FROM arrests")[1, ]
+
+# Named savepoints can be nested --------------------------------------------
+dbBegin(con, "a")
+dbBegin(con, "b")
+dbRollback(con, "b")
+dbCommit(con, "a")
+
+dbDisconnect(con)
+}
+
diff --git a/src/RS-DBI.c b/src/RS-DBI.c
deleted file mode 100644
index 27a2dc1..0000000
--- a/src/RS-DBI.c
+++ /dev/null
@@ -1,1229 +0,0 @@
-/* 
- * Copyright (C) 1999-2002 The Omega Project for Statistical Computing
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "RS-DBI.h"
-
-#include <R_ext/RS.h>
-/* TODO: monitor memory/object size consumption against S limits 
- *       in $SHOME/include/options.h we find "max_memory". We then
- *       mem_size to make sure we're not bumping into problems.
- *       But, is mem_size() reliable?  How should we do this?
- *
- * TODO: invoke user-specified generators 
- *
- * TODO: Implement exception objects for each dbObject.
- */
-
-static RS_DBI_manager *dbManager = NULL;
-
-static int HANDLE_LENGTH(SEXP handle)
-{
-    SEXP h = R_ExternalPtrProtected(handle);
-    if (TYPEOF(h) == VECSXP) h = VECTOR_ELT(h, 0);
-    return Rf_length(h);
-}
-
-Mgr_Handle
-RS_DBI_allocManager(const char *drvName, Sint max_con,
-		    Sint fetch_default_rec, Sint force_realloc)
-{
-  /* Currently, the dbManager is a singleton (therefore we don't 
-   * completly free all the space).  Here we alloc space
-   * for the dbManager and return its mgrHandle.  force_realloc
-   * means to re-allocate number of connections, etc. (in this case
-   * we require to have all connections closed).  (Note that if we
-   * re-allocate, we don't re-set the counter, and thus we make sure
-   * we don't recycle connection Ids in a giver S/R session).
-   */
-  Mgr_Handle mgrHandle;
-  RS_DBI_manager *mgr;
-  Sint counter;
-  Sint mgr_id = (Sint) getpid();
-  int i;
-
-  mgrHandle = RS_DBI_asMgrHandle(mgr_id);
-
-  if(!dbManager){                      /* alloc for the first time */
-    counter = 0;                       /* connections handled so far */
-    mgr = (RS_DBI_manager*) malloc(sizeof(RS_DBI_manager));
-  }
-  else {                               /* we're re-entering */
-    if(dbManager->connections){        /* and mgr is valid */
-      if(!force_realloc)            
-	return mgrHandle;
-      else
-	RS_DBI_freeManager(mgrHandle);  /* i.e., free connection arrays*/    
-    }
-    counter = dbManager->counter;
-    mgr = dbManager;
-  }
- /* Ok, we're here to expand number of connections, etc.*/
-  if(!mgr)
-    RS_DBI_errorMessage("could not malloc the dbManger", RS_DBI_ERROR);
-  mgr->drvName = RS_DBI_copyString(drvName);
-  mgr->drvData = (void *) NULL;
-  mgr->managerId = mgr_id;
-  mgr->connections =  (RS_DBI_connection **) 
-    calloc((size_t) max_con, sizeof(RS_DBI_connection));
-  if(!mgr->connections){
-    free(mgr);
-    RS_DBI_errorMessage("could not calloc RS_DBI_connections", RS_DBI_ERROR);
-  }
-  mgr->connectionIds = (Sint *) calloc((size_t)max_con, sizeof(Sint));
-  if(!mgr->connectionIds){
-    free(mgr->connections);
-    free(mgr);
-    RS_DBI_errorMessage("could not calloc vector of connection Ids",
-          RS_DBI_ERROR);
-  }
-  mgr->counter = counter;
-  mgr->length = max_con;
-  mgr->num_con = (Sint) 0;
-  mgr->fetch_default_rec = fetch_default_rec;
-  for(i=0; i < max_con; i++){
-    mgr->connectionIds[i] = -1;
-    mgr->connections[i] = (RS_DBI_connection *) NULL;
-  }
-  
-  dbManager = mgr;
-
-  return mgrHandle;
-}
-
-/* We don't want to completely free the dbManager, but rather we 
- * re-initialize all the fields except for mgr->counter to ensure we don't
- * re-cycle connection ids across R/S DBI sessions in the the same pid
- * (S/R session).
- */
-void
-RS_DBI_freeManager(Mgr_Handle mgrHandle)
-{
-  RS_DBI_manager *mgr;
-
-  mgr = RS_DBI_getManager(mgrHandle);
-  if(mgr->num_con > 0){    
-    char *errMsg = "all opened connections were forcebly closed";
-    RS_DBI_errorMessage(errMsg, RS_DBI_WARNING);
-  }
-  if(mgr->drvData){
-    char *errMsg = "mgr->drvData was not freed (some memory leaked)";
-    RS_DBI_errorMessage(errMsg, RS_DBI_WARNING);
-  }
-  if(mgr->drvName){
-    free(mgr->drvName);
-    mgr->drvName = (char *) NULL;
-  }
-  if(mgr->connections) {
-    free(mgr->connections);
-    mgr->connections = (RS_DBI_connection **) NULL;
-  }
-  if(mgr->connectionIds) {
-    free(mgr->connectionIds);
-    mgr->connectionIds = (Sint *) NULL;
-  }
-  return;
-}
-
-Con_Handle
-RS_DBI_allocConnection(Mgr_Handle mgrHandle, Sint max_res)
-{
-  RS_DBI_manager    *mgr;
-  RS_DBI_connection *con;
-  Con_Handle conHandle;
-  Sint  i, con_id;
-  
-  mgr = RS_DBI_getManager(mgrHandle);
-  con = (RS_DBI_connection *) malloc(sizeof(RS_DBI_connection));
-  if(!con){
-    RS_DBI_errorMessage("could not malloc dbConnection", RS_DBI_ERROR);
-  }
-  con->managerId = MGR_ID(mgrHandle);
-  con_id = mgr->counter;
-  con->connectionId = con_id;
-  con->drvConnection = (void *) NULL;
-  con->drvData = (void *) NULL;    /* to be used by the driver in any way*/
-  con->conParams = (void *) NULL;
-  con->counter = (Sint) 0;
-  con->length = max_res;           /* length of resultSet vector */
-  
-  /* result sets for this connection */
-  con->resultSets = (RS_DBI_resultSet **)
-    calloc((size_t) max_res, sizeof(RS_DBI_resultSet));
-  if(!con->resultSets){
-    free(con);
-    RS_DBI_errorMessage("could not calloc resultSets for the dbConnection",
-                        RS_DBI_ERROR);
-  }
-  con->num_res = (Sint) 0;
-  con->resultSetIds = (Sint *) calloc((size_t) max_res, sizeof(Sint));
-  if(!con->resultSetIds) {
-    free(con->resultSets);
-    free(con);
-    RS_DBI_errorMessage("could not calloc vector of resultSet Ids",
-                        RS_DBI_ERROR);
-  }
-  for(i=0; i<max_res; i++){
-    con->resultSets[i] = (RS_DBI_resultSet *) NULL;
-    con->resultSetIds[i] = -1;
-  }
-
-  /* Finally, update connection table in mgr */
-  mgr->num_con += (Sint) 1;
-  mgr->counter += (Sint) 1;
-  conHandle = RS_DBI_asConHandle(MGR_ID(mgrHandle), con_id, con);
-  return conHandle;
-}
-
-/* the invoking (freeing) function must provide a function for
- * freeing the conParams, and by setting the (*free_drvConParams)(void *)
- * pointer.
- */
-
-void 
-RS_DBI_freeConnection(SEXP conHandle)
-{
-  RS_DBI_connection *con;
-  RS_DBI_manager    *mgr;
-
-  con = RS_DBI_getConnection(conHandle);
-  mgr = RS_DBI_getManager(conHandle);
-
-  /* Are there open resultSets? If so, free them first */
-  if(con->num_res > 0) {
-    char *errMsg = "opened resultSet(s) forcebly closed";
-    int  i;
-    for(i=0; i < con->num_res; i++){
-        RS_DBI_freeResultSet0(con->resultSets[i], con);
-    }
-    RS_DBI_errorMessage(errMsg, RS_DBI_WARNING);
-  }
-  if(con->drvConnection) {
-    char *errMsg = 
-      "internal error in RS_DBI_freeConnection: driver might have left open its connection on the server";
-    RS_DBI_errorMessage(errMsg, RS_DBI_WARNING);
-  }
-  if(con->conParams){
-    char *errMsg =
-      "internal error in RS_DBI_freeConnection: non-freed con->conParams (tiny memory leaked)";
-    RS_DBI_errorMessage(errMsg, RS_DBI_WARNING);
-  }
-  if(con->drvData){
-    char *errMsg = 
-      "internal error in RS_DBI_freeConnection: non-freed con->drvData (some memory leaked)";
-    RS_DBI_errorMessage(errMsg, RS_DBI_WARNING);
-  }
-  /* delete this connection from manager's connection table */
-  if(con->resultSets) free(con->resultSets);
-  if(con->resultSetIds) free(con->resultSetIds);
-
-  /* update the manager's connection table */
-  mgr->num_con -= (Sint) 1;
-
-  free(con);
-  con = (RS_DBI_connection *) NULL;
-  R_ClearExternalPtr(conHandle);
-}
-
-SEXP
-RS_DBI_allocResultSet(SEXP conHandle)
-{
-  RS_DBI_connection *con = NULL;
-  RS_DBI_resultSet  *result = NULL;
-  Sint indx, res_id;
-
-  con = RS_DBI_getConnection(conHandle);
-  indx = RS_DBI_newEntry(con->resultSetIds, con->length);
-  if(indx < 0){
-    char msg[128], fmt[128];
-    (void) strcpy(fmt, "cannot allocate a new resultSet -- ");
-    (void) strcat(fmt, "maximum of %d resultSets already reached");
-    (void) sprintf(msg, fmt, con->length);
-    RS_DBI_errorMessage(msg, RS_DBI_ERROR);
-  }
-
-  result = (RS_DBI_resultSet *) malloc(sizeof(RS_DBI_resultSet));
-  if(!result){
-    char *errMsg = "could not malloc dbResultSet";
-    RS_DBI_freeEntry(con->resultSetIds, indx);
-    RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-  }
-  result->drvResultSet = (void *) NULL; /* driver's own resultSet (cursor)*/
-  result->drvData = (void *) NULL;   /* this can be used by driver*/
-  result->statement = (char *) NULL;
-  result->managerId = MGR_ID(conHandle);
-  result->connectionId = CON_ID(conHandle);
-  result->resultSetId = con->counter;
-  result->isSelect = (Sint) -1;
-  result->rowsAffected = (Sint) -1;
-  result->rowCount = (Sint) 0;
-  result->completed = (Sint) -1;
-  result->fields = (RS_DBI_fields *) NULL;
-  
-  /* update connection's resultSet table */
-  res_id = con->counter;
-  con->num_res += (Sint) 1;
-  con->counter += (Sint) 1;
-  con->resultSets[indx] = result;
-  con->resultSetIds[indx] = res_id;
-
-  return RS_DBI_asResHandle(MGR_ID(conHandle), CON_ID(conHandle), res_id,
-                            conHandle);
-}
-
-void RS_DBI_freeResultSet0(RS_DBI_resultSet *result, RS_DBI_connection *con)
-{
-    if(result->drvResultSet) {
-        char *errMsg =
-            "internal error in RS_DBI_freeResultSet: "
-            "non-freed result->drvResultSet (some memory leaked)";
-        RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-    }
-    if (result->drvData) {
-        char *errMsg =
-            "internal error in RS_DBI_freeResultSet: "
-            "non-freed result->drvData (some memory leaked)";
-        RS_DBI_errorMessage(errMsg, RS_DBI_WARNING);
-    }
-    if (result->statement)
-        free(result->statement);
-    if (result->fields)
-        RS_DBI_freeFields(result->fields);
-    free(result);
-    result = (RS_DBI_resultSet *) NULL;
-
-    /* update connection's resultSet table */
-    /* indx = RS_DBI_lookup(con->resultSetIds, con->length, RES_ID(rsHandle)); */
-    /* SQLite connections only ever have one result set */
-    RS_DBI_freeEntry(con->resultSetIds, 0);
-    con->resultSets[0] = NULL;
-    con->num_res -= 1;
-}
-
-void
-RS_DBI_freeResultSet(Res_Handle rsHandle)
-{
-  RS_DBI_freeResultSet0(RS_DBI_getResultSet(rsHandle),
-                        RS_DBI_getConnection(rsHandle));
-}
-
-RS_DBI_fields *
-RS_DBI_allocFields(int num_fields)
-{
-  RS_DBI_fields *flds;
-  size_t n;
-
-  flds = (RS_DBI_fields *)malloc(sizeof(RS_DBI_fields));
-  if(!flds){
-    char *errMsg = "could not malloc RS_DBI_fields";
-    RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-  }
-  n = (size_t) num_fields;
-  flds->num_fields = num_fields;
-  flds->name =     (char **) calloc(n, sizeof(char *));
-  flds->type =     (Sint *) calloc(n, sizeof(Sint));
-  flds->length =   (Sint *) calloc(n, sizeof(Sint));
-  flds->precision= (Sint *) calloc(n, sizeof(Sint));
-  flds->scale =    (Sint *) calloc(n, sizeof(Sint));
-  flds->nullOk =   (Sint *) calloc(n, sizeof(Sint));
-  flds->isVarLength = (Sint *) calloc(n, sizeof(Sint));
-  flds->Sclass =   (Stype *) calloc(n, sizeof(Stype));
-
-  return flds;
-}
-
-void
-RS_DBI_freeFields(RS_DBI_fields *flds)
-{
-  if(flds->name) free(flds->name);
-  if(flds->type) free(flds->type);
-  if(flds->length) free(flds->length);
-  if(flds->precision) free(flds->precision);
-  if(flds->scale) free(flds->scale);
-  if(flds->nullOk) free(flds->nullOk);
-  if(flds->isVarLength) free(flds->isVarLength);
-  if(flds->Sclass) free(flds->Sclass);
-  free(flds);
-  flds = (RS_DBI_fields *) NULL;
-  return;
-}
-
-/* Make a data.frame from a named list by adding row.names, and class 
- * attribute.  Use "1", "2", .. as row.names.
- * NOTE: Only tested  under R (not tested at all under S4 or Splus5+).
- */
-void
-RS_DBI_makeDataFrame(SEXP data)
-{
-   SEXP row_names, df_class_name; 
-   Sint   i, n;
-   char   buf[1024];
-   
-   PROTECT(data);
-   PROTECT(df_class_name = NEW_CHARACTER((Sint) 1));
-   SET_CHR_EL(df_class_name, 0, C_S_CPY("data.frame"));
-
-   /* row.names */
-   n = GET_LENGTH(LST_EL(data,0));            /* length(data[[1]]) */
-   PROTECT(row_names = NEW_CHARACTER(n));
-   for(i=0; i<n; i++){
-      (void) sprintf(buf, "%d", i+1);
-      SET_CHR_EL(row_names, i, C_S_CPY(buf));
-   }
-   SET_ROWNAMES(data, row_names);
-   SET_CLASS_NAME(data, df_class_name);
-   UNPROTECT(3);
-   return;
-}
-
-void
-RS_DBI_allocOutput(SEXP output, RS_DBI_fields *flds,
-		   Sint num_rec, Sint  expand)
-{
-  SEXP names, s_tmp;
-  Sint   j; 
-  int    num_fields;
-  Stype  *fld_Sclass;
-
-  PROTECT(output);
-
-  num_fields = flds->num_fields;
-  if(expand){
-    for(j = 0; j < (Sint) num_fields; j++){
-      /* Note that in R-1.2.3 (at least) we need to protect SET_LENGTH */
-      s_tmp = LST_EL(output,j);
-      PROTECT(SET_LENGTH(s_tmp, num_rec));  
-      SET_VECTOR_ELT(output, j, s_tmp);
-      UNPROTECT(1);
-    }
-    UNPROTECT(1);
-    return;
-  }
-
-  fld_Sclass = flds->Sclass;
-  for(j = 0; j < (Sint) num_fields; j++){
-    switch((int)fld_Sclass[j]){
-    case LGLSXP:    
-      SET_VECTOR_ELT(output, j, NEW_LOGICAL(num_rec));
-      break;
-    case STRSXP:
-      SET_VECTOR_ELT(output, j, NEW_CHARACTER(num_rec));
-      break;
-    case INTSXP:
-      SET_VECTOR_ELT(output, j, NEW_INTEGER(num_rec));
-      break;
-    case REALSXP:
-      SET_VECTOR_ELT(output, j, NEW_NUMERIC(num_rec));
-      break;
-    case RAWSXP:                /* falls through */
-    case VECSXP:
-      SET_VECTOR_ELT(output, j, NEW_LIST(num_rec));
-      break;
-    default:
-      RS_DBI_errorMessage("unsupported data type", RS_DBI_ERROR);
-    }
-  }
-
-  PROTECT(names = NEW_CHARACTER((Sint) num_fields));
-  for(j = 0; j< (Sint) num_fields; j++){
-    SET_CHR_EL(names,j, C_S_CPY(flds->name[j]));
-  }
-  SET_NAMES(output, names);
-  UNPROTECT(2);
-  return;
-}
-
-SEXP  		/* boolean */
-RS_DBI_validHandle(Db_Handle handle)
-{ 
-    SEXP valid, contents;
-    int  handleType = 0;
-    if (TYPEOF(handle) != EXTPTRSXP) return 0;
-    contents = R_ExternalPtrProtected(handle);
-    if (TYPEOF(contents) == VECSXP) {
-        handleType = RES_HANDLE_TYPE;
-    } else {
-        switch(length(contents)) {
-        case MGR_HANDLE_TYPE:
-            handleType = MGR_HANDLE_TYPE;
-            break;
-        case CON_HANDLE_TYPE:
-            handleType = CON_HANDLE_TYPE;
-            break;
-        case RES_HANDLE_TYPE:
-            handleType = RES_HANDLE_TYPE;
-            break;
-        }
-    }
-    PROTECT(valid = NEW_LOGICAL((Sint) 1));
-    LGL_EL(valid,0) = (Sint) is_validHandle(handle, handleType);
-    UNPROTECT(1);
-    return valid;
-}
-    
-void 
-RS_DBI_setException(Db_Handle handle, DBI_EXCEPTION exceptionType,
-		    int errorNum, const char *errorMsg)
-{
-  HANDLE_TYPE handleType;
-  
-  handleType = (int) GET_LENGTH(handle);
-  if(handleType == MGR_HANDLE_TYPE){
-    RS_DBI_manager *obj;
-    obj =  RS_DBI_getManager(handle);
-    obj->exception->exceptionType = exceptionType;
-    obj->exception->errorNum = errorNum;
-    obj->exception->errorMsg = RS_DBI_copyString(errorMsg);
-  } 
-  else if(handleType==CON_HANDLE_TYPE){
-    RS_DBI_connection *obj;
-    obj = RS_DBI_getConnection(handle);
-    obj->exception->exceptionType = exceptionType;
-    obj->exception->errorNum = errorNum;
-    obj->exception->errorMsg = RS_DBI_copyString(errorMsg);
-  } 
-  else {
-    RS_DBI_errorMessage(
-          "internal error in RS_DBI_setException: could not setException",
-          RS_DBI_ERROR);
-  }
-  return;
-}
-
-void 
-RS_DBI_errorMessage(const char *msg, DBI_EXCEPTION exception_type)
-{
-  char *driver = "RS-DBI";   /* TODO: use the actual driver name */
-  
-  switch(exception_type) {
-  case RS_DBI_MESSAGE:
-    PROBLEM "%s driver message: (%s)", driver, msg WARN; /* was PRINT_IT */
-    break;
-  case RS_DBI_WARNING:
-    PROBLEM "%s driver warning: (%s)", driver, msg WARN;
-    break;
-  case RS_DBI_ERROR:
-    PROBLEM  "%s driver: (%s)", driver, msg ERROR;
-    break;
-  case RS_DBI_TERMINATE:
-    PROBLEM "%s driver fatal: (%s)", driver, msg ERROR; /* was TERMINATE */
-    break;
-  }
-  return;
-}
-
-void DBI_MSG(char *msg, DBI_EXCEPTION exception_type, char *driver)
-{
-  switch (exception_type) {
-  case RS_DBI_MESSAGE:
-    PROBLEM "%s driver message: (%s)", driver, msg WARN;
-    break;
-  case RS_DBI_WARNING:
-    PROBLEM "%s driver warning: (%s)", driver, msg WARN;
-    break;
-  case RS_DBI_ERROR:
-    PROBLEM  "%s driver: (%s)", driver, msg ERROR;
-    break;
-  case RS_DBI_TERMINATE:        /* is this used? */
-    PROBLEM "%s driver fatal: (%s)", driver, msg ERROR;
-    break;
-  }
-  return;
-}
-
-/* wrapper to strcpy */
-char *
-RS_DBI_copyString(const char *str)
-{
-  char *buffer;
-
-  buffer = (char *) malloc((size_t) strlen(str)+1);
-  if(!buffer)
-    RS_DBI_errorMessage(
-          "internal error in RS_DBI_copyString: could not alloc string space", 
-          RS_DBI_ERROR);
-  return strcpy(buffer, str);
-}
-
-/* wrapper to strncpy, plus (optionally) deleting trailing spaces */
-char *
-RS_DBI_nCopyString(const char *str, size_t len, int del_blanks)
-{
-  char *str_buffer, *end;
-  
-  str_buffer = (char *) malloc(len+1);
-  if(!str_buffer){
-    char errMsg[128];
-    (void) sprintf(errMsg, 
-		   "could not malloc %ld bytes in RS_DBI_nCopyString",
-		   (long) len+1);
-    RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-  }
-  if(len==0){
-    *str_buffer = '\0';
-    return str_buffer;
-  }
-
-  (void) strncpy(str_buffer, str, len);
-
-  /* null terminate string whether we delete trailing blanks or not*/
-  if(del_blanks){
-    for(end = str_buffer+len-1; end>=str_buffer; end--)
-      if(*end != ' ') { end++; break; }
-    *end = '\0';
-  }
-  else { 
-    end = str_buffer + len;
-    *end = '\0';
-  }
-  return str_buffer;
-}
-
-SEXP 
-RS_DBI_copyfields(RS_DBI_fields *flds)
-{
-  SEXP S_fields;
-  Sint  n = (Sint) 8;
-  char  *desc[]={"name", "Sclass", "type", "len", "precision",
- 		 "scale","isVarLength", "nullOK"};
-  Stype types[] = {STRSXP, INTSXP, INTSXP,
-		   INTSXP, INTSXP, INTSXP,
-		   LGLSXP, LGLSXP};
-  Sint  lengths[8];
-  int   i, j, num_fields;
-
-  num_fields = flds->num_fields;
-  for(j = 0; j < n; j++) 
-    lengths[j] = (Sint) num_fields;
-  S_fields =  RS_DBI_createNamedList(desc, types, lengths, n);
-  /* copy contentes from flds into an R/S list */
-  for(i = 0; i < num_fields; i++){
-    SET_LST_CHR_EL(S_fields,0,i, C_S_CPY(flds->name[i]));
-    LST_INT_EL(S_fields,1,i) = (Sint) flds->Sclass[i];
-    LST_INT_EL(S_fields,2,i) = (Sint) flds->type[i];
-    LST_INT_EL(S_fields,3,i) = (Sint) flds->length[i];
-    LST_INT_EL(S_fields,4,i) = (Sint) flds->precision[i];
-    LST_INT_EL(S_fields,5,i) = (Sint) flds->scale[i];
-    LST_INT_EL(S_fields,6,i) = (Sint) flds->isVarLength[i];
-    LST_INT_EL(S_fields,7,i) = (Sint) flds->nullOk[i];
-  }
-
-  return S_fields;
-} 
-
-SEXP 
-RS_DBI_createNamedList(char **names, Stype *types, Sint *lengths, Sint  n)
-{
-  SEXP output, output_names, obj = S_NULL_ENTRY;
-  Sint  num_elem;
-  int   j;
-
-  PROTECT(output = NEW_LIST(n));
-  PROTECT(output_names = NEW_CHARACTER(n));
-  for(j = 0; j < n; j++){
-    num_elem = lengths[j];
-    switch((int)types[j]){
-    case LGLSXP: 
-      PROTECT(obj = NEW_LOGICAL(num_elem));
-      break;
-    case INTSXP:
-      PROTECT(obj = NEW_INTEGER(num_elem));
-      break;
-    case REALSXP:
-      PROTECT(obj = NEW_NUMERIC(num_elem));
-      break;
-    case STRSXP:
-      PROTECT(obj = NEW_CHARACTER(num_elem));
-      break;
-    case RAWSXP:                /* falls through */
-    case LIST_TYPE:
-      PROTECT(obj = NEW_LIST(num_elem));
-      break;
-    default:
-      RS_DBI_errorMessage("unsupported data type", RS_DBI_ERROR);
-    }
-    SET_VECTOR_ELT(output, (Sint)j, obj);
-    SET_CHR_EL(output_names, j, C_S_CPY(names[j]));
-  }
-  SET_NAMES(output, output_names);
-  UNPROTECT(n+2);
-  return(output);
-}
-
-SEXP 
-RS_DBI_SclassNames(SEXP type)
-{
-  SEXP typeNames;
-  Sint *typeCodes;
-  Sint n;
-  int  i;
-  char *s;
-  
-  if(type==S_NULL_ENTRY)
-     RS_DBI_errorMessage(
-           "internal error in RS_DBI_SclassNames: input S types must be nonNULL",
-           RS_DBI_ERROR);
-  n = LENGTH(type);
-  typeCodes = INTEGER_DATA(type);
-  PROTECT(typeNames = NEW_CHARACTER(n));
-  for(i = 0; i < n; i++) {
-    s = RS_DBI_getTypeName(typeCodes[i], RS_dataTypeTable);
-    if(!s)
-      RS_DBI_errorMessage(
-            "internal error RS_DBI_SclassNames: unrecognized S type", 
-            RS_DBI_ERROR);
-    SET_CHR_EL(typeNames, i, C_S_CPY(s));
-  }
-  UNPROTECT(1);
-  return typeNames;
-}
-
-/* The following functions roughly implement a simple object
- * database. 
- */
-
-SEXP
-RS_DBI_asMgrHandle(int mgrId)
-{
-    SEXP mgrHandle, label, ids;
-    PROTECT(ids = allocVector(INTSXP, 1));
-    INTEGER(ids)[0] = mgrId;
-    PROTECT(label = mkString("DBI MGR"));
-    mgrHandle = R_MakeExternalPtr(NULL, label, ids);
-    UNPROTECT(2);
-    /* FIXME: add finalizer code */
-    return mgrHandle;
-}
-
-/* FIXME: need to address this fwd declaration */
-SEXP
-RS_SQLite_closeConnection(Con_Handle conHandle);
-
-static void _finalize_con_handle(SEXP xp)
-{
-    if (R_ExternalPtrAddr(xp)) {
-        RS_SQLite_closeConnection(xp);
-        R_ClearExternalPtr(xp);
-    }
-}
-
-SEXP
-RS_DBI_asConHandle(int mgrId, int conId, RS_DBI_connection *con)
-{
-    SEXP conHandle, s_ids, label;
-    int *ids;
-    PROTECT(s_ids = allocVector(INTSXP, 2));
-    ids = INTEGER(s_ids);
-    ids[0] = mgrId;
-    ids[1] = conId;
-    PROTECT(label = mkString("DBI CON"));
-    conHandle = R_MakeExternalPtr(con, label, s_ids);
-    UNPROTECT(2);
-    R_RegisterCFinalizerEx(conHandle, _finalize_con_handle, 1);
-    return conHandle;
-}
-
-SEXP
-DBI_newResultHandle(SEXP xp, SEXP resId)
-{
-    int *ids = INTEGER(R_ExternalPtrProtected(xp));
-    return RS_DBI_asResHandle(ids[0], ids[1], INTEGER(resId)[0], xp);
-}
-
-SEXP
-RS_DBI_asResHandle(int mgrId, int conId, int resId, SEXP conxp)
-{
-    SEXP resHandle, s_ids, label, v;
-    int *ids;
-    PROTECT(s_ids = allocVector(INTSXP, 3));
-    ids = INTEGER(s_ids);
-    ids[0] = mgrId;
-    ids[1] = conId;
-    ids[2] = resId;
-    PROTECT(v = allocVector(VECSXP, 2));
-    SET_VECTOR_ELT(v, 0, s_ids);
-    /* this ensures the connection is preserved as long as
-       there is a reference to a result set
-     */
-    SET_VECTOR_ELT(v, 1, conxp);
-    PROTECT(label = mkString("DBI RES"));
-    resHandle = R_MakeExternalPtr(R_ExternalPtrAddr(conxp), label, v);
-    UNPROTECT(3);
-    /* FIXME: add finalizer code */
-    return resHandle;
-}
-
-RS_DBI_manager *
-RS_DBI_getManager(SEXP handle)
-{
-  RS_DBI_manager  *mgr;
-
-  if(!is_validHandle(handle, MGR_HANDLE_TYPE))
-    RS_DBI_errorMessage("invalid dbManager handle", RS_DBI_ERROR);
-  mgr = dbManager;
-  if(!mgr)
-    RS_DBI_errorMessage(
-          "internal error in RS_DBI_getManager: corrupt dbManager handle",
-	  RS_DBI_ERROR);
-  return mgr;
-}
-
-RS_DBI_connection *
-RS_DBI_getConnection(SEXP conHandle)
-{
-    RS_DBI_connection *con = (RS_DBI_connection *)R_ExternalPtrAddr(conHandle);
-    if (!con) RS_DBI_errorMessage("expired SQLiteConnection", RS_DBI_ERROR);
-    return con;
-}
-
-RS_DBI_resultSet *
-RS_DBI_getResultSet(SEXP rsHandle)
-{
-  RS_DBI_connection *con;
-  con = RS_DBI_getConnection(rsHandle);
-  if(!con)
-    RS_DBI_errorMessage(
-          "internal error in RS_DBI_getResultSet: bad connection",
-          RS_DBI_ERROR);
-  return con->resultSets[0];
-}
-
-/* Very simple objectId (mapping) table. newEntry() returns an index
- * to an empty cell in table, and lookup() returns the position in the
- * table of obj_id.  Notice that we decided not to touch the entries
- * themselves to give total control to the invoking functions (this 
- * simplify error management in the invoking routines.)
- */
-Sint
-RS_DBI_newEntry(Sint *table, Sint length)
-{
-  Sint i, indx, empty_val;
-
-  indx = empty_val = (Sint) -1;
-  for(i = 0; i < length; i++)
-    if(table[i] == empty_val){
-      indx = i;
-      break;
-    }
-  return indx;
-}
-
-Sint
-RS_DBI_lookup(Sint *table, Sint length, Sint obj_id)
-{
-  Sint i, indx = (Sint) -1;
-  if (obj_id != -1) {
-      for (i = 0; i < length; ++i) {
-          if (table[i] == obj_id) {
-              indx = i;
-              break;
-          }
-      }
-  }
-  return indx;
-}
-
-/* return a list of entries pointed by *entries (we allocate the space,
- * but the caller should free() it).  The function returns the number
- * of entries.
- */
-Sint 
-RS_DBI_listEntries(Sint *table, Sint length, Sint *entries)
-{
-  int i,n;
-
-  for(i=n=0; i<length; i++){
-    if(table[i]<0) continue;
-    entries[n++] = table[i];
-  }
-  return n;
-}
-
-void 
-RS_DBI_freeEntry(Sint *table, Sint indx)
-{ /* no error checking!!! */
-  Sint empty_val = (Sint) -1;
-  table[indx] = empty_val;
-  return;
-}
-
-int 
-is_validHandle(SEXP handle, HANDLE_TYPE handleType)
-{
-    int mgr_id, len, indx;
-    RS_DBI_manager *mgr;
-    RS_DBI_connection *con;
-
-  if (TYPEOF(handle) != EXTPTRSXP) return 0;
-  len = HANDLE_LENGTH(handle);
-  if(len<handleType || handleType<1 || handleType>3) 
-    return 0;
-  mgr_id = MGR_ID(handle);
-  if(mgr_id <= 0) return 0;
-
-  /* at least we have a potential valid dbManager */
-  mgr = dbManager;
-  if(!mgr || !mgr->connections)  return 0;   /* expired manager*/
-  if(handleType == MGR_HANDLE_TYPE) return 1;     /* valid manager id */
-
-  /* ... on to connections */
-  con = R_ExternalPtrAddr(handle);
-  if (!con) return 0;
-  if(!con->resultSets) return 0;       /* un-initialized (invalid) */
-  if(handleType==CON_HANDLE_TYPE) return 1; /* valid connection id */
-
-  /* .. on to resultSets */
-  indx = RS_DBI_lookup(con->resultSetIds, con->length, RES_ID(handle));
-  if(indx < 0) return 0;
-  if(!con->resultSets[indx]) return 0;
-
-  return 1;
-}
-
-/* The following 3 routines provide metadata for the 3 main objects 
- * dbManager, dbConnection and dbResultSet.  These functions 
- * an object Id and return a list with all the meta-data. In R/S we 
- * simply invoke one of these and extract the metadata piece we need, 
- * which can be NULL if non-existent or un-implemented.
- * 
- * Actually, each driver should modify these functions to add the
- * driver-specific info, such as server version, client version, etc.
- * That's how the various RS_MySQL_managerInfo, etc., were implemented.
- */
-
-SEXP          /* named list */
-RS_DBI_managerInfo(Mgr_Handle mgrHandle)
-{
-  RS_DBI_manager *mgr;
-  SEXP output;
-  Sint  i, num_con;
-  Sint n = (Sint) 7;
-  char *mgrDesc[] = {"connectionIds", "fetch_default_rec","managerId",
-		     "length", "num_con", "counter", "clientVersion"};
-  Stype mgrType[] = {INTSXP, INTSXP, INTSXP,
-		     INTSXP, INTSXP, INTSXP, 
-                     STRSXP};
-  Sint  mgrLen[]  = {1, 1, 1, 1, 1, 1, 1};
-  
-  mgr = RS_DBI_getManager(mgrHandle);
-  num_con = (Sint) mgr->num_con;
-  mgrLen[0] = num_con;
-
-  output = RS_DBI_createNamedList(mgrDesc, mgrType, mgrLen, n);
-  for(i = 0; i < num_con; i++)
-    LST_INT_EL(output,0,i) = (Sint) mgr->connectionIds[i];
-
-  LST_INT_EL(output,1,0) = (Sint) mgr->fetch_default_rec;
-  LST_INT_EL(output,2,0) = (Sint) mgr->managerId;
-  LST_INT_EL(output,3,0) = (Sint) mgr->length;
-  LST_INT_EL(output,4,0) = (Sint) mgr->num_con;
-  LST_INT_EL(output,5,0) = (Sint) mgr->counter;
-  SET_LST_CHR_EL(output,6,0,C_S_CPY("NA"));   /* client versions? */
-
-  return output;
-}
-
-/* The following should be considered templetes to be 
- * implemented by individual drivers.
- */
-
-SEXP         /* return a named list */
-RS_DBI_connectionInfo(Con_Handle conHandle)
-{
-  RS_DBI_connection  *con;
-  SEXP output;
-  Sint     i;
-  Sint  n = (Sint) 8;
-  char *conDesc[] = {"host", "user", "dbname", "conType",
-		     "serverVersion", "protocolVersion",
-		     "threadId", "rsHandle"};
-  Stype conType[] = {STRSXP, STRSXP, STRSXP,
-		      STRSXP, STRSXP, INTSXP,
-		      INTSXP, INTSXP};
-  Sint  conLen[]  = {1, 1, 1, 1, 1, 1, 1, -1};
-
-  con = RS_DBI_getConnection(conHandle);
-  conLen[7] = con->num_res;   /* number of resultSets opened */
-
-  output = RS_DBI_createNamedList(conDesc, conType, conLen, n);
-  /* dummy */
-  SET_LST_CHR_EL(output,0,0,C_S_CPY("NA"));        /* host */
-  SET_LST_CHR_EL(output,1,0,C_S_CPY("NA"));        /* dbname */
-  SET_LST_CHR_EL(output,2,0,C_S_CPY("NA"));        /* user */
-  SET_LST_CHR_EL(output,3,0,C_S_CPY("NA"));        /* conType */
-  SET_LST_CHR_EL(output,4,0,C_S_CPY("NA"));        /* serverVersion */
-
-  LST_INT_EL(output,5,0) = (Sint) -1;            /* protocolVersion */
-  LST_INT_EL(output,6,0) = (Sint) -1;            /* threadId */
-
-  for(i=0; i < con->num_res; i++)
-    LST_INT_EL(output,7,(Sint) i) = con->resultSetIds[i];
-
-  return output;
-}
-
-SEXP        /* return a named list */
-RS_DBI_resultSetInfo(Res_Handle rsHandle)
-{
-  RS_DBI_resultSet       *result;
-  SEXP output, flds;
-  Sint  n = (Sint) 6;
-  char  *rsDesc[] = {"statement", "isSelect", "rowsAffected",
-		     "rowCount", "completed", "fields"};
-  Stype rsType[]  = {STRSXP, INTSXP, INTSXP,
-		     INTSXP,   INTSXP, LIST_TYPE};
-  Sint  rsLen[]   = {1, 1, 1, 1, 1, 1};
-
-  result = RS_DBI_getResultSet(rsHandle);
-  if(result->fields)
-    flds = RS_DBI_copyfields(result->fields);
-  else
-    flds = S_NULL_ENTRY;
-
-  output = RS_DBI_createNamedList(rsDesc, rsType, rsLen, n);
-  SET_LST_CHR_EL(output,0,0,C_S_CPY(result->statement));
-  LST_INT_EL(output,1,0) = result->isSelect;
-  LST_INT_EL(output,2,0) = result->rowsAffected;
-  LST_INT_EL(output,3,0) = result->rowCount;
-  LST_INT_EL(output,4,0) = result->completed;
-  SET_VECTOR_ELT(LST_EL(output, 5), (Sint) 0, flds);
-
-  return output;
-}
-
-SEXP     /* named list */
-RS_DBI_getFieldDescriptions(RS_DBI_fields *flds)
-{
-  SEXP S_fields;
-  Sint  n = (Sint) 7;
-  Sint  lengths[7];
-  char  *desc[]={"name", "Sclass", "type", "len", "precision",
-		"scale","nullOK"};
-  Stype types[] = {STRSXP, INTSXP, INTSXP,
-		   INTSXP, INTSXP, INTSXP,
-		   LGLSXP};
-  Sint   i, j;
-  int    num_fields;
-
-  num_fields = flds->num_fields;
-  for(j = 0; j < n; j++) 
-    lengths[j] = (Sint) num_fields;
-  PROTECT(S_fields =  RS_DBI_createNamedList(desc, types, lengths, n));
-  /* copy contentes from flds into an R/S list */
-  for(i = 0; i < (Sint) num_fields; i++){
-    SET_LST_CHR_EL(S_fields,0,i,C_S_CPY(flds->name[i]));
-    LST_INT_EL(S_fields,1,i) = (Sint) flds->Sclass[i];
-    LST_INT_EL(S_fields,2,i) = (Sint) flds->type[i];
-    LST_INT_EL(S_fields,3,i) = (Sint) flds->length[i];
-    LST_INT_EL(S_fields,4,i) = (Sint) flds->precision[i];
-    LST_INT_EL(S_fields,5,i) = (Sint) flds->scale[i];
-    LST_INT_EL(S_fields,6,i) = (Sint) flds->nullOk[i];
-  }
-  UNPROTECT(1);
-  return(S_fields);
-}
-
-/* given a type id return its human-readable name.
- * We define an RS_DBI_dataTypeTable */
-char *
-RS_DBI_getTypeName(Sint t, const struct data_types table[])
-{
-  int i;
-  char buf[128];
-
-  for (i = 0; table[i].typeName != (char *) 0; i++) {
-    if (table[i].typeId == t)
-      return table[i].typeName;
-  }
-  sprintf(buf, "unknown (%ld)", (long) t);
-  RS_DBI_errorMessage(buf, RS_DBI_WARNING);
-  return (char *) 0; /* for -Wall */
-}
-
-/* Translate R/S identifiers (and only R/S names!!!) into 
- * valid SQL identifiers;  overwrite input vector. Currently,
- *   (1) translate "." into "_".  
- *   (2) first character should be a letter (traslate to "X" if not),
- *       but a double quote signals a "delimited identifier"
- *   (3) check that length <= 18, but only warn, since most (all?)
- *       dbms allow much longer identifiers.
- *   (4) SQL reserved keywords are handled in the R/S calling 
- *       function make.SQL.names(), not here.
- * BUG: Compound SQL identifiers are not handled properly.
- *      Note the the dot "." is a valid SQL delimiter, used for specifying
- *      user/table in a compound identifier.  Thus, it's possible that 
- *      such compound name is mapped into a legal R/S identifier (preserving
- *      the "."), and then we incorrectly map such delimiting "dot" into "_" 
- *      thus loosing the original SQL compound identifier.  
- */
-#define RS_DBI_MAX_IDENTIFIER_LENGTH 18      /* as per SQL92 */
-SEXP 
-RS_DBI_makeSQLNames(SEXP snames)
-{
-   long     nstrings;
-   char *name;
-   SEXP schar;
-   char c;
-   char     errMsg[128];
-   size_t   len;
-   Sint     i;
-
-   nstrings = (Sint) GET_LENGTH(snames);
-   for(i = 0; i<nstrings; i++){
-       schar = STRING_ELT(snames, i);
-       name = CallocCharBuf(length(schar));
-       strncpy(name, CHAR(schar), length(schar));
-
-      if(strlen(name)> RS_DBI_MAX_IDENTIFIER_LENGTH){
-	 (void) sprintf(errMsg,"SQL identifier %s longer than %d chars", 
-			name, RS_DBI_MAX_IDENTIFIER_LENGTH);
-	 RS_DBI_errorMessage(errMsg, RS_DBI_WARNING);
-      }
-      /* check for delimited-identifiers (those in double-quotes);
-       * if missing closing double-quote, warn and treat as non-delim 
-       */
-      c = *name;
-      len = strlen(name);
-      if(c=='"' && name[len-1] =='"') 
-         continue;  
-      if(!isalpha(c) && c!='"') *name = 'X';
-      name++;
-      while((c=*name)){
-	 /* TODO: recognize SQL delim "." instances that may have
-	  * originated in SQL and R/S make.names() left alone */
-	 if(c=='.') *name='_';
-	 name++;
-      }
-      SET_STRING_ELT(snames, i, mkChar(name));
-      Free(name);
-   }
-
-   return snames;
-}
-
-/*  These 2 R-specific functions are used by the C macros IS_NA(p,t) 
- *  and NA_SET(p,t) (in this way one simply use macros to test and set
- *  NA's regardless whether we're using R or S.
- */
-void RS_na_set(void *ptr, Stype type)
-{
-  double *d;
-  Sint   *i;
-  const char   *c;
-  switch(type){
-  case INTSXP:
-    i = (Sint *) ptr;
-    *i = NA_INTEGER;
-    break;
-  case LGLSXP:
-    i = (Sint *) ptr;
-    *i = NA_LOGICAL;
-    break;
-  case REALSXP:
-    d = (double *) ptr;
-    *d = NA_REAL;
-    break;
-  case CHARSXP:
-    c = (const char *) ptr;
-    c = CHAR(NA_STRING);
-    break;
-  }
-}
-
-int RS_is_na(void *ptr, Stype type)
-{
-   int *i, out = -2;
-   const char *c;
-   double *d;
-
-   switch(type){
-   case INTSXP:
-   case LGLSXP:
-      i = (int *) ptr;
-      out = (int) ((*i) == NA_INTEGER);
-      break;
-   case REALSXP:
-      d = (double *) ptr;
-      out = ISNA(*d);
-      break;
-   case CHARSXP:
-      c = (const char *) ptr;
-      out = (int) (strcmp(c, CHAR(NA_STRING))==0);
-      break;
-   }
-   return out;
-}
-
-/* the codes come from from R/src/main/util.c */
-const struct data_types RS_dataTypeTable[] = {
-    { "NULL",		NILSXP	   },  /* real types */
-    { "symbol",		SYMSXP	   },
-    { "pairlist",	LISTSXP	   },
-    { "closure",	CLOSXP	   },
-    { "environment",	ENVSXP	   },
-    { "promise",	PROMSXP	   },
-    { "language",	LANGSXP	   },
-    { "special",	SPECIALSXP },
-    { "builtin",	BUILTINSXP },
-    { "char",		CHARSXP	   },
-    { "logical",	LGLSXP	   },
-    { "integer",	INTSXP	   },
-    { "double",		REALSXP	   }, /*-  "real", for R <= 0.61.x */
-    { "complex",	CPLXSXP	   },
-    { "character",	STRSXP	   },
-    { "...",		DOTSXP	   },
-    { "any",		ANYSXP	   },
-    { "expression",	EXPRSXP	   },
-    { "list",		VECSXP	   },
-    { "raw",		RAWSXP	   },
-    /* aliases : */
-    { "numeric",	REALSXP	   },
-    { "name",		SYMSXP	   },
-    { (char *)0,	-1	   }
-};
-
-SEXP DBI_handle_to_string(SEXP xp)
-{
-    char *buf;
-    SEXP ans, tag, ids;
-    int len, *v;
-    if (TYPEOF(xp) != EXTPTRSXP)
-        RS_DBI_errorMessage("DBI_handle_to_string: invalid handle",
-                            RS_DBI_ERROR);
-    tag = STRING_ELT(R_ExternalPtrTag(xp), 0);
-    ids = R_ExternalPtrProtected(xp);
-    if (TYPEOF(ids) == VECSXP) ids = VECTOR_ELT(ids, 0);
-    len = strlen(CHAR(tag)) + 20;
-    buf = CallocCharBuf(len);
-    v = INTEGER(ids);
-    switch (length(ids)) {
-    case 1:
-        snprintf(buf, len, "%s (%d)", CHAR(tag), v[0]);
-        break;
-    case 2:
-        snprintf(buf, len, "%s (%d, %d)", CHAR(tag), v[0], v[1]);
-        break;
-    case 3:
-        snprintf(buf, len, "%s (%d, %d, %d)", CHAR(tag), v[0], v[1], v[2]);
-        break;
-    default:
-        snprintf(buf, len, "%s", "BAD LENGTH");
-    }
-    ans = mkString(buf);
-    Free(buf);
-    return ans;
-}
diff --git a/src/RS-DBI.h b/src/RS-DBI.h
deleted file mode 100644
index 069564b..0000000
--- a/src/RS-DBI.h
+++ /dev/null
@@ -1,289 +0,0 @@
-#ifndef _RS_DBI_H
-#define _RS_DBI_H 1
-/*  
- *  $Id$
- *
- * Copyright (C) 1999-2002 The Omega Project for Statistical Computing.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* The following include file defines a number of C macros that hide
- * differences between R and S (e.g., the macro for type "Sint" expand
- * to "long" in the case of S and to int in the case of R, etc.)
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "Rhelpers.h"
-#include <ctype.h>
-
-#ifdef WIN64
-# include <process.h>
-# define pid_t int
-/* Microsoft Visual C++ uses int _getpid()  */
-#elif defined(WIN32)
-# include <process.h>
-# define getpid _getpid
-# define pid_t int
-#else
-# include <sys/types.h>
-# include <unistd.h>
-#endif
-
-
-/* We now define 4 important data structures:
- * RS_DBI_manager, RS_DBI_connection, RS_DBI_resultSet, and
- * RS_DBI_fields, corresponding to dbManager, dbConnection,
- * dbResultSet, and list of field descriptions.
- */
-/* In R/S a dbObject is a foreign reference consisting of a vector
- * of 1, 2 or 3 integers.  In the C implementation we use these 
- * R/S vectors as handles (we could have use pointers).
- */
-typedef enum enum_dbi_exception {
-  RS_DBI_MESSAGE,
-  RS_DBI_WARNING,
-  RS_DBI_ERROR,
-  RS_DBI_TERMINATE
-} DBI_EXCEPTION;
-
-/* dbObject handles are simple S/R integer vectors of 1, 2, or 3 integers
- * the *_ID macros extract the appropriate scalar.
- */
-
-#define Mgr_Handle SEXP
-#define Con_Handle SEXP
-#define Res_Handle SEXP
-#define Db_Handle  SEXP       /* refers to any one of the above */
-/* The integer value for the following enum's needs to equal 
- * GET_LENGTH(handle) for the various handles.
- */
-typedef enum enum_handle_type {
-  MGR_HANDLE_TYPE = 1,     /* dbManager handle */
-  CON_HANDLE_TYPE = 2,     /* dbConnection handle */
-  RES_HANDLE_TYPE = 3      /* dbResult handle */
-} HANDLE_TYPE; 
-
-static int MGR_ID(SEXP handle)
-{
-    SEXP h = R_ExternalPtrProtected(handle);
-    if (TYPEOF(h) == VECSXP) h = VECTOR_ELT(h, 0);
-    return INTEGER(h)[0];
-}
-
-static int CON_ID(SEXP handle)
-{
-    SEXP h = R_ExternalPtrProtected(handle);
-    if (TYPEOF(h) == VECSXP) h = VECTOR_ELT(h, 0);
-    return INTEGER(h)[1];
-}
-
-#define RES_ID(handle) INTEGER(VECTOR_ELT(R_ExternalPtrProtected(handle), 0))[2]
-
-
-/* First, the following fully describes the field output by a select
- * (or select-like) statement, and the mappings from the internal
- * database types to S classes.  This structure contains the info we need
- * to build the R/S list (or data.frame) that will receive the SQL
- * output.  It still needs some work to handle arbitrty BLOB's (namely
- * methods to map BLOBs into user-defined S objects).
- * Each element is an array of num_fields, this flds->Sclass[3] stores
- * the S class for the 4th output fields.
- */
-typedef struct st_sdbi_fields {
-  int num_fields;
-  char  **name;         /* DBMS field names */
-  Sint  *type;          /* DBMS internal types */
-  Sint  *length;        /* DBMS lengths in bytes */
-  Sint  *precision;     /* DBMS num of digits for numeric types */
-  Sint  *scale;         /* DBMS num of decimals for numeric types */
-  Sint  *nullOk;        /* DBMS indicator for DBMS'  NULL type */
-  Sint  *isVarLength;   /* DBMS variable-length char type */
-  Stype *Sclass;        /* R/S class (type) -- may be overriden */
-  /* TODO: Need a table of fun pointers to converters */
-} RS_DBI_fields;
-
-typedef struct st_sdbi_exception {
-  DBI_EXCEPTION  exceptionType; /* one of RS_DBI_WARN, RS_RBI_ERROR, etc */
-  int  errorNum;            /* SQL error number (possibly driver-dependent*/
-  char *errorMsg;           /* SQL error message */
-} RS_DBI_exception;
-
-/* The RS-DBI resultSet consists of a pointer to the actual DBMS 
- * resultSet (e.g., MySQL, Oracle) possibly NULL,  plus the fields 
- * defined by the RS-DBI implementation. 
- */
-typedef struct st_sdbi_resultset {
-  void  *drvResultSet;   /* the actual (driver's) cursor/result set */
-  void  *drvData;        /* a pointer to driver-specific data */
-  Sint  managerId;       /* the 3 *Id's are used for   */
-  Sint  connectionId;    /* validating stuff coming from S */
-  Sint  resultSetId;  
-  Sint  isSelect;        /* boolean for testing SELECTs */
-  char  *statement;      /* SQL statement */
-  Sint  rowsAffected;    /* used by non-SELECT statements */
-  Sint  rowCount;        /* rows fetched so far (SELECT-types)*/
-  Sint  completed;       /* have we fetched all rows? */
-  RS_DBI_fields *fields;
-} RS_DBI_resultSet;
-
-/* A dbConnection consists of a pointer to the actual implementation
- * (MySQL, Oracle, etc.) connection plus a resultSet and other
- * goodies used by the RS-DBI implementation.
- * The connection parameters (user, password, database name, etc.) are
- * defined by the actual driver -- we just set aside a void pointer.
- */
-
-typedef struct st_sdbi_connection {
-  void  *conParams;      /* pointer to connection params (host, user, etc)*/
-  void  *drvConnection;  /* pointer to the actual DBMS connection struct*/
-  void  *drvData;        /* to be used at will by individual drivers */
-  RS_DBI_resultSet  **resultSets;    /* vector to result set ptrs  */
-  Sint   *resultSetIds;
-  Sint   length;                     /* max num of concurrent resultSets */
-  Sint   num_res;                    /* num of open resultSets */
-  Sint   counter;                    /* total number of queries */
-  Sint   managerId;
-  Sint   connectionId; 
-  RS_DBI_exception *exception;
-} RS_DBI_connection;
-
-/* dbManager */
-typedef struct st_sdbi_manager {
-  char *drvName;                    /* what driver are we implementing?*/
-  void *drvData;                    /* to be used by the drv implementation*/
-  RS_DBI_connection **connections;  /* list of dbConnections */
-  Sint *connectionIds;              /* array of connectionIds */
-  Sint length;                      /* max num of concurrent connections */
-  Sint num_con;                     /* num of opened connections */
-  Sint counter;                     /* num of connections handled so far*/
-  Sint fetch_default_rec;           /* default num of records per fetch */
-  Sint managerId;                   /* typically, process id */
-  RS_DBI_exception *exception;    
-} RS_DBI_manager;
-
-/* All RS_DBI functions and their signatures */
-
-/* Note: the following alloc functions allocate the space for the
- * corresponding manager, connection, resultSet; they all 
- * return handles.  All DBI functions (free/get/etc) use the handle 
- * to work with the various dbObjects.
- */
-Mgr_Handle RS_DBI_allocManager(const char *drvName, Sint max_con, 
-				    Sint fetch_default_rec, 
-				    Sint force_realloc);
-void            RS_DBI_freeManager(Mgr_Handle mgrHandle);
-RS_DBI_manager *RS_DBI_getManager(Db_Handle handle);
-Mgr_Handle RS_DBI_asMgrHandle(Sint pid);   
-SEXP RS_DBI_managerInfo(Mgr_Handle mgrHandle);
-
-/* dbConnection */
-Con_Handle RS_DBI_allocConnection(Mgr_Handle mgrHandle, 
-					  Sint max_res);
-void               RS_DBI_freeConnection(Con_Handle conHandle);
-RS_DBI_connection *RS_DBI_getConnection(Db_Handle handle);
-Con_Handle RS_DBI_asConHandle(Sint mgrId, Sint conId, RS_DBI_connection *con);
-SEXP RS_DBI_connectionInfo(Con_Handle con_Handle);
-
-/* dbResultSet */
-Res_Handle RS_DBI_allocResultSet(Con_Handle conHandle);
-void               RS_DBI_freeResultSet(Res_Handle rsHandle);
-void RS_DBI_freeResultSet0(RS_DBI_resultSet *result, RS_DBI_connection *con);
-RS_DBI_resultSet  *RS_DBI_getResultSet(Res_Handle rsHandle);
-Res_Handle RS_DBI_asResHandle(Sint pid, Sint conId, Sint resId, SEXP conxp);
-SEXP RS_DBI_resultSetInfo(Res_Handle rsHandle);
-
-/* utility funs */
-SEXP RS_DBI_validHandle(Db_Handle handle); /* callable from S/R */
-int       is_validHandle(Db_Handle handle, HANDLE_TYPE handleType);
-
-/* a simple object database (mapping table) -- it uses simple linear 
- * search (we don't expect to have more than a handful of simultaneous 
- * connections and/or resultSets. If this is not the case, we could
- * use a hash table, but I doubt it's worth it (famous last words!).
- * These are used for storing/retrieving object ids, such as
- * connection ids from the manager object, and resultSet ids from a 
- * connection object;  of course, this is transparent to the various
- * drivers -- they should deal with handles exclusively.
- */
-Sint  RS_DBI_newEntry(Sint *table, Sint length);
-Sint  RS_DBI_lookup(Sint *table, Sint length, Sint obj_id);
-Sint  RS_DBI_listEntries(Sint *table, Sint length, Sint *entries);
-void  RS_DBI_freeEntry(Sint *table, Sint indx);
-
-/* description of the fields in a result set */
-RS_DBI_fields *RS_DBI_allocFields(int num_fields);
-SEXP RS_DBI_getFieldDescriptions(RS_DBI_fields *flds);
-void           RS_DBI_freeFields(RS_DBI_fields *flds);
-
-/* we (re)allocate the actual output list in here (with the help of
- * RS_DBI_fields).  This should be some kind of R/S "relation"
- * table, not a dataframe nor a list.
- */
-void  RS_DBI_allocOutput(SEXP output, 
-			RS_DBI_fields *flds,
-			Sint num_rec,
-			Sint expand);
-void RS_DBI_makeDataFrame(SEXP data);
-
-/* TODO: We need to elevate RS_DBI_errorMessage to either
- * dbManager and/or dbConnection methods.  I still need to 
- * go back and re-code the error-handling throughout, darn!
- */
-void  RS_DBI_errorMessage(const char *msg, DBI_EXCEPTION exceptionType);
-void  RS_DBI_setException(Db_Handle handle, 
-			  DBI_EXCEPTION exceptionType,
-			  int errorNum, 
-			  const char *errorMsg);
-void DBI_MSG(char *msg, DBI_EXCEPTION exception_type, char *driver);
-
-/* utility funs (copy strings, convert from R/S types to string, etc.*/
-char     *RS_DBI_copyString(const char *str);
-char     *RS_DBI_nCopyString(const char *str, size_t len, int del_blanks);
-
-/* We now define a generic data type name-Id mapping struct
- * and initialize the RS_dataTypeTable[].  Each driver could
- * define similar table for generating friendly type names
- */
-struct data_types {
-    char *typeName;
-    Sint typeId;
-};
-
-/* return the primitive type name for a primitive type id */
-char     *RS_DBI_getTypeName(Sint typeCode, const struct data_types table[]);
-/* same, but callable from S/R and vectorized */
-SEXP RS_DBI_SclassNames(SEXP types);  
-
-SEXP RS_DBI_createNamedList(char  **names, 
-				 Stype *types,
-				 Sint  *lengths,
-				 Sint  n);
-SEXP RS_DBI_copyFields(RS_DBI_fields *flds);
-
-void RS_na_set(void *ptr, Stype type);
-int  RS_is_na(void *ptr, Stype type);
-extern const struct data_types RS_dataTypeTable[];
-
-SEXP DBI_handle_to_string(SEXP xp);
-SEXP DBI_newResultHandle(SEXP xp, SEXP resId);
-
-#ifdef __cplusplus 
-}
-#endif
-#endif   /* _RS_DBI_H */
diff --git a/src/RS-SQLite.c b/src/RS-SQLite.c
deleted file mode 100644
index 560dbb2..0000000
--- a/src/RS-SQLite.c
+++ /dev/null
@@ -1,1673 +0,0 @@
-/* $Id$
- *
- *
- * Copyright (C) 1999-2003 The Omega Project for Statistical Computing.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "RS-SQLite.h"
-#include "param_binding.h"
-
-/* size_t getline(char**, size_t*, FILE*); */
-char *compiledVarsion = SQLITE_VERSION;
-
-int RS_sqlite_import(sqlite3 *db, const char *zTable,
-                     const char *zFile, const char *separator, const char *eol, int skip);
-
-void RSQLite_closeResultSet0(RS_DBI_resultSet *result, RS_DBI_connection *con);
-
-/* The macro NA_STRING is a CHRSXP in R but a char * in Splus */
-#define RS_NA_STRING CHAR(NA_STRING)
-
-/* R and S Database Interface to the SQLite embedded SQL engine
- *
- * C Function library which can be used to run SQL queries from
- * inside of Splus5.x, or R.
- * This driver hooks R/S and SQLite and implements the proposed S-DBI
- * generic R/S-database interface 0.2.
- *
- * We need to simulate (fake) exception objects. We do this piggy-
- * backing on the member "drvData" of the RS_DBI_connection structure.
- * The exception is a 2-member struct with errorNum and erroMsg
- * (this should be extended to allow multiple errors in the structure,
- * like in the ODBC API.)
- *
- * For details on SQLite see http://www.sqlite.org.
- * TODO:
- *    1. Make sure the code is thread-safe, in particular,
- *       we need to remove the PROBLEM ... ERROR macros
- *       in RS_DBI_errorMessage() because it's definetely not
- *       thread-safe.  But see RS_DBI_setException().
- *     2. Use proper types instead of getting everything as character
- */
-
-
-Mgr_Handle
-RS_SQLite_init(SEXP config_params, SEXP reload, SEXP cache)
-{
-    /* Currently we can specify the 2 defaults max conns and records per
-     * fetch (this last one can be over-ridden explicitly in the S call to fetch).
-     */
-    RS_DBI_manager *mgr;
-    Mgr_Handle mgrHandle;
-    Sint  fetch_default_rec, force_reload;
-    Sint  *shared_cache;
-    const char *drvName = "SQLite";
-    const char *clientVersion = sqlite3_libversion();
-
-    /* make sure we're running with the "right" version of the SQLite library */
-    if(strcmp(clientVersion, compiledVarsion)){
-        char  buf[256];
-        (void) sprintf(buf,
-                       "%s mismatch between compiled version %s and runtime version %s",
-                       drvName, compiledVarsion, clientVersion);
-        RS_DBI_errorMessage(buf, RS_DBI_WARNING);
-    }
-    if(GET_LENGTH(config_params)!=2){
-        RS_DBI_errorMessage(
-            "initialization error: must specify max num of conenctions and default number of rows per fetch",
-            RS_DBI_ERROR);
-    }
-    /* max_con is now IGNORED as connections are not tracked by the
-     * manager; instead they are held in external pointers with
-     * finalizers. */
-    /* max_con = INT_EL(config_params, 0); */
-    fetch_default_rec = INT_EL(config_params,1);
-    force_reload = LGL_EL(reload,0);
-
-    /* The manager does not keep track of connections, so there is no
-       pre-set max connections.  We set this to 1 for now until more
-       of the code is refactored.
-     */
-    mgrHandle = RS_DBI_allocManager(drvName, 1, fetch_default_rec,
-                                    force_reload);
-
-    mgr = RS_DBI_getManager(mgrHandle);
-
-    shared_cache = (Sint *)malloc(sizeof(Sint));
-    if(!shared_cache){
-        RS_DBI_errorMessage(
-            "could not malloc space for driver data", RS_DBI_ERROR);
-    }
-
-    *shared_cache = LGL_EL(cache,0);
-    mgr->drvData = (void *)shared_cache;
-
-    if(*shared_cache)
-        sqlite3_enable_shared_cache(1);
-
-    return mgrHandle;
-}
-
-SEXP 
-RS_SQLite_closeManager(Mgr_Handle mgrHandle)
-{
-    RS_DBI_manager *mgr;
-    SEXP status;
-    Sint *shared_cache;
-
-    mgr = RS_DBI_getManager(mgrHandle);
-    if(mgr->num_con)
-        RS_DBI_errorMessage("there are opened connections -- close them first",
-                            RS_DBI_ERROR);
-
-    sqlite3_enable_shared_cache(0);
-    shared_cache = (Sint *)mgr->drvData;
-    if(shared_cache){
-        free(shared_cache);
-        mgr->drvData = NULL;
-    }
-
-    RS_DBI_freeManager(mgrHandle);
-
-    PROTECT(status = NEW_LOGICAL((Sint) 1));
-    LGL_EL(status,0) = TRUE;
-    UNPROTECT(1);
-    return status;
-}
-
-/* open a connection with the same parameters used for in conHandle */
-Con_Handle
-RS_SQLite_cloneConnection(Con_Handle conHandle)
-{
-    RS_DBI_connection  *con = RS_DBI_getConnection(conHandle);
-    Mgr_Handle mgrHandle = RS_DBI_asMgrHandle(MGR_ID(conHandle));
-    RS_SQLite_conParams *conParams = (RS_SQLite_conParams *) con->conParams;
-    SEXP dbname, allow_ext, vfs, flags;
-    Con_Handle ans;
-
-    /* copy dbname and loadable_extensions into a 2-element character
-     * vector to be passed to the RS_SQLite_newConnection() function.
-     */
-    PROTECT(dbname = mkString(conParams->dbname));
-    PROTECT(allow_ext = ScalarLogical(conParams->loadable_extensions));
-    PROTECT(vfs = mkString(conParams->vfs));
-    PROTECT(flags = ScalarInteger(conParams->flags));
-    ans = RS_SQLite_newConnection(mgrHandle, dbname, allow_ext, flags, vfs);
-    UNPROTECT(4);
-    return ans;
-}
-
-RS_SQLite_conParams *
-RS_SQLite_allocConParams(const char *dbname, int loadable_extensions,
-                         int flags, const char *vfs)
-{
-    RS_SQLite_conParams *conParams;
-
-    conParams = (RS_SQLite_conParams *) malloc(sizeof(RS_SQLite_conParams));
-    if(!conParams){
-        RS_DBI_errorMessage("could not malloc space for connection params",
-                            RS_DBI_ERROR);
-    }
-    conParams->dbname = RS_DBI_copyString(dbname);
-    if (vfs)
-        conParams->vfs = RS_DBI_copyString(vfs);
-    else
-        conParams->vfs = RS_DBI_copyString("");
-    conParams->loadable_extensions = loadable_extensions;
-    conParams->flags = flags;
-    return conParams;
-}
-
-void
-RS_SQLite_freeConParams(RS_SQLite_conParams *conParams)
-{
-    if (conParams->dbname) free(conParams->dbname);
-    if (conParams->vfs) free(conParams->vfs);
-    /* conParams->loadable_extensions is an int, thus needs no free */
-    free(conParams);
-    conParams = (RS_SQLite_conParams *)NULL;
-    return;
-}
-
-/* set exception object (allocate memory if needed) */
-void
-RS_SQLite_setException(RS_DBI_connection *con, int err_no, const char *err_msg)
-{
-    RS_SQLite_exception *ex;
-
-    ex = (RS_SQLite_exception *) con->drvData;
-    if(!ex){    /* brand new exception object */
-        ex = (RS_SQLite_exception *) malloc(sizeof(RS_SQLite_exception));
-        if(!ex)
-            RS_DBI_errorMessage("could not allocate SQLite exception object",
-                                RS_DBI_ERROR);
-    }
-    else
-        free(ex->errorMsg);      /* re-use existing object */
-
-    ex->errorNum = err_no;
-    if(err_msg)
-        ex->errorMsg = RS_DBI_copyString(err_msg);
-    else
-        ex->errorMsg = (char *) NULL;
-
-    con->drvData = (void *) ex;
-    return;
-}
-
-void
-RS_SQLite_freeException(RS_DBI_connection *con)
-{
-    RS_SQLite_exception *ex = (RS_SQLite_exception *) con->drvData;
-
-    if(!ex) return;
-    if(ex->errorMsg) free(ex->errorMsg);
-    free(ex);
-    return;
-}
-
-SEXP
-RS_SQLite_newConnection(Mgr_Handle mgrHandle, SEXP dbfile, SEXP allow_ext,
-                        SEXP s_flags, SEXP s_vfs)
-{
-    RS_DBI_connection   *con;
-    RS_SQLite_conParams *conParams;
-    Con_Handle conHandle;
-    sqlite3     *db_connection;
-    const char  *dbname = NULL, *vfs = NULL;
-    int         rc, loadable_extensions, open_flags = 0;
-
-    if(!is_validHandle(mgrHandle, MGR_HANDLE_TYPE))
-        RS_DBI_errorMessage("invalid SQLiteManager", RS_DBI_ERROR);
-
-    if (TYPEOF(dbfile) != STRSXP || length(dbfile) != 1
-        || STRING_ELT(dbfile, 0) == NA_STRING)
-        error("'dbname' must be a length one character vector and not NA");
-    dbname = CHAR(STRING_ELT(dbfile, 0));
-
-    if (!isLogical(allow_ext))
-        error("'allow_ext' must be TRUE or FALSE");
-    loadable_extensions = LOGICAL(allow_ext)[0];
-    if (loadable_extensions == NA_LOGICAL)
-        error("'allow_ext' must be TRUE or FALSE, not NA");
-
-    if (!isNull(s_vfs)) {
-        if (!isString(s_vfs) || length(s_vfs) != 1
-            || STRING_ELT(s_vfs, 0) == NA_STRING) {
-            error("invalid argument 'vfs'");
-        }
-        vfs = CHAR(STRING_ELT(s_vfs, 0));
-        /* "" is not valid, NULL gives default value */
-        if (strlen(vfs) == 0) vfs = NULL;
-    }
-  
-    if (!isInteger(s_flags) || length(s_flags) != 1)
-        error("argument 'mode' must be length 1 integer, got %s, length: %d",
-              type2char(TYPEOF(s_flags)), length(s_flags));
-    open_flags = INTEGER(s_flags)[0];
-  
-    rc = sqlite3_open_v2(dbname, &db_connection, open_flags, vfs);
-    if(rc != SQLITE_OK){
-        char buf[256];
-        sprintf(buf, "could not connect to dbname:\n%s\n",
-                sqlite3_errmsg(db_connection));
-
-        RS_DBI_errorMessage(buf, RS_DBI_ERROR);
-    }
-
-    /* SQLite connections can only have 1 result set open at a time */
-    conHandle = RS_DBI_allocConnection(mgrHandle, (Sint) 1);
-    /* Note, while RS_DBI_getConnection can raise an error, conHandle
-     * will be valid if RS_DBI_allocConnection returns without
-     * error. */
-    con = RS_DBI_getConnection(conHandle);
-    if(!con){
-        (void) sqlite3_close(db_connection);
-        RS_DBI_freeConnection(conHandle);
-        RS_DBI_errorMessage("could not alloc space for connection object",
-                            RS_DBI_ERROR);
-    }
-    /* save connection parameters in the connection object */
-    conParams = RS_SQLite_allocConParams(dbname, loadable_extensions,
-                                         open_flags, vfs);
-    con->drvConnection = (void *) db_connection;
-    con->conParams = (void *) conParams;
-    RS_SQLite_setException(con, SQLITE_OK, "OK");
-
-    /* enable loadable extensions if required */
-    if(loadable_extensions != 0)
-        sqlite3_enable_load_extension(db_connection, 1);
-
-    return conHandle;
-}
-
-SEXP 
-RS_SQLite_closeConnection(Con_Handle conHandle)
-{
-    RS_DBI_connection *con = RS_DBI_getConnection(conHandle);
-    sqlite3 *db_connection;
-    int      rc;
-
-    if(con->num_res>0){
-        /* we used to error out here telling the user to
-           close pending result sets.  Now we warn and close the set ourself.
-         */
-        RS_DBI_errorMessage("closing pending result sets before closing "
-                            "this connection", RS_DBI_WARNING);
-        RSQLite_closeResultSet0(con->resultSets[0], con);
-    }
-
-    db_connection = (sqlite3 *) con->drvConnection;
-    rc = sqlite3_close(db_connection);  /* it also frees db_connection */
-    if (rc == SQLITE_BUSY) {
-        /* This will happen if there is an unfinalized prepared statement or
-           an unfinalized BLOB reference.  Should not happen under normal
-           operation -- even if user is doing things out of order.
-         */
-        RS_DBI_errorMessage(
-            "unfinalized prepared statements before closing this connection",
-            RS_DBI_WARNING);
-    }
-    else if(rc!=SQLITE_OK){
-        RS_DBI_errorMessage("internal error: "
-                            "SQLite could not close the connection",
-                            RS_DBI_WARNING);
-    }
-
-    /* make sure we first free the conParams and SQLite connection from
-     * the RS-RBI connection object.
-     */
-    if(con->conParams){
-        RS_SQLite_freeConParams(con->conParams);
-        /* we must set con->conParms to NULL (not just free it) to signal
-         * RS_DBI_freeConnection that it is okay to free the connection itself.
-         */
-        con->conParams = NULL;
-    }
-    con->drvConnection = NULL;
-    RS_SQLite_freeException(con);
-    con->drvData = NULL;
-    RS_DBI_freeConnection(conHandle);
-    return ScalarLogical(1);
-}
-
-int SQLite_decltype_to_type(const char* decltype)
-{
-    unsigned int h = 0;
-    if (!decltype)
-        return SQLITE_TEXT;
-    int len = strlen(decltype);
-    const unsigned char *zIn = (unsigned char*)decltype;
-    const unsigned char *zEnd = (unsigned char*)&(decltype[len]);
-    int col_type = SQLITE_FLOAT;
-
-    while( zIn!=zEnd ){
-        h = (h<<8) + tolower(*zIn);
-        zIn++;
-        if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){             /* CHAR */
-            col_type = SQLITE_TEXT;
-        }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){       /* CLOB */
-            col_type = SQLITE_TEXT;
-        }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){       /* TEXT */
-            col_type = SQLITE_TEXT;
-        }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b')          /* BLOB */
-                  && col_type==SQLITE_FLOAT ){
-            col_type = SQLITE_BLOB;
-#ifndef SQLITE_OMIT_FLOATING_POINT
-        }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l')          /* REAL */
-                  && col_type==SQLITE_FLOAT ){
-            col_type = SQLITE_FLOAT;
-        }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a')          /* FLOA */
-                  && col_type==SQLITE_FLOAT ){
-            col_type = SQLITE_FLOAT;
-        }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b')          /* DOUB */
-                  && col_type==SQLITE_FLOAT ){
-            col_type = SQLITE_FLOAT;
-#endif
-        }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){    /* INT */
-            col_type = SQLITE_INTEGER;
-            break;
-        }
-    }
-    return col_type;
-}
-
-
-int RS_SQLite_get_row_count(sqlite3* db, const char* tname) {
-    char* sqlQuery;
-    const char* sqlFmt = "select rowid from %s order by rowid desc limit 1";
-    int qrylen = strlen(sqlFmt);
-    int rc = 0;
-    int ans;
-    sqlite3_stmt* stmt;
-    const char* tail;
-
-    qrylen += strlen(tname) + 1;
-    sqlQuery = (char*)  R_alloc(qrylen, sizeof(char));
-    snprintf(sqlQuery, qrylen, sqlFmt, tname);
-    rc = sqlite3_prepare_v2(db, sqlQuery, -1, &stmt, &tail);
-    if (rc != SQLITE_OK) {
-        sqlite3_finalize(stmt);
-        error("SQL error: %s\n", sqlite3_errmsg(db));
-    }
-    rc = sqlite3_step(stmt);
-    if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
-        sqlite3_finalize(stmt);
-        error("SQL error: %s\n", sqlite3_errmsg(db));
-    }
-    ans = sqlite3_column_int(stmt, 0);
-    sqlite3_finalize(stmt);
-    return ans;
-}
-
-
-SEXP RS_SQLite_quick_column(Con_Handle conHandle, SEXP table, SEXP column)
-{
-    SEXP ans = R_NilValue, rawv;
-    RS_DBI_connection *con = RS_DBI_getConnection(conHandle);
-    sqlite3 *db_connection = (sqlite3 *) con->drvConnection;
-    sqlite3_stmt *stmt = NULL;
-    int numrows, rc, i = 0, col_type, *intans = NULL, blob_len;
-    char sqlQuery[500];
-    const char *table_name = NULL, *column_name = NULL, *tail = NULL;
-    double *doubleans = NULL;
-    const Rbyte *blob_data;
-
-    table_name = CHAR(STRING_ELT(table, 0));
-    column_name = CHAR(STRING_ELT(column, 0));
-    numrows = RS_SQLite_get_row_count(db_connection, table_name);
-    snprintf(sqlQuery, sizeof(sqlQuery), "select %s from %s",
-             column_name, table_name);
-
-    rc = sqlite3_prepare_v2(db_connection, sqlQuery, strlen(sqlQuery), &stmt, &tail);
-    /* FIXME: how should we be handling errors?
-       Could either follow the pattern in the rest of the package or
-       start to use the condition system and raise specific conditions.
-    */
-    if(rc != SQLITE_OK) {
-        error("SQL error: %s\n", sqlite3_errmsg(db_connection));
-    }
-
-    rc = sqlite3_step(stmt);
-    if (rc != SQLITE_ROW) {
-        error("SQL error: %s\n", sqlite3_errmsg(db_connection));
-    }
-    col_type = sqlite3_column_type(stmt, 0);
-    switch(col_type) {
-    case SQLITE_INTEGER:
-        PROTECT(ans = allocVector(INTSXP, numrows));
-        intans = INTEGER(ans);
-        break;
-    case SQLITE_FLOAT:
-        PROTECT(ans = allocVector(REALSXP, numrows));
-        doubleans = REAL(ans);
-        break;
-    case SQLITE_TEXT:
-        PROTECT(ans = allocVector(STRSXP, numrows));
-        break;
-    case SQLITE_NULL:
-        error("RS_SQLite_quick_column: encountered NULL column");
-        break;
-    case SQLITE_BLOB:
-        PROTECT(ans = allocVector(VECSXP, numrows));
-        break;
-    default:
-        error("RS_SQLite_quick_column: unknown column type %d", col_type);
-    }
-
-    i = 0;
-    while (rc == SQLITE_ROW && i < numrows) {
-        switch (col_type) {
-        case SQLITE_INTEGER:
-            intans[i] = sqlite3_column_int(stmt, 0);
-            break;
-        case SQLITE_FLOAT:
-            doubleans[i] = sqlite3_column_double(stmt, 0);
-            break;
-        case SQLITE_TEXT:
-            SET_STRING_ELT(ans, i, /* cast for -Wall */
-                           mkChar((char*)sqlite3_column_text(stmt, 0)));
-            break;
-        case SQLITE_BLOB:
-            blob_data = (const Rbyte *) sqlite3_column_blob(stmt, 0);
-            blob_len = sqlite3_column_bytes(stmt, 0);
-            PROTECT(rawv = allocVector(RAWSXP, blob_len));
-            memcpy(RAW(rawv), blob_data, blob_len * sizeof(Rbyte));;
-            SET_VECTOR_ELT(ans, i, rawv);
-            UNPROTECT(1);
-            break;
-        }
-        i++;
-        rc = sqlite3_step(stmt);
-    }
-    sqlite3_finalize(stmt);
-    UNPROTECT(1);
-    return ans;
-}
-
-static void RSQLite_freeResultSet0(RS_DBI_resultSet *result, RS_DBI_connection *con)
-{
-    if (result->drvResultSet) {
-        sqlite3_finalize((sqlite3_stmt *)result->drvResultSet);
-        result->drvResultSet = NULL;
-    }
-    if (result->drvData) {
-        RS_SQLite_bindParams *params = (RS_SQLite_bindParams *)result->drvData;
-        R_ReleaseObject(params->data);
-        RS_SQLite_freeParameterBinding(&params);
-        result->drvData = NULL;
-    }
-    RS_DBI_freeResultSet0(result, con);
-}
-
-/* Helper function to clean up and report an error during a call to
-   RS_SQLite_exec */
-static void
-exec_error(const char *msg,
-           RS_DBI_connection *con,
-           int bind_count,
-           RS_SQLite_bindParams *params,
-           Res_Handle rsHandle)
-{
-    sqlite3 *db = (sqlite3 *) con->drvConnection;
-    int errcode = db ? sqlite3_errcode(db) : -1;
-    char buf[2048];
-    const char *db_msg = "";
-    const char *sep = "";
-    if (db && errcode != SQLITE_OK) {
-        db_msg = sqlite3_errmsg(db);
-        sep = ": ";
-    }
-    snprintf(buf, sizeof(buf), "%s%s%s", msg, sep, db_msg);
-    RS_SQLite_setException(con, errcode, buf);
-    if (rsHandle) {
-        RSQLite_freeResultSet0(RS_DBI_getResultSet(rsHandle), con);
-        rsHandle = NULL;
-    }
-    if (params) {
-        RS_SQLite_freeParameterBinding(&params);
-        params = NULL;
-    }
-    RS_DBI_errorMessage(buf, RS_DBI_ERROR);
-}
-
-static void
-select_prepared_query(sqlite3_stmt *db_statement,
-                      SEXP bind_data,
-                      int bind_count,
-                      int rows,
-                      RS_DBI_connection *con,
-                      SEXP rsHandle)
-{
-    RS_DBI_resultSet *res;
-    char bindingErrorMsg[2048]; bindingErrorMsg[0] = '\0';
-    RS_SQLite_bindParams *params =
-        RS_SQLite_createParameterBinding(bind_count, bind_data,
-                                         db_statement, bindingErrorMsg);
-    if (params == NULL) {
-        /* FIXME: this UNPROTECT is ugly, paired to caller */
-        UNPROTECT(1);
-        exec_error(bindingErrorMsg, con, 0, NULL, rsHandle);
-    }
-    res = RS_DBI_getResultSet(rsHandle);
-    res->drvData = params;
-}
-
-static int
-bind_params_to_stmt(RS_SQLite_bindParams *params,
-                    sqlite3_stmt *db_statement, int row)
-{
-    int state = SQLITE_OK, j;
-    for (j = 0; j < params->count; j++) {
-        SEXP pdata = VECTOR_ELT(params->data, j), v_elt;
-        int integer;
-        double number;
-        Rbyte *raw;
-
-        switch(TYPEOF(pdata)){
-        case INTSXP:
-            integer = INTEGER(pdata)[row];
-            if (IS_NA(&integer, INTSXP))
-                state = sqlite3_bind_null(db_statement, j+1);
-            else
-                state = sqlite3_bind_int(db_statement, j+1, integer);
-            break;
-        case REALSXP:
-            number = NUM_EL(pdata, row);
-            if (IS_NA(&number, REALSXP))
-                state = sqlite3_bind_null(db_statement, j+1);
-            else
-                state = sqlite3_bind_double(db_statement, j+1, number);
-            break;
-        case VECSXP:            /* BLOB */
-            v_elt = VECTOR_ELT(pdata, row);
-            if (v_elt == R_NilValue) {
-                state = sqlite3_bind_null(db_statement, j+1);
-            } else {
-                raw = RAW(v_elt);
-                state = sqlite3_bind_blob(db_statement, j+1,
-                                          raw, LENGTH(v_elt), SQLITE_STATIC);
-            }
-            break;
-        case STRSXP:
-            /* falls through */
-        default:
-            v_elt = STRING_ELT(pdata, row);
-            if (NA_STRING == v_elt)
-                state = sqlite3_bind_null(db_statement, j+1);
-            else
-                state = sqlite3_bind_text(db_statement, j+1,
-                                          CHAR(v_elt), -1, SQLITE_STATIC);
-            break;
-        }
-        if (state != SQLITE_OK) break;
-    }
-    return state;
-}
-
-static void
-non_select_prepared_query(sqlite3_stmt *db_statement,
-                          SEXP bind_data,
-                          int bind_count,
-                          int rows,
-                          RS_DBI_connection *con,
-                          SEXP rsHandle)
-{
-    int state, i;
-    char bindingErrorMsg[2048]; bindingErrorMsg[0] = '\0';
-    RS_SQLite_bindParams *params =
-        RS_SQLite_createParameterBinding(bind_count, bind_data,
-                                         db_statement, bindingErrorMsg);
-    if (params == NULL) {
-        /* FIXME: this UNPROTECT is ugly, paired to caller */
-        UNPROTECT(1);
-        exec_error(bindingErrorMsg, con, 0, NULL, rsHandle);
-    }
-
-    /* we need to step through the query for each row */
-    for (i=0; i<rows; i++) {
-        state = bind_params_to_stmt(params, db_statement, i);
-        if (state != SQLITE_OK) {
-            UNPROTECT(1);
-            /* FIXME: add errmsg from sqlite */
-            exec_error("RS_SQLite_exec: could not bind data",
-                       con, 0, NULL, rsHandle);
-        }
-        state = sqlite3_step(db_statement);
-        if (state != SQLITE_DONE) {
-            UNPROTECT(1);
-            /* FIXME: add errmsg from sqlite */
-            exec_error("RS_SQLite_exec: could not execute",
-                       con, 0, NULL, rsHandle);
-        }
-        state = sqlite3_reset(db_statement);
-        sqlite3_clear_bindings(db_statement);
-        if (state != SQLITE_OK) {
-            UNPROTECT(1);
-            exec_error("RS_SQLite_exec: could not reset statement",
-                       con, 0, NULL, rsHandle);
-        }
-    }
-    RS_SQLite_freeParameterBinding(&params);
-}
-
-
-Res_Handle RS_SQLite_exec(Con_Handle conHandle, SEXP statement, SEXP bind_data)
-{
-    RS_DBI_connection *con = RS_DBI_getConnection(conHandle);
-    Res_Handle rsHandle;
-    RS_DBI_resultSet *res;
-    sqlite3 *db_connection = (sqlite3 *) con->drvConnection;
-    sqlite3_stmt *db_statement = NULL;
-    int state, bind_count;
-    int rows = 0, cols = 0;
-    char *dyn_statement = RS_DBI_copyString(CHR_EL(statement,0));
-
-    /* Do we have a pending resultSet in the current connection?
-     * SQLite only allows  one resultSet per connection.
-     */
-    if (con->num_res>0) {
-        Sint res_id = (Sint) con->resultSetIds[0]; /* SQLite has only 1 res */
-        rsHandle = RS_DBI_asResHandle(MGR_ID(conHandle),
-                                      CON_ID(conHandle), res_id, conHandle);
-        res = RS_DBI_getResultSet(rsHandle);
-        if (res->completed != 1) {
-            free(dyn_statement);
-            RS_DBI_errorMessage(
-                "connection with pending rows, close resultSet before continuing",
-                RS_DBI_ERROR);
-        } else
-            RS_SQLite_closeResultSet(rsHandle);
-    }
-
-    /* allocate and init a new result set */
-    PROTECT(rsHandle = RS_DBI_allocResultSet(conHandle));
-    res = RS_DBI_getResultSet(rsHandle);
-    res->completed = (Sint) 0;
-    res->statement = dyn_statement;
-    res->drvResultSet = db_statement;
-    state = sqlite3_prepare_v2(db_connection, dyn_statement, -1,
-                               &db_statement, NULL);
-    if (state != SQLITE_OK) {
-        UNPROTECT(1);
-        exec_error("error in statement", con, 0, NULL, rsHandle);
-    }
-
-    if (db_statement == NULL) {
-        UNPROTECT(1);
-        exec_error("nothing to execute", con, 0, NULL, rsHandle);
-    }
-    res->drvResultSet = (void *) db_statement;
-    bind_count = sqlite3_bind_parameter_count(db_statement);
-    if (bind_count > 0 && bind_data != R_NilValue) {
-        rows = GET_LENGTH(GET_ROWNAMES(bind_data));
-        cols = GET_LENGTH(bind_data);
-    }
-
-
-    res->isSelect = sqlite3_column_count(db_statement) > 0;
-    res->rowCount = 0;      /* fake's cursor's row count */
-    res->rowsAffected = -1; /* no rows affected */
-    RS_SQLite_setException(con, state, "OK");
-
-    if (res->isSelect) {
-        if (bind_count > 0) {
-            select_prepared_query(db_statement, bind_data, bind_count,
-                                  rows, con, rsHandle);
-        }
-    } else {
-        if (bind_count > 0) {
-            non_select_prepared_query(db_statement, bind_data, bind_count,
-                                      rows, con, rsHandle);
-        }
-        else {
-            state = sqlite3_step(db_statement);
-            if (state != SQLITE_DONE) {
-                UNPROTECT(1);
-                exec_error("RS_SQLite_exec: could not execute1",
-                           con, 0, NULL, rsHandle);
-            }
-        }
-        res->completed = (Sint) 1;          /* BUG: what if query is async?*/
-        res->rowsAffected = (Sint) sqlite3_changes(db_connection);
-    }
-    UNPROTECT(1);
-    return rsHandle;
-}
-
-RS_DBI_fields *
-RS_SQLite_createDataMappings(Res_Handle rsHandle)
-{
-    sqlite3_stmt  *db_statement;
-    RS_DBI_resultSet   *result;
-    RS_DBI_fields      *flds;
-    int     j, ncol, col_type;
-    const char *col_decltype = NULL;
-    char *col_name;
-
-    result = RS_DBI_getResultSet(rsHandle);
-    db_statement = (sqlite3_stmt *) result->drvResultSet;
-
-    ncol = sqlite3_column_count(db_statement);
-    flds = RS_DBI_allocFields(ncol); /* BUG: mem leak if this fails? */
-    flds->num_fields = (Sint) ncol;
-
-    for(j=0; j<ncol; j++){
-        col_name = (char*)sqlite3_column_name(db_statement, j); /* -Wall */
-        if (col_name)
-            flds->name[j] = RS_DBI_copyString(col_name);
-        else {                   /* weird failure */
-            RS_DBI_freeFields(flds);
-            flds = NULL;
-            return NULL;
-        }
-        /* XXX: We do our best to determine the type of the column.  When
-           the first row retrieved contains a NULL and does not reference
-           a table column, we give up.
-        */
-        col_type = sqlite3_column_type(db_statement, j);
-        if (col_type == SQLITE_NULL) {
-            /* try to get type from origin column */
-            col_decltype = sqlite3_column_decltype(db_statement, j);
-            col_type = SQLite_decltype_to_type(col_decltype);
-        }
-        switch(col_type) {
-        case SQLITE_INTEGER:
-            flds->type[j] = SQL92_TYPE_INTEGER;
-            flds->Sclass[j] = INTSXP;
-            flds->length[j] = (Sint) sizeof(int);
-            flds->isVarLength[j] = (Sint) 0;
-            break;
-        case SQLITE_FLOAT:
-            flds->type[j] = SQL92_TYPE_DOUBLE;
-            flds->Sclass[j] = REALSXP;
-            flds->length[j] = (Sint) sizeof(double);
-            flds->isVarLength[j] = (Sint) 0;
-            break;
-        case SQLITE_TEXT:
-            flds->type[j] = SQL92_TYPE_CHAR_VAR;
-            flds->Sclass[j] = STRSXP;
-            flds->length[j] = (Sint) -1;   /* unknown */
-            flds->isVarLength[j] = (Sint) 1;
-            break;
-        case SQLITE_NULL:
-            error("NULL column handling not implemented");
-            break;
-        case SQLITE_BLOB:
-            flds->type[j] = SQLns_TYPE_BLOB;
-            flds->Sclass[j] = VECSXP;
-            flds->length[j] = (Sint) -1;   /* unknown */
-            flds->isVarLength[j] = (Sint) 1;
-            break;
-        default:
-            error("unknown column type %d", col_type);
-        }
-        flds->precision[j] = (Sint) -1;
-        flds->scale[j] = (Sint) -1;
-        /* For nullOk, could use sqlite3_column_origin_name and
-           sqlite3_table_column_metadata to determine this.  It
-           won't always be possible as the query column may not
-           refer to a table column.
-        */
-        flds->nullOk[j] = (Sint) -1;
-    }
-    return flds;
-}
-
-
-/* Fills the output VECSXP with one row of data from the resultset
- */
-static void fill_one_row(sqlite3_stmt *db_statement, SEXP output, int row_idx,
-                         RS_DBI_fields *flds)
-{
-    int j, null_item, blob_len;
-    SEXP rawv;
-    const Rbyte *blob_data;
-
-    for (j = 0; j < flds->num_fields; j++) {
-        null_item = (sqlite3_column_type(db_statement, j) == SQLITE_NULL);
-        switch (flds->Sclass[j]) {
-        case INTSXP:
-            if (null_item)
-                NA_SET(&(LST_INT_EL(output, j, row_idx)), INTSXP);
-            else
-                LST_INT_EL(output, j, row_idx) =
-                    sqlite3_column_int(db_statement, j);
-            break;
-        case REALSXP:
-            if (null_item)
-                NA_SET(&(LST_NUM_EL(output,j,row_idx)), REALSXP);
-            else
-                LST_NUM_EL(output,j,row_idx) =
-                    sqlite3_column_double(db_statement, j);
-            break;
-        case VECSXP:            /* BLOB */
-            if (null_item) {
-                rawv = R_NilValue;
-            } else {
-                blob_data = (const Rbyte *)sqlite3_column_blob(db_statement, j);
-                blob_len = sqlite3_column_bytes(db_statement, j);
-                PROTECT(rawv = allocVector(RAWSXP, blob_len));
-                memcpy(RAW(rawv), blob_data, blob_len * sizeof(Rbyte));
-            }
-            SET_VECTOR_ELT(VECTOR_ELT(output, j), row_idx, rawv);
-            if (rawv != R_NilValue) UNPROTECT(1);
-            break;
-        case STRSXP:
-            /* falls through */
-        default:
-            if (null_item)
-                SET_LST_CHR_EL(output,j,row_idx, NA_STRING);
-            else
-                SET_LST_CHR_EL(output,j,row_idx, /* cast for -Wall */
-                               C_S_CPY((char*)sqlite3_column_text(db_statement, j)));
-            break;
-        }
-    }
-}
-
-static int do_select_step(RS_DBI_resultSet *res, int row_idx)
-{
-    int state;
-    RS_SQLite_bindParams * params = NULL;
-    sqlite3_stmt *stmt = (sqlite3_stmt *)res->drvResultSet;
-    if (res->drvData) {         /* we have parameters to bind */
-        params = (RS_SQLite_bindParams *)res->drvData;
-        if (params->row_complete) {
-            params->row_complete = 0;
-            sqlite3_clear_bindings(stmt);
-            state = bind_params_to_stmt(params,
-                                        stmt,
-                                        params->rows_used);
-            if (state != SQLITE_OK) return state;
-            params->rows_used++;
-        }
-    }
-    state = sqlite3_step(stmt);
-    if (params && state == SQLITE_DONE) {
-        params->row_complete = 1;
-        if (params->rows_used < params->row_count) {
-            state = sqlite3_reset(stmt);
-            if (state != SQLITE_OK) return state;
-            return do_select_step(res, row_idx);
-        }
-    }
-    return state;
-}
-
-/* Return a data.frame containing the requested number of rows from
-   the resultset.
-
-   We try to determine the correct R type for each column in the
-   result.  Currently, type detection happens only for the first fetch
-   on a given resultset and the first row of the resultset is used for
-   type interpolation.  If a NULL value appears in the first row of
-   the resultset and the column corresponds to a DB table column, we
-   guess the type based on the DB schema definition for the column.
-   If the NULL value does not correspond to a table column, then we
-   force character.
-
-   TODO: consider making this smarter by keeping track of unknown
-   columns and setting the type based on the first non-NULL.
-
-   TODO: consider adding ability for users to specify desired types
-   for result columns.  This could happen either via coercion in R or
-   at the SQLite level (which would be more efficient, but less
-   flexible).
-
-*/
-SEXP RS_SQLite_fetch(SEXP rsHandle, SEXP max_rec)
-{
-    RS_DBI_resultSet *res;
-    RS_DBI_fields *flds;
-    sqlite3_stmt *db_statement;
-    SEXP output, s_tmp;
-    int j, state, expand;
-    Sint num_rec;
-    int num_fields, row_idx = 0;
-
-    res = RS_DBI_getResultSet(rsHandle);
-    if (res->isSelect != 1) {
-        RSQLITE_MSG("resultSet does not correspond to a SELECT statement",
-                    RS_DBI_WARNING);
-        return R_NilValue;
-    }
-    if (res->completed == 1)
-        return R_NilValue;
-
-    /* We need to step once to be able to create the data mappings */
-    state = do_select_step(res, row_idx);
-    db_statement = (sqlite3_stmt *)res->drvResultSet;
-    if (state != SQLITE_ROW && state != SQLITE_DONE) {
-        char errMsg[2048];
-        (void)sprintf(errMsg, "RS_SQLite_fetch: failed first step: %s",
-                      sqlite3_errmsg(sqlite3_db_handle(db_statement)));
-        RSQLITE_MSG(errMsg, RS_DBI_ERROR);
-    }
-    if (!res->fields) {
-        if (!(res->fields = RS_SQLite_createDataMappings(rsHandle))) {
-            RSQLITE_MSG("corrupt SQLite resultSet, missing fieldDescription",
-                        RS_DBI_ERROR);
-        }
-    }
-    flds = res->fields;
-    num_fields = flds->num_fields;
-    num_rec = INT_EL(max_rec, 0);
-    expand = (num_rec < 0);   /* dyn expand output to accommodate all rows*/
-    if (expand || num_rec == 0) {
-        num_rec = RS_DBI_getManager(rsHandle)->fetch_default_rec;
-    }
-
-    PROTECT(output = NEW_LIST((Sint) num_fields));
-    RS_DBI_allocOutput(output, flds, num_rec, 0);
-    while (state != SQLITE_DONE) {
-        fill_one_row(db_statement, output, row_idx, flds);
-        row_idx++;
-        if (row_idx == num_rec) {  /* request satisfied or exhausted allocated space */
-            if (expand) {    /* do we extend or return the records fetched so far*/
-                num_rec = 2 * num_rec;
-                RS_DBI_allocOutput(output, flds, num_rec, expand);
-            }
-            else
-                break;       /* okay, no more fetching for now */
-        }
-        state = do_select_step(res, row_idx);
-        if (state != SQLITE_ROW && state != SQLITE_DONE) {
-            char errMsg[2048];
-            (void)sprintf(errMsg, "RS_SQLite_fetch: failed: %s",
-                          sqlite3_errmsg(sqlite3_db_handle(db_statement)));
-            RSQLITE_MSG(errMsg, RS_DBI_ERROR);
-        }
-    } /* end row loop */
-    if (state == SQLITE_DONE) {
-        res->completed = (Sint) 1;
-    }
-    /* size to actual number of records fetched */
-    if (row_idx < num_rec) {
-        num_rec = row_idx;
-        /* adjust the length of each of the members in the output_list */
-        for (j = 0; j<num_fields; j++) {
-            s_tmp = LST_EL(output, j);
-            PROTECT(SET_LENGTH(s_tmp, num_rec));
-            SET_VECTOR_ELT(output, j, s_tmp);
-            UNPROTECT(1);
-        }
-    }
-    res->rowCount += num_rec;
-    UNPROTECT(1);
-    return output;
-}
-
-/* The following mget-like function is EXPERIMENTAL
-
-   The purpose is to return a compact list structure directly instead
-   of, for example, pulling across a two-column table and calling
-   split.
-
-*/
-#if 0
-/* declare function that needs to be added to R API */
-SEXP R_NewHashedEnv(SEXP);
-
-SEXP       /* data.frame */
-RS_SQLite_mget(SEXP rsHandle, SEXP max_rec)
-{
-    RS_DBI_resultSet *res;
-    RS_DBI_fields    *flds;
-    sqlite3_stmt     *db_statement;
-    SEXP output, *s_tmp;
-    int    i, j, state, expand, vlen;
-    Sint   num_rec;
-    int    num_fields, row_idx;
-    int *key_breaks;
-    int breaks_idx;
-    const char *cur_key = NULL;
-    char *prev_key = NULL;
-    SEXP env, vect;
-
-
-    res = RS_DBI_getResultSet(rsHandle);
-    if(res->isSelect != 1){
-        RS_DBI_errorMessage("resultSet does not correspond to a SELECT statement",
-                            RS_DBI_WARNING);
-        return S_NULL_ENTRY;
-    }
-
-    if(res->completed == 1)
-        return R_NilValue;
-
-    db_statement = (sqlite3_stmt *)res->drvResultSet;
-    if(db_statement == NULL){
-        RS_DBI_errorMessage("corrupt SQLite resultSet, missing statement handle",
-                            RS_DBI_ERROR);
-    }
-
-    state = sqlite3_step(db_statement);
-    row_idx = 0;
-    if(state!=SQLITE_ROW && state!=SQLITE_DONE){
-        char errMsg[2048];
-        (void)sprintf(errMsg, "RS_SQLite_fetch: failed first step: %s",
-                      sqlite3_errmsg(sqlite3_db_handle(db_statement)));
-        RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-    }
-    if (!res->fields) {
-        if (!(res->fields = RS_SQLite_createDataMappings(rsHandle))) {
-            RS_DBI_errorMessage("corrupt SQLite resultSet, missing fieldDescription",
-                                RS_DBI_ERROR);
-        }
-    }
-    flds = res->fields;
-    /* force first column to character */
-    flds->Sclass[0] = STRSXP;
-
-    num_fields = flds->num_fields;
-    num_rec = INT_EL(max_rec,0);
-    expand = (num_rec < 0);   /* dyn expand output to accommodate all rows*/
-    if(expand || num_rec == 0){
-        num_rec = RS_DBI_getManager(rsHandle)->fetch_default_rec;
-    }
-
-    PROTECT(output = NEW_LIST((Sint) num_fields));
-    RS_DBI_allocOutput(output, flds, num_rec, 0);
-    key_breaks = (int *)R_alloc(num_rec, sizeof(int));
-    key_breaks[0] = 0;
-    breaks_idx++;
-    while (state != SQLITE_DONE) {
-        if (sqlite3_column_type(db_statement, 0) == SQLITE_NULL)
-            error("RS_SQLite_mget: encounted NULL key");
-        cur_key = sqlite3_column_text(db_statement, 0);
-        if (prev_key == NULL || strcmp(prev_key, cur_key) != 0) {
-            if (prev_key != NULL) {
-                Free(prev_key);
-                key_breaks[breaks_idx++] = row_idx;
-            }
-            prev_key = Calloc(strlen(cur_key) + 1, char);
-            strcpy(prev_key, cur_key);
-        }
-
-        for (j = 0; j < num_fields; j++) {
-            int null_item = (sqlite3_column_type(db_statement, j) == SQLITE_NULL);
-            switch(flds->Sclass[j]){
-            case INTSXP:
-                if(null_item)
-                    NA_SET(&(LST_INT_EL(output,j,row_idx)), INTSXP);
-                else
-                    LST_INT_EL(output,j,row_idx) =
-                        sqlite3_column_int(db_statement, j);
-                break;
-            case REALSXP:
-                if(null_item)
-                    NA_SET(&(LST_NUM_EL(output,j,row_idx)), REALSXP);
-                else
-                    LST_NUM_EL(output,j,row_idx) =
-                        sqlite3_column_double(db_statement, j);
-                break;
-            case STRSXP:
-                /* falls through */
-            default:
-                if(null_item)
-                    SET_LST_CHR_EL(output,j,row_idx, NA_STRING);
-                else
-                    SET_LST_CHR_EL(output,j,row_idx,
-                                   C_S_CPY(sqlite3_column_text(db_statement, j)));
-                break;
-            }
-        } /* end column loop */
-        row_idx++;
-        if (row_idx == num_rec) {  /* request satisfied or exhausted allocated space */
-            if (expand) {    /* do we extend or return the records fetched so far*/
-                key_breaks = (int *)S_realloc((char *)key_breaks, 2 * num_rec, num_rec,
-                                              sizeof(int));
-                num_rec = 2 * num_rec;
-                RS_DBI_allocOutput(output, flds, num_rec, expand);
-            }
-            else
-                break;       /* okay, no more fetching for now */
-        }
-        state = sqlite3_step(db_statement);
-        if (state != SQLITE_ROW && state != SQLITE_DONE) {
-            char errMsg[2048];
-            (void)sprintf(errMsg, "RS_SQLite_fetch: failed: %s",
-                          sqlite3_errmsg(sqlite3_db_handle(db_statement)));
-            RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-        }
-    } /* end row loop */
-    if (state == SQLITE_DONE) {
-        res->completed = (Sint) 1;
-    }
-    /* size to actual number of records fetched */
-    if(row_idx < num_rec){
-        num_rec = row_idx;
-        /* adjust the length of each of the members in the output_list */
-        for(j = 0; j<num_fields; j++){
-            s_tmp = LST_EL(output,j);
-            PROTECT(SET_LENGTH(s_tmp, num_rec));
-            SET_VECTOR_ELT(output, j, s_tmp);
-            UNPROTECT(1);
-        }
-    }
-    res->rowCount += num_rec;
-    key_breaks[breaks_idx++] = num_rec;
-    PROTECT(env = R_NewHashedEnv(R_NilValue));
-    for (j = 1; j < breaks_idx; j++) {
-        vlen = key_breaks[j] - key_breaks[j - 1];
-        s_tmp = LST_EL(output, 1);
-        PROTECT(vect = allocVector(TYPEOF(s_tmp), vlen));
-        for (i = 0; i < vlen; i++) {
-            switch (TYPEOF(vect)) {
-            case INTSXP:
-                INTEGER(vect)[i] = INTEGER(s_tmp)[key_breaks[j-1]+i];
-                break;
-            case REALSXP:
-                REAL(vect)[i] = REAL(s_tmp)[key_breaks[j-1]+i];
-                break;
-            case STRSXP:
-                SET_STRING_ELT(vect, i, STRING_ELT(s_tmp, key_breaks[j-1]+i));
-                break;
-            default:
-                error("unknown type");
-                break;
-            }
-        }
-        s_tmp = STRING_ELT(LST_EL(output, 0), key_breaks[j]-1);
-        defineVar(install(CHAR(s_tmp)), vect, env);
-        UNPROTECT(1);
-    }
-
-    if (prev_key)
-        Free(prev_key);
-    UNPROTECT(2);
-    return env;
-}
-#endif
-
-/* return a 2-elem list with the last exception number and exception message on a given connection.
- * NOTE: RS_SQLite_getException() is meant to be used mostly directory R.
- */
-SEXP 
-RS_SQLite_getException(SEXP conHandle)
-{
-    SEXP output;
-    RS_DBI_connection   *con = RS_DBI_getConnection(conHandle);
-    RS_SQLite_exception *err;
-    Sint  n = 2;
-    char *exDesc[] = {"errorNum", "errorMsg"};
-    Stype exType[] = {INTSXP, STRSXP};
-    Sint  exLen[]  = {1, 1};
-
-    if(!con->drvConnection)
-        RS_DBI_errorMessage("internal error: corrupt connection handle",
-                            RS_DBI_ERROR);
-    PROTECT(output = RS_DBI_createNamedList(exDesc, exType, exLen, n));
-    err = (RS_SQLite_exception *) con->drvData;
-    LST_INT_EL(output,0,0) = (Sint) err->errorNum;
-    SET_LST_CHR_EL(output,1,0,C_S_CPY(err->errorMsg));
-    UNPROTECT(1);
-    return output;
-}
-
-void RSQLite_closeResultSet0(RS_DBI_resultSet *result, RS_DBI_connection *con)
-{
-   if(result->drvResultSet == NULL)
-       RS_DBI_errorMessage("corrupt SQLite resultSet, missing statement handle",
-                           RS_DBI_ERROR);
-    RSQLite_freeResultSet0(result, con);
-}
-
-SEXP 
-RS_SQLite_closeResultSet(SEXP resHandle)
-{
-    RSQLite_closeResultSet0(RS_DBI_getResultSet(resHandle),
-                            RS_DBI_getConnection(resHandle));
-    /* The connection external ptr is stored within the result handle
-       so that an active result keeps the connection protected.  When
-       we close the result set, we remove the reference to the
-       connection so that the connection can be gc'd.
-     */
-    SET_VECTOR_ELT(R_ExternalPtrProtected(resHandle), 1, R_NilValue);
-    RES_ID(resHandle) = -1;
-    return ScalarLogical(1);
-}
-
-SEXP 
-RS_SQLite_managerInfo(Mgr_Handle mgrHandle)
-{
-    RS_DBI_manager *mgr;
-    SEXP output;
-    Sint i, num_con, max_con, *cons, ncon, *shared_cache;
-    Sint j, n = 9;
-    char *mgrDesc[] = {"drvName",   "connectionIds", "fetch_default_rec",
-                       "managerId", "length",        "num_con",
-                       "counter",   "clientVersion", "shared_cache"};
-    Stype mgrType[] = {STRSXP, INTSXP, INTSXP,
-                       INTSXP,   INTSXP, INTSXP,
-                       INTSXP,   STRSXP, STRSXP };
-    Sint  mgrLen[]  = {1, 1, 1, 1, 1, 1, 1, 1, 1};
-
-    mgr = RS_DBI_getManager(mgrHandle);
-    if(!mgr)
-        RS_DBI_errorMessage("driver not loaded yet", RS_DBI_ERROR);
-    num_con = (Sint) mgr->num_con;
-    max_con = (Sint) mgr->length;
-    shared_cache = (Sint *) mgr->drvData;
-    mgrLen[1] = num_con;
-
-    PROTECT(output = RS_DBI_createNamedList(mgrDesc, mgrType, mgrLen, n));
-    j = (Sint) 0;
-    if(mgr->drvName)
-        SET_LST_CHR_EL(output,j++,0,C_S_CPY(mgr->drvName));
-    else
-        SET_LST_CHR_EL(output,j++,0,C_S_CPY(""));
-
-    cons = (Sint *) S_alloc((long)max_con, (int)sizeof(Sint));
-    ncon = RS_DBI_listEntries(mgr->connectionIds, mgr->length, cons);
-    /* expecting ncon == 0 alwasy */
-    if(ncon != 0){
-        RS_DBI_errorMessage(
-            "internal error: corrupt RS_DBI connection table",
-            RS_DBI_ERROR);
-    }
-    for(i = 0; i < num_con; i++)
-        LST_INT_EL(output, j, i) = cons[i];
-    j++;
-    LST_INT_EL(output,j++,0) = mgr->fetch_default_rec;
-    LST_INT_EL(output,j++,0) = mgr->managerId;
-    LST_INT_EL(output,j++,0) = mgr->length;
-    LST_INT_EL(output,j++,0) = mgr->num_con;
-    LST_INT_EL(output,j++,0) = mgr->counter;
-    SET_LST_CHR_EL(output,j++,0,C_S_CPY(SQLITE_VERSION));
-    if(*shared_cache)
-        SET_LST_CHR_EL(output,j++,0,C_S_CPY("on"));
-    else
-        SET_LST_CHR_EL(output,j++,0,C_S_CPY("off"));
-    UNPROTECT(1);
-    return output;
-}
-
-SEXP 
-RSQLite_connectionInfo(Con_Handle conHandle)
-{
-    int info_count = 6, i = 0, nres;
-    RS_DBI_connection *con = RS_DBI_getConnection(conHandle);
-    RS_SQLite_conParams *params = (RS_SQLite_conParams *) con->conParams;
-    SEXP rsIds;
-
-    SEXP info = PROTECT(NEW_LIST(info_count));
-    SEXP info_nms = PROTECT(NEW_CHARACTER(info_count));
-    SET_NAMES(info, info_nms);
-    UNPROTECT(1);
-
-    SET_STRING_ELT(info_nms, i, mkChar("dbname"));
-    SET_VECTOR_ELT(info, i++, mkString(params->dbname));
-
-    SET_STRING_ELT(info_nms, i, mkChar("serverVersion"));
-    SET_VECTOR_ELT(info, i++, mkString(SQLITE_VERSION));
-
-    SET_STRING_ELT(info_nms, i, mkChar("rsId"));
-    rsIds = PROTECT(NEW_INTEGER(con->length));
-    nres = RS_DBI_listEntries(con->resultSetIds, con->length, INTEGER(rsIds));
-    SET_LENGTH(rsIds, nres);
-    SET_VECTOR_ELT(info, i++, rsIds);
-    UNPROTECT(1);
-
-    SET_STRING_ELT(info_nms, i, mkChar("loadableExtensions"));
-    SET_VECTOR_ELT(info, i++,
-                   mkString(params->loadable_extensions ? "on" : "off"));
-
-    SET_STRING_ELT(info_nms, i, mkChar("flags"));
-    SET_VECTOR_ELT(info, i++, ScalarInteger(params->flags));
-
-    SET_STRING_ELT(info_nms, i, mkChar("vfs"));
-    SET_VECTOR_ELT(info, i++, mkString(params->vfs));
-
-    UNPROTECT(1);
-    return info;
-}
-
-SEXP 
-RS_SQLite_resultSetInfo(Res_Handle rsHandle)
-{
-    RS_DBI_resultSet   *result;
-    SEXP output, flds;
-    Sint  n = 6;
-    char  *rsDesc[] = {"statement", "isSelect", "rowsAffected",
-                       "rowCount", "completed", "fieldDescription"};
-    Stype rsType[]  = {STRSXP, INTSXP, INTSXP,
-                       INTSXP,   INTSXP, LIST_TYPE};
-    Sint  rsLen[]   = {1, 1, 1, 1, 1, 1};
-
-    result = RS_DBI_getResultSet(rsHandle);
-    if(result->fields)
-        PROTECT(flds = RS_DBI_getFieldDescriptions(result->fields));
-    else
-        PROTECT(flds = S_NULL_ENTRY);
-
-    PROTECT(output = RS_DBI_createNamedList(rsDesc, rsType, rsLen, n));
-    SET_LST_CHR_EL(output,0,0,C_S_CPY(result->statement));
-    LST_INT_EL(output,1,0) = result->isSelect;
-    LST_INT_EL(output,2,0) = result->rowsAffected;
-    LST_INT_EL(output,3,0) = result->rowCount;
-    LST_INT_EL(output,4,0) = result->completed;
-    if(flds != S_NULL_ENTRY)
-        SET_VECTOR_ELT(LST_EL(output, 5), (Sint) 0, flds);
-
-    UNPROTECT(2);
-    return output;
-}
-
-SEXP 
-RS_SQLite_typeNames(SEXP typeIds)
-{
-    SEXP typeNames;
-    Sint n;
-    Sint *typeCodes;
-    int i;
-    char *s;
-
-    n = LENGTH(typeIds);
-    typeCodes = INTEGER_DATA(typeIds);
-    PROTECT(typeNames = NEW_CHARACTER(n));
-    for(i = 0; i < n; i++) {
-        s = RS_DBI_getTypeName(typeCodes[i], RS_SQLite_fieldTypes);
-        SET_CHR_EL(typeNames, i, C_S_CPY(s));
-    }
-    UNPROTECT(1);
-    return typeNames;
-}
-
-SEXP     /* returns TRUE/FALSE */
-RS_SQLite_importFile(
-    Con_Handle conHandle,
-    SEXP s_tablename,
-    SEXP s_filename,
-    SEXP s_separator,
-    SEXP s_eol,
-    SEXP s_skip
-    )
-{
-    RS_DBI_connection *con = RS_DBI_getConnection(conHandle);
-    sqlite3           *db_connection = (sqlite3 *) con->drvConnection;
-    char              *zFile, *zTable, *zSep, *zEol;
-    const char *s, *s1;
-    Sint              rc, skip;
-    SEXP output;
-
-    s = CHR_EL(s_tablename, 0);
-    zTable = (char *) malloc( strlen(s)+1);
-    if(!zTable){
-        RS_DBI_errorMessage("could not allocate memory", RS_DBI_ERROR);
-    }
-    (void) strcpy(zTable, s);
-
-    s = CHR_EL(s_filename, 0);
-    zFile = (char *) malloc( strlen(s)+1);
-    if(!zFile){
-        free(zTable);
-        RS_DBI_errorMessage("could not allocate memory", RS_DBI_ERROR);
-    }
-    (void) strcpy(zFile, s);
-
-    s = CHR_EL(s_separator, 0);
-    s1 = CHR_EL(s_eol, 0);
-    zSep = (char *) malloc( strlen(s)+1);
-    zEol = (char *) malloc(strlen(s1)+1);
-    if(!zSep || !zEol){
-        free(zTable);
-        free(zFile);
-        if(zSep) free(zSep);
-        if(zEol) free(zEol);
-        RS_DBI_errorMessage("could not allocate memory", RS_DBI_ERROR);
-    }
-    (void) strcpy(zSep, s);
-    (void) strcpy(zEol, s1);
-    skip = (Sint) INT_EL(s_skip, 0);
-
-    rc = RS_sqlite_import(db_connection, zTable, zFile, zSep, zEol, skip);
-
-    free(zTable);
-    free(zFile);
-    free(zSep);
-
-    PROTECT(output = NEW_LOGICAL((Sint) 1));
-    LOGICAL_POINTER(output)[0] = rc;
-    UNPROTECT(1);
-    return output;
-}
-
-/* The following code comes directly from SQLite's shell.c, with
- * obvious minor changes.
- */
-int
-RS_sqlite_import(
-    sqlite3 *db,
-    const char *zTable,          /* table must already exist */
-    const char *zFile,
-    const char *separator,
-    const char *eol,
-    Sint skip
-    )
-{
-    sqlite3_stmt *pStmt;        /* A statement */
-    int rc;                     /* Result code */
-    int nCol;                   /* Number of columns in the table */
-    int nByte;                  /* Number of bytes in an SQL string */
-    int i, j;                   /* Loop counters */
-    int nSep;                   /* Number of bytes in separator[] */
-    char *zSql;                 /* An SQL statement */
-    char *zLine = NULL;         /* A single line of input from the file */
-    char **azCol;               /* zLine[] broken up into columns */
-    char *zCommit;              /* How to commit changes */
-    FILE *in;                   /* The input file */
-    int lineno = 0;             /* Line number of input file */
-    char errMsg[512];
-    char *z;
-
-    nSep = strlen(separator);
-    if( nSep==0 ){
-        RS_DBI_errorMessage(
-            "RS_sqlite_import: non-null separator required for import",
-            RS_DBI_ERROR);
-    }
-    zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
-    if( zSql==0 ) return 0;
-    nByte = strlen(zSql);
-    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
-    sqlite3_free(zSql);
-    if (rc != SQLITE_OK) {
-        sqlite3_finalize(pStmt);
-        (void) sprintf(errMsg, "RS_sqlite_import: %s", sqlite3_errmsg(db));
-        RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-        nCol = 0;
-    }else{
-        nCol = sqlite3_column_count(pStmt);
-    }
-    sqlite3_finalize(pStmt);
-    if( nCol==0 ) return 0;
-    zSql = malloc( nByte + 20 + nCol*2 );
-    if( zSql==0 ) return 0;
-    sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable);
-    j = strlen(zSql);
-    for(i=1; i<nCol; i++){
-        zSql[j++] = ',';
-        zSql[j++] = '?';
-    }
-    zSql[j++] = ')';
-    zSql[j] = 0;
-    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
-    free(zSql);
-    if (rc != SQLITE_OK) {
-        sqlite3_finalize(pStmt);
-        (void) sprintf(errMsg, "RS_sqlite_import: %s", sqlite3_errmsg(db));
-        RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-    }
-    in = fopen(zFile, "rb");
-    if( in==0 ){
-        (void) sprintf(errMsg, "RS_sqlite_import: cannot open file %s", zFile);
-        sqlite3_finalize(pStmt);
-        RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-    }
-    azCol = malloc( sizeof(azCol[0])*(nCol+1) );
-    if( azCol==0 ) return 0;
-    sqlite3_exec(db, "BEGIN", 0, 0, 0);
-    zCommit = "COMMIT";
-    while( (zLine = RS_sqlite_getline(in, eol)) != NULL){
-        lineno++;
-        if(lineno <= skip) continue;
-        i = 0;
-        azCol[0] = zLine;
-        for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){
-            if( *z==separator[0] && strncmp(z, separator, nSep)==0 ){
-                *z = 0;
-                i++;
-                if( i<nCol ){
-                    azCol[i] = &z[nSep];
-                    z += nSep-1;
-                }
-            }
-        }
-        if( i+1!=nCol ){
-            (void) sprintf(errMsg,
-                           "RS_sqlite_import: %s line %d expected %d columns of data but found %d",
-                           zFile, lineno, nCol, i+1);
-            zCommit = "ROLLBACK";
-            break;
-        }
-
-        for(i=0; i<nCol; i++){
-            if(azCol[i][0]=='\\' && azCol[i][1]=='N'){   /* insert NULL for NA */
-                sqlite3_bind_null(pStmt, i+1);
-            }
-            else {
-                sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
-            }
-        }
-
-        rc = sqlite3_step(pStmt);
-        if (rc != SQLITE_DONE && rc != SQLITE_SCHEMA) {
-            sqlite3_finalize(pStmt);
-            (void) sprintf(errMsg, "RS_sqlite_import: %s", sqlite3_errmsg(db));
-            RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-        }
-        rc = sqlite3_reset(pStmt);
-        free(zLine);
-        zLine = NULL;
-        if (rc != SQLITE_OK) {
-            sqlite3_finalize(pStmt);
-            (void) sprintf(errMsg,"RS_sqlite_import: %s", sqlite3_errmsg(db));
-            zCommit = "ROLLBACK";
-            break;
-        }
-    }
-    free(azCol);
-    fclose(in);
-    sqlite3_finalize(pStmt);
-    sqlite3_exec(db, zCommit, 0, 0, 0);
-    if (strcmp(zCommit, "ROLLBACK") == 0) {
-        RS_DBI_errorMessage(errMsg, RS_DBI_ERROR);
-    }
-    return 1;
-}
-
-/* the following is only needed (?) on windows (getline is a GNU extension
- * and it gave me problems with minGW).  Note that we drop the (UNIX)
- * new line character.  The R function safe.write() explicitly uses
- * eol = '\n' even on Windows.
- */
-
-char *
-RS_sqlite_getline(FILE *in, const char *eol)
-{
-    /* caller must free memory */
-    char *buf, ceol;
-    size_t nc, i;
-    int c, j, neol;
-    int found_eol = 0;
-
-    nc = 1024; i = 0;
-    buf = (char *) malloc(nc);
-    if(!buf)
-        RS_DBI_errorMessage("RS_sqlite_getline could not malloc", RS_DBI_ERROR);
-
-    neol = strlen(eol);  /* num of eol chars */
-    ceol = eol[neol-1];  /* last char in eol */
-    while(TRUE){
-        c=fgetc(in);
-        if(i==nc){
-            nc = 2 * nc;
-            buf = (char *) realloc((void *) buf, nc);
-            if(!buf)
-                RS_DBI_errorMessage(
-                    "RS_sqlite_getline could not realloc", RS_DBI_ERROR);
-        }
-        if(c==EOF)
-            break;
-        buf[i++] = c;
-        if (c == ceol) {
-            /* see if we've got eol */
-            found_eol = 1;
-            for (j = neol - 1; j > 0; j--) {
-                if (buf[(i - 1) - j] != eol[neol - 1 - j]) {
-                    found_eol = 0;
-                    break;
-                }
-            }
-            if (found_eol) {
-                buf[i-neol] = '\0';   /* drop the newline char(s) */
-                break;
-            }
-        }
-    }
-
-    if (i == 0 || strlen(buf) == 0) {    /* empty line */
-        free(buf);
-        buf = (char *) NULL;
-    }
-
-    return buf;
-}
-
-SEXP RS_SQLite_copy_database(Con_Handle fromConHandle, Con_Handle toConHandle)
-{
-    sqlite3_backup *backup = NULL;
-    RS_DBI_connection *fromCon = RS_DBI_getConnection(fromConHandle);
-    RS_DBI_connection *toCon = RS_DBI_getConnection(toConHandle);
-    sqlite3 *dbFrom = (sqlite3 *)fromCon->drvConnection;
-    sqlite3 *dbTo = (sqlite3 *)toCon->drvConnection;
-    int rc = 0;
-
-    backup = sqlite3_backup_init(dbTo, "main", dbFrom, "main");
-    if (backup) {
-        sqlite3_backup_step(backup, -1);
-        sqlite3_backup_finish(backup);
-    }
-    rc = sqlite3_errcode(dbTo);
-    if (rc != SQLITE_OK) {
-        RS_SQLite_setException(toCon, rc, sqlite3_errmsg(dbTo));
-        RS_DBI_errorMessage(sqlite3_errmsg(dbTo), RS_DBI_ERROR);
-    }
-    return R_NilValue;
-}
diff --git a/src/RS-SQLite.h b/src/RS-SQLite.h
deleted file mode 100644
index 0774403..0000000
--- a/src/RS-SQLite.h
+++ /dev/null
@@ -1,188 +0,0 @@
-#ifndef _RS_SQLite_H
-#define _RS_SQLite_H 1
-/*
- * $Id$
- *
- * Copyright (C) 1999-2002 The Omega Project for Statistical Computing.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifdef _cplusplus
-extern  "C" {
-#endif
-
-#include "sqlite.h"
-
-#include <string.h>
-#include <unistd.h>   /* needed by getlogin() -- is this portable??? */
-
-#include "RS-DBI.h"
-
-/* These control the open mode for new connections and
-   are mapped to the appropriate SQLite flag.
- */
-#define RSQLITE_RWC 0
-#define RSQLITE_RW  1
-#define RSQLITE_RO  2
-
-/* SQLite connection parameters struct, allocating and freeing
- * methods.  This is pretty simple, since SQLite does not recognise users
- * TODO: SQLite 3.0 api allows for key/value strings.
- */
-typedef struct st_sdbi_conParams {
-  char *dbname;
-  int  loadable_extensions;
-  int  flags;
-  char *vfs;
-} RS_SQLite_conParams;
-
-typedef struct st_sqlite_err {
-   int  errorNum;
-   char *errorMsg;
-} RS_SQLite_exception;
-
-
-#define RSQLITE_MSG(msg, err_type) DBI_MSG(msg, err_type, "RSQLite")
-
-RS_SQLite_conParams *RS_SQLite_allocConParams(const char *dbname,
-                                              int loadable_extensions,
-                                              int flags, const char *vfs);
-
-void                RS_SQLite_freeConParams(RS_SQLite_conParams *conParams);
-
-/* Convert declared column type string to SQLite column type.
- * For example, "varchar" => SQLITE_TEXT
- *
- */
-int                 SQLite_decltype_to_type(const char *decltype);
-
-/* The following functions are the S/R entry into the C implementation (i.e.,
- * these are the only ones visible from R/S) we use the prefix "RS_SQLite" in
- * function names to denote this.  These functions are  built on top of the
- * underlying RS_DBI manager, connection, and resultsets structures and
- * functions (see RS-DBI.h).
- *
- * Note: A handle is just an R/S object (see RS-DBI.h for details), i.e.,
- * Mgr_Handle, Con_Handle, Res_Handle, Db_Handle are s_object.
- */
-
-/* dbManager */
-Mgr_Handle RS_SQLite_init(SEXP config_params, SEXP reload,
-                           SEXP cache);
-SEXP RS_SQLite_close(Mgr_Handle mgrHandle);
-
-/* dbConnection */
-Con_Handle RS_SQLite_newConnection(Mgr_Handle mgrHandle, SEXP dbfile,
-                                   SEXP allow_ext, SEXP s_flags, SEXP s_vfs);
-Con_Handle RS_SQLite_cloneConnection(Con_Handle conHandle);
-SEXP RS_SQLite_closeConnection(Con_Handle conHandle);
-/* we simulate db exceptions ourselves */
-void        RS_SQLite_setException(RS_DBI_connection *con, int errorNum,
-                                   const char *errorMsg);
-SEXP RS_SQLite_getException(Con_Handle conHandle);
-/* err No, Msg */
-
-/* currently we only provide a "standard" callback to sqlite_exec() -- this
- * callback collects all the rows and puts them in a cache in the results set
- * (res->drvData) to simulate a cursor so that we can fetch() like in any other
- * driver.  Other interesting callbacks should allow us to easily implement the
- * dbApply() ideas also in the RMySQL driver
- */
-int       RS_SQLite_stdCallback(void *resHandle, int ncol, char **row,
-                                char **colNames);
-
-/* dbResultSet */
-Res_Handle RS_SQLite_exec(Con_Handle conHandle, SEXP statement,
-                           SEXP bind_data);
-SEXP RS_SQLite_fetch(Res_Handle rsHandle, SEXP max_rec);
-SEXP RS_SQLite_closeResultSet(Res_Handle rsHandle);
-void        RS_SQLite_initFields(RS_DBI_resultSet *res, int ncol,
-                                 char **colNames);
-
-SEXP RS_SQLite_validHandle(Db_Handle handle);      /* boolean */
-
-RS_DBI_fields *RS_SQLite_createDataMappings(Res_Handle resHandle);
-
-/* the following funs return named lists with meta-data for
- * the manager, connections, and  result sets, respectively.
- */
-SEXP RS_SQLite_managerInfo(Mgr_Handle mgrHandle);
-SEXP RSQLite_connectionInfo(Con_Handle conHandle);
-SEXP RS_SQLite_resultSetInfo(Res_Handle rsHandle);
-
-/*  The following imports the delim-fields of a file into an existing table*/
-SEXP RS_SQLite_importFile(Con_Handle conHandle, SEXP s_tablename,
-             SEXP s_filename, SEXP s_separator, SEXP s_obj,
-             SEXP s_skip);
-
-SEXP RS_SQLite_copy_database(Con_Handle fromConHandle, Con_Handle toConHandle);
-
-/* TODO: general connection */
-char * RS_sqlite_getline(FILE *in, const char *eol);
-
-/* the following type names should be the  SQL-92 data types, and should
- * be moved to the RS-DBI.h
- */
-enum SQL92_field_types {
-     SQL92_TYPE_NULL,
-     SQL92_TYPE_BIT,
-     SQL92_TYPE_BIT_VAR,
-     SQL92_TYPE_CHAR,
-     SQL92_TYPE_CHAR_VAR,
-     SQL92_TYPE_NCHAR,
-     SQL92_TYPE_NCHAR_VAR,
-     SQL92_TYPE_SMALLINT,
-     SQL92_TYPE_INTEGER,
-     SQL92_TYPE_DECIMAL,
-     SQL92_TYPE_FLOAT,
-     SQL92_TYPE_REAL,
-     SQL92_TYPE_DOUBLE,
-     SQL92_TYPE_TIMESTAMP,
-     SQL92_TYPE_DATE,
-     SQL92_TYPE_TIME,
-     SQL92_TYPE_DATETIME,
-     SQLns_TYPE_BLOB
-};
-
-const struct data_types RS_SQLite_fieldTypes[] = {
-     { "SQL92_TYPE_NULL",       SQL92_TYPE_NULL     },
-     { "SQL92_TYPE_BIT",        SQL92_TYPE_BIT      },
-     { "SQL92_TYPE_BIT_VAR",    SQL92_TYPE_BIT_VAR  },
-     { "SQL92_TYPE_CHAR",       SQL92_TYPE_CHAR     },
-     { "SQL92_TYPE_CHAR_VAR",   SQL92_TYPE_CHAR_VAR },
-     { "SQL92_TYPE_NCHAR",      SQL92_TYPE_NCHAR    },
-     { "SQL92_TYPE_NCHAR_VAR",  SQL92_TYPE_NCHAR_VAR},
-     { "SQL92_TYPE_SMALLINT",   SQL92_TYPE_SMALLINT },
-     { "SQL92_TYPE_INTEGER",    SQL92_TYPE_INTEGER  },
-     { "SQL92_TYPE_DECIMAL",    SQL92_TYPE_DECIMAL  },
-     { "SQL92_TYPE_FLOAT",      SQL92_TYPE_FLOAT    },
-     { "SQL92_TYPE_REAL",       SQL92_TYPE_REAL     },
-     { "SQL92_TYPE_DOUBLE",     SQL92_TYPE_DOUBLE   },
-     { "SQL92_TYPE_TIMESTAMP",  SQL92_TYPE_TIMESTAMP},
-     { "SQL92_TYPE_DATE",       SQL92_TYPE_DATE     },
-     { "SQL92_TYPE_TIME",       SQL92_TYPE_TIME     },
-     { "SQL92_TYPE_DATETIME",   SQL92_TYPE_DATETIME },
-     { "SQLns_TYPE_DATETIME",   SQLns_TYPE_BLOB     },
-     { (char *) 0,              -1                  }
-};
-
-SEXP RS_SQLite_typeNames(SEXP typeIds);
-
-#ifdef _cplusplus
-}
-#endif
-
-#endif   /* _RS_SQLite_H */
diff --git a/src/Rhelpers.h b/src/Rhelpers.h
deleted file mode 100644
index 84af0a8..0000000
--- a/src/Rhelpers.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Convenience macros for R programming
- *
- */
-
-#ifndef RHELPERS_H
-#define RHELPERS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Some of these come from MASS, some from packages developed under
- * the Omega project, and some from RS-DBI itself.
- */
-
-#  include "Rversion.h"
-
-#  include "Rdefines.h"
-#  include "S.h"
-#  define singl double
-#  define Sint  int
-#  define charPtr SEXP *
-#  define C_S_CPY(p)    COPY_TO_USER_STRING(p)    /* cpy C string to R */
-
-/* The following are macros defined in the Green Book, but missing
- * in Rdefines.h.  The semantics are as close to S4's as possible (?).
- */
-
-#  define COPY(x) duplicate(x)                  
-#  define COPY_ALL(x) duplicate(x)               
-#  define EVAL_IN_FRAME(expr,n)  eval(expr,n)     
-#  define GET_FROM_FRAME(name,n) findVar(install(name),n)
-#  define ASSIGN_IN_FRAME(name,obj,n) defineVar(install(name),COPY(obj),n)
-
-
-/* data types common to R and S4 */
-
-#  define Stype          SEXPTYPE
-#  define LOGICAL_TYPE	 LGLSXP
-#  define INTEGER_TYPE	 INTSXP
-#  define NUMERIC_TYPE	 REALSXP
-#  define SINGLE_TYPE    REALSXP
-#  define REAL_TYPE      REALSXP
-#  define CHARACTER_TYPE STRSXP
-#  define STRING_TYPE    STRSXP
-#  define COMPLEX_TYPE	 CPLXSXP
-#  define LIST_TYPE	 VECSXP
-
-#  define S_NULL_ENTRY R_NilValue
-
-/* We simplify one- and two-level access to object and list
- * (mostly built on top of jmc's macros)
- *
- * NOTE: Recall that list element vectors should *not* be set 
- * directly, but only thru SET_ELEMENT (Green book, Appendix A), e.g.,
- *      LIST_POINTER(x)[i] = NEW_CHARACTER(100);    BAD!!
- *      LST_EL(x,i) = NEW_CHARACTER(100);           BAD!!
- *      SET_ELEMENT(x, i, NEW_CHARACTER(100));      Okay
- *
- * It's okay to directly set the i'th element of the j'th list element:
- *      LST_CHR_EL(x,i,j) = C_S_CPY(str);           Okay (but not in R-1.2.1)
- *
- * For R >= 1.2.0 define
- *      SET_LST_CHR_EL(x,i,j,val)
- */
-
-/* x[i] */
-#define LGL_EL(x,i) LOGICAL_POINTER((x))[(i)]
-#define INT_EL(x,i) INTEGER_POINTER((x))[(i)]
-#define SGL_EL(x,i) SINGLE_POINTER((x))[(i)]
-#define FLT_EL(x,i) SGL_EL((x),(i))
-#define NUM_EL(x,i) NUMERIC_POINTER((x))[(i)]
-#define DBL_EL(x,i) NUM_EL((x),(i))
-#define RAW_EL(x,i) RAW_POINTER((x))[(i)]
-#if defined(R_VERSION) && R_VERSION >= R_Version(1,2,0) 
-#  define LST_EL(x,i) VECTOR_ELT((x),(i))
-#  define CHR_EL(x,i) CHAR(STRING_ELT((x),(i)))
-#  define SET_CHR_EL(x,i,val)  SET_STRING_ELT((x),(i), (val))
-#endif
-
-/* x[[i]][j] -- can be also assigned if x[[i]] is a numeric type */
-#define LST_CHR_EL(x,i,j) CHR_EL(LST_EL((x),(i)), (j))
-#define LST_LGL_EL(x,i,j) LGL_EL(LST_EL((x),(i)), (j))
-#define LST_INT_EL(x,i,j) INT_EL(LST_EL((x),(i)), (j))
-#define LST_SGL_EL(x,i,j) SGL_EL(LST_EL((x),(i)), (j))
-#define LST_FLT_EL(x,i,j) LST_SGL_EL((x),(i),(j))
-#define LST_NUM_EL(x,i,j) NUM_EL(LST_EL((x),(i)), (j))
-#define LST_DBL_EL(x,i,j) LST_NUM_EL((x),(i),(j))
-#define LST_RAW_EL(x,i,j) RAW_EL(LST_EL((x),(i)), (j))
-#define LST_LST_EL(x,i,j) LST_EL(LST_EL((x),(i)), (j))
-
-/* x[[i]][j] -- for the case when x[[i]] is a character type */
-#if defined(R_VERSION) && R_VERSION >= R_Version(1,2,0) 
-#  define SET_LST_CHR_EL(x,i,j,val) SET_STRING_ELT(LST_EL(x,i), j, val)
-#else   
-#  define SET_LST_CHR_EL(x,i,j,val) (CHR_EL(LST_EL(x,i),j)=val)
-#endif
-
-/* setting and querying NA's -- in the case of R, we need to
- * use our own RS_na_set and RS_is_na functions (these need work!)
- */
-
-#  define NA_SET(p,t)   RS_na_set((p),(t))
-#  define NA_CHR_SET(p) SET_CHR_EL(p, 0, NA_STRING)
-#  define IS_NA(p,t)    RS_is_na((p),(t))
-
-
-/* SET_ROWNAMES() and SET_CLASS_NAME() don't exist in S4 
- */
-#  define SET_ROWNAMES(df,n)  setAttrib(df, R_RowNamesSymbol, n)
-#  define GET_CLASS_NAME(x)   GET_CLASS(x)
-#  define SET_CLASS_NAME(x,n) SET_CLASS(x, n)
-
-/* end of RS-DBI macros */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* RHELPERS_H */
diff --git a/src/connection.c b/src/connection.c
new file mode 100644
index 0000000..284f8f9
--- /dev/null
+++ b/src/connection.c
@@ -0,0 +1,149 @@
+/* 
+ * Copyright (C) 1999-2002 The Omega Project for Statistical Computing
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "rsqlite.h"
+
+static void _finalize_connection_handle(SEXP xp) {
+  if (!R_ExternalPtrAddr(xp)) return;
+
+  rsqlite_connection_destroy(xp);
+}
+
+SQLiteConnection* rsqlite_connection_from_handle(SEXP handle) {
+  SQLiteConnection* con = (SQLiteConnection*) R_ExternalPtrAddr(handle);
+  if (!con)
+    error("expired SQLiteConnection");
+
+  return con;
+}
+
+SEXP rsqlite_connection_create(SEXP dbname_, SEXP allow_ext_, SEXP flags_,
+                    SEXP vfs_) {
+  const char* dbname = CHAR(asChar(dbname_));
+
+  if (!isLogical(allow_ext_)) {
+    error("'allow_ext' must be TRUE or FALSE");
+  }
+  int allow_ext = asLogical(allow_ext_);
+  if (allow_ext == NA_LOGICAL)
+    error("'allow_ext' must be TRUE or FALSE, not NA");
+
+  if (!isInteger(flags_)) {
+    error("'flags' must be integer");
+  }
+  int flags = asInteger(flags_);
+
+  const char* vfs = NULL;
+  if (!isNull(vfs_)) {
+    vfs = CHAR(asChar(vfs_));
+    if (strlen(vfs) == 0) vfs = NULL;
+  }
+
+  // Create external pointer to connection object
+  SQLiteConnection* con = malloc(sizeof(SQLiteConnection));
+  if (con == NULL) {
+    error("could not malloc dbConnection");
+  }
+  con->exception = NULL;
+  con->resultSet = NULL;
+
+  // Initialise SQLite3 database connection
+  sqlite3* db_connection;
+  int rc = sqlite3_open_v2(dbname, &db_connection, flags, vfs);
+  if (rc != SQLITE_OK) {
+    error("Could not connect to database:\n%s", sqlite3_errmsg(db_connection));
+  }
+  if (allow_ext) {
+    sqlite3_enable_load_extension(db_connection, 1);
+  }
+  con->drvConnection = db_connection;
+
+  // Finally, update connection table in driver
+  SQLiteDriver* driver = rsqlite_driver();
+  driver->num_con += 1;
+  driver->counter += 1;
+
+  rsqlite_exception_set(con, SQLITE_OK, "OK");
+
+  // Create handle
+  SEXP handle = R_MakeExternalPtr(con, R_NilValue, R_NilValue);
+  R_RegisterCFinalizerEx(handle, _finalize_connection_handle, 1);
+  return handle;
+}
+
+
+SEXP rsqlite_connection_destroy(SEXP handle) {
+  SQLiteConnection* con = rsqlite_connection_from_handle(handle);
+
+  // close & free result set (if open)
+  if (con->resultSet) {
+    warning("Closing open result set");
+    rsqlite_result_free(con);
+  }
+
+  // close & free db connection
+  sqlite3* db_connection = con->drvConnection;
+  int rc = sqlite3_close(db_connection);  /* it also frees db_connection */
+  if (rc == SQLITE_BUSY) {
+    warning("Unfinalized prepared statements.");
+  } else if (rc != SQLITE_OK) {
+    warning("Internal error: could not close SQLte connection.");
+  }
+  con->drvConnection = NULL;
+  rsqlite_exception_free(con);
+
+  // update driver connection table
+  SQLiteDriver* drv = rsqlite_driver();
+  drv->num_con -= 1;
+
+  free(con);
+  con = NULL;
+  R_ClearExternalPtr(handle);
+
+  return ScalarLogical(1);
+}
+
+SEXP rsqlite_connection_valid(SEXP dbObj) {
+  SQLiteConnection* con = R_ExternalPtrAddr(dbObj);
+
+  if (!con)
+    return ScalarLogical(0);
+  if (!con->drvConnection)
+    return ScalarLogical(0);
+
+  return ScalarLogical(1);
+}
+
+SEXP rsqlite_connection_info(SEXP conHandle) {
+  SQLiteConnection* con = rsqlite_connection_from_handle(conHandle);
+
+  SEXP info = PROTECT(allocVector(VECSXP, 2));
+  SEXP info_nms = PROTECT(allocVector(STRSXP, 2));
+  SET_NAMES(info, info_nms);
+  UNPROTECT(1);
+
+  int i = 0;
+  SET_STRING_ELT(info_nms, i, mkChar("serverVersion"));
+  SET_VECTOR_ELT(info, i++, mkString(SQLITE_VERSION));
+
+  SET_STRING_ELT(info_nms, i, mkChar("results"));
+  SET_VECTOR_ELT(info, i++, ScalarLogical(con->resultSet != NULL));
+
+  UNPROTECT(1);
+  return info;
+}
diff --git a/src/driver.c b/src/driver.c
new file mode 100644
index 0000000..c444d70
--- /dev/null
+++ b/src/driver.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 1999-2003 The Omega Project for Statistical Computing.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "rsqlite.h"
+
+char* compiledVersion = SQLITE_VERSION;
+
+// Driver ----------------------------------------------------------------------
+
+static SQLiteDriver* dbManager = NULL;
+
+SQLiteDriver* rsqlite_driver() {
+  if (!dbManager) error("Corrupt dbManager handle.");
+  return dbManager;
+}
+
+void rsqlite_driver_init(SEXP records_, SEXP cache_) {
+  if (dbManager) return; // Already allocated
+
+  const char* clientVersion = sqlite3_libversion();
+  if (strcmp(clientVersion, compiledVersion)) {
+    error("SQLite mismatch between compiled version %s and runtime version %s",
+        compiledVersion, clientVersion
+    );
+  }
+
+  dbManager = malloc(sizeof(SQLiteDriver));
+  if (!dbManager) {
+    error("could not malloc the dbManger");
+  }
+
+  dbManager->counter = 0;
+  dbManager->num_con = 0;
+  dbManager->fetch_default_rec = asInteger(records_);
+
+  if (asLogical(cache_)) {
+    dbManager->shared_cache = 1;
+    sqlite3_enable_shared_cache(1);
+  } else {
+    dbManager->shared_cache = 0;
+  }
+
+  return;
+}
+
+SEXP rsqlite_driver_close() {
+  SQLiteDriver* mgr = rsqlite_driver();
+  if (mgr->num_con) {
+    error("Open connections -- close them first");
+  }
+  sqlite3_enable_shared_cache(0);
+
+  return ScalarLogical(1);
+}
+
+
+SEXP rsqlite_driver_valid() {
+  if (!rsqlite_driver()) return ScalarLogical(0);
+
+  return ScalarLogical(1);
+}
+
+
+SEXP rsqlite_driver_info() {
+  SQLiteDriver* mgr = rsqlite_driver();
+
+  SEXP info = PROTECT(allocVector(VECSXP, 5));
+  SEXP info_nms = PROTECT(allocVector(STRSXP, 5));
+  SET_NAMES(info, info_nms);
+  UNPROTECT(1);
+
+  int i = 0;
+  SET_STRING_ELT(info_nms, i, mkChar("fetch_default_rec"));
+  SET_VECTOR_ELT(info, i++, ScalarInteger(mgr->fetch_default_rec));
+
+  SET_STRING_ELT(info_nms, i, mkChar("num_con"));
+  SET_VECTOR_ELT(info, i++, ScalarInteger(mgr->num_con));
+
+  SET_STRING_ELT(info_nms, i, mkChar("counter"));
+  SET_VECTOR_ELT(info, i++, ScalarInteger(mgr->counter));
+
+  SET_STRING_ELT(info_nms, i, mkChar("clientVersion"));
+  SET_VECTOR_ELT(info, i++, mkString(SQLITE_VERSION));
+
+  SET_STRING_ELT(info_nms, i, mkChar("shared_cache"));
+  SET_VECTOR_ELT(info, i++, ScalarLogical(mgr->shared_cache));
+
+  UNPROTECT(1);
+  return info;
+}
diff --git a/src/exceptions.c b/src/exceptions.c
new file mode 100644
index 0000000..82cab01
--- /dev/null
+++ b/src/exceptions.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 1999-2003 The Omega Project for Statistical Computing.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "rsqlite.h"
+
+void rsqlite_exception_set(SQLiteConnection* con, int err_no, const char* err_msg) {
+
+  RSQLiteException* ex = con->exception;
+  if (!ex) {
+    // Create new exception object
+    ex = malloc(sizeof(RSQLiteException));
+    if (!ex) {
+      error("could not allocate SQLite exception object");
+    }
+  } else {
+    // Reuse existing
+    free(ex->errorMsg);
+  }
+
+  ex->errorNum = err_no;
+  if (err_msg) {
+    ex->errorMsg = RS_DBI_copyString(err_msg);
+  } else {
+    ex->errorMsg = NULL;
+  }
+
+  con->exception = ex;
+  return;
+}
+
+void rsqlite_exception_free(SQLiteConnection* con) {
+  RSQLiteException* ex = con->exception;
+
+  if (!ex)
+    return;
+  if (ex->errorMsg)
+    free(ex->errorMsg);
+  free(ex);
+
+  con->exception = NULL;
+  return;
+}
+
+SEXP rsqlite_exception_info(SEXP handle) {
+  SQLiteConnection* con = rsqlite_connection_from_handle(handle);
+  if (!con->drvConnection)
+    error("internal error: corrupt connection handle");
+
+  RSQLiteException* err = con->exception;
+
+  SEXP output = PROTECT(allocVector(VECSXP, 2));
+  SEXP output_nms = PROTECT(allocVector(STRSXP, 2));
+  SET_NAMES(output, output_nms);
+  UNPROTECT(1);
+
+  SET_STRING_ELT(output_nms, 0, mkChar("errorNum"));
+  SET_VECTOR_ELT(output, 0, ScalarInteger(err->errorNum));
+
+  SET_STRING_ELT(output_nms, 1, mkChar("errorMsg"));
+  SET_VECTOR_ELT(output, 1, mkString(err->errorMsg));
+
+  UNPROTECT(1);
+  return output;
+}
diff --git a/src/extension-functions.c b/src/extension-functions.c
new file mode 100644
index 0000000..f79a344
--- /dev/null
+++ b/src/extension-functions.c
@@ -0,0 +1,1938 @@
+/*
+This library will provide common mathematical and string functions in
+SQL queries using the operating system libraries or provided
+definitions.  It includes the following functions:
+
+Math: acos, asin, atan, atn2, atan2, acosh, asinh, atanh, difference,
+degrees, radians, cos, sin, tan, cot, cosh, sinh, tanh, coth, exp,
+log, log10, power, sign, sqrt, square, ceil, floor, pi.
+
+String: replicate, charindex, leftstr, rightstr, ltrim, rtrim, trim,
+replace, reverse, proper, padl, padr, padc, strfilter.
+
+Aggregate: stdev, variance, mode, median, lower_quartile,
+upper_quartile.
+
+The string functions ltrim, rtrim, trim, replace are included in
+recent versions of SQLite and so by default do not build.
+
+Compilation instructions:
+ Compile this C source file into a dynamic library as follows:
+ * Linux:
+   gcc -fPIC -lm -shared extension-functions.c -o libsqlitefunctions.so
+ * Mac OS X:
+   gcc -fno-common -dynamiclib extension-functions.c -o libsqlitefunctions.dylib
+ (You may need to add flags
+  -I /opt/local/include/ -L/opt/local/lib -lsqlite3
+  if your sqlite3 is installed from Mac ports, or
+  -I /sw/include/ -L/sw/lib -lsqlite3
+  if installed with Fink.)
+ * Windows:
+  1. Install MinGW (http://www.mingw.org/) and you will get the gcc
+  (gnu compiler collection)
+  2. add the path to your path variable (isn't done during the
+   installation!)
+  3. compile:
+   gcc -shared -I "path" -o libsqlitefunctions.so extension-functions.c
+   (path = path of sqlite3ext.h; i.e. C:\programs\sqlite)
+
+Usage instructions for applications calling the sqlite3 API functions:
+  In your application, call sqlite3_enable_load_extension(db,1) to
+  allow loading external libraries.  Then load the library libsqlitefunctions
+  using sqlite3_load_extension; the third argument should be 0.
+  See http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions.
+  Select statements may now use these functions, as in
+  SELECT cos(radians(inclination)) FROM satsum WHERE satnum = 25544;
+
+Usage instructions for the sqlite3 program:
+  If the program is built so that loading extensions is permitted,
+  the following will work:
+   sqlite> SELECT load_extension('./libsqlitefunctions.so');
+   sqlite> select cos(radians(45));
+   0.707106781186548
+  Note: Loading extensions is by default prohibited as a
+  security measure; see "Security Considerations" in
+  http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions.
+  If the sqlite3 program and library are built this
+  way, you cannot use these functions from the program, you 
+  must write your own program using the sqlite3 API, and call
+  sqlite3_enable_load_extension as described above, or else
+  rebuilt the sqlite3 program to allow loadable extensions.
+
+Alterations:
+The instructions are for Linux, Mac OS X, and Windows; users of other
+OSes may need to modify this procedure.  In particular, if your math
+library lacks one or more of the needed trig or log functions, comment
+out the appropriate HAVE_ #define at the top of file.  If you do not
+wish to make a loadable module, comment out the define for
+COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE.  If you are using a
+version of SQLite without the trim functions and replace, comment out
+the HAVE_TRIM #define.
+
+Liam Healy
+
+History:
+2010-01-06 Correct check for argc in squareFunc, and add Windows
+compilation instructions.
+2009-06-24 Correct check for argc in properFunc.
+2008-09-14 Add check that memory was actually allocated after
+sqlite3_malloc or sqlite3StrDup, call sqlite3_result_error_nomem if
+not.  Thanks to Robert Simpson.
+2008-06-13 Change to instructions to indicate use of the math library
+and that program might work.
+2007-10-01 Minor clarification to instructions.
+2007-09-29 Compilation as loadable module is optional with
+COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE.
+2007-09-28 Use sqlite3_extension_init and macros
+SQLITE_EXTENSION_INIT1, SQLITE_EXTENSION_INIT2, so that it works with
+sqlite3_load_extension.  Thanks to Eric Higashino and Joe Wilson.
+New instructions for Mac compilation.
+2007-09-17 With help from Joe Wilson and Nuno Luca, made use of
+external interfaces so that compilation is no longer dependent on
+SQLite source code.  Merged source, header, and README into a single
+file.  Added casts so that Mac will compile without warnings (unsigned
+and signed char).
+2007-09-05 Included some definitions from sqlite 3.3.13 so that this
+will continue to work in newer versions of sqlite.  Completed
+description of functions available.
+2007-03-27 Revised description.
+2007-03-23 Small cleanup and a bug fix on the code.  This was mainly
+letting errno flag errors encountered in the math library and checking
+the result, rather than pre-checking.  This fixes a bug in power that
+would cause an error if any non-positive number was raised to any
+power.
+2007-02-07 posted by Mikey C to sqlite mailing list.
+Original code 2006 June 05 by relicoder.
+
+*/
+
+//#include "config.h"
+
+#define COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE 1
+#define HAVE_ACOSH 1
+#define HAVE_ASINH 1
+#define HAVE_ATANH 1
+#define HAVE_SINH 1
+#define HAVE_COSH 1
+#define HAVE_TANH 1
+#define HAVE_LOG10 1
+#define HAVE_ISBLANK 1
+#define SQLITE_SOUNDEX 1
+#define HAVE_TRIM 1		/* LMH 2007-03-25 if sqlite has trim functions */
+
+#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE
+#include "sqlite/sqlite3ext.h"
+SQLITE_EXTENSION_INIT1
+#else
+#include "sqlite3.h"
+#endif
+
+#include <ctype.h>
+/* relicoder */
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>		/* LMH 2007-03-25 */
+
+#include <stdlib.h>
+#include <assert.h>
+
+#ifndef _MAP_H_
+#define _MAP_H_
+
+#include <stdint.h>
+
+/*
+** Simple binary tree implementation to use in median, mode and quartile calculations
+** Tree is not necessarily balanced. That would require something like red&black trees of AVL
+*/
+
+typedef int(*cmp_func)(const void *, const void *);
+typedef void(*map_iterator)(void*, int64_t, void*);
+
+typedef struct node{
+  struct node *l;
+  struct node *r;
+  void* data;
+  int64_t count;
+} node;
+
+typedef struct map{
+  node *base;
+  cmp_func cmp;
+} map;
+
+/*
+** creates a map given a comparison function
+*/
+map map_make(cmp_func cmp);
+
+/*
+** inserts the element e into map m
+*/
+void map_insert(map *m, void *e);
+
+/*
+** executes function iter over all elements in the map, in key increasing order
+*/
+void map_iterate(map *m, map_iterator iter, void* p);
+
+/*
+** frees all memory used by a map
+*/
+void map_destroy(map *m);
+
+/*
+** compares 2 integers
+** to use with map_make
+*/
+int int_cmp(const void *a, const void *b);
+
+/*
+** compares 2 doubles
+** to use with map_make
+*/
+int double_cmp(const void *a, const void *b);
+
+#endif /* _MAP_H_ */
+
+typedef uint8_t         u8;
+typedef uint16_t        u16;
+typedef int64_t         i64;
+
+static char *sqlite3StrDup( const char *z ) {
+    char *res = sqlite3_malloc( strlen(z)+1 );
+    return strcpy( res, z );
+}
+
+/*
+** These are copied verbatim from fun.c so as to not have the names exported
+*/
+
+/* LMH from sqlite3 3.3.13 */
+/*
+** This table maps from the first byte of a UTF-8 character to the number
+** of trailing bytes expected. A value '4' indicates that the table key
+** is not a legal first byte for a UTF-8 character.
+*/
+static const u8 xtra_utf8_bytes[256]  = {
+/* 0xxxxxxx */
+0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
+
+/* 10wwwwww */
+4, 4, 4, 4, 4, 4, 4, 4,     4, 4, 4, 4, 4, 4, 4, 4,
+4, 4, 4, 4, 4, 4, 4, 4,     4, 4, 4, 4, 4, 4, 4, 4,
+4, 4, 4, 4, 4, 4, 4, 4,     4, 4, 4, 4, 4, 4, 4, 4,
+4, 4, 4, 4, 4, 4, 4, 4,     4, 4, 4, 4, 4, 4, 4, 4,
+
+/* 110yyyyy */
+1, 1, 1, 1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1,     1, 1, 1, 1, 1, 1, 1, 1,
+
+/* 1110zzzz */
+2, 2, 2, 2, 2, 2, 2, 2,     2, 2, 2, 2, 2, 2, 2, 2,
+
+/* 11110yyy */
+3, 3, 3, 3, 3, 3, 3, 3,     4, 4, 4, 4, 4, 4, 4, 4,
+};
+
+
+/*
+** This table maps from the number of trailing bytes in a UTF-8 character
+** to an integer constant that is effectively calculated for each character
+** read by a naive implementation of a UTF-8 character reader. The code
+** in the READ_UTF8 macro explains things best.
+*/
+static const int xtra_utf8_bits[] =  {
+  0,
+  12416,          /* (0xC0 << 6) + (0x80) */
+  925824,         /* (0xE0 << 12) + (0x80 << 6) + (0x80) */
+  63447168        /* (0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80 */
+};
+
+/*
+** If a UTF-8 character contains N bytes extra bytes (N bytes follow
+** the initial byte so that the total character length is N+1) then
+** masking the character with utf8_mask[N] must produce a non-zero
+** result.  Otherwise, we have an (illegal) overlong encoding.
+*/
+static const int utf_mask[] = {
+  0x00000000,
+  0xffffff80,
+  0xfffff800,
+  0xffff0000,
+};
+
+/* LMH salvaged from sqlite3 3.3.13 source code src/utf.c */
+#define READ_UTF8(zIn, c) { \
+  int xtra;                                            \
+  c = *(zIn)++;                                        \
+  xtra = xtra_utf8_bytes[c];                           \
+  switch( xtra ){                                      \
+    case 4: c = (int)0xFFFD; break;                    \
+    case 3: c = (c<<6) + *(zIn)++;                     \
+    case 2: c = (c<<6) + *(zIn)++;                     \
+    case 1: c = (c<<6) + *(zIn)++;                     \
+    c -= xtra_utf8_bits[xtra];                         \
+    if( (utf_mask[xtra]&c)==0                          \
+        || (c&0xFFFFF800)==0xD800                      \
+        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }    \
+  }                                                    \
+}
+
+static int sqlite3ReadUtf8(const unsigned char *z){
+  int c;
+  READ_UTF8(z, c);
+  return c;
+}
+
+#define SKIP_UTF8(zIn) {                               \
+  zIn += (xtra_utf8_bytes[*(u8 *)zIn] + 1);            \
+}
+
+/*
+** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
+** return the number of unicode characters in pZ up to (but not including)
+** the first 0x00 byte. If nByte is not less than zero, return the
+** number of unicode characters in the first nByte of pZ (or up to 
+** the first 0x00, whichever comes first).
+*/
+static int sqlite3Utf8CharLen(const char *z, int nByte){
+  int r = 0;
+  const char *zTerm;
+  if( nByte>=0 ){
+    zTerm = &z[nByte];
+  }else{
+    zTerm = (const char *)(-1);
+  }
+  assert( z<=zTerm );
+  while( *z!=0 && z<zTerm ){
+    SKIP_UTF8(z);
+    r++;
+  }
+  return r;
+}
+
+/*
+** X is a pointer to the first byte of a UTF-8 character.  Increment
+** X so that it points to the next character.  This only works right
+** if X points to a well-formed UTF-8 string.
+*/
+#define sqliteNextChar(X)  while( (0xc0&*++(X))==0x80 ){}
+#define sqliteCharVal(X)   sqlite3ReadUtf8(X)
+
+/*
+** This is a macro that facilitates writting wrappers for math.h functions
+** it creates code for a function to use in SQlite that gets one numeric input
+** and returns a floating point value.
+**
+** Could have been implemented using pointers to functions but this way it's inline
+** and thus more efficient. Lower * ranking though...
+** 
+** Parameters:
+** name:      function name to de defined (eg: sinFunc)
+** function:  function defined in math.h to wrap (eg: sin)
+** domain:    boolean condition that CAN'T happen in terms of the input parameter rVal
+**            (eg: rval<0 for sqrt)
+*/
+/* LMH 2007-03-25 Changed to use errno and remove domain; no pre-checking for errors. */
+#define GEN_MATH_WRAP_DOUBLE_1(name, function) \
+static void name(sqlite3_context *context, int argc, sqlite3_value **argv){\
+  double rVal = 0.0, val;\
+  assert( argc==1 );\
+  switch( sqlite3_value_type(argv[0]) ){\
+    case SQLITE_NULL: {\
+      sqlite3_result_null(context);\
+      break;\
+    }\
+    default: {\
+      rVal = sqlite3_value_double(argv[0]);\
+      errno = 0;\
+      val = function(rVal);\
+      if (errno == 0) {\
+        sqlite3_result_double(context, val);\
+      } else {\
+        sqlite3_result_error(context, strerror(errno), errno);\
+      }\
+      break;\
+    }\
+  }\
+}\
+
+
+/*
+** Example of GEN_MATH_WRAP_DOUBLE_1 usage
+** this creates function sqrtFunc to wrap the math.h standard function sqrt(x)=x^0.5
+*/
+GEN_MATH_WRAP_DOUBLE_1(sqrtFunc, sqrt)
+
+/* trignometric functions */
+GEN_MATH_WRAP_DOUBLE_1(acosFunc, acos)
+GEN_MATH_WRAP_DOUBLE_1(asinFunc, asin)
+GEN_MATH_WRAP_DOUBLE_1(atanFunc, atan)
+
+/*
+** Many of systems don't have inverse hyperbolic trig functions so this will emulate
+** them on those systems in terms of log and sqrt (formulas are too trivial to demand 
+** written proof here)
+*/
+
+#ifndef HAVE_ACOSH
+static double acosh(double x){
+  return log(x + sqrt(x*x - 1.0));
+}
+#endif
+
+GEN_MATH_WRAP_DOUBLE_1(acoshFunc, acosh)
+
+#ifndef HAVE_ASINH
+static double asinh(double x){
+  return log(x + sqrt(x*x + 1.0));
+}
+#endif
+
+GEN_MATH_WRAP_DOUBLE_1(asinhFunc, asinh)
+
+#ifndef HAVE_ATANH
+static double atanh(double x){
+  return (1.0/2.0)*log((1+x)/(1-x)) ;
+}
+#endif
+
+GEN_MATH_WRAP_DOUBLE_1(atanhFunc, atanh)
+
+/*
+** math.h doesn't require cot (cotangent) so it's defined here
+*/
+static double cot(double x){
+  return 1.0/tan(x);
+}
+
+GEN_MATH_WRAP_DOUBLE_1(sinFunc, sin)
+GEN_MATH_WRAP_DOUBLE_1(cosFunc, cos)
+GEN_MATH_WRAP_DOUBLE_1(tanFunc, tan)
+GEN_MATH_WRAP_DOUBLE_1(cotFunc, cot)
+
+static double coth(double x){
+  return 1.0/tanh(x);
+}
+
+/*
+** Many systems don't have hyperbolic trigonometric functions so this will emulate
+** them on those systems directly from the definition in terms of exp
+*/
+#ifndef HAVE_SINH
+static double sinh(double x){
+  return (exp(x)-exp(-x))/2.0;
+}
+#endif
+
+GEN_MATH_WRAP_DOUBLE_1(sinhFunc, sinh)
+
+#ifndef HAVE_COSH
+static double cosh(double x){
+  return (exp(x)+exp(-x))/2.0;
+}
+#endif
+
+GEN_MATH_WRAP_DOUBLE_1(coshFunc, cosh)
+
+#ifndef HAVE_TANH
+static double tanh(double x){
+  return sinh(x)/cosh(x);
+}
+#endif
+
+GEN_MATH_WRAP_DOUBLE_1(tanhFunc, tanh)
+
+GEN_MATH_WRAP_DOUBLE_1(cothFunc, coth)
+
+/*
+** Some systems lack log in base 10. This will emulate it
+*/
+
+#ifndef HAVE_LOG10
+static double log10(double x){
+  static double l10 = -1.0;
+  if( l10<0.0 ){
+    l10 = log(10.0);
+  }
+  return log(x)/l10;
+}
+#endif
+
+GEN_MATH_WRAP_DOUBLE_1(logFunc, log)
+GEN_MATH_WRAP_DOUBLE_1(log10Func, log10)
+GEN_MATH_WRAP_DOUBLE_1(expFunc, exp)
+
+/*
+** Fallback for systems where math.h doesn't define M_PI
+*/
+#undef M_PI
+#ifndef M_PI
+/*
+** static double PI = acos(-1.0);
+** #define M_PI (PI)
+*/
+#define M_PI 3.14159265358979323846
+#endif
+
+/* Convert Degrees into Radians */
+static double deg2rad(double x){
+  return x*M_PI/180.0;
+}
+
+/* Convert Radians into Degrees */
+static double rad2deg(double x){
+  return 180.0*x/M_PI;
+}
+
+GEN_MATH_WRAP_DOUBLE_1(rad2degFunc, rad2deg)
+GEN_MATH_WRAP_DOUBLE_1(deg2radFunc, deg2rad)
+
+/* constant function that returns the value of PI=3.1415... */
+static void piFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  sqlite3_result_double(context, M_PI);
+}
+
+/*
+** Implements the sqrt function, it has the peculiarity of returning an integer when the
+** the argument is an integer.
+** Since SQLite isn't strongly typed (almost untyped actually) this is a bit pedantic
+*/
+static void squareFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  i64 iVal = 0;
+  double rVal = 0.0;
+  assert( argc==1 );
+  switch( sqlite3_value_type(argv[0]) ){
+    case SQLITE_INTEGER: {
+      iVal = sqlite3_value_int64(argv[0]);
+      sqlite3_result_int64(context, iVal*iVal);
+      break;
+    }
+    case SQLITE_NULL: {
+      sqlite3_result_null(context);
+      break;
+    }
+    default: {
+      rVal = sqlite3_value_double(argv[0]);
+      sqlite3_result_double(context, rVal*rVal);
+      break;
+    }
+  }
+}
+
+/*
+** Wraps the pow math.h function
+** When both the base and the exponent are integers the result should be integer
+** (see sqrt just before this). Here the result is always double
+*/
+/* LMH 2007-03-25 Changed to use errno; no pre-checking for errors.  Also removes
+  but that was present in the pre-checking that called sqlite3_result_error on 
+  a non-positive first argument, which is not always an error. */
+static void powerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  double r1 = 0.0;
+  double r2 = 0.0;
+  double val;
+
+  assert( argc==2 );
+  
+  if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){
+    sqlite3_result_null(context); 
+  }else{
+    r1 = sqlite3_value_double(argv[0]);
+    r2 = sqlite3_value_double(argv[1]);
+    errno = 0;
+    val = pow(r1,r2);
+    if (errno == 0) {
+      sqlite3_result_double(context, val);
+    } else {  
+      sqlite3_result_error(context, strerror(errno), errno);
+    }  
+  }
+}
+
+/*
+** atan2 wrapper
+*/
+static void atn2Func(sqlite3_context *context, int argc, sqlite3_value **argv){
+  double r1 = 0.0;
+  double r2 = 0.0;
+
+  assert( argc==2 );
+  
+  if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){
+    sqlite3_result_null(context); 
+  }else{
+    r1 = sqlite3_value_double(argv[0]);
+    r2 = sqlite3_value_double(argv[1]);
+    sqlite3_result_double(context, atan2(r1,r2));
+  }
+}
+
+/*
+** Implementation of the sign() function
+** return one of 3 possibilities +1,0 or -1 when the argument is respectively
+** positive, 0 or negative.
+** When the argument is NULL the result is also NULL (completly conventional)
+*/
+static void signFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  double rVal=0.0;
+  i64 iVal=0;
+  assert( argc==1 );
+  switch( sqlite3_value_type(argv[0]) ){
+    case SQLITE_INTEGER: {
+      iVal = sqlite3_value_int64(argv[0]);
+      iVal = ( iVal > 0) ? 1: ( iVal < 0 ) ? -1: 0;
+      sqlite3_result_int64(context, iVal);
+      break;
+    }
+    case SQLITE_NULL: {
+      sqlite3_result_null(context);
+      break;
+    }
+    default: {
+ /* 2nd change below. Line for abs was: if( rVal<0 ) rVal = rVal * -1.0;  */
+
+      rVal = sqlite3_value_double(argv[0]);
+      rVal = ( rVal > 0) ? 1: ( rVal < 0 ) ? -1: 0;
+      sqlite3_result_double(context, rVal);
+      break;
+    }
+  }
+}
+
+
+/*
+** smallest integer value not less than argument
+*/
+static void ceilFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  double rVal=0.0;
+  assert( argc==1 );
+  switch( sqlite3_value_type(argv[0]) ){
+    case SQLITE_INTEGER: {
+      i64 iVal = sqlite3_value_int64(argv[0]);
+      sqlite3_result_int64(context, iVal);
+      break;
+    }
+    case SQLITE_NULL: {
+      sqlite3_result_null(context);
+      break;
+    }
+    default: {
+      rVal = sqlite3_value_double(argv[0]);
+      sqlite3_result_int64(context, (i64) ceil(rVal));
+      break;
+    }
+  }
+}
+
+/*
+** largest integer value not greater than argument
+*/
+static void floorFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  double rVal=0.0;
+  assert( argc==1 );
+  switch( sqlite3_value_type(argv[0]) ){
+    case SQLITE_INTEGER: {
+      i64 iVal = sqlite3_value_int64(argv[0]);
+      sqlite3_result_int64(context, iVal);
+      break;
+    }
+    case SQLITE_NULL: {
+      sqlite3_result_null(context);
+      break;
+    }
+    default: {
+      rVal = sqlite3_value_double(argv[0]);
+      sqlite3_result_int64(context, (i64) floor(rVal));
+      break;
+    }
+  }
+}
+
+/*
+** Given a string (s) in the first argument and an integer (n) in the second returns the 
+** string that constains s contatenated n times
+*/
+static void replicateFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  unsigned char *z;        /* input string */
+  unsigned char *zo;       /* result string */
+  i64 iCount;              /* times to repeat */
+  i64 nLen;                /* length of the input string (no multibyte considerations) */ 
+  i64 nTLen;               /* length of the result string (no multibyte considerations) */
+  i64 i=0;
+
+  if( argc!=2 || SQLITE_NULL==sqlite3_value_type(argv[0]) )
+    return;
+
+  iCount = sqlite3_value_int64(argv[1]);
+
+  if( iCount<0 ){
+    sqlite3_result_error(context, "domain error", -1);
+  }else{
+
+    nLen  = sqlite3_value_bytes(argv[0]);
+    nTLen = nLen*iCount;
+    z=sqlite3_malloc(nTLen+1);
+    zo=sqlite3_malloc(nLen+1);
+    if (!z || !zo){
+      sqlite3_result_error_nomem(context);
+      if (z) sqlite3_free(z);
+      if (zo) sqlite3_free(zo);
+      return;
+    }
+    strcpy((char*)zo, (char*)sqlite3_value_text(argv[0]));
+
+    for(i=0; i<iCount; ++i){
+      strcpy((char*)(z+i*nLen), (char*)zo);
+    }
+
+    sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT);
+    sqlite3_free(z);
+    sqlite3_free(zo);
+  }
+}
+
+/* 
+** Some systems (win32 among others) don't have an isblank function, this will emulate it.
+** This function is not UFT-8 safe since it only analyses a byte character.
+*/
+#ifndef HAVE_ISBLANK
+int isblank(char c){
+  return( ' '==c || '\t'==c );
+}
+#endif
+
+static void properFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  const unsigned char *z;     /* input string */
+  unsigned char *zo;          /* output string */
+  unsigned char *zt;          /* iterator */
+  char r;
+  int c=1;
+
+  assert( argc==1);
+  if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){
+    sqlite3_result_null(context);
+    return;
+  }
+
+  z = sqlite3_value_text(argv[0]);
+  zo = (unsigned char *)sqlite3StrDup((char *) z);
+  if (!zo) {
+    sqlite3_result_error_nomem(context);
+    return;
+  }
+  zt = zo;
+
+  while( (r = *(z++))!=0 ){
+    if( isblank(r) ){
+      c=1;
+    }else{
+      if( c==1 ){
+        r = toupper(r);
+      }else{
+        r = tolower(r);
+      }
+      c=0;
+    }
+    *(zt++) = r;
+  }
+  *zt = '\0';
+
+  sqlite3_result_text(context, (char*)zo, -1, SQLITE_TRANSIENT);
+  sqlite3_free(zo);
+}
+
+/*
+** given an input string (s) and an integer (n) adds spaces at the begining of  s
+** until it has a length of n characters.
+** When s has a length >=n it's a NOP
+** padl(NULL) = NULL
+*/
+static void padlFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  i64 ilen;          /* length to pad to */
+  i64 zl;            /* length of the input string (UTF-8 chars) */
+  int i = 0;
+  const char *zi;    /* input string */
+  char *zo;          /* output string */
+  char *zt;
+
+  assert( argc==2 );
+  
+  if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){
+    sqlite3_result_null(context); 
+  }else{
+    zi = (char *)sqlite3_value_text(argv[0]);
+    ilen = sqlite3_value_int64(argv[1]);
+    /* check domain */
+    if(ilen<0){
+      sqlite3_result_error(context, "domain error", -1);
+      return;
+    }
+    zl = sqlite3Utf8CharLen(zi, -1);
+    if( zl>=ilen ){
+      /* string is longer than the requested pad length, return the same string (dup it) */
+      zo = sqlite3StrDup(zi);
+      if (!zo){
+        sqlite3_result_error_nomem(context);
+        return;
+      }
+      sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
+    }else{
+      zo = sqlite3_malloc(strlen(zi)+ilen-zl+1);
+      if (!zo){
+        sqlite3_result_error_nomem(context);
+        return;
+      }
+      zt = zo;
+      for(i=1; i+zl<=ilen; ++i){
+        *(zt++)=' ';
+      }
+      /* no need to take UTF-8 into consideration here */
+      strcpy(zt,zi);
+    }
+    sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
+    sqlite3_free(zo);
+  }
+}
+
+/*
+** given an input string (s) and an integer (n) appends spaces at the end of  s
+** until it has a length of n characters.
+** When s has a length >=n it's a NOP
+** padl(NULL) = NULL
+*/
+static void padrFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  i64 ilen;          /* length to pad to */
+  i64 zl;            /* length of the input string (UTF-8 chars) */
+  i64 zll;           /* length of the input string (bytes) */
+  int i = 0;
+  const char *zi;    /* input string */
+  char *zo;          /* output string */
+  char *zt;
+
+  assert( argc==2 );
+  
+  if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){
+    sqlite3_result_null(context); 
+  }else{
+    zi = (char *)sqlite3_value_text(argv[0]);
+    ilen = sqlite3_value_int64(argv[1]);
+    /* check domain */
+    if(ilen<0){
+      sqlite3_result_error(context, "domain error", -1);
+      return;
+    }
+    zl = sqlite3Utf8CharLen(zi, -1);
+    if( zl>=ilen ){
+      /* string is longer than the requested pad length, return the same string (dup it) */
+      zo = sqlite3StrDup(zi);
+      if (!zo){
+        sqlite3_result_error_nomem(context);
+        return;
+      }
+      sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
+    }else{
+      zll = strlen(zi);
+      zo = sqlite3_malloc(zll+ilen-zl+1);
+      if (!zo){
+        sqlite3_result_error_nomem(context);
+        return;
+      }
+      zt = strcpy(zo,zi)+zll;
+      for(i=1; i+zl<=ilen; ++i){
+        *(zt++) = ' ';
+      }
+      *zt = '\0';
+    }
+    sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
+    sqlite3_free(zo);
+  }
+}
+
+/*
+** given an input string (s) and an integer (n) appends spaces at the end of  s
+** and adds spaces at the begining of s until it has a length of n characters.
+** Tries to add has many characters at the left as at the right.
+** When s has a length >=n it's a NOP
+** padl(NULL) = NULL
+*/
+static void padcFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  i64 ilen;           /* length to pad to */
+  i64 zl;             /* length of the input string (UTF-8 chars) */
+  i64 zll;            /* length of the input string (bytes) */
+  int i = 0;
+  const char *zi;     /* input string */
+  char *zo;           /* output string */
+  char *zt;
+
+  assert( argc==2 );
+  
+  if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){
+    sqlite3_result_null(context); 
+  }else{
+    zi = (char *)sqlite3_value_text(argv[0]);
+    ilen = sqlite3_value_int64(argv[1]);
+    /* check domain */
+    if(ilen<0){
+      sqlite3_result_error(context, "domain error", -1);
+      return;
+    }
+    zl = sqlite3Utf8CharLen(zi, -1);
+    if( zl>=ilen ){
+      /* string is longer than the requested pad length, return the same string (dup it) */
+      zo = sqlite3StrDup(zi);
+      if (!zo){
+        sqlite3_result_error_nomem(context);
+        return;
+      }
+      sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
+    }else{
+      zll = strlen(zi);
+      zo = sqlite3_malloc(zll+ilen-zl+1);
+      if (!zo){
+        sqlite3_result_error_nomem(context);
+        return;
+      }
+      zt = zo;
+      for(i=1; 2*i+zl<=ilen; ++i){
+        *(zt++) = ' ';
+      }
+      strcpy(zt, zi);
+      zt+=zll;
+      for(; i+zl<=ilen; ++i){
+        *(zt++) = ' ';
+      }
+      *zt = '\0';
+    }
+    sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
+    sqlite3_free(zo);
+  }
+}
+
+/*
+** given 2 string (s1,s2) returns the string s1 with the characters NOT in s2 removed
+** assumes strings are UTF-8 encoded
+*/
+static void strfilterFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  const char *zi1;        /* first parameter string (searched string) */
+  const char *zi2;        /* second parameter string (vcontains valid characters) */
+  const char *z1;
+  const char *z21;
+  const char *z22;
+  char *zo;               /* output string */
+  char *zot;
+  int c1 = 0;
+  int c2 = 0;
+
+  assert( argc==2 );
+  
+  if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){
+    sqlite3_result_null(context); 
+  }else{
+    zi1 = (char *)sqlite3_value_text(argv[0]);
+    zi2 = (char *)sqlite3_value_text(argv[1]);
+    /* 
+    ** maybe I could allocate less, but that would imply 2 passes, rather waste 
+    ** (possibly) some memory
+    */
+    zo = sqlite3_malloc(strlen(zi1)+1); 
+    if (!zo){
+      sqlite3_result_error_nomem(context);
+      return;
+    }
+    zot = zo;
+    z1 = zi1;
+    while( (c1=sqliteCharVal((unsigned char *)z1))!=0 ){
+      z21=zi2;
+      while( (c2=sqliteCharVal((unsigned char *)z21))!=0 && c2!=c1 ){
+        sqliteNextChar(z21);
+      }
+      if( c2!=0){
+        z22=z21;
+        sqliteNextChar(z22);
+        strncpy(zot, z21, z22-z21);
+        zot+=z22-z21;
+      }
+      sqliteNextChar(z1);
+    }
+    *zot = '\0';
+
+    sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
+    sqlite3_free(zo);
+  }
+}
+
+/*
+** Given a string z1, retutns the (0 based) index of it's first occurence
+** in z2 after the first s characters.
+** Returns -1 when there isn't a match.
+** updates p to point to the character where the match occured.
+** This is an auxiliary function.
+*/
+static int _substr(const char* z1, const char* z2, int s, const char** p){
+  int c = 0;
+  int rVal=-1;
+  const char* zt1;
+  const char* zt2;
+  int c1,c2;
+
+  if( '\0'==*z1 ){
+    return -1;
+  }
+  
+  while( (sqliteCharVal((unsigned char *)z2) != 0) && (c++)<s){
+    sqliteNextChar(z2);
+  }
+  
+  c = 0;
+  while( (sqliteCharVal((unsigned char *)z2)) != 0 ){
+    zt1 = z1;
+    zt2 = z2;
+
+    do{
+      c1 = sqliteCharVal((unsigned char *)zt1);
+      c2 = sqliteCharVal((unsigned char *)zt2);
+      sqliteNextChar(zt1);
+      sqliteNextChar(zt2);
+    }while( c1 == c2 && c1 != 0 && c2 != 0 );
+
+    if( c1 == 0 ){
+      rVal = c;
+      break; 
+    }
+    
+    sqliteNextChar(z2);
+    ++c;
+  }
+  if(p){
+    *p=z2;
+  }
+  return rVal >=0 ? rVal+s : rVal;
+}
+
+/*
+** given 2 input strings (s1,s2) and an integer (n) searches from the nth character
+** for the string s1. Returns the position where the match occured.
+** Characters are counted from 1.
+** 0 is returned when no match occurs.
+*/
+
+static void charindexFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  const u8 *z1;          /* s1 string */
+  u8 *z2;                /* s2 string */
+  int s=0;
+  int rVal=0;
+
+  assert( argc==3 ||argc==2);
+
+  if( SQLITE_NULL==sqlite3_value_type(argv[0]) || SQLITE_NULL==sqlite3_value_type(argv[1])){
+    sqlite3_result_null(context);
+    return;
+  }
+
+  z1 = sqlite3_value_text(argv[0]);
+  if( z1==0 ) return;
+  z2 = (u8*) sqlite3_value_text(argv[1]);
+  if(argc==3){
+    s = sqlite3_value_int(argv[2])-1;
+    if(s<0){
+      s=0;
+    }
+  }else{
+    s = 0;
+  }
+
+  rVal = _substr((char *)z1,(char *)z2,s,NULL);
+  sqlite3_result_int(context, rVal+1);
+}
+
+/*
+** given a string (s) and an integer (n) returns the n leftmost (UTF-8) characters
+** if the string has a length<=n or is NULL this function is NOP
+*/
+static void leftFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  int c=0;
+  int cc=0;
+  int l=0;
+  const unsigned char *z;       /* input string */
+  const unsigned char *zt;
+  unsigned char *rz;            /* output string */
+
+  assert( argc==2);
+
+  if( SQLITE_NULL==sqlite3_value_type(argv[0]) || SQLITE_NULL==sqlite3_value_type(argv[1])){
+    sqlite3_result_null(context);
+    return;
+  }
+
+  z  = sqlite3_value_text(argv[0]);
+  l  = sqlite3_value_int(argv[1]);
+  zt = z;
+
+  while( sqliteCharVal(zt) && c++<l)
+    sqliteNextChar(zt);
+
+  cc=zt-z;
+
+  rz = sqlite3_malloc(zt-z+1);
+  if (!rz){
+    sqlite3_result_error_nomem(context);
+    return;
+  }
+  strncpy((char*) rz, (char*) z, zt-z);
+  *(rz+cc) = '\0';
+  sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT); 
+  sqlite3_free(rz);
+}
+
+/*
+** given a string (s) and an integer (n) returns the n rightmost (UTF-8) characters
+** if the string has a length<=n or is NULL this function is NOP
+*/
+static void rightFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  int l=0;
+  int c=0;
+  int cc=0;
+  const char *z;
+  const char *zt;
+  const char *ze;
+  char *rz;
+
+  assert( argc==2);
+
+  if( SQLITE_NULL == sqlite3_value_type(argv[0]) || SQLITE_NULL == sqlite3_value_type(argv[1])){
+    sqlite3_result_null(context);
+    return;
+  }
+
+  z  = (char *)sqlite3_value_text(argv[0]);
+  l  = sqlite3_value_int(argv[1]);
+  zt = z;
+
+  while( sqliteCharVal((unsigned char *)zt)!=0){
+    sqliteNextChar(zt);
+    ++c;
+  }
+
+  ze = zt;
+  zt = z;
+
+  cc=c-l;
+  if(cc<0)
+    cc=0;
+  
+  while( cc-- > 0 ){
+    sqliteNextChar(zt);
+  }
+
+  rz = sqlite3_malloc(ze-zt+1);
+  if (!rz){
+    sqlite3_result_error_nomem(context);
+    return;
+  }
+  strcpy((char*) rz, (char*) (zt));
+  sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT); 
+  sqlite3_free(rz);
+}
+
+#ifndef HAVE_TRIM
+/*
+** removes the whitespaces at the begining of a string.
+*/
+const char* ltrim(const char* s){
+  while( *s==' ' )
+    ++s;
+  return s;
+}
+
+/*
+** removes the whitespaces at the end of a string.
+** !mutates the input string!
+*/
+void rtrim(char* s){
+  char* ss = s+strlen(s)-1;
+  while( ss>=s && *ss==' ' )
+    --ss;
+  *(ss+1)='\0';
+}
+
+/*
+**  Removes the whitespace at the begining of a string
+*/
+static void ltrimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  const char *z;
+
+  assert( argc==1);
+
+  if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){
+    sqlite3_result_null(context);
+    return;
+  }
+  z = sqlite3_value_text(argv[0]);
+  sqlite3_result_text(context, ltrim(z), -1, SQLITE_TRANSIENT); 
+}
+
+/*
+**  Removes the whitespace at the end of a string
+*/
+static void rtrimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  const char *z;
+  char *rz;
+  /* try not to change data in argv */
+
+  assert( argc==1);
+
+  if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){
+    sqlite3_result_null(context);
+    return;
+  }
+  z = sqlite3_value_text(argv[0]);
+  rz = sqlite3StrDup(z);
+  rtrim(rz);
+  sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT);
+  sqlite3_free(rz);
+}
+
+/*
+**  Removes the whitespace at the begining and end of a string
+*/
+static void trimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  const char *z;
+  char *rz;
+  /* try not to change data in argv */
+
+  assert( argc==1);
+
+  if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){
+    sqlite3_result_null(context);
+    return;
+  }
+  z = sqlite3_value_text(argv[0]);
+  rz = sqlite3StrDup(z);
+  rtrim(rz);
+  sqlite3_result_text(context, ltrim(rz), -1, SQLITE_TRANSIENT);
+  sqlite3_free(rz);
+}
+#endif
+
+/*
+** given a pointer to a string s1, the length of that string (l1), a new string (s2)
+** and it's length (l2) appends s2 to s1.
+** All lengths in bytes.
+** This is just an auxiliary function
+*/
+// static void _append(char **s1, int l1, const char *s2, int l2){
+//   *s1 = realloc(*s1, (l1+l2+1)*sizeof(char));
+//   strncpy((*s1)+l1, s2, l2);
+//   *(*(s1)+l1+l2) = '\0';
+// }
+
+#ifndef HAVE_TRIM
+
+/*
+** given strings s, s1 and s2 replaces occurrences of s1 in s by s2
+*/
+static void replaceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  const char *z1;     /* string s (first parameter) */
+  const char *z2;     /* string s1 (second parameter) string to look for */
+  const char *z3;     /* string s2 (third parameter) string to replace occurrences of s1 with */
+  int lz1;
+  int lz2;
+  int lz3;
+  int lzo=0;
+  char *zo=0;
+  int ret=0;
+  const char *zt1;
+  const char *zt2;
+
+  assert( 3==argc );
+
+  if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){
+    sqlite3_result_null(context);
+    return;
+  }
+
+  z1 = sqlite3_value_text(argv[0]);
+  z2 = sqlite3_value_text(argv[1]);
+  z3 = sqlite3_value_text(argv[2]);
+  /* handle possible null values */
+  if( 0==z2 ){
+    z2="";
+  }
+  if( 0==z3 ){
+    z3="";
+  }
+
+  lz1 = strlen(z1);
+  lz2 = strlen(z2);
+  lz3 = strlen(z3);
+
+#if 0
+  /* special case when z2 is empty (or null) nothing will be changed */
+  if( 0==lz2 ){
+    sqlite3_result_text(context, z1, -1, SQLITE_TRANSIENT);
+    return;
+  }
+#endif
+
+  zt1=z1;
+  zt2=z1;
+
+  while(1){
+    ret=_substr(z2,zt1 , 0, &zt2);
+
+    if( ret<0 )
+      break;
+
+    _append(&zo, lzo, zt1, zt2-zt1);
+    lzo+=zt2-zt1;
+    _append(&zo, lzo, z3, lz3);
+    lzo+=lz3;
+
+    zt1=zt2+lz2;
+  }
+  _append(&zo, lzo, zt1, lz1-(zt1-z1));
+  sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT);
+  sqlite3_free(zo);
+}
+#endif
+
+/*
+** given a string returns the same string but with the characters in reverse order
+*/
+static void reverseFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  const char *z;
+  const char *zt;
+  char *rz;
+  char *rzt;
+  int l = 0;
+  int i = 0;
+
+  assert( 1==argc );
+
+  if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){
+    sqlite3_result_null(context);
+    return;
+  }
+  z = (char *)sqlite3_value_text(argv[0]);
+  l = strlen(z);
+  rz = sqlite3_malloc(l+1);
+  if (!rz){
+    sqlite3_result_error_nomem(context);
+    return;
+  }
+  rzt = rz+l;
+  *(rzt--) = '\0';
+
+  zt=z;
+  while( sqliteCharVal((unsigned char *)zt)!=0 ){
+    z=zt;
+    sqliteNextChar(zt);
+    for(i=1; zt-i>=z; ++i){
+      *(rzt--)=*(zt-i);
+    }
+  }
+
+  sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT);
+  sqlite3_free(rz);
+}
+
+/*
+** An instance of the following structure holds the context of a
+** stdev() or variance() aggregate computation.
+** implementaion of http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Algorithm_II
+** less prone to rounding errors
+*/
+typedef struct StdevCtx StdevCtx;
+struct StdevCtx {
+  double rM;
+  double rS;
+  i64 cnt;          /* number of elements */
+};
+
+/*
+** An instance of the following structure holds the context of a
+** mode() or median() aggregate computation.
+** Depends on structures defined in map.c (see map & map)
+** These aggregate functions only work for integers and floats although
+** they could be made to work for strings. This is usually considered meaningless.
+** Only usuall order (for median), no use of collation functions (would this even make sense?)
+*/
+typedef struct ModeCtx ModeCtx;
+struct ModeCtx {
+  i64 riM;            /* integer value found so far */
+  double rdM;         /* double value found so far */
+  i64 cnt;            /* number of elements so far */
+  double pcnt;        /* number of elements smaller than a percentile */
+  i64 mcnt;           /* maximum number of occurrences (for mode) */
+  i64 mn;             /* number of occurrences (for mode and percentiles) */
+  i64 is_double;      /* whether the computation is being done for doubles (>0) or integers (=0) */
+  map* m;             /* map structure used for the computation */
+  int done;           /* whether the answer has been found */
+};
+
+/*
+** called for each value received during a calculation of stdev or variance
+*/
+static void varianceStep(sqlite3_context *context, int argc, sqlite3_value **argv){
+  StdevCtx *p;
+
+  double delta;
+  double x;
+
+  assert( argc==1 );
+  p = sqlite3_aggregate_context(context, sizeof(*p));
+  /* only consider non-null values */
+  if( SQLITE_NULL != sqlite3_value_numeric_type(argv[0]) ){
+    p->cnt++;
+    x = sqlite3_value_double(argv[0]);
+    delta = (x-p->rM);
+    p->rM += delta/p->cnt;
+    p->rS += delta*(x-p->rM);
+  }
+}
+
+/*
+** called for each value received during a calculation of mode of median
+*/
+static void modeStep(sqlite3_context *context, int argc, sqlite3_value **argv){
+  ModeCtx *p;
+  i64 xi=0;
+  double xd=0.0;
+  i64 *iptr;
+  double *dptr;
+  int type;
+
+  assert( argc==1 );
+  type = sqlite3_value_numeric_type(argv[0]);
+
+  if( type == SQLITE_NULL)
+    return;
+  
+  p = sqlite3_aggregate_context(context, sizeof(*p));
+
+  if( 0==(p->m) ){
+    p->m = calloc(1, sizeof(map));
+    if( type==SQLITE_INTEGER ){
+      /* map will be used for integers */
+      *(p->m) = map_make(int_cmp);
+      p->is_double = 0;
+    }else{
+      p->is_double = 1;
+      /* map will be used for doubles */
+      *(p->m) = map_make(double_cmp);
+    }
+  }
+
+  ++(p->cnt);
+
+  if( 0==p->is_double ){
+    xi = sqlite3_value_int64(argv[0]);
+    iptr = (i64*)calloc(1,sizeof(i64));
+    *iptr = xi;
+    map_insert(p->m, iptr);
+  }else{
+    xd = sqlite3_value_double(argv[0]);
+    dptr = (double*)calloc(1,sizeof(double));
+    *dptr = xd;
+    map_insert(p->m, dptr);
+  }
+}
+
+/*
+**  Auxiliary function that iterates all elements in a map and finds the mode
+**  (most frequent value)
+*/
+static void modeIterate(void* e, i64 c, void* pp){
+  i64 ei;
+  double ed;
+  ModeCtx *p = (ModeCtx*)pp;
+  
+  if( 0==p->is_double ){
+    ei = *(int*)(e);
+
+	if( p->mcnt==c ){
+      ++p->mn;
+    }else if( p->mcnt<c ){
+      p->riM = ei;
+      p->mcnt = c;
+	  p->mn=1;
+    }
+  }else{
+    ed = *(double*)(e);
+
+	if( p->mcnt==c ){
+      ++p->mn;
+    }else if(p->mcnt<c){
+      p->rdM = ed;
+      p->mcnt = c;
+	  p->mn=1;
+    }
+  }
+}
+
+/*
+**  Auxiliary function that iterates all elements in a map and finds the median
+**  (the value such that the number of elements smaller is equal the the number of 
+**  elements larger)
+*/
+static void medianIterate(void* e, i64 c, void* pp){
+  i64 ei;
+  double ed;
+  double iL;
+  double iR;
+  int il;
+  int ir;
+  ModeCtx *p = (ModeCtx*)pp;
+
+  if(p->done>0)
+    return;
+
+  iL = p->pcnt;
+  iR = p->cnt - p->pcnt;
+  il = p->mcnt + c;
+  ir = p->cnt - p->mcnt;
+
+  if( il >= iL ){
+    if( ir >= iR ){
+    ++p->mn;
+      if( 0==p->is_double ){
+        ei = *(int*)(e);
+        p->riM += ei;
+      }else{
+        ed = *(double*)(e);
+        p->rdM += ed;
+      }
+    }else{
+      p->done=1;
+    }
+  }
+  p->mcnt+=c;
+}
+
+/*
+** Returns the mode value
+*/
+static void modeFinalize(sqlite3_context *context){
+  ModeCtx *p;
+  p = sqlite3_aggregate_context(context, 0);
+  if( p && p->m ){
+    map_iterate(p->m, modeIterate, p);
+    map_destroy(p->m);
+    free(p->m);
+
+    if( 1==p->mn ){
+      if( 0==p->is_double )
+        sqlite3_result_int64(context, p->riM);
+      else
+        sqlite3_result_double(context, p->rdM);
+    }
+  }
+}
+
+/*
+** auxiliary function for percentiles
+*/
+static void _medianFinalize(sqlite3_context *context){
+  ModeCtx *p;
+  p = (ModeCtx*) sqlite3_aggregate_context(context, 0);
+  if( p && p->m ){
+    p->done=0;
+    map_iterate(p->m, medianIterate, p);
+    map_destroy(p->m);
+    free(p->m);
+
+    if( 0==p->is_double )
+      if( 1==p->mn )
+      	sqlite3_result_int64(context, p->riM);
+      else
+      	sqlite3_result_double(context, p->riM*1.0/p->mn);
+    else
+      sqlite3_result_double(context, p->rdM/p->mn);
+  }
+}
+
+/*
+** Returns the median value
+*/
+static void medianFinalize(sqlite3_context *context){
+  ModeCtx *p;
+  p = (ModeCtx*) sqlite3_aggregate_context(context, 0);
+  if( p!=0 ){
+    p->pcnt = (p->cnt)/2.0;
+    _medianFinalize(context);
+  }
+}
+
+/*
+** Returns the lower_quartile value
+*/
+static void lower_quartileFinalize(sqlite3_context *context){
+  ModeCtx *p;
+  p = (ModeCtx*) sqlite3_aggregate_context(context, 0);
+  if( p!=0 ){
+    p->pcnt = (p->cnt)/4.0;
+    _medianFinalize(context);
+  }
+}
+
+/*
+** Returns the upper_quartile value
+*/
+static void upper_quartileFinalize(sqlite3_context *context){
+  ModeCtx *p;
+  p = (ModeCtx*) sqlite3_aggregate_context(context, 0);
+  if( p!=0 ){
+    p->pcnt = (p->cnt)*3/4.0;
+    _medianFinalize(context);
+  }
+}
+
+/*
+** Returns the stdev value
+*/
+static void stdevFinalize(sqlite3_context *context){
+  StdevCtx *p;
+  p = sqlite3_aggregate_context(context, 0);
+  if( p && p->cnt>1 ){
+    sqlite3_result_double(context, sqrt(p->rS/(p->cnt-1)));
+  }else{
+    sqlite3_result_double(context, 0.0);
+  }
+}
+
+/*
+** Returns the variance value
+*/
+static void varianceFinalize(sqlite3_context *context){
+  StdevCtx *p;
+  p = sqlite3_aggregate_context(context, 0);
+  if( p && p->cnt>1 ){
+    sqlite3_result_double(context, p->rS/(p->cnt-1));
+  }else{
+    sqlite3_result_double(context, 0.0);
+  }
+}
+
+#ifdef SQLITE_SOUNDEX
+
+/* relicoder factored code */
+/*
+** Calculates the soundex value of a string
+*/
+
+static void soundex(const u8 *zIn, char *zResult){
+  int i, j;
+  static const unsigned char iCode[] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
+    1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
+    0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
+    1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
+  };
+
+  for(i=0; zIn[i] && !isalpha(zIn[i]); i++){}
+  if( zIn[i] ){
+    zResult[0] = toupper(zIn[i]);
+    for(j=1; j<4 && zIn[i]; i++){
+      int code = iCode[zIn[i]&0x7f];
+      if( code>0 ){
+        zResult[j++] = code + '0';
+      }
+    }
+    while( j<4 ){
+      zResult[j++] = '0';
+    }
+    zResult[j] = 0;
+  }else{
+    strcpy(zResult, "?000");
+  }
+}
+
+/*
+** computes the number of different characters between the soundex value fo 2 strings
+*/
+static void differenceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  char zResult1[8];
+  char zResult2[8];
+  char *zR1 = zResult1;
+  char *zR2 = zResult2;
+  int rVal = 0;
+  int i = 0;
+  const u8 *zIn1;
+  const u8 *zIn2;
+
+  assert( argc==2 );
+  
+  if( sqlite3_value_type(argv[0])==SQLITE_NULL || sqlite3_value_type(argv[1])==SQLITE_NULL ){
+    sqlite3_result_null(context);
+    return;
+  }
+  
+  zIn1 = (u8*)sqlite3_value_text(argv[0]);
+  zIn2 = (u8*)sqlite3_value_text(argv[1]);
+
+  soundex(zIn1, zR1);
+  soundex(zIn2, zR2);
+
+  for(i=0; i<4; ++i){
+    if( sqliteCharVal((unsigned char *)zR1)==sqliteCharVal((unsigned char *)zR2) )
+      ++rVal;
+    sqliteNextChar(zR1);
+    sqliteNextChar(zR2);
+  }
+  sqlite3_result_int(context, rVal);
+}
+#endif
+
+/*
+** This function registered all of the above C functions as SQL
+** functions.  This should be the only routine in this file with
+** external linkage.
+*/
+int RegisterExtensionFunctions(sqlite3 *db){
+  static const struct FuncDef {
+     char *zName;
+     signed char nArg;
+     u8 argType;           /* 0: none.  1: db  2: (-1) */
+     u8 eTextRep;          /* 1: UTF-16.  0: UTF-8 */
+     u8 needCollSeq;
+     void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
+  } aFuncs[] = {
+    /* math.h */
+    { "acos",               1, 0, SQLITE_UTF8,    0, acosFunc  },
+    { "asin",               1, 0, SQLITE_UTF8,    0, asinFunc  },
+    { "atan",               1, 0, SQLITE_UTF8,    0, atanFunc  },
+    { "atn2",               2, 0, SQLITE_UTF8,    0, atn2Func  },
+    /* XXX alias */
+    { "atan2",              2, 0, SQLITE_UTF8,    0, atn2Func  },
+    { "acosh",              1, 0, SQLITE_UTF8,    0, acoshFunc  },
+    { "asinh",              1, 0, SQLITE_UTF8,    0, asinhFunc  },
+    { "atanh",              1, 0, SQLITE_UTF8,    0, atanhFunc  },
+
+    { "difference",         2, 0, SQLITE_UTF8,    0, differenceFunc},
+    { "degrees",            1, 0, SQLITE_UTF8,    0, rad2degFunc  },
+    { "radians",            1, 0, SQLITE_UTF8,    0, deg2radFunc  },
+
+    { "cos",                1, 0, SQLITE_UTF8,    0, cosFunc  },
+    { "sin",                1, 0, SQLITE_UTF8,    0, sinFunc },
+    { "tan",                1, 0, SQLITE_UTF8,    0, tanFunc },
+    { "cot",                1, 0, SQLITE_UTF8,    0, cotFunc },
+    { "cosh",               1, 0, SQLITE_UTF8,    0, coshFunc  },
+    { "sinh",               1, 0, SQLITE_UTF8,    0, sinhFunc },
+    { "tanh",               1, 0, SQLITE_UTF8,    0, tanhFunc },
+    { "coth",               1, 0, SQLITE_UTF8,    0, cothFunc },
+
+    { "exp",                1, 0, SQLITE_UTF8,    0, expFunc  },
+    { "log",                1, 0, SQLITE_UTF8,    0, logFunc  },
+    { "log10",              1, 0, SQLITE_UTF8,    0, log10Func  },
+    { "power",              2, 0, SQLITE_UTF8,    0, powerFunc  },
+    { "sign",               1, 0, SQLITE_UTF8,    0, signFunc },
+    { "sqrt",               1, 0, SQLITE_UTF8,    0, sqrtFunc },
+    { "square",             1, 0, SQLITE_UTF8,    0, squareFunc },
+
+    { "ceil",               1, 0, SQLITE_UTF8,    0, ceilFunc },
+    { "floor",              1, 0, SQLITE_UTF8,    0, floorFunc },
+
+    { "pi",                 0, 0, SQLITE_UTF8,    1, piFunc },
+
+
+    /* string */
+    { "replicate",          2, 0, SQLITE_UTF8,    0, replicateFunc },
+    { "charindex",          2, 0, SQLITE_UTF8,    0, charindexFunc },
+    { "charindex",          3, 0, SQLITE_UTF8,    0, charindexFunc },
+    { "leftstr",            2, 0, SQLITE_UTF8,    0, leftFunc },
+    { "rightstr",           2, 0, SQLITE_UTF8,    0, rightFunc },
+#ifndef HAVE_TRIM
+    { "ltrim",              1, 0, SQLITE_UTF8,    0, ltrimFunc },
+    { "rtrim",              1, 0, SQLITE_UTF8,    0, rtrimFunc },
+    { "trim",               1, 0, SQLITE_UTF8,    0, trimFunc },
+    { "replace",            3, 0, SQLITE_UTF8,    0, replaceFunc },
+#endif
+    { "reverse",            1, 0, SQLITE_UTF8,    0, reverseFunc },
+    { "proper",             1, 0, SQLITE_UTF8,    0, properFunc },
+    { "padl",               2, 0, SQLITE_UTF8,    0, padlFunc },
+    { "padr",               2, 0, SQLITE_UTF8,    0, padrFunc },
+    { "padc",               2, 0, SQLITE_UTF8,    0, padcFunc },
+    { "strfilter",          2, 0, SQLITE_UTF8,    0, strfilterFunc },
+
+  };
+  /* Aggregate functions */
+  static const struct FuncDefAgg {
+    char *zName;
+    signed char nArg;
+    u8 argType;
+    u8 needCollSeq;
+    void (*xStep)(sqlite3_context*,int,sqlite3_value**);
+    void (*xFinalize)(sqlite3_context*);
+  } aAggs[] = {
+    { "stdev",            1, 0, 0, varianceStep, stdevFinalize  },
+    { "variance",         1, 0, 0, varianceStep, varianceFinalize  },
+    { "mode",             1, 0, 0, modeStep,     modeFinalize  },
+    { "median",           1, 0, 0, modeStep,     medianFinalize  },
+    { "lower_quartile",   1, 0, 0, modeStep,     lower_quartileFinalize  },
+    { "upper_quartile",   1, 0, 0, modeStep,     upper_quartileFinalize  },
+  };
+  int i;
+
+  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
+    void *pArg = 0;
+    switch( aFuncs[i].argType ){
+      case 1: pArg = db; break;
+      case 2: pArg = (void *)(-1); break;
+    }
+    //sqlite3CreateFunc
+    /* LMH no error checking */
+    sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
+        aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
+#if 0
+    if( aFuncs[i].needCollSeq ){
+      struct 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;
+      }
+    }
+#endif
+  }
+
+  for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
+    void *pArg = 0;
+    switch( aAggs[i].argType ){
+      case 1: pArg = db; break;
+      case 2: pArg = (void *)(-1); break;
+    }
+    //sqlite3CreateFunc
+    /* LMH no error checking */
+    sqlite3_create_function(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8, 
+        pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
+#if 0
+    if( aAggs[i].needCollSeq ){
+      struct FuncDefAgg *pFunc = sqlite3FindFunction( db, aAggs[i].zName,
+          strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0);
+      if( pFunc && aAggs[i].needCollSeq ){
+        pFunc->needCollSeq = 1;
+      }
+    }
+#endif
+  }
+  return 0;
+}
+
+#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE
+int sqlite3_extension_init(
+    sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi){
+  SQLITE_EXTENSION_INIT2(pApi);
+  RegisterExtensionFunctions(db);
+  return 0;
+}
+#endif /* COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE */
+
+map map_make(cmp_func cmp){
+  map r;
+  r.cmp=cmp;
+  r.base = 0;
+
+  return r;
+}
+
+void* xcalloc(size_t nmemb, size_t size, char* s){
+  void* ret = calloc(nmemb, size);
+  return ret;
+}
+
+void xfree(void* p){
+  free(p);
+}
+
+void node_insert(node** n, cmp_func cmp, void *e){
+  int c;
+  node* nn;
+  if(*n==0){
+    nn = (node*)xcalloc(1,sizeof(node), "for node");
+    nn->data = e;
+    nn->count = 1;
+    *n=nn;
+  }else{
+    c=cmp((*n)->data,e);
+    if(0==c){
+      ++((*n)->count);
+      xfree(e);
+    }else if(c>0){
+      /* put it right here */
+      node_insert(&((*n)->l), cmp, e);
+    }else{
+      node_insert(&((*n)->r), cmp, e);
+    }
+  }
+}
+
+void map_insert(map *m, void *e){
+  node_insert(&(m->base), m->cmp, e);
+}
+
+void node_iterate(node *n, map_iterator iter, void* p){
+  if(n){
+    if(n->l)
+      node_iterate(n->l, iter, p);
+    iter(n->data, n->count, p);
+    if(n->r)
+      node_iterate(n->r, iter, p);
+  }
+}
+
+void map_iterate(map *m, map_iterator iter, void* p){
+  node_iterate(m->base, iter, p);
+}
+
+void node_destroy(node *n){
+  if(0!=n){
+    xfree(n->data);
+    if(n->l)
+      node_destroy(n->l);
+    if(n->r)
+      node_destroy(n->r);
+
+    xfree(n);
+  }
+}
+
+void map_destroy(map *m){
+  node_destroy(m->base);
+}
+
+int int_cmp(const void *a, const void *b){
+  int64_t aa = *(int64_t *)(a);
+  int64_t bb = *(int64_t *)(b);
+  /* printf("cmp %d <=> %d\n",aa,bb); */
+  if(aa==bb)
+    return 0;
+  else if(aa<bb)
+    return -1;
+  else
+    return 1;
+}
+
+int double_cmp(const void *a, const void *b){
+  double aa = *(double *)(a);
+  double bb = *(double *)(b);
+  /* printf("cmp %d <=> %d\n",aa,bb); */
+  if(aa==bb)
+    return 0;
+  else if(aa<bb)
+    return -1;
+  else
+    return 1;
+}
diff --git a/src/fetch.c b/src/fetch.c
new file mode 100644
index 0000000..4eb173c
--- /dev/null
+++ b/src/fetch.c
@@ -0,0 +1,392 @@
+/* 
+ * Copyright (C) 1999-2002 The Omega Project for Statistical Computing
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "rsqlite.h"
+
+void rsqlite_output_alloc(SEXP output, SQLiteFields* flds, int num_rec) {
+  PROTECT(output);
+  int p = flds->num_fields;
+
+  for (int j = 0; j < p; j++) {
+    SET_VECTOR_ELT(output, j, allocVector(flds->Sclass[j], num_rec));
+  }
+
+  SEXP names = PROTECT(allocVector(STRSXP, p));
+  SET_NAMES(output, names);
+  UNPROTECT(1);
+  for (int j = 0; j < p; j++) {
+    SET_STRING_ELT(names, j, mkChar(flds->name[j]));
+  }
+
+  UNPROTECT(1);
+  return;
+}
+
+void rsqlite_output_expand(SEXP output, SQLiteFields* flds, int num_rec) {
+  PROTECT(output);
+  int p = flds->num_fields;
+
+  for (int j = 0; j < p; j++) {
+    /* Note that in R-1.2.3 (at least) we need to protect SET_LENGTH */
+    SEXP s_tmp = VECTOR_ELT(output, j);
+    PROTECT(SET_LENGTH(s_tmp, num_rec));
+    SET_VECTOR_ELT(output, j, s_tmp);
+    UNPROTECT(1);
+  }
+  UNPROTECT(1);
+}
+
+// Combines error text with error message from database, and frees result set
+void exec_error(SQLiteConnection* con, const char* msg) {
+  const char* db_msg = "";
+  const char* sep = "";
+
+  sqlite3* db = con->drvConnection;
+  int errcode = db ? sqlite3_errcode(db) : -1;
+  if (errcode != SQLITE_OK) {
+    db_msg = sqlite3_errmsg(db);
+    sep = ": ";
+  }
+  char buf[2048];
+  snprintf(buf, sizeof(buf), "%s%s%s", msg, sep, db_msg);
+
+  rsqlite_exception_set(con, errcode, buf);
+  rsqlite_result_free(con);
+
+  error(buf);
+}
+
+static void
+select_prepared_query(sqlite3_stmt* db_statement,
+                      SEXP bind_data,
+                      int bind_count,
+                      int rows,
+                      SQLiteConnection* con) {
+  char bindingErrorMsg[2048];
+  bindingErrorMsg[0] = '\0';
+  RSQLiteParams* params =
+      RS_SQLite_createParameterBinding(bind_count, bind_data,
+          db_statement, bindingErrorMsg);
+  if (params == NULL) {
+    /* FIXME: this UNPROTECT is ugly, paired to caller */
+    UNPROTECT(1);
+    exec_error(con, bindingErrorMsg);
+  }
+  con->resultSet->drvData = params;
+}
+
+static int
+bind_params_to_stmt(RSQLiteParams* params,
+                    sqlite3_stmt* db_statement, int row) {
+  int state = SQLITE_OK, j;
+  for (j = 0; j < params->count; j++) {
+    SEXP pdata = VECTOR_ELT(params->data, j), v_elt;
+    int integer;
+    double number;
+    Rbyte* raw;
+
+    switch (TYPEOF(pdata)) {
+      case INTSXP:
+        integer = INTEGER(pdata)[row];
+        if (integer == NA_INTEGER)
+          state = sqlite3_bind_null(db_statement, j + 1);
+        else
+          state = sqlite3_bind_int(db_statement, j + 1, integer);
+        break;
+      case REALSXP:
+        number = REAL(pdata)[row];
+        if (ISNA(number))
+          state = sqlite3_bind_null(db_statement, j + 1);
+        else
+          state = sqlite3_bind_double(db_statement, j + 1, number);
+        break;
+      case VECSXP:            /* BLOB */
+        v_elt = VECTOR_ELT(pdata, row);
+        if (v_elt == R_NilValue) {
+          state = sqlite3_bind_null(db_statement, j + 1);
+        } else {
+          raw = RAW(v_elt);
+          state = sqlite3_bind_blob(db_statement, j + 1,
+              raw, LENGTH(v_elt), SQLITE_STATIC);
+        }
+        break;
+      case STRSXP:
+        /* falls through */
+      default:
+        v_elt = STRING_ELT(pdata, row);
+        if (NA_STRING == v_elt)
+          state = sqlite3_bind_null(db_statement, j + 1);
+        else
+          state = sqlite3_bind_text(db_statement, j + 1,
+              CHAR(v_elt), -1, SQLITE_STATIC);
+        break;
+    }
+    if (state != SQLITE_OK) break;
+  }
+  return state;
+}
+
+static void
+non_select_prepared_query(sqlite3_stmt* db_statement,
+                          SEXP bind_data,
+                          int bind_count,
+                          int rows,
+                          SQLiteConnection* con) {
+  int state, i;
+  char bindingErrorMsg[2048];
+  bindingErrorMsg[0] = '\0';
+  RSQLiteParams* params =
+      RS_SQLite_createParameterBinding(bind_count, bind_data,
+          db_statement, bindingErrorMsg);
+  if (params == NULL) {
+    /* FIXME: this UNPROTECT is ugly, paired to caller */
+    UNPROTECT(1);
+    exec_error(con, bindingErrorMsg);
+  }
+
+  /* we need to step through the query for each row */
+  for (i = 0; i < rows; i++) {
+    state = bind_params_to_stmt(params, db_statement, i);
+    if (state != SQLITE_OK) {
+      UNPROTECT(1);
+      exec_error(con, "rsqlite_query_send: could not bind data");
+    }
+    state = sqlite3_step(db_statement);
+    if (state != SQLITE_DONE) {
+      UNPROTECT(1);
+      exec_error(con, "rsqlite_query_send: could not execute");
+    }
+    state = sqlite3_reset(db_statement);
+    sqlite3_clear_bindings(db_statement);
+    if (state != SQLITE_OK) {
+      UNPROTECT(1);
+      exec_error(con, "rsqlite_query_send: could not reset statement");
+    }
+  }
+  RS_SQLite_freeParameterBinding(&params);
+}
+
+
+SEXP rsqlite_query_send(SEXP handle, SEXP statement, SEXP bind_data) {
+  SQLiteConnection* con = rsqlite_connection_from_handle(handle);
+  sqlite3* db_connection = con->drvConnection;
+  sqlite3_stmt* db_statement = NULL;
+  int state, bind_count;
+  int rows = 0, cols = 0;
+
+  if (con->resultSet) {
+    if (con->resultSet->completed != 1)
+      warning("Closing result set with pending rows");
+    rsqlite_result_free(con);
+  }
+  rsqlite_result_alloc(con);
+  SQLiteResult* res = con->resultSet;
+
+  /* allocate and init a new result set */
+  res->completed = 0;
+  char* dyn_statement = RS_DBI_copyString(CHAR(asChar(statement)));
+  res->statement = dyn_statement;
+  res->drvResultSet = db_statement;
+  state = sqlite3_prepare_v2(db_connection, dyn_statement, -1,
+      &db_statement, NULL);
+
+  if (state != SQLITE_OK) {
+    exec_error(con, "error in statement");
+  }
+  if (db_statement == NULL) {
+    exec_error(con, "nothing to execute");
+  }
+  res->drvResultSet = (void*) db_statement;
+  bind_count = sqlite3_bind_parameter_count(db_statement);
+  if (bind_count > 0 && bind_data != R_NilValue) {
+    rows = GET_LENGTH(GET_ROWNAMES(bind_data));
+    cols = GET_LENGTH(bind_data);
+  }
+
+  res->isSelect = sqlite3_column_count(db_statement) > 0;
+  res->rowCount = 0;      /* fake's cursor's row count */
+  res->rowsAffected = -1; /* no rows affected */
+  rsqlite_exception_set(con, state, "OK");
+
+  if (res->isSelect) {
+    if (bind_count > 0) {
+      select_prepared_query(db_statement, bind_data, bind_count, rows, con);
+    }
+  } else {
+    if (bind_count > 0) {
+      non_select_prepared_query(db_statement, bind_data, bind_count, rows, con);
+    } else {
+      state = sqlite3_step(db_statement);
+      if (state != SQLITE_DONE) {
+        exec_error(con, "rsqlite_query_send: could not execute1");
+      }
+    }
+    res->completed = 1;
+    res->rowsAffected = sqlite3_changes(db_connection);
+  }
+
+  return handle;
+}
+
+/* Fills the output VECSXP with one row of data from the resultset
+ */
+void fill_one_row(sqlite3_stmt* db_statement, SEXP output, int row_idx,
+                  SQLiteFields* flds) {
+
+  for (int j = 0; j < flds->num_fields; j++) {
+    int is_null = (sqlite3_column_type(db_statement, j) == SQLITE_NULL);
+
+    SEXP col = VECTOR_ELT(output, j);
+    switch (flds->Sclass[j]) {
+      case INTSXP:
+        INTEGER(col)[row_idx] = is_null ? NA_INTEGER :
+            sqlite3_column_int(db_statement, j);
+        break;
+      case REALSXP:
+        REAL(col)[row_idx] = is_null ? NA_REAL :
+            sqlite3_column_double(db_statement, j);
+        break;
+      case VECSXP:            /* BLOB */
+        if (is_null) continue;
+
+        const Rbyte* blob_data = (const Rbyte*) sqlite3_column_blob(db_statement, j);
+        int blob_len = sqlite3_column_bytes(db_statement, j);
+        SEXP rawv = PROTECT(allocVector(RAWSXP, blob_len));
+        memcpy(RAW(rawv), blob_data, blob_len * sizeof(Rbyte));
+        SET_VECTOR_ELT(col, row_idx, rawv);
+        UNPROTECT(1);
+        break;
+      case STRSXP:
+        /* falls through */
+      default:
+        SET_STRING_ELT(col, row_idx, is_null ? NA_STRING :
+            mkChar((char*) sqlite3_column_text(db_statement, j)));
+        break;
+    }
+  }
+}
+
+static int do_select_step(SQLiteResult* res, int row_idx) {
+  int state;
+  RSQLiteParams* params = NULL;
+  sqlite3_stmt* stmt = (sqlite3_stmt*) res->drvResultSet;
+  if (res->drvData) {         /* we have parameters to bind */
+    params = (RSQLiteParams*) res->drvData;
+    if (params->row_complete) {
+      params->row_complete = 0;
+      sqlite3_clear_bindings(stmt);
+      state = bind_params_to_stmt(params,
+          stmt,
+          params->rows_used);
+      if (state != SQLITE_OK) return state;
+      params->rows_used++;
+    }
+  }
+  state = sqlite3_step(stmt);
+  if (params && state == SQLITE_DONE) {
+    params->row_complete = 1;
+    if (params->rows_used < params->row_count) {
+      state = sqlite3_reset(stmt);
+      if (state != SQLITE_OK) return state;
+      return do_select_step(res, row_idx);
+    }
+  }
+  return state;
+}
+
+/* Return a data.frame containing the requested number of rows from
+   the resultset.
+
+   We try to determine the correct R type for each column in the
+   result.  Currently, type detection happens only for the first fetch
+   on a given resultset and the first row of the resultset is used for
+   type interpolation.  If a NULL value appears in the first row of
+   the resultset and the column corresponds to a DB table column, we
+   guess the type based on the DB schema definition for the column.
+   If the NULL value does not correspond to a table column, then we
+   force character.
+*/
+SEXP rsqlite_query_fetch(SEXP handle, SEXP max_rec) {
+  SQLiteResult* res = rsqlite_result_from_handle(handle);
+  if (res->isSelect != 1) {
+    warning("resultSet does not correspond to a SELECT statement");
+    return R_NilValue;
+  }
+  if (res->completed == 1) {
+    return R_NilValue;
+  }
+
+  /* We need to step once to be able to create the data mappings */
+  int row_idx = 0;
+  int state = do_select_step(res, row_idx);
+  sqlite3_stmt* db_statement = (sqlite3_stmt*) res->drvResultSet;
+
+  if (state != SQLITE_ROW && state != SQLITE_DONE) {
+    error("rsqlite_query_fetch: failed first step: %s",
+        sqlite3_errmsg(sqlite3_db_handle(db_statement)));
+  }
+
+  SQLiteFields* flds = rsqlite_result_fields(res);
+
+  int num_fields = flds->num_fields;
+  int num_rec = asInteger(max_rec);
+  int expand = (num_rec < 0);   /* dyn expand output to accommodate all rows*/
+  if (expand || num_rec == 0) {
+    num_rec = rsqlite_driver()->fetch_default_rec;
+  }
+
+  SEXP output = PROTECT(NEW_LIST(num_fields));
+  rsqlite_output_alloc(output, flds, num_rec);
+  while (state != SQLITE_DONE) {
+    fill_one_row(db_statement, output, row_idx, flds);
+    row_idx++;
+    if (row_idx == num_rec) {  /* request satisfied or exhausted allocated space */
+      if (expand) {    /* do we extend or return the records fetched so far*/
+        num_rec = 1.5 * num_rec;
+        rsqlite_output_expand(output, flds, num_rec);
+      } else {
+        break;       /* okay, no more fetching for now */
+      }
+    }
+    state = do_select_step(res, row_idx);
+    if (state != SQLITE_ROW && state != SQLITE_DONE) {
+      error("rsqlite_query_fetch: failed: %s",
+          sqlite3_errmsg(sqlite3_db_handle(db_statement)));
+    }
+  } /* end row loop */
+
+  if (state == SQLITE_DONE) {
+    res->completed = 1;
+  }
+
+  /* size to actual number of records fetched */
+  if (row_idx < num_rec) {
+    num_rec = row_idx;
+    /* adjust the length of each of the members in the output_list */
+    for (int j = 0; j < num_fields; j++) {
+      SEXP s_tmp = VECTOR_ELT(output, j);
+      PROTECT(SET_LENGTH(s_tmp, num_rec));
+      SET_VECTOR_ELT(output, j, s_tmp);
+      UNPROTECT(1);
+    }
+  }
+  res->rowCount += num_rec;
+  UNPROTECT(1);
+  return output;
+}
+
diff --git a/src/fields.c b/src/fields.c
new file mode 100644
index 0000000..f8561b2
--- /dev/null
+++ b/src/fields.c
@@ -0,0 +1,92 @@
+/* 
+ * Copyright (C) 1999-2002 The Omega Project for Statistical Computing
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "rsqlite.h"
+
+SQLiteFields* rsqlite_fields_alloc(int n) {
+  SQLiteFields* flds;
+
+  flds = malloc(sizeof(SQLiteFields));
+  if (!flds) {
+    error("Could not malloc SQLiteFields.");
+  }
+  flds->num_fields = n;
+  flds->name = calloc(n, sizeof(char*));
+  flds->type = calloc(n, sizeof(int));
+  flds->length = calloc(n, sizeof(int));
+  flds->Sclass = calloc(n, sizeof(SEXPTYPE));
+
+  return flds;
+}
+
+void rsqlite_fields_free(SQLiteFields* flds) {
+  if (flds->name) free(flds->name);
+  if (flds->type) free(flds->type);
+  if (flds->length) free(flds->length);
+  if (flds->Sclass) free(flds->Sclass);
+  free(flds);
+  flds = NULL;
+  return;
+}
+
+SEXP rsqlite_field_info(SQLiteFields* flds) {
+  int n = flds ? flds->num_fields : 0;
+
+  SEXP info = PROTECT(allocVector(VECSXP, 4));
+  SEXP info_nms = PROTECT(allocVector(STRSXP, 4));
+  SET_NAMES(info, info_nms);
+  UNPROTECT(1);
+
+  int i = 0;
+  SET_STRING_ELT(info_nms, i, mkChar("name"));
+  SEXP names = PROTECT(allocVector(STRSXP, n));
+  for (int j = 0; j < n; j++) {
+    SET_STRING_ELT(names, j, mkChar(flds->name[j]));
+  }
+  SET_VECTOR_ELT(info, i++, names);
+  UNPROTECT(1);
+
+  SET_STRING_ELT(info_nms, i, mkChar("Sclass"));
+  SEXP sclass = PROTECT(allocVector(STRSXP, n));
+  for (int j = 0; j < n; j++) {
+    const char* type = type2char(flds->Sclass[j]);
+    SET_STRING_ELT(sclass, j, mkChar(type));
+  }
+  SET_VECTOR_ELT(info, i++, sclass);
+  UNPROTECT(1);
+
+  SET_STRING_ELT(info_nms, i, mkChar("type"));
+  SEXP types = PROTECT(allocVector(STRSXP, n));
+  for (int j = 0; j < n; j++) {
+    char* type = field_type(flds->type[j]);
+    SET_STRING_ELT(types, j, mkChar(type));
+  }
+  SET_VECTOR_ELT(info, i++, types);
+  UNPROTECT(1);
+
+  SET_STRING_ELT(info_nms, i, mkChar("len"));
+  SEXP lens = PROTECT(allocVector(INTSXP, n));
+  for (int j = 0; j < n; j++) {
+    INTEGER(lens)[j] = flds->length[j];
+  }
+  SET_VECTOR_ELT(info, i++, lens);
+  UNPROTECT(1);
+
+  UNPROTECT(1);
+  return info;
+}
diff --git a/src/importFile.c b/src/importFile.c
new file mode 100644
index 0000000..e227160
--- /dev/null
+++ b/src/importFile.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 1999-2003 The Omega Project for Statistical Computing.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "rsqlite.h"
+
+SEXP     /* returns TRUE/FALSE */
+RS_SQLite_importFile(
+    SEXP conHandle,
+    SEXP s_tablename,
+    SEXP s_filename,
+    SEXP s_separator,
+    SEXP s_eol,
+    SEXP s_skip
+) {
+  SQLiteConnection* con = rsqlite_connection_from_handle(conHandle);
+  sqlite3* db_connection = (sqlite3*) con->drvConnection;
+  char* zFile, * zTable, * zSep, * zEol;
+  const char* s, * s1;
+  int rc, skip;
+  SEXP output;
+
+  s = CHAR(asChar(s_tablename));
+  zTable = malloc(strlen(s) + 1);
+  if (!zTable) {
+    error("could not allocate memory");
+  }
+  (void) strcpy(zTable, s);
+
+  s = CHAR(asChar(s_filename));
+  zFile = malloc(strlen(s) + 1);
+  if (!zFile) {
+    free(zTable);
+    error("could not allocate memory");
+  }
+  (void) strcpy(zFile, s);
+
+  s = CHAR(asChar(s_separator));
+  s1 = CHAR(asChar(s_eol));
+  zSep = malloc(strlen(s) + 1);
+  zEol = malloc(strlen(s1) + 1);
+  if (!zSep || !zEol) {
+    free(zTable);
+    free(zFile);
+    if (zSep) free(zSep);
+    if (zEol) free(zEol);
+    error("could not allocate memory");
+  }
+  (void) strcpy(zSep, s);
+  (void) strcpy(zEol, s1);
+  skip = asInteger(s_skip);
+
+  rc = RS_sqlite_import(db_connection, zTable, zFile, zSep, zEol, skip);
+
+  free(zTable);
+  free(zFile);
+  free(zSep);
+
+  PROTECT(output = NEW_LOGICAL(1));
+  LOGICAL_POINTER(output)[0] = rc;
+  UNPROTECT(1);
+  return output;
+}
+
+/* The following code comes directly from SQLite's shell.c, with
+ * obvious minor changes.
+ */
+int
+RS_sqlite_import(
+    sqlite3* db,
+    const char* zTable,          /* table must already exist */
+    const char* zFile,
+    const char* separator,
+    const char* eol,
+    int skip
+) {
+  sqlite3_stmt* pStmt;        /* A statement */
+  int rc;                     /* Result code */
+  int nCol;                   /* Number of columns in the table */
+  int nByte;                  /* Number of bytes in an SQL string */
+  int i, j;                   /* Loop counters */
+  int nSep;                   /* Number of bytes in separator[] */
+  char* zSql;                 /* An SQL statement */
+  char* zLine = NULL;         /* A single line of input from the file */
+  char** azCol;               /* zLine[] broken up into columns */
+  FILE* in;                   /* The input file */
+  int lineno = 0;             /* Line number of input file */
+  char* z;
+
+  nSep = strlen(separator);
+  if (nSep == 0) {
+    error("RS_sqlite_import: non-null separator required for import");
+  }
+  zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
+  if (zSql == 0) return 0;
+  nByte = strlen(zSql);
+  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+  sqlite3_free(zSql);
+  if (rc != SQLITE_OK) {
+    sqlite3_finalize(pStmt);
+    error("RS_sqlite_import: %s", sqlite3_errmsg(db));
+    nCol = 0;
+  } else {
+    nCol = sqlite3_column_count(pStmt);
+  }
+  sqlite3_finalize(pStmt);
+  if (nCol == 0) return 0;
+  zSql = malloc(nByte + 20 + nCol * 2);
+  if (zSql == 0) return 0;
+  sqlite3_snprintf(nByte + 20, zSql, "INSERT INTO '%q' VALUES(?", zTable);
+  j = strlen(zSql);
+  for (i = 1; i < nCol; i++) {
+    zSql[j++] = ',';
+    zSql[j++] = '?';
+  }
+  zSql[j++] = ')';
+  zSql[j] = 0;
+  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+  free(zSql);
+  if (rc != SQLITE_OK) {
+    sqlite3_finalize(pStmt);
+    error("RS_sqlite_import: %s", sqlite3_errmsg(db));
+  }
+  in = fopen(zFile, "rb");
+  if (in == 0) {
+    error("RS_sqlite_import: cannot open file %s", zFile);
+    sqlite3_finalize(pStmt);
+  }
+  azCol = malloc(sizeof(azCol[0]) * (nCol + 1));
+  if (azCol == 0) return 0;
+
+  while ((zLine = RS_sqlite_getline(in, eol)) != NULL) {
+    lineno++;
+    if (lineno <= skip) continue;
+    i = 0;
+    azCol[0] = zLine;
+    for (i = 0, z = zLine; *z && *z != '\n' && *z != '\r'; z++) {
+      if (*z == separator[0] && strncmp(z, separator, nSep) == 0) {
+        *z = 0;
+        i++;
+        if (i < nCol) {
+          azCol[i] = &z[nSep];
+          z += nSep - 1;
+        }
+      }
+    }
+    if (i + 1 != nCol) {
+      error("RS_sqlite_import: %s line %d expected %d columns of data but found %d",
+          zFile, lineno, nCol, i + 1);
+    }
+
+    for (i = 0; i < nCol; i++) {
+      if (azCol[i][0] == '\\' && azCol[i][1] == 'N') {   /* insert NULL for NA */
+        sqlite3_bind_null(pStmt, i + 1);
+      }
+      else {
+        sqlite3_bind_text(pStmt, i + 1, azCol[i], -1, SQLITE_STATIC);
+      }
+    }
+
+    rc = sqlite3_step(pStmt);
+    if (rc != SQLITE_DONE && rc != SQLITE_SCHEMA) {
+      sqlite3_finalize(pStmt);
+      error("RS_sqlite_import: %s", sqlite3_errmsg(db));
+    }
+    rc = sqlite3_reset(pStmt);
+    free(zLine);
+    zLine = NULL;
+    if (rc != SQLITE_OK) {
+      sqlite3_finalize(pStmt);
+      error("RS_sqlite_import: %s", sqlite3_errmsg(db));
+    }
+  }
+  free(azCol);
+  fclose(in);
+  sqlite3_finalize(pStmt);
+  return 1;
+}
+
+/* the following is only needed (?) on windows (getline is a GNU extension
+ * and it gave me problems with minGW).  Note that we drop the (UNIX)
+ * new line character.  The R function safe.write() explicitly uses
+ * eol = '\n' even on Windows.
+ */
+
+char*
+RS_sqlite_getline(FILE* in, const char* eol) {
+  /* caller must free memory */
+  char* buf, ceol;
+  size_t nc, i;
+  int c, j, neol;
+  int found_eol = 0;
+
+  nc = 1024;
+  i = 0;
+  buf = malloc(nc);
+  if (!buf) error("RS_sqlite_getline could not malloc");
+
+  neol = strlen(eol);  /* num of eol chars */
+  ceol = eol[neol - 1];  /* last char in eol */
+  while (TRUE) {
+    c = fgetc(in);
+    if (i == nc) {
+      nc = 2 * nc;
+      buf = (char*) realloc((void*) buf, nc);
+      if (!buf)
+        error("RS_sqlite_getline could not realloc");
+    }
+    if (c == EOF)
+      break;
+    buf[i++] = c;
+    if (c == ceol) {
+      /* see if we've got eol */
+      found_eol = 1;
+      for (j = neol - 1; j > 0; j--) {
+        if (buf[(i - 1) - j] != eol[neol - 1 - j]) {
+          found_eol = 0;
+          break;
+        }
+      }
+      if (found_eol) {
+        buf[i - neol] = '\0';   /* drop the newline char(s) */
+        break;
+      }
+    }
+  }
+
+  if (i == 0 || strlen(buf) == 0) {    /* empty line */
+    free(buf);
+    buf = NULL;
+  }
+
+  return buf;
+}
diff --git a/src/param_binding.c b/src/param_binding.c
index f20b25c..498edba 100644
--- a/src/param_binding.c
+++ b/src/param_binding.c
@@ -1,172 +1,165 @@
-#include "param_binding.h"
-#include "Rhelpers.h"
-#include <string.h>
-#include <stdlib.h>
+#include "rsqlite.h"
 
+static int*
+init_bindParams(int num_cols) {
+  int i;
+  /* FIXME: this could probably move to R_alloc */
+  int* used_index = malloc(sizeof(int) * num_cols);
+  if (!used_index) return NULL;
 
-static int *
-init_bindParams(int num_cols)
-{
-    int i;
-    /* FIXME: this could probably move to R_alloc */
-    int *used_index = (int *)malloc(sizeof(int) * num_cols);
-    if (!used_index) return NULL;
-
-    for (i = 0; i < num_cols; i++){
-        used_index[i] = -1;
-    }
-    return used_index;
+  for (i = 0; i < num_cols; i++) {
+    used_index[i] = -1;
+  }
+  return used_index;
 }
 
-static int first_not_used(const int *used_index, int len)
-{
-    int j, current = -1;
-    for (j = 0; j < len; j++) {
-        if (used_index[j] == -1) {
-            current = j;
-            break;
-        }
+static int first_not_used(const int* used_index, int len) {
+  int j, current = -1;
+  for (j = 0; j < len; j++) {
+    if (used_index[j] == -1) {
+      current = j;
+      break;
     }
-    return current;
+  }
+  return current;
 }
 
-void add_data_to_param_binding(RS_SQLite_bindParams *params, int i, SEXP data)
-{
-    int did_alloc = 1;
-    SEXP col_data;
-    if (isFactor(data)) {
-        col_data = Rf_asCharacterFactor(data);
-    }
-    else {
-        switch (TYPEOF(data)) {
-        case LGLSXP:
-            col_data = Rf_coerceVector(data, INTSXP);
-            break;
-        case INTSXP: case REALSXP: case STRSXP: case VECSXP: /* VECSXP => BLOB */
-            did_alloc = 0;
-            col_data = data;
-            break;
-        default:
-            col_data = Rf_coerceVector(data, STRSXP);
-        }
-    }
-    /* Since params->data is preserved, this provides protection from
-       GC */
-    SET_VECTOR_ELT(params->data, i, col_data);
-    if (!did_alloc) {
-        /* we want to hold on to the data columns and make sure that
-           they are duplicated on modification so our copy is
-           preserved. */
-        SET_NAMED(data, 2);
+void add_data_to_param_binding(RSQLiteParams* params, int i, SEXP data) {
+  int did_alloc = 1;
+  SEXP col_data;
+  if (isFactor(data)) {
+    col_data = Rf_asCharacterFactor(data);
+  }
+  else {
+    switch (TYPEOF(data)) {
+      case LGLSXP:
+        col_data = Rf_coerceVector(data, INTSXP);
+        break;
+      case INTSXP:
+      case REALSXP:
+      case STRSXP:
+      case VECSXP: /* VECSXP => BLOB */
+        did_alloc = 0;
+        col_data = data;
+        break;
+      default:
+        col_data = Rf_coerceVector(data, STRSXP);
     }
+  }
+  /* Since params->data is preserved, this provides protection from
+     GC */
+  SET_VECTOR_ELT(params->data, i, col_data);
+  if (!did_alloc) {
+    /* we want to hold on to the data columns and make sure that
+       they are duplicated on modification so our copy is
+       preserved. */
+    SET_NAMED(data, 2);
+  }
 }
 
-static int find_by_name(const char *paramName, SEXP colNames)
-{
-    int i = 0, len = length(colNames), ans = -1;
-    const char *pname = paramName + 1;    /* skip past initial bind identifier */
-    for (i = 0; i < len; i++) {
-        const char *s = CHAR(STRING_ELT(colNames, i));
-        if (strcmp(pname, s) == 0) {
-            ans = i;
-            break;
-        }
+static int find_by_name(const char* paramName, SEXP colNames) {
+  int i = 0, len = length(colNames), ans = -1;
+  const char* pname = paramName + 1;    /* skip past initial bind identifier */
+  for (i = 0; i < len; i++) {
+    const char* s = CHAR(STRING_ELT(colNames, i));
+    if (strcmp(pname, s) == 0) {
+      ans = i;
+      break;
     }
-    return ans;
+  }
+  return ans;
 }
 
-RS_SQLite_bindParams *
+RSQLiteParams*
 RS_SQLite_createParameterBinding(int n, SEXP bind_data,
-                                 sqlite3_stmt *stmt, char *errorMsg)
-{
-    RS_SQLite_bindParams *params;
-    int i, *used_index, current, num_cols, err = 0;
-    SEXP colNames, col_data;
+                                 sqlite3_stmt* stmt, char* errorMsg) {
+  RSQLiteParams* params;
+  int i, * used_index, current, num_cols, err = 0;
+  SEXP colNames, col_data;
 
-    colNames = Rf_getAttrib(bind_data, R_NamesSymbol);
-    num_cols = length(colNames);
-    if (num_cols < n) {
-        sprintf(errorMsg,
-                "incomplete data binding: expected %d parameters, got %d",
-                n, num_cols);
-        return NULL;
-    }
+  colNames = Rf_getAttrib(bind_data, R_NamesSymbol);
+  num_cols = length(colNames);
+  if (num_cols < n) {
+    sprintf(errorMsg,
+        "incomplete data binding: expected %d parameters, got %d",
+        n, num_cols);
+    return NULL;
+  }
 
-    /* could this move to R_alloc? */
-    params = (RS_SQLite_bindParams *)malloc(sizeof(RS_SQLite_bindParams));
-    if (!params) {
-        sprintf(errorMsg, "could not allocate memory");
-        return NULL;
-    }
-    params->count = n;
-    params->row_count = length(VECTOR_ELT(bind_data, 0));
-    params->rows_used = 0;
-    params->row_complete = 1;
-    /* XXX: if the R allocation fails, we leak memory */
-    params->data = Rf_allocVector(VECSXP, n);
-    R_PreserveObject(params->data);
+  /* could this move to R_alloc? */
+  params = malloc(sizeof(RSQLiteParams));
+  if (!params) {
+    sprintf(errorMsg, "could not allocate memory");
+    return NULL;
+  }
+  params->count = n;
+  params->row_count = length(VECTOR_ELT(bind_data, 0));
+  params->rows_used = 0;
+  params->row_complete = 1;
+  /* XXX: if the R allocation fails, we leak memory */
+  params->data = Rf_allocVector(VECSXP, n);
+  R_PreserveObject(params->data);
 
-    used_index = init_bindParams(num_cols);
-    if (!used_index) {
-        RS_SQLite_freeParameterBinding(&params);
-        sprintf(errorMsg, "could not allocate memory");
-        return NULL;
-    }
+  used_index = init_bindParams(num_cols);
+  if (!used_index) {
+    RS_SQLite_freeParameterBinding(&params);
+    sprintf(errorMsg, "could not allocate memory");
+    return NULL;
+  }
 
-    for (i = 0; i < n; i++) {
-        const char *paramName = sqlite3_bind_parameter_name(stmt, i + 1);
-        current = -1;
-        if (paramName == NULL) { 
-            /* assume the first non-used column is the one we want */
-            current = first_not_used(used_index, num_cols);
-            if (current >= 0) {
-                used_index[current] = 1;
-            } else {
-                sprintf(errorMsg,
-                        "unable to bind data for positional parameter %d", i+1);
-                err = 1;
-                break;
-            }
+  for (i = 0; i < n; i++) {
+    const char* paramName = sqlite3_bind_parameter_name(stmt, i + 1);
+    current = -1;
+    if (paramName == NULL) {
+      /* assume the first non-used column is the one we want */
+      current = first_not_used(used_index, num_cols);
+      if (current >= 0) {
+        used_index[current] = 1;
+      } else {
+        sprintf(errorMsg,
+            "unable to bind data for positional parameter %d", i + 1);
+        err = 1;
+        break;
+      }
+    } else {
+      current = find_by_name(paramName, colNames);
+      if (current >= 0) {
+        if (used_index[current] == -1) {
+          used_index[current] = 1;
         } else {
-            current = find_by_name(paramName, colNames);
-            if (current >= 0) {
-                if (used_index[current] == -1) {
-                    used_index[current] = 1;
-                } else {
-                    sprintf(errorMsg,
-                            "attempted to re-bind column [%s] to positional "
-                            "parameter %d",
-                            CHAR(STRING_ELT(colNames, current)), i+1);
-                    err = 1;
-                    break;
-                }
-            } else { /* current < 0 */
-                /* FIXME: we should pass in size of errorMsg buffer and use
-                   snprint since size of paramName is unknown.
-                 */
-                sprintf(errorMsg,
-                        "unable to bind data for parameter '%s'", paramName);
-                err = 1;
-                break;
-            }
-        }
-        if (!err) {
-            col_data = VECTOR_ELT(bind_data, current);
-            add_data_to_param_binding(params, i, col_data);
+          sprintf(errorMsg,
+              "attempted to re-bind column [%s] to positional "
+                  "parameter %d",
+              CHAR(STRING_ELT(colNames, current)), i + 1);
+          err = 1;
+          break;
         }
+      } else { /* current < 0 */
+        /* FIXME: we should pass in size of errorMsg buffer and use
+           snprint since size of paramName is unknown.
+         */
+        sprintf(errorMsg,
+            "unable to bind data for parameter '%s'", paramName);
+        err = 1;
+        break;
+      }
     }
-    free(used_index);
-    used_index = NULL;
-    if (err) {
-        RS_SQLite_freeParameterBinding(&params);
+    if (!err) {
+      col_data = VECTOR_ELT(bind_data, current);
+      add_data_to_param_binding(params, i, col_data);
     }
-    return params;
+  }
+  free(used_index);
+  used_index = NULL;
+  if (err) {
+    RS_SQLite_freeParameterBinding(&params);
+  }
+  return params;
 }
 
 void
-RS_SQLite_freeParameterBinding(RS_SQLite_bindParams **params)
-{
-    if ((*params)->data) R_ReleaseObject((*params)->data);
-    free(*params);
-    *params = NULL;
+RS_SQLite_freeParameterBinding(RSQLiteParams** params) {
+  if ((*params)->data) R_ReleaseObject((*params)->data);
+  free(*params);
+  *params = NULL;
 }
diff --git a/src/param_binding.h b/src/param_binding.h
deleted file mode 100644
index 57b365c..0000000
--- a/src/param_binding.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef PARAM_BINDING_H_
-#define PARAM_BINDING_H_
-
-#include <Rinternals.h>
-#include "sqlite.h"
-
-typedef struct st_sqlite_bindparams {
-    int count;
-    int row_count;
-    int rows_used;
-    int row_complete;
-    SEXP data;
-} RS_SQLite_bindParams;
-
-
-RS_SQLite_bindParams *
-RS_SQLite_createParameterBinding(int n,
-                                 SEXP bind_data, sqlite3_stmt *stmt,
-                                 char *errorMsg);
-
-void RS_SQLite_freeParameterBinding(RS_SQLite_bindParams **);
-
-#endif  /* PARAM_BINDING_H_ */
diff --git a/src/quick_column.c b/src/quick_column.c
new file mode 100644
index 0000000..45db46f
--- /dev/null
+++ b/src/quick_column.c
@@ -0,0 +1,130 @@
+/* 
+ * Copyright (C) 1999-2002 The Omega Project for Statistical Computing
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "rsqlite.h"
+
+int RS_SQLite_get_row_count(sqlite3* db, const char* tname) {
+  char* sqlQuery;
+  const char* sqlFmt = "select rowid from %s order by rowid desc limit 1";
+  int qrylen = strlen(sqlFmt);
+  int rc = 0;
+  int ans;
+  sqlite3_stmt* stmt;
+  const char* tail;
+
+  qrylen += strlen(tname) + 1;
+  sqlQuery = (char*) R_alloc(qrylen, sizeof(char));
+  snprintf(sqlQuery, qrylen, sqlFmt, tname);
+  rc = sqlite3_prepare_v2(db, sqlQuery, -1, &stmt, &tail);
+  if (rc != SQLITE_OK) {
+    sqlite3_finalize(stmt);
+    error("SQL error: %s\n", sqlite3_errmsg(db));
+  }
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
+    sqlite3_finalize(stmt);
+    error("SQL error: %s\n", sqlite3_errmsg(db));
+  }
+  ans = sqlite3_column_int(stmt, 0);
+  sqlite3_finalize(stmt);
+  return ans;
+}
+
+
+SEXP RS_SQLite_quick_column(SEXP conHandle, SEXP table, SEXP column) {
+  SEXP ans = R_NilValue, rawv;
+  SQLiteConnection* con = rsqlite_connection_from_handle(conHandle);
+  sqlite3* db_connection = (sqlite3*) con->drvConnection;
+  sqlite3_stmt* stmt = NULL;
+  int numrows, rc, i = 0, col_type, * intans = NULL, blob_len;
+  char sqlQuery[500];
+  const char* table_name = NULL, * column_name = NULL, * tail = NULL;
+  double* doubleans = NULL;
+  const Rbyte* blob_data;
+
+  table_name = CHAR(STRING_ELT(table, 0));
+  column_name = CHAR(STRING_ELT(column, 0));
+  numrows = RS_SQLite_get_row_count(db_connection, table_name);
+  snprintf(sqlQuery, sizeof(sqlQuery), "select %s from %s",
+      column_name, table_name);
+
+  rc = sqlite3_prepare_v2(db_connection, sqlQuery, strlen(sqlQuery), &stmt, &tail);
+  /* FIXME: how should we be handling errors?
+  Could either follow the pattern in the rest of the package or
+  start to use the condition system and raise specific conditions.
+  */
+  if (rc != SQLITE_OK) {
+    error("SQL error: %s\n", sqlite3_errmsg(db_connection));
+  }
+
+  rc = sqlite3_step(stmt);
+  if (rc != SQLITE_ROW) {
+    error("SQL error: %s\n", sqlite3_errmsg(db_connection));
+  }
+  col_type = sqlite3_column_type(stmt, 0);
+  switch (col_type) {
+    case SQLITE_INTEGER:
+      PROTECT(ans = allocVector(INTSXP, numrows));
+      intans = INTEGER(ans);
+      break;
+    case SQLITE_FLOAT:
+      PROTECT(ans = allocVector(REALSXP, numrows));
+      doubleans = REAL(ans);
+      break;
+    case SQLITE_TEXT:
+      PROTECT(ans = allocVector(STRSXP, numrows));
+      break;
+    case SQLITE_NULL:
+      error("RS_SQLite_quick_column: encountered NULL column");
+      break;
+    case SQLITE_BLOB:
+      PROTECT(ans = allocVector(VECSXP, numrows));
+      break;
+    default:
+      error("RS_SQLite_quick_column: unknown column type %d", col_type);
+  }
+
+  i = 0;
+  while (rc == SQLITE_ROW && i < numrows) {
+    switch (col_type) {
+      case SQLITE_INTEGER:
+        intans[i] = sqlite3_column_int(stmt, 0);
+        break;
+      case SQLITE_FLOAT:
+        doubleans[i] = sqlite3_column_double(stmt, 0);
+        break;
+      case SQLITE_TEXT:
+        SET_STRING_ELT(ans, i, /* cast for -Wall */
+            mkChar((char*) sqlite3_column_text(stmt, 0)));
+        break;
+      case SQLITE_BLOB:
+        blob_data = (const Rbyte*) sqlite3_column_blob(stmt, 0);
+        blob_len = sqlite3_column_bytes(stmt, 0);
+        PROTECT(rawv = allocVector(RAWSXP, blob_len));
+        memcpy(RAW(rawv), blob_data, blob_len * sizeof(Rbyte));;
+        SET_VECTOR_ELT(ans, i, rawv);
+        UNPROTECT(1);
+        break;
+    }
+    i++;
+    rc = sqlite3_step(stmt);
+  }
+  sqlite3_finalize(stmt);
+  UNPROTECT(1);
+  return ans;
+}
diff --git a/src/result.c b/src/result.c
new file mode 100644
index 0000000..aac7519
--- /dev/null
+++ b/src/result.c
@@ -0,0 +1,180 @@
+/* 
+ * Copyright (C) 1999-2002 The Omega Project for Statistical Computing
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "rsqlite.h"
+
+void rsqlite_result_alloc(SQLiteConnection* con) {
+  SQLiteResult* result = malloc(sizeof(SQLiteResult));
+  if (!result) {
+    error("could not malloc dbResultSet");
+  }
+  result->drvResultSet = NULL;
+  result->drvData = NULL;
+  result->statement = NULL;
+  result->isSelect = -1;
+  result->rowsAffected = -1;
+  result->rowCount = 0;
+  result->completed = -1;
+  result->fields = NULL;
+
+  con->resultSet = result;
+}
+
+void rsqlite_result_free(SQLiteConnection* con) {
+  SQLiteResult* result = con->resultSet;
+
+  if (result->drvResultSet) {
+    sqlite3_finalize(result->drvResultSet);
+    result->drvResultSet = NULL;
+  }
+  if (result->drvData) {
+    RSQLiteParams* params = result->drvData;
+    R_ReleaseObject(params->data);
+    RS_SQLite_freeParameterBinding(&params);
+    result->drvData = NULL;
+  }
+
+  if (result->statement)
+    free(result->statement);
+  if (result->fields)
+    rsqlite_fields_free(result->fields);
+
+  free(result);
+
+  con->resultSet = NULL;
+}
+
+SEXP rsqlite_result_free_handle(SEXP handle) {
+  SQLiteConnection* con = rsqlite_connection_from_handle(handle);
+  rsqlite_result_free(con);
+
+  return ScalarLogical(1);
+}
+
+
+SQLiteResult* rsqlite_result_from_handle(SEXP handle) {
+  SQLiteConnection* con = rsqlite_connection_from_handle(handle);
+
+  if (!con->resultSet) {
+    error("Invalid result");
+  }
+
+  return con->resultSet;
+}
+
+SEXP rsqlite_result_valid(SEXP handle) {
+  SQLiteConnection* con = rsqlite_connection_from_handle(handle);
+  if (!con->resultSet)
+    return ScalarLogical(0);
+
+  return ScalarLogical(1);
+}
+
+SEXP rsqlite_result_info(SEXP handle) {
+  SQLiteResult* result = rsqlite_result_from_handle(handle);
+
+  SEXP info = PROTECT(allocVector(VECSXP, 6));
+  SEXP info_nms = PROTECT(allocVector(STRSXP, 6));
+  SET_NAMES(info, info_nms);
+  UNPROTECT(1);
+
+  int i = 0;
+  SET_STRING_ELT(info_nms, i, mkChar("statement"));
+  SET_VECTOR_ELT(info, i++, mkString(result->statement));
+
+  SET_STRING_ELT(info_nms, i, mkChar("isSelect"));
+  SET_VECTOR_ELT(info, i++, ScalarInteger(result->isSelect));
+
+  SET_STRING_ELT(info_nms, i, mkChar("rowsAffected"));
+  SET_VECTOR_ELT(info, i++, ScalarInteger(result->rowsAffected));
+
+  SET_STRING_ELT(info_nms, i, mkChar("rowCount"));
+  SET_VECTOR_ELT(info, i++, ScalarInteger(result->rowCount));
+
+  SET_STRING_ELT(info_nms, i, mkChar("completed"));
+  SET_VECTOR_ELT(info, i++, ScalarInteger(result->completed));
+
+  SET_STRING_ELT(info_nms, i, mkChar("fields"));
+  SEXP fields = PROTECT(rsqlite_field_info(result->fields));
+  SET_VECTOR_ELT(info, i++, fields);
+  UNPROTECT(1);
+
+  UNPROTECT(1);
+  return info;
+}
+
+SQLiteFields* rsqlite_result_fields(SQLiteResult* result) {
+  // Already computed, return cached result
+  if (result->fields)
+    return result->fields;
+
+  sqlite3_stmt* db_statement = (sqlite3_stmt*) result->drvResultSet;
+
+  int ncol = sqlite3_column_count(db_statement);
+  SQLiteFields* flds = rsqlite_fields_alloc(ncol);
+
+  for (int j = 0; j < ncol; j++) {
+    char* col_name = (char*) sqlite3_column_name(db_statement, j);
+    if (col_name) {
+      flds->name[j] = RS_DBI_copyString(col_name);
+    } else {
+      // weird failure
+      rsqlite_fields_free(flds);
+      flds = NULL;
+      return NULL;
+    }
+    // We do our best to determine the type of the column. If the first row 
+    // retrieved contains a NULL and does not reference a table column, we 
+    // give up.
+    int col_type = sqlite3_column_type(db_statement, j);
+    if (col_type == SQLITE_NULL) {
+      /* try to get type from origin column */
+      const char* col_decltype = sqlite3_column_decltype(db_statement, j);
+      col_type = SQLite_decltype_to_type(col_decltype);
+    }
+    switch (col_type) {
+      case SQLITE_INTEGER:
+        flds->type[j] = SQLITE_TYPE_INTEGER;
+        flds->Sclass[j] = INTSXP;
+        flds->length[j] = sizeof(int);
+        break;
+      case SQLITE_FLOAT:
+        flds->type[j] = SQLITE_TYPE_REAL;
+        flds->Sclass[j] = REALSXP;
+        flds->length[j] = sizeof(double);
+        break;
+      case SQLITE_TEXT:
+        flds->type[j] = SQLITE_TYPE_TEXT;
+        flds->Sclass[j] = STRSXP;
+        flds->length[j] = NA_INTEGER;
+        break;
+      case SQLITE_BLOB:
+        flds->type[j] = SQLITE_TYPE_BLOB;
+        flds->Sclass[j] = VECSXP;
+        flds->length[j] = NA_INTEGER;
+        break;
+      case SQLITE_NULL:
+        error("NULL column handling not implemented");
+        break;
+      default:
+        error("unknown column type %d", col_type);
+    }
+  }
+  result->fields = flds;
+  return flds;
+}
diff --git a/src/rsqlite.h b/src/rsqlite.h
new file mode 100644
index 0000000..84d717a
--- /dev/null
+++ b/src/rsqlite.h
@@ -0,0 +1,163 @@
+#ifndef _RSQLITE_H
+#define _RSQLITE_H 1
+/*  
+ * Copyright (C) 1999-2002 The Omega Project for Statistical Computing.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <R.h>
+#include <Rdefines.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include "sqlite.h"
+
+// Objects =====================================================================
+
+typedef struct RSQLiteParams {
+    int count;
+    int row_count;
+    int rows_used;
+    int row_complete;
+    SEXP data;
+} RSQLiteParams;
+
+/* First, the following fully describes the field output by a select
+ * (or select-like) statement, and the mappings from the internal
+ * database types to S classes.  This structure contains the info we need
+ * to build the R/S list (or data.frame) that will receive the SQL
+ * output.
+ */
+typedef struct SQLiteFields {
+  int num_fields;
+  char  **name;        /* DBMS field names */
+  int  *type;          /* DBMS types */
+  int  *length;        /* DBMS lengths in bytes */
+  SEXPTYPE *Sclass;    /* R class */
+} SQLiteFields;
+
+typedef struct RSQLiteException {
+   int  errorNum;
+   char *errorMsg;
+} RSQLiteException;
+
+/* The RS-DBI resultSet consists of a pointer to the actual DBMS 
+ * resultSet (e.g., MySQL, Oracle) possibly NULL,  plus the fields 
+ * defined by the RS-DBI implementation. 
+ */
+typedef struct SQLiteResult {
+  sqlite3_stmt* drvResultSet;   /* the actual (driver's) cursor/result set */
+  RSQLiteParams* drvData;        /* a pointer to driver-specific data */
+  int  resultSetId;  
+  int  isSelect;        /* boolean for testing SELECTs */
+  char  *statement;      /* SQL statement */
+  int  rowsAffected;    /* used by non-SELECT statements */
+  int  rowCount;        /* rows fetched so far (SELECT-types)*/
+  int  completed;       /* have we fetched all rows? */
+  SQLiteFields *fields;
+} SQLiteResult;
+
+enum SQLITE_TYPE {
+  SQLITE_TYPE_NULL,
+  SQLITE_TYPE_INTEGER,
+  SQLITE_TYPE_REAL,
+  SQLITE_TYPE_TEXT,
+  SQLITE_TYPE_BLOB
+};
+
+typedef struct SQLiteConnection {
+  sqlite3* drvConnection;  
+  SQLiteResult  *resultSet;
+  RSQLiteException *exception;
+} SQLiteConnection;
+
+typedef struct SQLiteDriver {
+  int shared_cache;                /* use SQLite shared cache? */
+  int num_con;                     /* num of opened connections */
+  int counter;                     /* num of connections handled so far*/
+  int fetch_default_rec;           /* default num of records per fetch */
+} SQLiteDriver;
+
+// Functions ===================================================================
+
+// Fields ----------------------------------------------------------------------
+
+SQLiteFields*  rsqlite_fields_alloc(int num_fields);
+void           rsqlite_fields_free(SQLiteFields *flds);
+SEXP           rsqlite_field_info(SQLiteFields *flds);
+
+// Result ----------------------------------------------------------------------
+
+void           rsqlite_result_alloc(SQLiteConnection* con);
+void           rsqlite_result_free(SQLiteConnection* con);
+SEXP           rsqlite_result_free_handle(SEXP con);
+SQLiteResult*  rsqlite_result_from_handle(SEXP handle);
+SEXP           rsqlite_result_valid(SEXP handle);
+SEXP           rsqlite_result_info(SEXP handle);
+SQLiteFields*  rsqlite_result_fields(SQLiteResult* handle);
+
+void           rsqlite_output_alloc(SEXP output, SQLiteFields *flds, int num_rec);
+void           rsqlite_output_expand(SEXP output, SQLiteFields *flds, int num_rec);
+
+SEXP           rsqlite_query_send(SEXP handle, SEXP statement, SEXP bind_data);
+SEXP           rsqlite_query_fetch(SEXP handle, SEXP max_rec);
+
+// Param binding 
+
+RSQLiteParams* RS_SQLite_createParameterBinding(int n, SEXP bind_data, sqlite3_stmt *stmt, char *errorMsg);
+void RS_SQLite_freeParameterBinding(RSQLiteParams **);
+
+// Exception -------------------------------------------------------------------
+
+void rsqlite_exception_set(SQLiteConnection *con, int err_no, const char *err_msg);
+void rsqlite_exception_free(SQLiteConnection *con);
+SEXP rsqlite_exception_info(SEXP handle);
+
+// Connection ------------------------------------------------------------------
+
+SQLiteConnection* rsqlite_connection_from_handle(SEXP handle);
+SEXP              rsqlite_connection_create(SEXP dbfile, SEXP allow_ext, SEXP s_flags, SEXP s_vfs);
+SEXP              rsqlite_connection_destroy(SEXP conHandle);
+SEXP              rsqlite_connection_valid(SEXP dbObj);
+SEXP              rsqlite_connection_info(SEXP conHandle);
+
+// Driver ----------------------------------------------------------------------
+
+SQLiteDriver* rsqlite_driver();
+void          rsqlite_driver_init(SEXP records_, SEXP cache_);
+SEXP          rsqlite_driver_close();
+SEXP          rsqlite_driver_valid();
+SEXP          rsqlite_driver_info();
+
+// Utilities -------------------------------------------------------------------
+
+char* RS_DBI_copyString(const char *str);
+SEXP RS_DBI_copyFields(SQLiteFields *flds);
+int SQLite_decltype_to_type(const char *decltype);
+SEXP RS_SQLite_importFile(SEXP conHandle, SEXP s_tablename, SEXP s_filename, SEXP s_separator, SEXP s_obj, SEXP s_skip);
+char * RS_sqlite_getline(FILE *in, const char *eol);
+SEXP RS_SQLite_copy_database(SEXP fromConHandle, SEXP toConHandle);
+int RS_sqlite_import(sqlite3 *db, const char *zTable, const char *zFile, const char *separator, const char *eol, int skip);
+char* field_type(int type);
+
+#ifdef __cplusplus 
+}
+#endif
+#endif   /* _RSQLITE_H */
diff --git a/src/sqlite-all.c b/src/sqlite-all.c
index eab541f..6226272 100644
--- a/src/sqlite-all.c
+++ b/src/sqlite-all.c
@@ -1,3 +1,3 @@
-#ifdef RSQLITE_USE_BUNDLED_SQLITE || WIN32
+#ifdef RSQLITE_USE_BUNDLED_SQLITE
 #  include "sqlite/sqlite3.c"
 #endif
diff --git a/src/sqlite-all.o-68d98681 b/src/sqlite-all.o-68d98681
new file mode 100644
index 0000000..e69de29
diff --git a/src/sqlite/sqlite3.c b/src/sqlite/sqlite3.c
index deef460..c1278e6 100644
--- a/src/sqlite/sqlite3.c
+++ b/src/sqlite/sqlite3.c
@@ -1,6 +1,6 @@
 /******************************************************************************
 ** This file is an amalgamation of many separate C source files from SQLite
-** version 3.7.17.  By combining all the individual C code files into this 
+** version 3.8.6.  By combining all the individual C code files into this 
 ** single large file, the entire code can be compiled as a single translation
 ** unit.  This allows many compilers to do optimizations that would not be
 ** possible if the files were compiled separately.  Performance improvements
@@ -60,6 +60,11 @@
 ** in Red Hat 6.0, so the code won't work.  Hence, for maximum binary
 ** portability you should omit LFS.
 **
+** The previous paragraph was written in 2005.  (This paragraph is written
+** on 2008-11-28.) These days, all Linux kernels support large files, so
+** you should probably leave LFS enabled.  But some embedded platforms might
+** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
+**
 ** Similar is true for Mac OS X.  LFS is only supported on Mac OS X 9 and later.
 */
 #ifndef SQLITE_DISABLE_LFS
@@ -71,502 +76,41 @@
 #endif
 
 /*
-** Include the configuration header output by 'configure' if we're using the
-** autoconf-based build
-*/
-#ifdef _HAVE_SQLITE_CONFIG_H
-#include "config.h"
-#endif
-
-/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
-/************** Begin file sqliteLimit.h *************************************/
-/*
-** 2007 May 7
-**
-** The author disclaims copyright to this source code.  In place of
-** a legal notice, here is a blessing:
-**
-**    May you do good and not evil.
-**    May you find forgiveness for yourself and forgive others.
-**    May you share freely, never taking more than you give.
-**
-*************************************************************************
-** 
-** This file defines various limits of what SQLite can process.
-*/
-
-/*
-** The maximum length of a TEXT or BLOB in bytes.   This also
-** limits the size of a row in a table or index.
-**
-** The hard limit is the ability of a 32-bit signed integer
-** to count the size: 2^31-1 or 2147483647.
-*/
-#ifndef SQLITE_MAX_LENGTH
-# define SQLITE_MAX_LENGTH 1000000000
-#endif
-
-/*
-** This is the maximum number of
-**
-**    * Columns in a table
-**    * Columns in an index
-**    * Columns in a view
-**    * Terms in the SET clause of an UPDATE statement
-**    * Terms in the result set of a SELECT statement
-**    * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
-**    * Terms in the VALUES clause of an INSERT statement
-**
-** The hard upper limit here is 32676.  Most database people will
-** tell you that in a well-normalized database, you usually should
-** not have more than a dozen or so columns in any table.  And if
-** that is the case, there is no point in having more than a few
-** dozen values in any of the other situations described above.
-*/
-#ifndef SQLITE_MAX_COLUMN
-# define SQLITE_MAX_COLUMN 2000
-#endif
-
-/*
-** The maximum length of a single SQL statement in bytes.
-**
-** It used to be the case that setting this value to zero would
-** turn the limit off.  That is no longer true.  It is not possible
-** to turn this limit off.
-*/
-#ifndef SQLITE_MAX_SQL_LENGTH
-# define SQLITE_MAX_SQL_LENGTH 1000000000
-#endif
-
-/*
-** The maximum depth of an expression tree. This is limited to 
-** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might 
-** want to place more severe limits on the complexity of an 
-** expression.
-**
-** A value of 0 used to mean that the limit was not enforced.
-** But that is no longer true.  The limit is now strictly enforced
-** at all times.
-*/
-#ifndef SQLITE_MAX_EXPR_DEPTH
-# define SQLITE_MAX_EXPR_DEPTH 1000
-#endif
-
-/*
-** The maximum number of terms in a compound SELECT statement.
-** The code generator for compound SELECT statements does one
-** level of recursion for each term.  A stack overflow can result
-** if the number of terms is too large.  In practice, most SQL
-** never has more than 3 or 4 terms.  Use a value of 0 to disable
-** any limit on the number of terms in a compount SELECT.
-*/
-#ifndef SQLITE_MAX_COMPOUND_SELECT
-# define SQLITE_MAX_COMPOUND_SELECT 500
-#endif
-
-/*
-** The maximum number of opcodes in a VDBE program.
-** Not currently enforced.
-*/
-#ifndef SQLITE_MAX_VDBE_OP
-# define SQLITE_MAX_VDBE_OP 25000
-#endif
-
-/*
-** The maximum number of arguments to an SQL function.
-*/
-#ifndef SQLITE_MAX_FUNCTION_ARG
-# define SQLITE_MAX_FUNCTION_ARG 127
-#endif
-
-/*
-** The maximum number of in-memory pages to use for the main database
-** table and for temporary tables.  The SQLITE_DEFAULT_CACHE_SIZE
-*/
-#ifndef SQLITE_DEFAULT_CACHE_SIZE
-# define SQLITE_DEFAULT_CACHE_SIZE  2000
-#endif
-#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
-# define SQLITE_DEFAULT_TEMP_CACHE_SIZE  500
-#endif
-
-/*
-** The default number of frames to accumulate in the log file before
-** checkpointing the database in WAL mode.
-*/
-#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
-# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT  1000
-#endif
-
-/*
-** The maximum number of attached databases.  This must be between 0
-** and 62.  The upper bound on 62 is because a 64-bit integer bitmap
-** is used internally to track attached databases.
-*/
-#ifndef SQLITE_MAX_ATTACHED
-# define SQLITE_MAX_ATTACHED 10
-#endif
-
-
-/*
-** The maximum value of a ?nnn wildcard that the parser will accept.
-*/
-#ifndef SQLITE_MAX_VARIABLE_NUMBER
-# define SQLITE_MAX_VARIABLE_NUMBER 999
-#endif
-
-/* Maximum page size.  The upper bound on this value is 65536.  This a limit
-** imposed by the use of 16-bit offsets within each page.
-**
-** Earlier versions of SQLite allowed the user to change this value at
-** compile time. This is no longer permitted, on the grounds that it creates
-** a library that is technically incompatible with an SQLite library 
-** compiled with a different limit. If a process operating on a database 
-** with a page-size of 65536 bytes crashes, then an instance of SQLite 
-** compiled with the default page-size limit will not be able to rollback 
-** the aborted transaction. This could lead to database corruption.
-*/
-#ifdef SQLITE_MAX_PAGE_SIZE
-# undef SQLITE_MAX_PAGE_SIZE
-#endif
-#define SQLITE_MAX_PAGE_SIZE 65536
-
-
-/*
-** The default size of a database page.
-*/
-#ifndef SQLITE_DEFAULT_PAGE_SIZE
-# define SQLITE_DEFAULT_PAGE_SIZE 1024
-#endif
-#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
-# undef SQLITE_DEFAULT_PAGE_SIZE
-# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
-#endif
-
-/*
-** Ordinarily, if no value is explicitly provided, SQLite creates databases
-** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
-** device characteristics (sector-size and atomic write() support),
-** SQLite may choose a larger value. This constant is the maximum value
-** SQLite will choose on its own.
-*/
-#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
-# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
-#endif
-#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
-# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
-# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
-#endif
-
-
-/*
-** Maximum number of pages in one database file.
-**
-** This is really just the default value for the max_page_count pragma.
-** This value can be lowered (or raised) at run-time using that the
-** max_page_count macro.
-*/
-#ifndef SQLITE_MAX_PAGE_COUNT
-# define SQLITE_MAX_PAGE_COUNT 1073741823
-#endif
-
-/*
-** Maximum length (in bytes) of the pattern in a LIKE or GLOB
-** operator.
-*/
-#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
-# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
-#endif
-
-/*
-** Maximum depth of recursion for triggers.
-**
-** A value of 1 means that a trigger program will not be able to itself
-** fire any triggers. A value of 0 means that no trigger programs at all 
-** may be executed.
-*/
-#ifndef SQLITE_MAX_TRIGGER_DEPTH
-# define SQLITE_MAX_TRIGGER_DEPTH 1000
-#endif
-
-/************** End of sqliteLimit.h *****************************************/
-/************** Continuing where we left off in sqliteInt.h ******************/
-
-/* Disable nuisance warnings on Borland compilers */
-#if defined(__BORLANDC__)
-#pragma warn -rch /* unreachable code */
-#pragma warn -ccc /* Condition is always true or false */
-#pragma warn -aus /* Assigned value is never used */
-#pragma warn -csu /* Comparing signed and unsigned */
-#pragma warn -spa /* Suspicious pointer arithmetic */
-#endif
-
-/* Needed for various definitions... */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
-#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
-# define _BSD_SOURCE
-#endif
-
-/*
-** Include standard header files as necessary
-*/
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-/*
-** The following macros are used to cast pointers to integers and
-** integers to pointers.  The way you do this varies from one compiler
-** to the next, so we have developed the following set of #if statements
-** to generate appropriate macros for a wide range of compilers.
-**
-** The correct "ANSI" way to do this is to use the intptr_t type. 
-** Unfortunately, that typedef is not available on all compilers, or
-** if it is available, it requires an #include of specific headers
-** that vary from one machine to the next.
-**
-** Ticket #3860:  The llvm-gcc-4.2 compiler from Apple chokes on
-** the ((void*)&((char*)0)[X]) construct.  But MSVC chokes on ((void*)(X)).
-** So we have to define the macros in different ways depending on the
-** compiler.
-*/
-#if defined(__PTRDIFF_TYPE__)  /* This case should work for GCC */
-# define SQLITE_INT_TO_PTR(X)  ((void*)(__PTRDIFF_TYPE__)(X))
-# define SQLITE_PTR_TO_INT(X)  ((int)(__PTRDIFF_TYPE__)(X))
-#elif !defined(__GNUC__)       /* Works for compilers other than LLVM */
-# define SQLITE_INT_TO_PTR(X)  ((void*)&((char*)0)[X])
-# define SQLITE_PTR_TO_INT(X)  ((int)(((char*)X)-(char*)0))
-#elif defined(HAVE_STDINT_H)   /* Use this case if we have ANSI headers */
-# define SQLITE_INT_TO_PTR(X)  ((void*)(intptr_t)(X))
-# define SQLITE_PTR_TO_INT(X)  ((int)(intptr_t)(X))
-#else                          /* Generates a warning - but it always works */
-# define SQLITE_INT_TO_PTR(X)  ((void*)(X))
-# define SQLITE_PTR_TO_INT(X)  ((int)(X))
-#endif
-
-/*
-** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
-** 0 means mutexes are permanently disable and the library is never
-** threadsafe.  1 means the library is serialized which is the highest
-** level of threadsafety.  2 means the libary is multithreaded - multiple
-** threads can use SQLite as long as no two threads try to use the same
-** database connection at the same time.
-**
-** Older versions of SQLite used an optional THREADSAFE macro.
-** We support that for legacy.
-*/
-#if !defined(SQLITE_THREADSAFE)
-# if defined(THREADSAFE)
-#   define SQLITE_THREADSAFE THREADSAFE
-# else
-#   define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
-# endif
-#endif
-
-/*
-** Powersafe overwrite is on by default.  But can be turned off using
-** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
-*/
-#ifndef SQLITE_POWERSAFE_OVERWRITE
-# define SQLITE_POWERSAFE_OVERWRITE 1
-#endif
-
-/*
-** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
-** It determines whether or not the features related to 
-** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
-** be overridden at runtime using the sqlite3_config() API.
-*/
-#if !defined(SQLITE_DEFAULT_MEMSTATUS)
-# define SQLITE_DEFAULT_MEMSTATUS 1
-#endif
-
-/*
-** Exactly one of the following macros must be defined in order to
-** specify which memory allocation subsystem to use.
-**
-**     SQLITE_SYSTEM_MALLOC          // Use normal system malloc()
-**     SQLITE_WIN32_MALLOC           // Use Win32 native heap API
-**     SQLITE_ZERO_MALLOC            // Use a stub allocator that always fails
-**     SQLITE_MEMDEBUG               // Debugging version of system malloc()
-**
-** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
-** assert() macro is enabled, each call into the Win32 native heap subsystem
-** will cause HeapValidate to be called.  If heap validation should fail, an
-** assertion will be triggered.
-**
-** (Historical note:  There used to be several other options, but we've
-** pared it down to just these three.)
-**
-** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
-** the default.
-*/
-#if defined(SQLITE_SYSTEM_MALLOC) \
-  + defined(SQLITE_WIN32_MALLOC) \
-  + defined(SQLITE_ZERO_MALLOC) \
-  + defined(SQLITE_MEMDEBUG)>1
-# error "Two or more of the following compile-time configuration options\
- are defined but at most one is allowed:\
- SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
- SQLITE_ZERO_MALLOC"
-#endif
-#if defined(SQLITE_SYSTEM_MALLOC) \
-  + defined(SQLITE_WIN32_MALLOC) \
-  + defined(SQLITE_ZERO_MALLOC) \
-  + defined(SQLITE_MEMDEBUG)==0
-# define SQLITE_SYSTEM_MALLOC 1
-#endif
-
-/*
-** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
-** sizes of memory allocations below this value where possible.
-*/
-#if !defined(SQLITE_MALLOC_SOFT_LIMIT)
-# define SQLITE_MALLOC_SOFT_LIMIT 1024
-#endif
-
-/*
-** We need to define _XOPEN_SOURCE as follows in order to enable
-** recursive mutexes on most Unix systems.  But Mac OS X is different.
-** The _XOPEN_SOURCE define causes problems for Mac OS X we are told,
-** so it is omitted there.  See ticket #2673.
-**
-** Later we learn that _XOPEN_SOURCE is poorly or incorrectly
-** implemented on some systems.  So we avoid defining it at all
-** if it is already defined or if it is unneeded because we are
-** not doing a threadsafe build.  Ticket #2681.
-**
-** See also ticket #2741.
-*/
-#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) \
- && !defined(__APPLE__) && SQLITE_THREADSAFE
-#  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
-
-/*
-** NDEBUG and SQLITE_DEBUG are opposites.  It should always be true that
-** defined(NDEBUG)==!defined(SQLITE_DEBUG).  If this is not currently true,
-** make it true by defining or undefining NDEBUG.
-**
-** Setting NDEBUG makes the code smaller and run faster by disabling the
-** number assert() statements in the code.  So we want the default action
-** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
-** is set.  Thus NDEBUG becomes an opt-in rather than an opt-out
-** feature.
-*/
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) 
-# define NDEBUG 1
-#endif
-#if defined(NDEBUG) && defined(SQLITE_DEBUG)
-# undef NDEBUG
-#endif
-
-/*
-** The testcase() macro is used to aid in coverage testing.  When 
-** doing coverage testing, the condition inside the argument to
-** testcase() must be evaluated both true and false in order to
-** get full branch coverage.  The testcase() macro is inserted
-** to help ensure adequate test coverage in places where simple
-** condition/decision coverage is inadequate.  For example, testcase()
-** can be used to make sure boundary values are tested.  For
-** bitmask tests, testcase() can be used to make sure each bit
-** is significant and used at least once.  On switch statements
-** where multiple cases go to the same block of code, testcase()
-** can insure that all cases are evaluated.
-**
-*/
-#ifdef SQLITE_COVERAGE_TEST
-SQLITE_PRIVATE   void sqlite3Coverage(int);
-# define testcase(X)  if( X ){ sqlite3Coverage(__LINE__); }
-#else
-# define testcase(X)
-#endif
-
-/*
-** The TESTONLY macro is used to enclose variable declarations or
-** other bits of code that are needed to support the arguments
-** within testcase() and assert() macros.
-*/
-#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
-# define TESTONLY(X)  X
-#else
-# define TESTONLY(X)
-#endif
-
-/*
-** Sometimes we need a small amount of code such as a variable initialization
-** to setup for a later assert() statement.  We do not want this code to
-** appear when assert() is disabled.  The following macro is therefore
-** used to contain that setup code.  The "VVA" acronym stands for
-** "Verification, Validation, and Accreditation".  In other words, the
-** code within VVA_ONLY() will only run during verification processes.
+** For MinGW, check to see if we can include the header file containing its
+** version information, among other things.  Normally, this internal MinGW
+** header file would [only] be included automatically by other MinGW header
+** files; however, the contained version information is now required by this
+** header file to work around binary compatibility issues (see below) and
+** this is the only known way to reliably obtain it.  This entire #if block
+** would be completely unnecessary if there was any other way of detecting
+** MinGW via their preprocessor (e.g. if they customized their GCC to define
+** some MinGW-specific macros).  When compiling for MinGW, either the
+** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be
+** defined; otherwise, detection of conditions specific to MinGW will be
+** disabled.
 */
-#ifndef NDEBUG
-# define VVA_ONLY(X)  X
-#else
-# define VVA_ONLY(X)
+#if defined(_HAVE_MINGW_H)
+# include "mingw.h"
+#elif defined(_HAVE__MINGW_H)
+# include "_mingw.h"
 #endif
 
 /*
-** The ALWAYS and NEVER macros surround boolean expressions which 
-** are intended to always be true or false, respectively.  Such
-** expressions could be omitted from the code completely.  But they
-** are included in a few cases in order to enhance the resilience
-** of SQLite to unexpected behavior - to make the code "self-healing"
-** or "ductile" rather than being "brittle" and crashing at the first
-** hint of unplanned behavior.
-**
-** In other words, ALWAYS and NEVER are added for defensive code.
-**
-** When doing coverage testing ALWAYS and NEVER are hard-coded to
-** be true and false so that the unreachable code then specify will
-** not be counted as untested code.
+** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T
+** define is required to maintain binary compatibility with the MSVC runtime
+** library in use (e.g. for Windows XP).
 */
-#if defined(SQLITE_COVERAGE_TEST)
-# define ALWAYS(X)      (1)
-# define NEVER(X)       (0)
-#elif !defined(NDEBUG)
-# define ALWAYS(X)      ((X)?1:(assert(0),0))
-# define NEVER(X)       ((X)?(assert(0),1):0)
-#else
-# define ALWAYS(X)      (X)
-# define NEVER(X)       (X)
+#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \
+    defined(_WIN32) && !defined(_WIN64) && \
+    defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
+    defined(__MSVCRT__)
+# define _USE_32BIT_TIME_T
 #endif
 
-/*
-** Return true (non-zero) if the input is a integer that is too large
-** to fit in 32-bits.  This macro is used inside of various testcase()
-** macros to verify that we have tested SQLite for large-file support.
-*/
-#define IS_BIG_INT(X)  (((X)&~(i64)0xffffffff)!=0)
-
-/*
-** The macro unlikely() is a hint that surrounds a boolean
-** expression that is usually false.  Macro likely() surrounds
-** a boolean expression that is usually true.  GCC is able to
-** use these hints to generate better code, sometimes.
+/* The public SQLite interface.  The _FILE_OFFSET_BITS macro must appear
+** first in QNX.  Also, the _USE_32BIT_TIME_T macro must appear first for
+** MinGW.
 */
-#if defined(__GNUC__) && 0
-# define likely(X)    __builtin_expect((X),1)
-# define unlikely(X)  __builtin_expect((X),0)
-#else
-# define likely(X)    !!(X)
-# define unlikely(X)  !!(X)
-#endif
-
 /************** Include sqlite3.h in the middle of sqliteInt.h ***************/
 /************** Begin file sqlite3.h *****************************************/
 /*
@@ -678,9 +222,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.7.17"
-#define SQLITE_VERSION_NUMBER 3007017
-#define SQLITE_SOURCE_ID      "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668"
+#define SQLITE_VERSION        "3.8.6"
+#define SQLITE_VERSION_NUMBER 3008006
+#define SQLITE_SOURCE_ID      "2014-08-15 11:46:33 9491ba7d738528f168657adb43a198238abde19e"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -840,7 +384,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 **
 ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
 ** for the [sqlite3] object.
-** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
+** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
 ** the [sqlite3] object is successfully destroyed and all associated
 ** resources are deallocated.
 **
@@ -848,7 +392,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** statements or unfinished sqlite3_backup objects then sqlite3_close()
 ** will leave the database connection open and return [SQLITE_BUSY].
 ** ^If sqlite3_close_v2() is called with unfinalized prepared statements
-** and unfinished sqlite3_backups, then the database connection becomes
+** and/or unfinished sqlite3_backups, then the database connection becomes
 ** an unusable "zombie" which will automatically be deallocated when the
 ** last prepared statement is finalized or the last sqlite3_backup is
 ** finished.  The sqlite3_close_v2() interface is intended for use with
@@ -861,7 +405,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** with the [sqlite3] object prior to attempting to close the object.  ^If
 ** sqlite3_close_v2() is called on a [database connection] that still has
 ** outstanding [prepared statements], [BLOB handles], and/or
-** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
+** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
 ** of resources is deferred until all [prepared statements], [BLOB handles],
 ** and [sqlite3_backup] objects are also destroyed.
 **
@@ -941,7 +485,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 ** <ul>
 ** <li> The application must insure that the 1st parameter to sqlite3_exec()
 **      is a valid and open [database connection].
-** <li> The application must not close [database connection] specified by
+** <li> The application must not close the [database connection] specified by
 **      the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
 ** <li> The application must not modify the SQL statement text passed into
 **      the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
@@ -957,16 +501,14 @@ SQLITE_API int sqlite3_exec(
 
 /*
 ** CAPI3REF: Result Codes
-** KEYWORDS: SQLITE_OK {error code} {error codes}
-** KEYWORDS: {result code} {result codes}
+** KEYWORDS: {result code definitions}
 **
 ** Many SQLite functions return an integer result code from the set shown
 ** here in order to indicate success or failure.
 **
 ** New error codes may be added in future versions of SQLite.
 **
-** See also: [SQLITE_IOERR_READ | extended result codes],
-** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
+** See also: [extended result code definitions]
 */
 #define SQLITE_OK           0   /* Successful result */
 /* beginning-of-error-codes */
@@ -1004,26 +546,19 @@ SQLITE_API int sqlite3_exec(
 
 /*
 ** CAPI3REF: Extended Result Codes
-** KEYWORDS: {extended error code} {extended error codes}
-** KEYWORDS: {extended result code} {extended result codes}
+** KEYWORDS: {extended result code definitions}
 **
-** In its default configuration, SQLite API routines return one of 26 integer
-** [SQLITE_OK | result codes].  However, experience has shown that many of
+** In its default configuration, SQLite API routines return one of 30 integer
+** [result codes].  However, experience has shown that many of
 ** these result codes are too coarse-grained.  They do not provide as
 ** much information about problems as programmers might like.  In an effort to
 ** address this, newer versions of SQLite (version 3.3.8 and later) include
 ** support for additional result codes that provide more detailed information
-** about errors. The extended result codes are enabled or disabled
+** about errors. These [extended result codes] are enabled or disabled
 ** on a per database connection basis using the
-** [sqlite3_extended_result_codes()] API.
-**
-** Some of the available extended result codes are listed here.
-** One may expect the number of extended result codes will be expand
-** over time.  Software that uses extended result codes should expect
-** to see new result codes in future releases of SQLite.
-**
-** The SQLITE_OK result code will never be extended.  It will always
-** be exactly zero.
+** [sqlite3_extended_result_codes()] API.  Or, the extended code for
+** the most recent error can be obtained using
+** [sqlite3_extended_errcode()].
 */
 #define SQLITE_IOERR_READ              (SQLITE_IOERR | (1<<8))
 #define SQLITE_IOERR_SHORT_READ        (SQLITE_IOERR | (2<<8))
@@ -1049,15 +584,20 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
 #define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
 #define SQLITE_IOERR_MMAP              (SQLITE_IOERR | (24<<8))
+#define SQLITE_IOERR_GETTEMPPATH       (SQLITE_IOERR | (25<<8))
+#define SQLITE_IOERR_CONVPATH          (SQLITE_IOERR | (26<<8))
 #define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
 #define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
+#define SQLITE_BUSY_SNAPSHOT           (SQLITE_BUSY   |  (2<<8))
 #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
 #define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
 #define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
+#define SQLITE_CANTOPEN_CONVPATH       (SQLITE_CANTOPEN | (4<<8))
 #define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
 #define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
 #define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
 #define SQLITE_READONLY_ROLLBACK       (SQLITE_READONLY | (3<<8))
+#define SQLITE_READONLY_DBMOVED        (SQLITE_READONLY | (4<<8))
 #define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
 #define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
 #define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
@@ -1068,8 +608,10 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
 #define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
 #define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
+#define SQLITE_CONSTRAINT_ROWID        (SQLITE_CONSTRAINT |(10<<8))
 #define SQLITE_NOTICE_RECOVER_WAL      (SQLITE_NOTICE | (1<<8))
 #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
+#define SQLITE_WARNING_AUTOINDEX       (SQLITE_WARNING | (1<<8))
 
 /*
 ** CAPI3REF: Flags For File Open Operations
@@ -1123,7 +665,11 @@ SQLITE_API int sqlite3_exec(
 ** after reboot following a crash or power loss, the only bytes in a
 ** file that were written at the application level might have changed
 ** and that adjacent bytes, even bytes within the same sector are
-** guaranteed to be unchanged.
+** guaranteed to be unchanged.  The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
+** flag indicate that a file cannot be deleted when open.  The
+** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
+** read-only media and cannot be changed even by processes with
+** elevated privileges.
 */
 #define SQLITE_IOCAP_ATOMIC                 0x00000001
 #define SQLITE_IOCAP_ATOMIC512              0x00000002
@@ -1138,6 +684,7 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_IOCAP_SEQUENTIAL             0x00000400
 #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN  0x00000800
 #define SQLITE_IOCAP_POWERSAFE_OVERWRITE    0x00001000
+#define SQLITE_IOCAP_IMMUTABLE              0x00002000
 
 /*
 ** CAPI3REF: File Locking Levels
@@ -1244,7 +791,7 @@ struct sqlite3_file {
 ** locking strategy (for example to use dot-file locks), to inquire
 ** about the status of a lock, or to break stale locks.  The SQLite
 ** core reserves all opcodes less than 100 for its own use.
-** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
+** A [file control opcodes | list of opcodes] less than 100 is available.
 ** Applications that define a custom xFileControl method should use opcodes
 ** greater than 100 to avoid conflicts.  VFS implementations should
 ** return [SQLITE_NOTFOUND] for file control opcodes that they do not
@@ -1317,6 +864,7 @@ struct sqlite3_io_methods {
 
 /*
 ** CAPI3REF: Standard File Control Opcodes
+** KEYWORDS: {file control opcodes} {file control opcode}
 **
 ** These integer constants are opcodes for the xFileControl method
 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
@@ -1354,15 +902,29 @@ struct sqlite3_io_methods {
 ** additional information.
 **
 ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
-** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
-** SQLite and sent to all VFSes in place of a call to the xSync method
-** when the database connection has [PRAGMA synchronous] set to OFF.)^
-** Some specialized VFSes need this signal in order to operate correctly
-** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
-** VFSes do not need this signal and should silently ignore this opcode.
-** Applications should not call [sqlite3_file_control()] with this
-** opcode as doing so may disrupt the operation of the specialized VFSes
-** that do require it.  
+** No longer in use.
+**
+** <li>[[SQLITE_FCNTL_SYNC]]
+** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
+** sent to the VFS immediately before the xSync method is invoked on a
+** database file descriptor. Or, if the xSync method is not invoked 
+** because the user has configured SQLite with 
+** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place 
+** of the xSync method. In most cases, the pointer argument passed with
+** this file-control is NULL. However, if the database file is being synced
+** as part of a multi-database commit, the argument points to a nul-terminated
+** string containing the transactions master-journal file name. VFSes that 
+** do not need this signal should silently ignore this opcode. Applications 
+** should not call [sqlite3_file_control()] with this opcode as doing so may 
+** disrupt the operation of the specialized VFSes that do require it.  
+**
+** <li>[[SQLITE_FCNTL_COMMIT_PHASETWO]]
+** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite
+** and sent to the VFS after a transaction has been committed immediately
+** but before the database is unlocked. VFSes that do not need this signal
+** should silently ignore this opcode. Applications should not call
+** [sqlite3_file_control()] with this opcode as doing so may disrupt the 
+** operation of the specialized VFSes that do require it.  
 **
 ** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
@@ -1478,6 +1040,26 @@ struct sqlite3_io_methods {
 ** can be queried by passing in a pointer to a negative number.  This
 ** file-control is used internally to implement [PRAGMA mmap_size].
 **
+** <li>[[SQLITE_FCNTL_TRACE]]
+** The [SQLITE_FCNTL_TRACE] file control provides advisory information
+** to the VFS about what the higher layers of the SQLite stack are doing.
+** This file control is used by some VFS activity tracing [shims].
+** The argument is a zero-terminated string.  Higher layers in the
+** SQLite stack may generate instances of this file control if
+** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled.
+**
+** <li>[[SQLITE_FCNTL_HAS_MOVED]]
+** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
+** pointer to an integer and it writes a boolean into that integer depending
+** on whether or not the file has been renamed, moved, or deleted since it
+** was first opened.
+**
+** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
+** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging.  This
+** opcode causes the xFileControl method to swap the file handle with the one
+** pointed to by the pArg argument.  This capability is used during testing
+** and only needs to be supported when SQLITE_TEST is defined.
+**
 ** </ul>
 */
 #define SQLITE_FCNTL_LOCKSTATE               1
@@ -1497,6 +1079,11 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_BUSYHANDLER            15
 #define SQLITE_FCNTL_TEMPFILENAME           16
 #define SQLITE_FCNTL_MMAP_SIZE              18
+#define SQLITE_FCNTL_TRACE                  19
+#define SQLITE_FCNTL_HAS_MOVED              20
+#define SQLITE_FCNTL_SYNC                   21
+#define SQLITE_FCNTL_COMMIT_PHASETWO        22
+#define SQLITE_FCNTL_WIN32_SET_HANDLE       23
 
 /*
 ** CAPI3REF: Mutex Handle
@@ -1941,7 +1528,7 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
 ** or [sqlite3_realloc()] first calls xRoundup.  If xRoundup returns 0, 
 ** that causes the corresponding memory allocation to fail.
 **
-** The xInit method initializes the memory allocator.  (For example,
+** The xInit method initializes the memory allocator.  For example,
 ** it might allocate any require mutexes or initialize internal data
 ** structures.  The xShutdown method is invoked (indirectly) by
 ** [sqlite3_shutdown()] and should deallocate any resources acquired
@@ -2183,27 +1770,27 @@ struct sqlite3_mem_methods {
 ** function must be threadsafe. </dd>
 **
 ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
-** <dd> This option takes a single argument of type int. If non-zero, then
+** <dd>^(This option takes a single argument of type int. If non-zero, then
 ** URI handling is globally enabled. If the parameter is zero, then URI handling
-** is globally disabled. If URI handling is globally enabled, all filenames
+** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
 ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
 ** specified as part of [ATTACH] commands are interpreted as URIs, regardless
 ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
-** connection is opened. If it is globally disabled, filenames are
+** connection is opened. ^If it is globally disabled, filenames are
 ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
-** database connection is opened. By default, URI handling is globally
+** database connection is opened. ^(By default, URI handling is globally
 ** disabled. The default value may be changed by compiling with the
-** [SQLITE_USE_URI] symbol defined.
+** [SQLITE_USE_URI] symbol defined.)^
 **
 ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
-** <dd> This option takes a single integer argument which is interpreted as
+** <dd>^This option takes a single integer argument which is interpreted as
 ** a boolean in order to enable or disable the use of covering indices for
-** full table scans in the query optimizer.  The default setting is determined
+** full table scans in the query optimizer.  ^The default setting is determined
 ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
 ** if that compile-time option is omitted.
 ** The ability to disable the use of covering indices for full table scans
 ** is because some incorrectly coded legacy applications might malfunction
-** malfunction when the optimization is enabled.  Providing the ability to
+** when the optimization is enabled.  Providing the ability to
 ** disable the optimization allows the older, buggy application code to work
 ** without change even with newer versions of SQLite.
 **
@@ -2232,17 +1819,24 @@ struct sqlite3_mem_methods {
 **
 ** [[SQLITE_CONFIG_MMAP_SIZE]]
 ** <dt>SQLITE_CONFIG_MMAP_SIZE
-** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
+** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
 ** that are the default mmap size limit (the default setting for
 ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
-** The default setting can be overridden by each database connection using
+** ^The default setting can be overridden by each database connection using
 ** either the [PRAGMA mmap_size] command, or by using the
-** [SQLITE_FCNTL_MMAP_SIZE] file control.  The maximum allowed mmap size
+** [SQLITE_FCNTL_MMAP_SIZE] file control.  ^(The maximum allowed mmap size
 ** cannot be changed at run-time.  Nor may the maximum allowed mmap size
 ** exceed the compile-time maximum mmap size set by the
-** [SQLITE_MAX_MMAP_SIZE] compile-time option.  
-** If either argument to this option is negative, then that argument is
+** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
+** ^If either argument to this option is negative, then that argument is
 ** changed to its compile-time default.
+**
+** [[SQLITE_CONFIG_WIN32_HEAPSIZE]]
+** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
+** <dd>^This option is only available if SQLite is compiled for Windows
+** with the [SQLITE_WIN32_MALLOC] pre-processor macro defined.
+** SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
+** that specifies the maximum size of the created heap.
 ** </dl>
 */
 #define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
@@ -2267,6 +1861,7 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
 #define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
 #define SQLITE_CONFIG_MMAP_SIZE    22  /* sqlite3_int64, sqlite3_int64 */
+#define SQLITE_CONFIG_WIN32_HEAPSIZE      23  /* int nByte */
 
 /*
 ** CAPI3REF: Database Connection Configuration Options
@@ -2343,19 +1938,21 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
 /*
 ** CAPI3REF: Last Insert Rowid
 **
-** ^Each entry in an SQLite table has a unique 64-bit signed
+** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables)
+** has a unique 64-bit signed
 ** integer key called the [ROWID | "rowid"]. ^The rowid is always available
 ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
 ** names are not also used by explicitly declared columns. ^If
 ** the table has a column of type [INTEGER PRIMARY KEY] then that column
 ** is another alias for the rowid.
 **
-** ^This routine returns the [rowid] of the most recent
-** successful [INSERT] into the database from the [database connection]
-** in the first argument.  ^As of SQLite version 3.7.7, this routines
-** records the last insert rowid of both ordinary tables and [virtual tables].
-** ^If no successful [INSERT]s
-** have ever occurred on that database connection, zero is returned.
+** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the 
+** most recent successful [INSERT] into a rowid table or [virtual table]
+** on database connection D.
+** ^Inserts into [WITHOUT ROWID] tables are not recorded.
+** ^If no successful [INSERT]s into rowid tables
+** have ever occurred on the database connection D, 
+** then sqlite3_last_insert_rowid(D) returns zero.
 **
 ** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
 ** method, then this routine will return the [rowid] of the inserted
@@ -2547,27 +2144,33 @@ SQLITE_API int sqlite3_complete16(const void *sql);
 /*
 ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
 **
-** ^This routine sets a callback function that might be invoked whenever
-** an attempt is made to open a database table that another thread
-** or process has locked.
+** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
+** that might be invoked with argument P whenever
+** an attempt is made to access a database table associated with
+** [database connection] D when another thread
+** or process has the table locked.
+** The sqlite3_busy_handler() interface is used to implement
+** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
 **
-** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
+** ^If the busy callback is NULL, then [SQLITE_BUSY]
 ** is returned immediately upon encountering the lock.  ^If the busy callback
 ** is not NULL, then the callback might be invoked with two arguments.
 **
 ** ^The first argument to the busy handler is a copy of the void* pointer which
 ** is the third argument to sqlite3_busy_handler().  ^The second argument to
 ** the busy handler callback is the number of times that the busy handler has
-** been invoked for this locking event.  ^If the
+** been invoked for the same locking event.  ^If the
 ** busy callback returns 0, then no additional attempts are made to
-** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
+** access the database and [SQLITE_BUSY] is returned
+** to the application.
 ** ^If the callback returns non-zero, then another attempt
-** is made to open the database for reading and the cycle repeats.
+** is made to access the database and the cycle repeats.
 **
 ** The presence of a busy handler does not guarantee that it will be invoked
 ** when there is lock contention. ^If SQLite determines that invoking the busy
 ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
-** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
+** to the application instead of invoking the 
+** busy handler.
 ** Consider a scenario where one process is holding a read lock that
 ** it is trying to promote to a reserved lock and
 ** a second process is holding a reserved lock that it is trying
@@ -2581,28 +2184,15 @@ SQLITE_API int sqlite3_complete16(const void *sql);
 **
 ** ^The default busy callback is NULL.
 **
-** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
-** when SQLite is in the middle of a large transaction where all the
-** changes will not fit into the in-memory cache.  SQLite will
-** already hold a RESERVED lock on the database file, but it needs
-** to promote this lock to EXCLUSIVE so that it can spill cache
-** pages into the database file without harm to concurrent
-** readers.  ^If it is unable to promote the lock, then the in-memory
-** cache will be left in an inconsistent state and so the error
-** code is promoted from the relatively benign [SQLITE_BUSY] to
-** the more severe [SQLITE_IOERR_BLOCKED].  ^This error code promotion
-** forces an automatic rollback of the changes.  See the
-** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
-** CorruptionFollowingBusyError</a> wiki page for a discussion of why
-** this is important.
-**
 ** ^(There can only be a single busy handler defined for each
 ** [database connection].  Setting a new busy handler clears any
 ** previously set handler.)^  ^Note that calling [sqlite3_busy_timeout()]
-** will also set or clear the busy handler.
+** or evaluating [PRAGMA busy_timeout=N] will change the
+** busy handler and thus clear any previously set busy handler.
 **
 ** The busy callback should not take any actions which modify the
-** database connection that invoked the busy handler.  Any such actions
+** database connection that invoked the busy handler.  In other words,
+** the busy handler is not reentrant.  Any such actions
 ** result in undefined behavior.
 ** 
 ** A busy handler must not close the database connection
@@ -2618,7 +2208,7 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
 ** will sleep multiple times until at least "ms" milliseconds of sleeping
 ** have accumulated.  ^After at least "ms" milliseconds of sleeping,
 ** the handler returns 0 which causes [sqlite3_step()] to return
-** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
+** [SQLITE_BUSY].
 **
 ** ^Calling this routine with an argument less than or equal to zero
 ** turns off all busy handlers.
@@ -2627,6 +2217,8 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
 ** [database connection] any any given moment.  If another busy handler
 ** was defined  (using [sqlite3_busy_handler()]) prior to calling
 ** this routine, that other busy handler is cleared.)^
+**
+** See also:  [PRAGMA busy_timeout]
 */
 SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
 
@@ -2921,11 +2513,13 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
 ** applications to access the same PRNG for other purposes.
 **
 ** ^A call to this routine stores N bytes of randomness into buffer P.
+** ^If N is less than one, then P can be a NULL pointer.
 **
-** ^The first time this routine is invoked (either internally or by
-** the application) the PRNG is seeded using randomness obtained
-** from the xRandomness method of the default [sqlite3_vfs] object.
-** ^On all subsequent invocations, the pseudo-randomness is generated
+** ^If this routine has not been previously called or if the previous
+** call had N less than one, then the PRNG is seeded using randomness
+** obtained from the xRandomness method of the default [sqlite3_vfs] object.
+** ^If the previous call to this routine had an N of 1 or more then
+** the pseudo-randomness is generated
 ** internally and without recourse to the [sqlite3_vfs] xRandomness
 ** method.
 */
@@ -3026,8 +2620,8 @@ SQLITE_API int sqlite3_set_authorizer(
 ** [sqlite3_set_authorizer | authorizer documentation] for additional
 ** information.
 **
-** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
-** from the [sqlite3_vtab_on_conflict()] interface.
+** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
+** returned from the [sqlite3_vtab_on_conflict()] interface.
 */
 #define SQLITE_DENY   1   /* Abort the SQL statement with an error */
 #define SQLITE_IGNORE 2   /* Don't allow access, but don't generate an error */
@@ -3085,6 +2679,7 @@ SQLITE_API int sqlite3_set_authorizer(
 #define SQLITE_FUNCTION             31   /* NULL            Function Name   */
 #define SQLITE_SAVEPOINT            32   /* Operation       Savepoint Name  */
 #define SQLITE_COPY                  0   /* No longer used */
+#define SQLITE_RECURSIVE            33   /* NULL            NULL            */
 
 /*
 ** CAPI3REF: Tracing And Profiling Functions
@@ -3128,9 +2723,10 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
 ** interface is to keep a GUI updated during a large query.
 **
 ** ^The parameter P is passed through as the only parameter to the 
-** callback function X.  ^The parameter N is the number of 
+** callback function X.  ^The parameter N is the approximate number of 
 ** [virtual machine instructions] that are evaluated between successive
-** invocations of the callback X.
+** invocations of the callback X.  ^If N is less than one then the progress
+** handler is disabled.
 **
 ** ^Only a single progress handler may be defined at one time per
 ** [database connection]; setting a new progress handler cancels the
@@ -3296,6 +2892,30 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
 **     a URI filename, its value overrides any behavior requested by setting
 **     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
+**
+**  <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
+**     "1") or "false" (or "off" or "no" or "0") to indicate that the
+**     [powersafe overwrite] property does or does not apply to the
+**     storage media on which the database file resides.  ^The psow query
+**     parameter only works for the built-in unix and Windows VFSes.
+**
+**  <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
+**     which if set disables file locking in rollback journal modes.  This
+**     is useful for accessing a database on a filesystem that does not
+**     support locking.  Caution:  Database corruption might result if two
+**     or more processes write to the same database and any one of those
+**     processes uses nolock=1.
+**
+**  <li> <b>immutable</b>: ^The immutable parameter is a boolean query
+**     parameter that indicates that the database file is stored on
+**     read-only media.  ^When immutable is set, SQLite assumes that the
+**     database file cannot be changed, even by a process with higher
+**     privilege, and so the database is opened read-only and all locking
+**     and change detection is disabled.  Caution: Setting the immutable
+**     property on a database file that does in fact change can result
+**     in incorrect query results and/or [SQLITE_CORRUPT] errors.
+**     See also: [SQLITE_IOCAP_IMMUTABLE].
+**       
 ** </ul>
 **
 ** ^Specifying an unknown parameter in the query component of a URI is not an
@@ -3325,8 +2945,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **          Open file "data.db" in the current directory for read-only access.
 **          Regardless of whether or not shared-cache mode is enabled by
 **          default, use a private cache.
-** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
-**          Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
+** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
+**          Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
+**          that uses dot-files in place of posix advisory locking.
 ** <tr><td> file:data.db?mode=readonly <td> 
 **          An error. "readonly" is not a valid option for the "mode" parameter.
 ** </table>
@@ -3664,7 +3285,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
 ** choice of query plan if the parameter is the left-hand side of a [LIKE]
 ** or [GLOB] operator or if the parameter is compared to an indexed column
 ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
-** the 
 ** </li>
 ** </ol>
 */
@@ -4326,19 +3946,19 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
 **
 ** <tr><td>  NULL    <td> INTEGER   <td> Result is 0
 ** <tr><td>  NULL    <td>  FLOAT    <td> Result is 0.0
-** <tr><td>  NULL    <td>   TEXT    <td> Result is NULL pointer
-** <tr><td>  NULL    <td>   BLOB    <td> Result is NULL pointer
+** <tr><td>  NULL    <td>   TEXT    <td> Result is a NULL pointer
+** <tr><td>  NULL    <td>   BLOB    <td> Result is a NULL pointer
 ** <tr><td> INTEGER  <td>  FLOAT    <td> Convert from integer to float
 ** <tr><td> INTEGER  <td>   TEXT    <td> ASCII rendering of the integer
 ** <tr><td> INTEGER  <td>   BLOB    <td> Same as INTEGER->TEXT
-** <tr><td>  FLOAT   <td> INTEGER   <td> Convert from float to integer
+** <tr><td>  FLOAT   <td> INTEGER   <td> [CAST] to INTEGER
 ** <tr><td>  FLOAT   <td>   TEXT    <td> ASCII rendering of the float
-** <tr><td>  FLOAT   <td>   BLOB    <td> Same as FLOAT->TEXT
-** <tr><td>  TEXT    <td> INTEGER   <td> Use atoi()
-** <tr><td>  TEXT    <td>  FLOAT    <td> Use atof()
+** <tr><td>  FLOAT   <td>   BLOB    <td> [CAST] to BLOB
+** <tr><td>  TEXT    <td> INTEGER   <td> [CAST] to INTEGER
+** <tr><td>  TEXT    <td>  FLOAT    <td> [CAST] to REAL
 ** <tr><td>  TEXT    <td>   BLOB    <td> No change
-** <tr><td>  BLOB    <td> INTEGER   <td> Convert to TEXT then use atoi()
-** <tr><td>  BLOB    <td>  FLOAT    <td> Convert to TEXT then use atof()
+** <tr><td>  BLOB    <td> INTEGER   <td> [CAST] to INTEGER
+** <tr><td>  BLOB    <td>  FLOAT    <td> [CAST] to REAL
 ** <tr><td>  BLOB    <td>   TEXT    <td> Add a zero terminator if needed
 ** </table>
 ** </blockquote>)^
@@ -4394,7 +4014,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
 ** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
 ** [sqlite3_finalize()] is called.  ^The memory space used to hold strings
 ** and BLOBs is freed automatically.  Do <b>not</b> pass the pointers returned
-** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
+** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
 ** [sqlite3_free()].
 **
 ** ^(If a memory allocation error occurs during the evaluation of any
@@ -4503,15 +4123,24 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
 **
 ** ^The fourth parameter, eTextRep, specifies what
 ** [SQLITE_UTF8 | text encoding] this SQL function prefers for
-** its parameters.  Every SQL function implementation must be able to work
-** with UTF-8, UTF-16le, or UTF-16be.  But some implementations may be
-** more efficient with one encoding than another.  ^An application may
-** invoke sqlite3_create_function() or sqlite3_create_function16() multiple
-** times with the same function but with different values of eTextRep.
+** its parameters.  The application should set this parameter to
+** [SQLITE_UTF16LE] if the function implementation invokes 
+** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the
+** implementation invokes [sqlite3_value_text16be()] on an input, or
+** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8]
+** otherwise.  ^The same SQL function may be registered multiple times using
+** different preferred text encodings, with different implementations for
+** each encoding.
 ** ^When multiple implementations of the same function are available, SQLite
 ** will pick the one that involves the least amount of data conversion.
-** If there is only a single implementation which does not care what text
-** encoding is used, then the fourth argument should be [SQLITE_ANY].
+**
+** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC]
+** to signal that the function will always return the same result given
+** the same inputs within a single SQL statement.  Most SQL functions are
+** deterministic.  The built-in [random()] SQL function is an example of a
+** function that is not deterministic.  The SQLite query planner is able to
+** perform additional optimizations on deterministic functions, so use
+** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
 **
 ** ^(The fifth parameter is an arbitrary pointer.  The implementation of the
 ** function can gain access to this pointer using [sqlite3_user_data()].)^
@@ -4597,10 +4226,20 @@ SQLITE_API int sqlite3_create_function_v2(
 #define SQLITE_UTF16LE        2
 #define SQLITE_UTF16BE        3
 #define SQLITE_UTF16          4    /* Use native byte order */
-#define SQLITE_ANY            5    /* sqlite3_create_function only */
+#define SQLITE_ANY            5    /* Deprecated */
 #define SQLITE_UTF16_ALIGNED  8    /* sqlite3_create_collation only */
 
 /*
+** CAPI3REF: Function Flags
+**
+** These constants may be ORed together with the 
+** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
+** to [sqlite3_create_function()], [sqlite3_create_function16()], or
+** [sqlite3_create_function_v2()].
+*/
+#define SQLITE_DETERMINISTIC    0x800
+
+/*
 ** CAPI3REF: Deprecated Functions
 ** DEPRECATED
 **
@@ -4750,41 +4389,49 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
 /*
 ** CAPI3REF: Function Auxiliary Data
 **
-** The following two functions may be used by scalar SQL functions to
+** These functions may be used by (non-aggregate) SQL functions to
 ** associate metadata with argument values. If the same value is passed to
 ** multiple invocations of the same SQL function during query execution, under
-** some circumstances the associated metadata may be preserved. This may
-** be used, for example, to add a regular-expression matching scalar
-** function. The compiled version of the regular expression is stored as
-** metadata associated with the SQL value passed as the regular expression
-** pattern.  The compiled regular expression can be reused on multiple
-** invocations of the same function so that the original pattern string
-** does not need to be recompiled on each invocation.
+** some circumstances the associated metadata may be preserved.  An example
+** of where this might be useful is in a regular-expression matching
+** function. The compiled version of the regular expression can be stored as
+** metadata associated with the pattern string.  
+** Then as long as the pattern string remains the same,
+** the compiled regular expression can be reused on multiple
+** invocations of the same function.
 **
 ** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
 ** associated by the sqlite3_set_auxdata() function with the Nth argument
-** value to the application-defined function. ^If no metadata has been ever
-** been set for the Nth argument of the function, or if the corresponding
-** function parameter has changed since the meta-data was set,
-** then sqlite3_get_auxdata() returns a NULL pointer.
-**
-** ^The sqlite3_set_auxdata() interface saves the metadata
-** pointed to by its 3rd parameter as the metadata for the N-th
-** argument of the application-defined function.  Subsequent
-** calls to sqlite3_get_auxdata() might return this data, if it has
-** not been destroyed.
-** ^If it is not NULL, SQLite will invoke the destructor
-** function given by the 4th parameter to sqlite3_set_auxdata() on
-** the metadata when the corresponding function parameter changes
-** or when the SQL statement completes, whichever comes first.
-**
-** SQLite is free to call the destructor and drop metadata on any
-** parameter of any function at any time.  ^The only guarantee is that
-** the destructor will be called before the metadata is dropped.
+** value to the application-defined function. ^If there is no metadata
+** associated with the function argument, this sqlite3_get_auxdata() interface
+** returns a NULL pointer.
+**
+** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
+** argument of the application-defined function.  ^Subsequent
+** calls to sqlite3_get_auxdata(C,N) return P from the most recent
+** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
+** NULL if the metadata has been discarded.
+** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
+** SQLite will invoke the destructor function X with parameter P exactly
+** once, when the metadata is discarded.
+** SQLite is free to discard the metadata at any time, including: <ul>
+** <li> when the corresponding function parameter changes, or
+** <li> when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
+**      SQL statement, or
+** <li> when sqlite3_set_auxdata() is invoked again on the same parameter, or
+** <li> during the original sqlite3_set_auxdata() call when a memory 
+**      allocation error occurs. </ul>)^
+**
+** Note the last bullet in particular.  The destructor X in 
+** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
+** sqlite3_set_auxdata() interface even returns.  Hence sqlite3_set_auxdata()
+** should be called near the end of the function implementation and the
+** function implementation should not make any use of P after
+** sqlite3_set_auxdata() has been called.
 **
 ** ^(In practice, metadata is preserved between function calls for
-** expressions that are constant at compile time. This includes literal
-** values and [parameters].)^
+** function parameters that are compile-time constants, including literal
+** values and [parameters] and expressions composed from the same.)^
 **
 ** These routines must be called from the same thread in which
 ** the SQL function is running.
@@ -5089,6 +4736,11 @@ SQLITE_API int sqlite3_key(
   sqlite3 *db,                   /* Database to be rekeyed */
   const void *pKey, int nKey     /* The key */
 );
+SQLITE_API int sqlite3_key_v2(
+  sqlite3 *db,                   /* Database to be rekeyed */
+  const char *zDbName,           /* Name of the database */
+  const void *pKey, int nKey     /* The key */
+);
 
 /*
 ** Change the key on an open database.  If the current database is not
@@ -5102,6 +4754,11 @@ SQLITE_API int sqlite3_rekey(
   sqlite3 *db,                   /* Database to be rekeyed */
   const void *pKey, int nKey     /* The new key */
 );
+SQLITE_API int sqlite3_rekey_v2(
+  sqlite3 *db,                   /* Database to be rekeyed */
+  const char *zDbName,           /* Name of the database */
+  const void *pKey, int nKey     /* The new key */
+);
 
 /*
 ** Specify the activation key for a SEE database.  Unless 
@@ -5151,6 +4808,13 @@ SQLITE_API int sqlite3_sleep(int);
 ** is a NULL pointer, then SQLite performs a search for an appropriate
 ** temporary file directory.
 **
+** Applications are strongly discouraged from using this global variable.
+** It is required to set a temporary folder on Windows Runtime (WinRT).
+** But for all other platforms, it is highly recommended that applications
+** neither read nor write this variable.  This global variable is a relic
+** that exists for backwards compatibility of legacy applications and should
+** be avoided in new projects.
+**
 ** It is not safe to read or modify this variable in more than one
 ** thread at a time.  It is not safe to read or modify this variable
 ** if a [database connection] is being used at the same time in a separate
@@ -5169,6 +4833,11 @@ SQLITE_API int sqlite3_sleep(int);
 ** Hence, if this variable is modified directly, either it should be
 ** made NULL or made to point to memory obtained from [sqlite3_malloc]
 ** or else the use of the [temp_store_directory pragma] should be avoided.
+** Except when requested by the [temp_store_directory pragma], SQLite
+** does not free the memory that sqlite3_temp_directory points to.  If
+** the application wants that memory to be freed, it must do
+** so itself, taking care to only do so after all [database connection]
+** objects have been destroyed.
 **
 ** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
 ** prior to calling [sqlite3_open] or [sqlite3_open_v2].  Otherwise, various
@@ -5353,12 +5022,13 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
 **
 ** ^The sqlite3_update_hook() interface registers a callback function
 ** with the [database connection] identified by the first argument
-** to be invoked whenever a row is updated, inserted or deleted.
+** to be invoked whenever a row is updated, inserted or deleted in
+** a rowid table.
 ** ^Any callback set by a previous call to this function
 ** for the same database connection is overridden.
 **
 ** ^The second argument is a pointer to the function to invoke when a
-** row is updated, inserted or deleted.
+** row is updated, inserted or deleted in a rowid table.
 ** ^The first argument to the callback is a copy of the third argument
 ** to sqlite3_update_hook().
 ** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
@@ -5371,6 +5041,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
 **
 ** ^(The update hook is not invoked when internal system tables are
 ** modified (i.e. sqlite_master and sqlite_sequence).)^
+** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
 **
 ** ^In the current implementation, the update hook
 ** is not invoked when duplication rows are deleted because of an
@@ -5452,8 +5123,8 @@ SQLITE_API int sqlite3_release_memory(int);
 **
 ** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
 ** memory as possible from database connection D. Unlike the
-** [sqlite3_release_memory()] interface, this interface is effect even
-** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
+** [sqlite3_release_memory()] interface, this interface is in effect even
+** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
 ** omitted.
 **
 ** See also: [sqlite3_release_memory()]
@@ -5687,11 +5358,24 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
 ** on the list of automatic extensions is a harmless no-op. ^No entry point
 ** will be called more than once for each database connection that is opened.
 **
-** See also: [sqlite3_reset_auto_extension()].
+** See also: [sqlite3_reset_auto_extension()]
+** and [sqlite3_cancel_auto_extension()]
 */
 SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
 
 /*
+** CAPI3REF: Cancel Automatic Extension Loading
+**
+** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
+** initialization routine X that was registered using a prior call to
+** [sqlite3_auto_extension(X)].  ^The [sqlite3_cancel_auto_extension(X)]
+** routine returns 1 if initialization routine X was successfully 
+** unregistered and it returns 0 if X was not on the list of initialization
+** routines.
+*/
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
+
+/*
 ** CAPI3REF: Reset Automatic Extension Loading
 **
 ** ^This interface disables all automatic extensions previously
@@ -5815,10 +5499,22 @@ struct sqlite3_module {
 ** the correct order to satisfy the ORDER BY clause so that no separate
 ** sorting step is required.
 **
-** ^The estimatedCost value is an estimate of the cost of doing the
-** particular lookup.  A full scan of a table with N entries should have
-** a cost of N.  A binary search of a table of N entries should have a
-** cost of approximately log(N).
+** ^The estimatedCost value is an estimate of the cost of a particular
+** strategy. A cost of N indicates that the cost of the strategy is similar
+** to a linear scan of an SQLite table with N rows. A cost of log(N) 
+** indicates that the expense of the operation is similar to that of a
+** binary search on a unique indexed field of an SQLite table with N rows.
+**
+** ^The estimatedRows value is an estimate of the number of rows that
+** will be returned by the strategy.
+**
+** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
+** structure for SQLite version 3.8.2. If a virtual table extension is
+** used with an SQLite version earlier than 3.8.2, the results of attempting 
+** to read or write the estimatedRows field are undefined (but are likely 
+** to included crashing the application). The estimatedRows field should
+** therefore only be used if [sqlite3_libversion_number()] returns a
+** value greater than or equal to 3008002.
 */
 struct sqlite3_index_info {
   /* Inputs */
@@ -5843,7 +5539,9 @@ struct sqlite3_index_info {
   char *idxStr;              /* String, possibly obtained from sqlite3_malloc */
   int needToFreeIdxStr;      /* Free idxStr using sqlite3_free() if true */
   int orderByConsumed;       /* True if output is already ordered */
-  double estimatedCost;      /* Estimated cost of using this index */
+  double estimatedCost;           /* Estimated cost of using this index */
+  /* Fields below are only available in SQLite 3.8.2 and later */
+  sqlite3_int64 estimatedRows;    /* Estimated number of rows returned */
 };
 
 /*
@@ -6047,6 +5745,9 @@ typedef struct sqlite3_blob sqlite3_blob;
 ** interface.  Use the [UPDATE] SQL command to change the size of a
 ** blob.
 **
+** ^The [sqlite3_blob_open()] interface will fail for a [WITHOUT ROWID]
+** table.  Incremental BLOB I/O is not possible on [WITHOUT ROWID] tables.
+**
 ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
 ** and the built-in [zeroblob] SQL function can be used, if desired,
 ** to create an empty, zero-filled blob in which to read or write using
@@ -6271,10 +5972,12 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
 ** <li>  SQLITE_MUTEX_RECURSIVE
 ** <li>  SQLITE_MUTEX_STATIC_MASTER
 ** <li>  SQLITE_MUTEX_STATIC_MEM
-** <li>  SQLITE_MUTEX_STATIC_MEM2
+** <li>  SQLITE_MUTEX_STATIC_OPEN
 ** <li>  SQLITE_MUTEX_STATIC_PRNG
 ** <li>  SQLITE_MUTEX_STATIC_LRU
-** <li>  SQLITE_MUTEX_STATIC_LRU2
+** <li>  SQLITE_MUTEX_STATIC_PMEM
+** <li>  SQLITE_MUTEX_STATIC_APP1
+** <li>  SQLITE_MUTEX_STATIC_APP2
 ** </ul>)^
 **
 ** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
@@ -6478,6 +6181,9 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
 #define SQLITE_MUTEX_STATIC_LRU       6  /* lru page list */
 #define SQLITE_MUTEX_STATIC_LRU2      7  /* NOT USED */
 #define SQLITE_MUTEX_STATIC_PMEM      7  /* sqlite3PageMalloc() */
+#define SQLITE_MUTEX_STATIC_APP1      8  /* For use by application */
+#define SQLITE_MUTEX_STATIC_APP2      9  /* For use by application */
+#define SQLITE_MUTEX_STATIC_APP3     10  /* For use by application */
 
 /*
 ** CAPI3REF: Retrieve the mutex for a database connection
@@ -6570,7 +6276,11 @@ SQLITE_API int sqlite3_test_control(int op, ...);
 #define SQLITE_TESTCTRL_SCRATCHMALLOC           17
 #define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
 #define SQLITE_TESTCTRL_EXPLAIN_STMT            19
-#define SQLITE_TESTCTRL_LAST                    19
+#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
+#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
+#define SQLITE_TESTCTRL_BYTEORDER               22
+#define SQLITE_TESTCTRL_ISINIT                  23
+#define SQLITE_TESTCTRL_LAST                    23
 
 /*
 ** CAPI3REF: SQLite Runtime Status
@@ -6803,6 +6513,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
 ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
 ** </dd>
+**
+** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
+** <dd>This parameter returns zero for the current value if and only if
+** all foreign key constraints (deferred or immediate) have been
+** resolved.)^  ^The highwater mark is always 0.
+** </dd>
 ** </dl>
 */
 #define SQLITE_DBSTATUS_LOOKASIDE_USED       0
@@ -6815,7 +6531,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 #define SQLITE_DBSTATUS_CACHE_HIT            7
 #define SQLITE_DBSTATUS_CACHE_MISS           8
 #define SQLITE_DBSTATUS_CACHE_WRITE          9
-#define SQLITE_DBSTATUS_MAX                  9   /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_DEFERRED_FKS        10
+#define SQLITE_DBSTATUS_MAX                 10   /* Largest defined DBSTATUS */
 
 
 /*
@@ -6869,11 +6586,21 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
 ** A non-zero value in this counter may indicate an opportunity to
 ** improvement performance by adding permanent indices that do not
 ** need to be reinitialized each time the statement is run.</dd>
+**
+** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
+** <dd>^This is the number of virtual machine operations executed
+** by the prepared statement if that number is less than or equal
+** to 2147483647.  The number of virtual machine operations can be 
+** used as a proxy for the total work done by the prepared statement.
+** If the number of virtual machine operations exceeds 2147483647
+** then the value returned by this statement status code is undefined.
+** </dd>
 ** </dl>
 */
 #define SQLITE_STMTSTATUS_FULLSCAN_STEP     1
 #define SQLITE_STMTSTATUS_SORT              2
 #define SQLITE_STMTSTATUS_AUTOINDEX         3
+#define SQLITE_STMTSTATUS_VM_STEP           4
 
 /*
 ** CAPI3REF: Custom Page Cache Object
@@ -7537,6 +7264,9 @@ SQLITE_API void *sqlite3_wal_hook(
 ** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
 ** from SQL.
 **
+** ^Checkpoints initiated by this mechanism are
+** [sqlite3_wal_checkpoint_v2|PASSIVE].
+**
 ** ^Every new [database connection] defaults to having the auto-checkpoint
 ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
 ** pages.  The use of this interface
@@ -7553,6 +7283,10 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
 ** empty string, then a checkpoint is run on all databases of
 ** connection D.  ^If the database connection D is not in
 ** [WAL | write-ahead log mode] then this interface is a harmless no-op.
+** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
+** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
+** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
+** or RESET checkpoint.
 **
 ** ^The [wal_checkpoint pragma] can be used to invoke this interface
 ** from SQL.  ^The [sqlite3_wal_autocheckpoint()] interface and the
@@ -7575,10 +7309,12 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
 **   Checkpoint as many frames as possible without waiting for any database 
 **   readers or writers to finish. Sync the db file if all frames in the log
 **   are checkpointed. This mode is the same as calling 
-**   sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
+**   sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
+**   is never invoked.
 **
 ** <dt>SQLITE_CHECKPOINT_FULL<dd>
-**   This mode blocks (calls the busy-handler callback) until there is no
+**   This mode blocks (it invokes the
+**   [sqlite3_busy_handler|busy-handler callback]) until there is no
 **   database writer and all readers are reading from the most recent database
 **   snapshot. It then checkpoints all frames in the log file and syncs the
 **   database file. This call blocks database writers while it is running,
@@ -7586,7 +7322,8 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
 **
 ** <dt>SQLITE_CHECKPOINT_RESTART<dd>
 **   This mode works the same way as SQLITE_CHECKPOINT_FULL, except after 
-**   checkpointing the log file it blocks (calls the busy-handler callback)
+**   checkpointing the log file it blocks (calls the 
+**   [sqlite3_busy_handler|busy-handler callback])
 **   until all readers are reading from the database file only. This ensures 
 **   that the next client to write to the database file restarts the log file 
 **   from the beginning. This call blocks database writers while it is running,
@@ -7724,6 +7461,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
 
 /*
 ** CAPI3REF: Conflict resolution modes
+** KEYWORDS: {conflict resolution mode}
 **
 ** These constants are returned by [sqlite3_vtab_on_conflict()] to
 ** inform a [virtual table] implementation what the [ON CONFLICT] mode
@@ -7752,7 +7490,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
 #if 0
 }  /* End of the 'extern "C"' block */
 #endif
-#endif
+#endif /* _SQLITE3_H_ */
 
 /*
 ** 2010 August 30
@@ -7776,6 +7514,16 @@ extern "C" {
 #endif
 
 typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
+typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
+
+/* The double-precision datatype used by RTree depends on the
+** SQLITE_RTREE_INT_ONLY compile-time option.
+*/
+#ifdef SQLITE_RTREE_INT_ONLY
+  typedef sqlite3_int64 sqlite3_rtree_dbl;
+#else
+  typedef double sqlite3_rtree_dbl;
+#endif
 
 /*
 ** Register a geometry callback named zGeom that can be used as part of an
@@ -7786,11 +7534,7 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
 SQLITE_API int sqlite3_rtree_geometry_callback(
   sqlite3 *db,
   const char *zGeom,
-#ifdef SQLITE_RTREE_INT_ONLY
-  int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
-#else
-  int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
-#endif
+  int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
   void *pContext
 );
 
@@ -7802,11 +7546,60 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
 struct sqlite3_rtree_geometry {
   void *pContext;                 /* Copy of pContext passed to s_r_g_c() */
   int nParam;                     /* Size of array aParam[] */
-  double *aParam;                 /* Parameters passed to SQL geom function */
+  sqlite3_rtree_dbl *aParam;      /* Parameters passed to SQL geom function */
   void *pUser;                    /* Callback implementation user data */
   void (*xDelUser)(void *);       /* Called by SQLite to clean up pUser */
 };
 
+/*
+** Register a 2nd-generation geometry callback named zScore that can be 
+** used as part of an R-Tree geometry query as follows:
+**
+**   SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
+*/
+SQLITE_API int sqlite3_rtree_query_callback(
+  sqlite3 *db,
+  const char *zQueryFunc,
+  int (*xQueryFunc)(sqlite3_rtree_query_info*),
+  void *pContext,
+  void (*xDestructor)(void*)
+);
+
+
+/*
+** A pointer to a structure of the following type is passed as the 
+** argument to scored geometry callback registered using
+** sqlite3_rtree_query_callback().
+**
+** Note that the first 5 fields of this structure are identical to
+** sqlite3_rtree_geometry.  This structure is a subclass of
+** sqlite3_rtree_geometry.
+*/
+struct sqlite3_rtree_query_info {
+  void *pContext;                   /* pContext from when function registered */
+  int nParam;                       /* Number of function parameters */
+  sqlite3_rtree_dbl *aParam;        /* value of function parameters */
+  void *pUser;                      /* callback can use this, if desired */
+  void (*xDelUser)(void*);          /* function to free pUser */
+  sqlite3_rtree_dbl *aCoord;        /* Coordinates of node or entry to check */
+  unsigned int *anQueue;            /* Number of pending entries in the queue */
+  int nCoord;                       /* Number of coordinates */
+  int iLevel;                       /* Level of current node or entry */
+  int mxLevel;                      /* The largest iLevel value in the tree */
+  sqlite3_int64 iRowid;             /* Rowid for current entry */
+  sqlite3_rtree_dbl rParentScore;   /* Score of parent node */
+  int eParentWithin;                /* Visibility of parent node */
+  int eWithin;                      /* OUT: Visiblity */
+  sqlite3_rtree_dbl rScore;         /* OUT: Write the score here */
+};
+
+/*
+** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
+*/
+#define NOT_WITHIN       0   /* Object completely outside of query region */
+#define PARTLY_WITHIN    1   /* Object partially overlaps query region */
+#define FULLY_WITHIN     2   /* Object fully contained within query region */
+
 
 #if 0
 }  /* end of the 'extern "C"' block */
@@ -7817,10 +7610,19 @@ struct sqlite3_rtree_geometry {
 
 /************** End of sqlite3.h *********************************************/
 /************** Continuing where we left off in sqliteInt.h ******************/
-/************** Include hash.h in the middle of sqliteInt.h ******************/
-/************** Begin file hash.h ********************************************/
+
 /*
-** 2001 September 22
+** Include the configuration header output by 'configure' if we're using the
+** autoconf-based build
+*/
+#ifdef _HAVE_SQLITE_CONFIG_H
+#include "config.h"
+#endif
+
+/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
+/************** Begin file sqliteLimit.h *************************************/
+/*
+** 2007 May 7
 **
 ** The author disclaims copyright to this source code.  In place of
 ** a legal notice, here is a blessing:
@@ -7830,667 +7632,471 @@ struct sqlite3_rtree_geometry {
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This is the header file for the generic hash-table implementation
-** used in SQLite.
-*/
-#ifndef _SQLITE_HASH_H_
-#define _SQLITE_HASH_H_
-
-/* Forward declarations of structures. */
-typedef struct Hash Hash;
-typedef struct HashElem HashElem;
-
-/* A complete hash table is an instance of the following structure.
-** The internals of this structure are intended to be opaque -- client
-** code should not attempt to access or modify the fields of this structure
-** directly.  Change this structure only by using the routines below.
-** However, some of the "procedures" and "functions" for modifying and
-** accessing this structure are really macros, so we can't really make
-** this structure opaque.
-**
-** All elements of the hash table are on a single doubly-linked list.
-** Hash.first points to the head of this list.
-**
-** There are Hash.htsize buckets.  Each bucket points to a spot in
-** the global doubly-linked list.  The contents of the bucket are the
-** element pointed to plus the next _ht.count-1 elements in the list.
-**
-** Hash.htsize and Hash.ht may be zero.  In that case lookup is done
-** by a linear search of the global list.  For small tables, the 
-** Hash.ht table is never allocated because if there are few elements
-** in the table, it is faster to do a linear search than to manage
-** the hash table.
+** 
+** This file defines various limits of what SQLite can process.
 */
-struct Hash {
-  unsigned int htsize;      /* Number of buckets in the hash table */
-  unsigned int count;       /* Number of entries in this table */
-  HashElem *first;          /* The first element of the array */
-  struct _ht {              /* the hash table */
-    int count;                 /* Number of entries with this hash */
-    HashElem *chain;           /* Pointer to first entry with this hash */
-  } *ht;
-};
 
-/* Each element in the hash table is an instance of the following 
-** structure.  All elements are stored on a single doubly-linked list.
+/*
+** The maximum length of a TEXT or BLOB in bytes.   This also
+** limits the size of a row in a table or index.
 **
-** Again, this structure is intended to be opaque, but it can't really
-** be opaque because it is used by macros.
+** The hard limit is the ability of a 32-bit signed integer
+** to count the size: 2^31-1 or 2147483647.
 */
-struct HashElem {
-  HashElem *next, *prev;       /* Next and previous elements in the table */
-  void *data;                  /* Data associated with this element */
-  const char *pKey; int nKey;  /* Key associated with this element */
-};
+#ifndef SQLITE_MAX_LENGTH
+# define SQLITE_MAX_LENGTH 1000000000
+#endif
 
 /*
-** Access routines.  To delete, insert a NULL pointer.
+** This is the maximum number of
+**
+**    * Columns in a table
+**    * Columns in an index
+**    * Columns in a view
+**    * Terms in the SET clause of an UPDATE statement
+**    * Terms in the result set of a SELECT statement
+**    * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
+**    * Terms in the VALUES clause of an INSERT statement
+**
+** The hard upper limit here is 32676.  Most database people will
+** tell you that in a well-normalized database, you usually should
+** not have more than a dozen or so columns in any table.  And if
+** that is the case, there is no point in having more than a few
+** dozen values in any of the other situations described above.
 */
-SQLITE_PRIVATE void sqlite3HashInit(Hash*);
-SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData);
-SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey, int nKey);
-SQLITE_PRIVATE void sqlite3HashClear(Hash*);
+#ifndef SQLITE_MAX_COLUMN
+# define SQLITE_MAX_COLUMN 2000
+#endif
 
 /*
-** Macros for looping over all elements of a hash table.  The idiom is
-** like this:
+** The maximum length of a single SQL statement in bytes.
 **
-**   Hash h;
-**   HashElem *p;
-**   ...
-**   for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){
-**     SomeStructure *pData = sqliteHashData(p);
-**     // do something with pData
-**   }
+** It used to be the case that setting this value to zero would
+** turn the limit off.  That is no longer true.  It is not possible
+** to turn this limit off.
 */
-#define sqliteHashFirst(H)  ((H)->first)
-#define sqliteHashNext(E)   ((E)->next)
-#define sqliteHashData(E)   ((E)->data)
-/* #define sqliteHashKey(E)    ((E)->pKey) // NOT USED */
-/* #define sqliteHashKeysize(E) ((E)->nKey)  // NOT USED */
+#ifndef SQLITE_MAX_SQL_LENGTH
+# define SQLITE_MAX_SQL_LENGTH 1000000000
+#endif
 
 /*
-** Number of entries in a hash table
+** The maximum depth of an expression tree. This is limited to 
+** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might 
+** want to place more severe limits on the complexity of an 
+** expression.
+**
+** A value of 0 used to mean that the limit was not enforced.
+** But that is no longer true.  The limit is now strictly enforced
+** at all times.
 */
-/* #define sqliteHashCount(H)  ((H)->count) // NOT USED */
-
-#endif /* _SQLITE_HASH_H_ */
-
-/************** End of hash.h ************************************************/
-/************** Continuing where we left off in sqliteInt.h ******************/
-/************** Include parse.h in the middle of sqliteInt.h *****************/
-/************** Begin file parse.h *******************************************/
-#define TK_SEMI                            1
-#define TK_EXPLAIN                         2
-#define TK_QUERY                           3
-#define TK_PLAN                            4
-#define TK_BEGIN                           5
-#define TK_TRANSACTION                     6
-#define TK_DEFERRED                        7
-#define TK_IMMEDIATE                       8
-#define TK_EXCLUSIVE                       9
-#define TK_COMMIT                         10
-#define TK_END                            11
-#define TK_ROLLBACK                       12
-#define TK_SAVEPOINT                      13
-#define TK_RELEASE                        14
-#define TK_TO                             15
-#define TK_TABLE                          16
-#define TK_CREATE                         17
-#define TK_IF                             18
-#define TK_NOT                            19
-#define TK_EXISTS                         20
-#define TK_TEMP                           21
-#define TK_LP                             22
-#define TK_RP                             23
-#define TK_AS                             24
-#define TK_COMMA                          25
-#define TK_ID                             26
-#define TK_INDEXED                        27
-#define TK_ABORT                          28
-#define TK_ACTION                         29
-#define TK_AFTER                          30
-#define TK_ANALYZE                        31
-#define TK_ASC                            32
-#define TK_ATTACH                         33
-#define TK_BEFORE                         34
-#define TK_BY                             35
-#define TK_CASCADE                        36
-#define TK_CAST                           37
-#define TK_COLUMNKW                       38
-#define TK_CONFLICT                       39
-#define TK_DATABASE                       40
-#define TK_DESC                           41
-#define TK_DETACH                         42
-#define TK_EACH                           43
-#define TK_FAIL                           44
-#define TK_FOR                            45
-#define TK_IGNORE                         46
-#define TK_INITIALLY                      47
-#define TK_INSTEAD                        48
-#define TK_LIKE_KW                        49
-#define TK_MATCH                          50
-#define TK_NO                             51
-#define TK_KEY                            52
-#define TK_OF                             53
-#define TK_OFFSET                         54
-#define TK_PRAGMA                         55
-#define TK_RAISE                          56
-#define TK_REPLACE                        57
-#define TK_RESTRICT                       58
-#define TK_ROW                            59
-#define TK_TRIGGER                        60
-#define TK_VACUUM                         61
-#define TK_VIEW                           62
-#define TK_VIRTUAL                        63
-#define TK_REINDEX                        64
-#define TK_RENAME                         65
-#define TK_CTIME_KW                       66
-#define TK_ANY                            67
-#define TK_OR                             68
-#define TK_AND                            69
-#define TK_IS                             70
-#define TK_BETWEEN                        71
-#define TK_IN                             72
-#define TK_ISNULL                         73
-#define TK_NOTNULL                        74
-#define TK_NE                             75
-#define TK_EQ                             76
-#define TK_GT                             77
-#define TK_LE                             78
-#define TK_LT                             79
-#define TK_GE                             80
-#define TK_ESCAPE                         81
-#define TK_BITAND                         82
-#define TK_BITOR                          83
-#define TK_LSHIFT                         84
-#define TK_RSHIFT                         85
-#define TK_PLUS                           86
-#define TK_MINUS                          87
-#define TK_STAR                           88
-#define TK_SLASH                          89
-#define TK_REM                            90
-#define TK_CONCAT                         91
-#define TK_COLLATE                        92
-#define TK_BITNOT                         93
-#define TK_STRING                         94
-#define TK_JOIN_KW                        95
-#define TK_CONSTRAINT                     96
-#define TK_DEFAULT                        97
-#define TK_NULL                           98
-#define TK_PRIMARY                        99
-#define TK_UNIQUE                         100
-#define TK_CHECK                          101
-#define TK_REFERENCES                     102
-#define TK_AUTOINCR                       103
-#define TK_ON                             104
-#define TK_INSERT                         105
-#define TK_DELETE                         106
-#define TK_UPDATE                         107
-#define TK_SET                            108
-#define TK_DEFERRABLE                     109
-#define TK_FOREIGN                        110
-#define TK_DROP                           111
-#define TK_UNION                          112
-#define TK_ALL                            113
-#define TK_EXCEPT                         114
-#define TK_INTERSECT                      115
-#define TK_SELECT                         116
-#define TK_DISTINCT                       117
-#define TK_DOT                            118
-#define TK_FROM                           119
-#define TK_JOIN                           120
-#define TK_USING                          121
-#define TK_ORDER                          122
-#define TK_GROUP                          123
-#define TK_HAVING                         124
-#define TK_LIMIT                          125
-#define TK_WHERE                          126
-#define TK_INTO                           127
-#define TK_VALUES                         128
-#define TK_INTEGER                        129
-#define TK_FLOAT                          130
-#define TK_BLOB                           131
-#define TK_REGISTER                       132
-#define TK_VARIABLE                       133
-#define TK_CASE                           134
-#define TK_WHEN                           135
-#define TK_THEN                           136
-#define TK_ELSE                           137
-#define TK_INDEX                          138
-#define TK_ALTER                          139
-#define TK_ADD                            140
-#define TK_TO_TEXT                        141
-#define TK_TO_BLOB                        142
-#define TK_TO_NUMERIC                     143
-#define TK_TO_INT                         144
-#define TK_TO_REAL                        145
-#define TK_ISNOT                          146
-#define TK_END_OF_FILE                    147
-#define TK_ILLEGAL                        148
-#define TK_SPACE                          149
-#define TK_UNCLOSED_STRING                150
-#define TK_FUNCTION                       151
-#define TK_COLUMN                         152
-#define TK_AGG_FUNCTION                   153
-#define TK_AGG_COLUMN                     154
-#define TK_CONST_FUNC                     155
-#define TK_UMINUS                         156
-#define TK_UPLUS                          157
-
-/************** End of parse.h ***********************************************/
-/************** Continuing where we left off in sqliteInt.h ******************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stddef.h>
+#ifndef SQLITE_MAX_EXPR_DEPTH
+# define SQLITE_MAX_EXPR_DEPTH 1000
+#endif
 
 /*
-** If compiling for a processor that lacks floating point support,
-** substitute integer for floating-point
+** The maximum number of terms in a compound SELECT statement.
+** The code generator for compound SELECT statements does one
+** level of recursion for each term.  A stack overflow can result
+** if the number of terms is too large.  In practice, most SQL
+** never has more than 3 or 4 terms.  Use a value of 0 to disable
+** any limit on the number of terms in a compount SELECT.
 */
-#ifdef SQLITE_OMIT_FLOATING_POINT
-# define double sqlite_int64
-# define float sqlite_int64
-# define LONGDOUBLE_TYPE sqlite_int64
-# ifndef SQLITE_BIG_DBL
-#   define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
-# endif
-# define SQLITE_OMIT_DATETIME_FUNCS 1
-# define SQLITE_OMIT_TRACE 1
-# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
-# undef SQLITE_HAVE_ISNAN
-#endif
-#ifndef SQLITE_BIG_DBL
-# define SQLITE_BIG_DBL (1e99)
+#ifndef SQLITE_MAX_COMPOUND_SELECT
+# define SQLITE_MAX_COMPOUND_SELECT 500
 #endif
 
 /*
-** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0
-** afterward. Having this macro allows us to cause the C compiler 
-** to omit code used by TEMP tables without messy #ifndef statements.
+** The maximum number of opcodes in a VDBE program.
+** Not currently enforced.
 */
-#ifdef SQLITE_OMIT_TEMPDB
-#define OMIT_TEMPDB 1
-#else
-#define OMIT_TEMPDB 0
+#ifndef SQLITE_MAX_VDBE_OP
+# define SQLITE_MAX_VDBE_OP 25000
 #endif
 
 /*
-** The "file format" number is an integer that is incremented whenever
-** the VDBE-level file format changes.  The following macros define the
-** the default file format for new databases and the maximum file format
-** that the library can read.
+** The maximum number of arguments to an SQL function.
 */
-#define SQLITE_MAX_FILE_FORMAT 4
-#ifndef SQLITE_DEFAULT_FILE_FORMAT
-# define SQLITE_DEFAULT_FILE_FORMAT 4
+#ifndef SQLITE_MAX_FUNCTION_ARG
+# define SQLITE_MAX_FUNCTION_ARG 127
 #endif
 
 /*
-** Determine whether triggers are recursive by default.  This can be
-** changed at run-time using a pragma.
+** The maximum number of in-memory pages to use for the main database
+** table and for temporary tables.  The SQLITE_DEFAULT_CACHE_SIZE
 */
-#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
-# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0
+#ifndef SQLITE_DEFAULT_CACHE_SIZE
+# define SQLITE_DEFAULT_CACHE_SIZE  2000
+#endif
+#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
+# define SQLITE_DEFAULT_TEMP_CACHE_SIZE  500
 #endif
 
 /*
-** Provide a default value for SQLITE_TEMP_STORE in case it is not specified
-** on the command-line
+** The default number of frames to accumulate in the log file before
+** checkpointing the database in WAL mode.
 */
-#ifndef SQLITE_TEMP_STORE
-# define SQLITE_TEMP_STORE 1
-# define SQLITE_TEMP_STORE_xc 1  /* Exclude from ctime.c */
+#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
+# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT  1000
 #endif
 
 /*
-** GCC does not define the offsetof() macro so we'll have to do it
-** ourselves.
+** The maximum number of attached databases.  This must be between 0
+** and 62.  The upper bound on 62 is because a 64-bit integer bitmap
+** is used internally to track attached databases.
 */
-#ifndef offsetof
-#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
+#ifndef SQLITE_MAX_ATTACHED
+# define SQLITE_MAX_ATTACHED 10
 #endif
 
+
 /*
-** Check to see if this machine uses EBCDIC.  (Yes, believe it or
-** not, there are still machines out there that use EBCDIC.)
+** The maximum value of a ?nnn wildcard that the parser will accept.
 */
-#if 'A' == '\301'
-# define SQLITE_EBCDIC 1
-#else
-# define SQLITE_ASCII 1
+#ifndef SQLITE_MAX_VARIABLE_NUMBER
+# define SQLITE_MAX_VARIABLE_NUMBER 999
 #endif
 
-/*
-** Integers of known sizes.  These typedefs might change for architectures
-** where the sizes very.  Preprocessor macros are available so that the
-** types can be conveniently redefined at compile-type.  Like this:
+/* Maximum page size.  The upper bound on this value is 65536.  This a limit
+** imposed by the use of 16-bit offsets within each page.
 **
-**         cc '-DUINTPTR_TYPE=long long int' ...
+** Earlier versions of SQLite allowed the user to change this value at
+** compile time. This is no longer permitted, on the grounds that it creates
+** a library that is technically incompatible with an SQLite library 
+** compiled with a different limit. If a process operating on a database 
+** with a page-size of 65536 bytes crashes, then an instance of SQLite 
+** compiled with the default page-size limit will not be able to rollback 
+** the aborted transaction. This could lead to database corruption.
 */
-#ifndef UINT32_TYPE
-# ifdef HAVE_UINT32_T
-#  define UINT32_TYPE uint32_t
-# else
-#  define UINT32_TYPE unsigned int
-# endif
-#endif
-#ifndef UINT16_TYPE
-# ifdef HAVE_UINT16_T
-#  define UINT16_TYPE uint16_t
-# else
-#  define UINT16_TYPE unsigned short int
-# endif
-#endif
-#ifndef INT16_TYPE
-# ifdef HAVE_INT16_T
-#  define INT16_TYPE int16_t
-# else
-#  define INT16_TYPE short int
-# endif
-#endif
-#ifndef UINT8_TYPE
-# ifdef HAVE_UINT8_T
-#  define UINT8_TYPE uint8_t
-# else
-#  define UINT8_TYPE unsigned char
-# endif
-#endif
-#ifndef INT8_TYPE
-# ifdef HAVE_INT8_T
-#  define INT8_TYPE int8_t
-# else
-#  define INT8_TYPE signed char
-# endif
-#endif
-#ifndef LONGDOUBLE_TYPE
-# define LONGDOUBLE_TYPE long double
+#ifdef SQLITE_MAX_PAGE_SIZE
+# undef SQLITE_MAX_PAGE_SIZE
 #endif
-typedef sqlite_int64 i64;          /* 8-byte signed integer */
-typedef sqlite_uint64 u64;         /* 8-byte unsigned integer */
-typedef UINT32_TYPE u32;           /* 4-byte unsigned integer */
-typedef UINT16_TYPE u16;           /* 2-byte unsigned integer */
-typedef INT16_TYPE i16;            /* 2-byte signed integer */
-typedef UINT8_TYPE u8;             /* 1-byte unsigned integer */
-typedef INT8_TYPE i8;              /* 1-byte signed integer */
+#define SQLITE_MAX_PAGE_SIZE 65536
 
-/*
-** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value
-** that can be stored in a u32 without loss of data.  The value
-** is 0x00000000ffffffff.  But because of quirks of some compilers, we
-** have to specify the value in the less intuitive manner shown:
-*/
-#define SQLITE_MAX_U32  ((((u64)1)<<32)-1)
 
 /*
-** The datatype used to store estimates of the number of rows in a
-** table or index.  This is an unsigned integer type.  For 99.9% of
-** the world, a 32-bit integer is sufficient.  But a 64-bit integer
-** can be used at compile-time if desired.
+** The default size of a database page.
 */
-#ifdef SQLITE_64BIT_STATS
- typedef u64 tRowcnt;    /* 64-bit only if requested at compile-time */
-#else
- typedef u32 tRowcnt;    /* 32-bit is the default */
+#ifndef SQLITE_DEFAULT_PAGE_SIZE
+# define SQLITE_DEFAULT_PAGE_SIZE 1024
+#endif
+#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
+# undef SQLITE_DEFAULT_PAGE_SIZE
+# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
 #endif
 
 /*
-** Macros to determine whether the machine is big or little endian,
-** evaluated at runtime.
+** Ordinarily, if no value is explicitly provided, SQLite creates databases
+** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
+** device characteristics (sector-size and atomic write() support),
+** SQLite may choose a larger value. This constant is the maximum value
+** SQLite will choose on its own.
 */
-#ifdef SQLITE_AMALGAMATION
-SQLITE_PRIVATE const int sqlite3one = 1;
-#else
-SQLITE_PRIVATE const int sqlite3one;
+#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
+# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
 #endif
-#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
-                             || defined(__x86_64) || defined(__x86_64__)
-# define SQLITE_BIGENDIAN    0
-# define SQLITE_LITTLEENDIAN 1
-# define SQLITE_UTF16NATIVE  SQLITE_UTF16LE
-#else
-# define SQLITE_BIGENDIAN    (*(char *)(&sqlite3one)==0)
-# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
-# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
+#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
+# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
+# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
 #endif
 
-/*
-** Constants for the largest and smallest possible 64-bit signed integers.
-** These macros are designed to work correctly on both 32-bit and 64-bit
-** compilers.
-*/
-#define LARGEST_INT64  (0xffffffff|(((i64)0x7fffffff)<<32))
-#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
 
-/* 
-** Round up a number to the next larger multiple of 8.  This is used
-** to force 8-byte alignment on 64-bit architectures.
+/*
+** Maximum number of pages in one database file.
+**
+** This is really just the default value for the max_page_count pragma.
+** This value can be lowered (or raised) at run-time using that the
+** max_page_count macro.
 */
-#define ROUND8(x)     (((x)+7)&~7)
+#ifndef SQLITE_MAX_PAGE_COUNT
+# define SQLITE_MAX_PAGE_COUNT 1073741823
+#endif
 
 /*
-** Round down to the nearest multiple of 8
+** Maximum length (in bytes) of the pattern in a LIKE or GLOB
+** operator.
 */
-#define ROUNDDOWN8(x) ((x)&~7)
+#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
+# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
+#endif
 
 /*
-** Assert that the pointer X is aligned to an 8-byte boundary.  This
-** macro is used only within assert() to verify that the code gets
-** all alignment restrictions correct.
+** Maximum depth of recursion for triggers.
 **
-** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the
-** underlying malloc() implemention might return us 4-byte aligned
-** pointers.  In that case, only verify 4-byte alignment.
+** A value of 1 means that a trigger program will not be able to itself
+** fire any triggers. A value of 0 means that no trigger programs at all 
+** may be executed.
 */
-#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
-# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&3)==0)
-#else
-# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&7)==0)
+#ifndef SQLITE_MAX_TRIGGER_DEPTH
+# define SQLITE_MAX_TRIGGER_DEPTH 1000
 #endif
 
-/*
-** Disable MMAP on platforms where it is known to not work
-*/
-#if defined(__OpenBSD__) || defined(__QNXNTO__)
-# undef SQLITE_MAX_MMAP_SIZE
-# define SQLITE_MAX_MMAP_SIZE 0
+/************** End of sqliteLimit.h *****************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+
+/* Disable nuisance warnings on Borland compilers */
+#if defined(__BORLANDC__)
+#pragma warn -rch /* unreachable code */
+#pragma warn -ccc /* Condition is always true or false */
+#pragma warn -aus /* Assigned value is never used */
+#pragma warn -csu /* Comparing signed and unsigned */
+#pragma warn -spa /* Suspicious pointer arithmetic */
 #endif
 
-/*
-** Default maximum size of memory used by memory-mapped I/O in the VFS
-*/
-#ifdef __APPLE__
-# include <TargetConditionals.h>
-# if TARGET_OS_IPHONE
-#   undef SQLITE_MAX_MMAP_SIZE
-#   define SQLITE_MAX_MMAP_SIZE 0
-# endif
+/* Needed for various definitions... */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
 #endif
-#ifndef SQLITE_MAX_MMAP_SIZE
-# if defined(__linux__) \
-  || defined(_WIN32) \
-  || (defined(__APPLE__) && defined(__MACH__)) \
-  || defined(__sun)
-#   define SQLITE_MAX_MMAP_SIZE 0x7fff0000  /* 2147418112 */
-# else
-#   define SQLITE_MAX_MMAP_SIZE 0
-# endif
-# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */
+
+#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
+# define _BSD_SOURCE
 #endif
 
 /*
-** The default MMAP_SIZE is zero on all platforms.  Or, even if a larger
-** default MMAP_SIZE is specified at compile-time, make sure that it does
-** not exceed the maximum mmap size.
+** Include standard header files as necessary
 */
-#ifndef SQLITE_DEFAULT_MMAP_SIZE
-# define SQLITE_DEFAULT_MMAP_SIZE 0
-# define SQLITE_DEFAULT_MMAP_SIZE_xc 1  /* Exclude from ctime.c */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
 #endif
-#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
-# undef SQLITE_DEFAULT_MMAP_SIZE
-# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
 #endif
 
 /*
-** An instance of the following structure is used to store the busy-handler
-** callback for a given sqlite handle. 
+** The following macros are used to cast pointers to integers and
+** integers to pointers.  The way you do this varies from one compiler
+** to the next, so we have developed the following set of #if statements
+** to generate appropriate macros for a wide range of compilers.
 **
-** The sqlite.busyHandler member of the sqlite struct contains the busy
-** callback for the database handle. Each pager opened via the sqlite
-** handle is passed a pointer to sqlite.busyHandler. The busy-handler
-** callback is currently invoked only from within pager.c.
+** The correct "ANSI" way to do this is to use the intptr_t type. 
+** Unfortunately, that typedef is not available on all compilers, or
+** if it is available, it requires an #include of specific headers
+** that vary from one machine to the next.
+**
+** Ticket #3860:  The llvm-gcc-4.2 compiler from Apple chokes on
+** the ((void*)&((char*)0)[X]) construct.  But MSVC chokes on ((void*)(X)).
+** So we have to define the macros in different ways depending on the
+** compiler.
 */
-typedef struct BusyHandler BusyHandler;
-struct BusyHandler {
-  int (*xFunc)(void *,int);  /* The busy callback */
-  void *pArg;                /* First arg to busy callback */
-  int nBusy;                 /* Incremented with each busy call */
-};
-
-/*
-** Name of the master database table.  The master database table
-** is a special table that holds the names and attributes of all
-** user tables and indices.
+#if defined(__PTRDIFF_TYPE__)  /* This case should work for GCC */
+# define SQLITE_INT_TO_PTR(X)  ((void*)(__PTRDIFF_TYPE__)(X))
+# define SQLITE_PTR_TO_INT(X)  ((int)(__PTRDIFF_TYPE__)(X))
+#elif !defined(__GNUC__)       /* Works for compilers other than LLVM */
+# define SQLITE_INT_TO_PTR(X)  ((void*)&((char*)0)[X])
+# define SQLITE_PTR_TO_INT(X)  ((int)(((char*)X)-(char*)0))
+#elif defined(HAVE_STDINT_H)   /* Use this case if we have ANSI headers */
+# define SQLITE_INT_TO_PTR(X)  ((void*)(intptr_t)(X))
+# define SQLITE_PTR_TO_INT(X)  ((int)(intptr_t)(X))
+#else                          /* Generates a warning - but it always works */
+# define SQLITE_INT_TO_PTR(X)  ((void*)(X))
+# define SQLITE_PTR_TO_INT(X)  ((int)(X))
+#endif
+
+/*
+** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
+** 0 means mutexes are permanently disable and the library is never
+** threadsafe.  1 means the library is serialized which is the highest
+** level of threadsafety.  2 means the library is multithreaded - multiple
+** threads can use SQLite as long as no two threads try to use the same
+** database connection at the same time.
+**
+** Older versions of SQLite used an optional THREADSAFE macro.
+** We support that for legacy.
 */
-#define MASTER_NAME       "sqlite_master"
-#define TEMP_MASTER_NAME  "sqlite_temp_master"
+#if !defined(SQLITE_THREADSAFE)
+# if defined(THREADSAFE)
+#   define SQLITE_THREADSAFE THREADSAFE
+# else
+#   define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
+# endif
+#endif
 
 /*
-** The root-page of the master database table.
+** Powersafe overwrite is on by default.  But can be turned off using
+** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
 */
-#define MASTER_ROOT       1
+#ifndef SQLITE_POWERSAFE_OVERWRITE
+# define SQLITE_POWERSAFE_OVERWRITE 1
+#endif
 
 /*
-** The name of the schema table.
+** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
+** It determines whether or not the features related to 
+** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
+** be overridden at runtime using the sqlite3_config() API.
 */
-#define SCHEMA_TABLE(x)  ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME)
+#if !defined(SQLITE_DEFAULT_MEMSTATUS)
+# define SQLITE_DEFAULT_MEMSTATUS 1
+#endif
 
 /*
-** A convenience macro that returns the number of elements in
-** an array.
+** Exactly one of the following macros must be defined in order to
+** specify which memory allocation subsystem to use.
+**
+**     SQLITE_SYSTEM_MALLOC          // Use normal system malloc()
+**     SQLITE_WIN32_MALLOC           // Use Win32 native heap API
+**     SQLITE_ZERO_MALLOC            // Use a stub allocator that always fails
+**     SQLITE_MEMDEBUG               // Debugging version of system malloc()
+**
+** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
+** assert() macro is enabled, each call into the Win32 native heap subsystem
+** will cause HeapValidate to be called.  If heap validation should fail, an
+** assertion will be triggered.
+**
+** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
+** the default.
 */
-#define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))
+#if defined(SQLITE_SYSTEM_MALLOC) \
+  + defined(SQLITE_WIN32_MALLOC) \
+  + defined(SQLITE_ZERO_MALLOC) \
+  + defined(SQLITE_MEMDEBUG)>1
+# error "Two or more of the following compile-time configuration options\
+ are defined but at most one is allowed:\
+ SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
+ SQLITE_ZERO_MALLOC"
+#endif
+#if defined(SQLITE_SYSTEM_MALLOC) \
+  + defined(SQLITE_WIN32_MALLOC) \
+  + defined(SQLITE_ZERO_MALLOC) \
+  + defined(SQLITE_MEMDEBUG)==0
+# define SQLITE_SYSTEM_MALLOC 1
+#endif
 
 /*
-** Determine if the argument is a power of two
+** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
+** sizes of memory allocations below this value where possible.
 */
-#define IsPowerOfTwo(X) (((X)&((X)-1))==0)
+#if !defined(SQLITE_MALLOC_SOFT_LIMIT)
+# define SQLITE_MALLOC_SOFT_LIMIT 1024
+#endif
 
 /*
-** The following value as a destructor means to use sqlite3DbFree().
-** The sqlite3DbFree() routine requires two parameters instead of the 
-** one parameter that destructors normally want.  So we have to introduce 
-** this magic value that the code knows to handle differently.  Any 
-** pointer will work here as long as it is distinct from SQLITE_STATIC
-** and SQLITE_TRANSIENT.
+** We need to define _XOPEN_SOURCE as follows in order to enable
+** recursive mutexes on most Unix systems and fchmod() on OpenBSD.
+** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit
+** it.
 */
-#define SQLITE_DYNAMIC   ((sqlite3_destructor_type)sqlite3MallocSize)
+#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)
+#  define _XOPEN_SOURCE 600
+#endif
 
 /*
-** When SQLITE_OMIT_WSD is defined, it means that the target platform does
-** not support Writable Static Data (WSD) such as global and static variables.
-** All variables must either be on the stack or dynamically allocated from
-** the heap.  When WSD is unsupported, the variable declarations scattered
-** throughout the SQLite code must become constants instead.  The SQLITE_WSD
-** macro is used for this purpose.  And instead of referencing the variable
-** directly, we use its constant as a key to lookup the run-time allocated
-** buffer that holds real variable.  The constant is also the initializer
-** for the run-time allocated buffer.
+** NDEBUG and SQLITE_DEBUG are opposites.  It should always be true that
+** defined(NDEBUG)==!defined(SQLITE_DEBUG).  If this is not currently true,
+** make it true by defining or undefining NDEBUG.
 **
-** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL
-** macros become no-ops and have zero performance impact.
+** Setting NDEBUG makes the code smaller and faster by disabling the
+** assert() statements in the code.  So we want the default action
+** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
+** is set.  Thus NDEBUG becomes an opt-in rather than an opt-out
+** feature.
 */
-#ifdef SQLITE_OMIT_WSD
-  #define SQLITE_WSD const
-  #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v)))
-  #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config)
-SQLITE_API   int sqlite3_wsd_init(int N, int J);
-SQLITE_API   void *sqlite3_wsd_find(void *K, int L);
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) 
+# define NDEBUG 1
+#endif
+#if defined(NDEBUG) && defined(SQLITE_DEBUG)
+# undef NDEBUG
+#endif
+
+/*
+** Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on.
+*/
+#if !defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) && defined(SQLITE_DEBUG)
+# define SQLITE_ENABLE_EXPLAIN_COMMENTS 1
+#endif
+
+/*
+** The testcase() macro is used to aid in coverage testing.  When 
+** doing coverage testing, the condition inside the argument to
+** testcase() must be evaluated both true and false in order to
+** get full branch coverage.  The testcase() macro is inserted
+** to help ensure adequate test coverage in places where simple
+** condition/decision coverage is inadequate.  For example, testcase()
+** can be used to make sure boundary values are tested.  For
+** bitmask tests, testcase() can be used to make sure each bit
+** is significant and used at least once.  On switch statements
+** where multiple cases go to the same block of code, testcase()
+** can insure that all cases are evaluated.
+**
+*/
+#ifdef SQLITE_COVERAGE_TEST
+SQLITE_PRIVATE   void sqlite3Coverage(int);
+# define testcase(X)  if( X ){ sqlite3Coverage(__LINE__); }
 #else
-  #define SQLITE_WSD 
-  #define GLOBAL(t,v) v
-  #define sqlite3GlobalConfig sqlite3Config
+# define testcase(X)
 #endif
 
 /*
-** The following macros are used to suppress compiler warnings and to
-** make it clear to human readers when a function parameter is deliberately 
-** left unused within the body of a function. This usually happens when
-** a function is called via a function pointer. For example the 
-** implementation of an SQL aggregate step callback may not use the
-** parameter indicating the number of arguments passed to the aggregate,
-** if it knows that this is enforced elsewhere.
+** The TESTONLY macro is used to enclose variable declarations or
+** other bits of code that are needed to support the arguments
+** within testcase() and assert() macros.
+*/
+#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
+# define TESTONLY(X)  X
+#else
+# define TESTONLY(X)
+#endif
+
+/*
+** Sometimes we need a small amount of code such as a variable initialization
+** to setup for a later assert() statement.  We do not want this code to
+** appear when assert() is disabled.  The following macro is therefore
+** used to contain that setup code.  The "VVA" acronym stands for
+** "Verification, Validation, and Accreditation".  In other words, the
+** code within VVA_ONLY() will only run during verification processes.
+*/
+#ifndef NDEBUG
+# define VVA_ONLY(X)  X
+#else
+# define VVA_ONLY(X)
+#endif
+
+/*
+** The ALWAYS and NEVER macros surround boolean expressions which 
+** are intended to always be true or false, respectively.  Such
+** expressions could be omitted from the code completely.  But they
+** are included in a few cases in order to enhance the resilience
+** of SQLite to unexpected behavior - to make the code "self-healing"
+** or "ductile" rather than being "brittle" and crashing at the first
+** hint of unplanned behavior.
 **
-** When a function parameter is not used at all within the body of a function,
-** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
-** However, these macros may also be used to suppress warnings related to
-** parameters that may or may not be used depending on compilation options.
-** For example those parameters only used in assert() statements. In these
-** cases the parameters are named as per the usual conventions.
+** In other words, ALWAYS and NEVER are added for defensive code.
+**
+** When doing coverage testing ALWAYS and NEVER are hard-coded to
+** be true and false so that the unreachable code they specify will
+** not be counted as untested code.
 */
-#define UNUSED_PARAMETER(x) (void)(x)
-#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
+#if defined(SQLITE_COVERAGE_TEST)
+# define ALWAYS(X)      (1)
+# define NEVER(X)       (0)
+#elif !defined(NDEBUG)
+# define ALWAYS(X)      ((X)?1:(assert(0),0))
+# define NEVER(X)       ((X)?(assert(0),1):0)
+#else
+# define ALWAYS(X)      (X)
+# define NEVER(X)       (X)
+#endif
 
 /*
-** Forward references to structures
+** Return true (non-zero) if the input is a integer that is too large
+** to fit in 32-bits.  This macro is used inside of various testcase()
+** macros to verify that we have tested SQLite for large-file support.
 */
-typedef struct AggInfo AggInfo;
-typedef struct AuthContext AuthContext;
-typedef struct AutoincInfo AutoincInfo;
-typedef struct Bitvec Bitvec;
-typedef struct CollSeq CollSeq;
-typedef struct Column Column;
-typedef struct Db Db;
-typedef struct Schema Schema;
-typedef struct Expr Expr;
-typedef struct ExprList ExprList;
-typedef struct ExprSpan ExprSpan;
-typedef struct FKey FKey;
-typedef struct FuncDestructor FuncDestructor;
-typedef struct FuncDef FuncDef;
-typedef struct FuncDefHash FuncDefHash;
-typedef struct IdList IdList;
-typedef struct Index Index;
-typedef struct IndexSample IndexSample;
-typedef struct KeyClass KeyClass;
-typedef struct KeyInfo KeyInfo;
-typedef struct Lookaside Lookaside;
-typedef struct LookasideSlot LookasideSlot;
-typedef struct Module Module;
-typedef struct NameContext NameContext;
-typedef struct Parse Parse;
-typedef struct RowSet RowSet;
-typedef struct Savepoint Savepoint;
-typedef struct Select Select;
-typedef struct SelectDest SelectDest;
-typedef struct SrcList SrcList;
-typedef struct StrAccum StrAccum;
-typedef struct Table Table;
-typedef struct TableLock TableLock;
-typedef struct Token Token;
-typedef struct Trigger Trigger;
-typedef struct TriggerPrg TriggerPrg;
-typedef struct TriggerStep TriggerStep;
-typedef struct UnpackedRecord UnpackedRecord;
-typedef struct VTable VTable;
-typedef struct VtabCtx VtabCtx;
-typedef struct Walker Walker;
-typedef struct WherePlan WherePlan;
-typedef struct WhereInfo WhereInfo;
-typedef struct WhereLevel WhereLevel;
+#define IS_BIG_INT(X)  (((X)&~(i64)0xffffffff)!=0)
 
 /*
-** Defer sourcing vdbe.h and btree.h until after the "u8" and 
-** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
-** pointer types (i.e. FuncDef) defined above.
+** The macro unlikely() is a hint that surrounds a boolean
+** expression that is usually false.  Macro likely() surrounds
+** a boolean expression that is usually true.  These hints could,
+** in theory, be used by the compiler to generate better code, but
+** currently they are just comments for human readers.
 */
-/************** Include btree.h in the middle of sqliteInt.h *****************/
-/************** Begin file btree.h *******************************************/
+#define likely(X)    (X)
+#define unlikely(X)  (X)
+
+/************** Include hash.h in the middle of sqliteInt.h ******************/
+/************** Begin file hash.h ********************************************/
 /*
-** 2001 September 15
+** 2001 September 22
 **
 ** The author disclaims copyright to this source code.  In place of
 ** a legal notice, here is a blessing:
@@ -8500,122 +8106,859 @@ typedef struct WhereLevel WhereLevel;
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This header file defines the interface that the sqlite B-Tree file
-** subsystem.  See comments in the source code for a detailed description
-** of what each interface routine does.
+** This is the header file for the generic hash-table implementation
+** used in SQLite.
 */
-#ifndef _BTREE_H_
-#define _BTREE_H_
+#ifndef _SQLITE_HASH_H_
+#define _SQLITE_HASH_H_
 
-/* TODO: This definition is just included so other modules compile. It
-** needs to be revisited.
+/* Forward declarations of structures. */
+typedef struct Hash Hash;
+typedef struct HashElem HashElem;
+
+/* A complete hash table is an instance of the following structure.
+** The internals of this structure are intended to be opaque -- client
+** code should not attempt to access or modify the fields of this structure
+** directly.  Change this structure only by using the routines below.
+** However, some of the "procedures" and "functions" for modifying and
+** accessing this structure are really macros, so we can't really make
+** this structure opaque.
+**
+** All elements of the hash table are on a single doubly-linked list.
+** Hash.first points to the head of this list.
+**
+** There are Hash.htsize buckets.  Each bucket points to a spot in
+** the global doubly-linked list.  The contents of the bucket are the
+** element pointed to plus the next _ht.count-1 elements in the list.
+**
+** Hash.htsize and Hash.ht may be zero.  In that case lookup is done
+** by a linear search of the global list.  For small tables, the 
+** Hash.ht table is never allocated because if there are few elements
+** in the table, it is faster to do a linear search than to manage
+** the hash table.
 */
-#define SQLITE_N_BTREE_META 10
+struct Hash {
+  unsigned int htsize;      /* Number of buckets in the hash table */
+  unsigned int count;       /* Number of entries in this table */
+  HashElem *first;          /* The first element of the array */
+  struct _ht {              /* the hash table */
+    int count;                 /* Number of entries with this hash */
+    HashElem *chain;           /* Pointer to first entry with this hash */
+  } *ht;
+};
+
+/* Each element in the hash table is an instance of the following 
+** structure.  All elements are stored on a single doubly-linked list.
+**
+** Again, this structure is intended to be opaque, but it can't really
+** be opaque because it is used by macros.
+*/
+struct HashElem {
+  HashElem *next, *prev;       /* Next and previous elements in the table */
+  void *data;                  /* Data associated with this element */
+  const char *pKey; int nKey;  /* Key associated with this element */
+};
 
 /*
-** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
-** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
+** Access routines.  To delete, insert a NULL pointer.
 */
-#ifndef SQLITE_DEFAULT_AUTOVACUUM
-  #define SQLITE_DEFAULT_AUTOVACUUM 0
-#endif
+SQLITE_PRIVATE void sqlite3HashInit(Hash*);
+SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData);
+SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey, int nKey);
+SQLITE_PRIVATE void sqlite3HashClear(Hash*);
 
-#define BTREE_AUTOVACUUM_NONE 0        /* Do not do auto-vacuum */
-#define BTREE_AUTOVACUUM_FULL 1        /* Do full auto-vacuum */
-#define BTREE_AUTOVACUUM_INCR 2        /* Incremental vacuum */
+/*
+** Macros for looping over all elements of a hash table.  The idiom is
+** like this:
+**
+**   Hash h;
+**   HashElem *p;
+**   ...
+**   for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){
+**     SomeStructure *pData = sqliteHashData(p);
+**     // do something with pData
+**   }
+*/
+#define sqliteHashFirst(H)  ((H)->first)
+#define sqliteHashNext(E)   ((E)->next)
+#define sqliteHashData(E)   ((E)->data)
+/* #define sqliteHashKey(E)    ((E)->pKey) // NOT USED */
+/* #define sqliteHashKeysize(E) ((E)->nKey)  // NOT USED */
 
 /*
-** Forward declarations of structure
+** Number of entries in a hash table
 */
-typedef struct Btree Btree;
-typedef struct BtCursor BtCursor;
-typedef struct BtShared BtShared;
+/* #define sqliteHashCount(H)  ((H)->count) // NOT USED */
 
+#endif /* _SQLITE_HASH_H_ */
 
-SQLITE_PRIVATE int sqlite3BtreeOpen(
-  sqlite3_vfs *pVfs,       /* VFS to use with this b-tree */
-  const char *zFilename,   /* Name of database file to open */
-  sqlite3 *db,             /* Associated database connection */
-  Btree **ppBtree,         /* Return open Btree* here */
-  int flags,               /* Flags */
-  int vfsFlags             /* Flags passed through to VFS open */
-);
+/************** End of hash.h ************************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+/************** Include parse.h in the middle of sqliteInt.h *****************/
+/************** Begin file parse.h *******************************************/
+#define TK_SEMI                             1
+#define TK_EXPLAIN                          2
+#define TK_QUERY                            3
+#define TK_PLAN                             4
+#define TK_BEGIN                            5
+#define TK_TRANSACTION                      6
+#define TK_DEFERRED                         7
+#define TK_IMMEDIATE                        8
+#define TK_EXCLUSIVE                        9
+#define TK_COMMIT                          10
+#define TK_END                             11
+#define TK_ROLLBACK                        12
+#define TK_SAVEPOINT                       13
+#define TK_RELEASE                         14
+#define TK_TO                              15
+#define TK_TABLE                           16
+#define TK_CREATE                          17
+#define TK_IF                              18
+#define TK_NOT                             19
+#define TK_EXISTS                          20
+#define TK_TEMP                            21
+#define TK_LP                              22
+#define TK_RP                              23
+#define TK_AS                              24
+#define TK_WITHOUT                         25
+#define TK_COMMA                           26
+#define TK_ID                              27
+#define TK_INDEXED                         28
+#define TK_ABORT                           29
+#define TK_ACTION                          30
+#define TK_AFTER                           31
+#define TK_ANALYZE                         32
+#define TK_ASC                             33
+#define TK_ATTACH                          34
+#define TK_BEFORE                          35
+#define TK_BY                              36
+#define TK_CASCADE                         37
+#define TK_CAST                            38
+#define TK_COLUMNKW                        39
+#define TK_CONFLICT                        40
+#define TK_DATABASE                        41
+#define TK_DESC                            42
+#define TK_DETACH                          43
+#define TK_EACH                            44
+#define TK_FAIL                            45
+#define TK_FOR                             46
+#define TK_IGNORE                          47
+#define TK_INITIALLY                       48
+#define TK_INSTEAD                         49
+#define TK_LIKE_KW                         50
+#define TK_MATCH                           51
+#define TK_NO                              52
+#define TK_KEY                             53
+#define TK_OF                              54
+#define TK_OFFSET                          55
+#define TK_PRAGMA                          56
+#define TK_RAISE                           57
+#define TK_RECURSIVE                       58
+#define TK_REPLACE                         59
+#define TK_RESTRICT                        60
+#define TK_ROW                             61
+#define TK_TRIGGER                         62
+#define TK_VACUUM                          63
+#define TK_VIEW                            64
+#define TK_VIRTUAL                         65
+#define TK_WITH                            66
+#define TK_REINDEX                         67
+#define TK_RENAME                          68
+#define TK_CTIME_KW                        69
+#define TK_ANY                             70
+#define TK_OR                              71
+#define TK_AND                             72
+#define TK_IS                              73
+#define TK_BETWEEN                         74
+#define TK_IN                              75
+#define TK_ISNULL                          76
+#define TK_NOTNULL                         77
+#define TK_NE                              78
+#define TK_EQ                              79
+#define TK_GT                              80
+#define TK_LE                              81
+#define TK_LT                              82
+#define TK_GE                              83
+#define TK_ESCAPE                          84
+#define TK_BITAND                          85
+#define TK_BITOR                           86
+#define TK_LSHIFT                          87
+#define TK_RSHIFT                          88
+#define TK_PLUS                            89
+#define TK_MINUS                           90
+#define TK_STAR                            91
+#define TK_SLASH                           92
+#define TK_REM                             93
+#define TK_CONCAT                          94
+#define TK_COLLATE                         95
+#define TK_BITNOT                          96
+#define TK_STRING                          97
+#define TK_JOIN_KW                         98
+#define TK_CONSTRAINT                      99
+#define TK_DEFAULT                        100
+#define TK_NULL                           101
+#define TK_PRIMARY                        102
+#define TK_UNIQUE                         103
+#define TK_CHECK                          104
+#define TK_REFERENCES                     105
+#define TK_AUTOINCR                       106
+#define TK_ON                             107
+#define TK_INSERT                         108
+#define TK_DELETE                         109
+#define TK_UPDATE                         110
+#define TK_SET                            111
+#define TK_DEFERRABLE                     112
+#define TK_FOREIGN                        113
+#define TK_DROP                           114
+#define TK_UNION                          115
+#define TK_ALL                            116
+#define TK_EXCEPT                         117
+#define TK_INTERSECT                      118
+#define TK_SELECT                         119
+#define TK_VALUES                         120
+#define TK_DISTINCT                       121
+#define TK_DOT                            122
+#define TK_FROM                           123
+#define TK_JOIN                           124
+#define TK_USING                          125
+#define TK_ORDER                          126
+#define TK_GROUP                          127
+#define TK_HAVING                         128
+#define TK_LIMIT                          129
+#define TK_WHERE                          130
+#define TK_INTO                           131
+#define TK_INTEGER                        132
+#define TK_FLOAT                          133
+#define TK_BLOB                           134
+#define TK_VARIABLE                       135
+#define TK_CASE                           136
+#define TK_WHEN                           137
+#define TK_THEN                           138
+#define TK_ELSE                           139
+#define TK_INDEX                          140
+#define TK_ALTER                          141
+#define TK_ADD                            142
+#define TK_TO_TEXT                        143
+#define TK_TO_BLOB                        144
+#define TK_TO_NUMERIC                     145
+#define TK_TO_INT                         146
+#define TK_TO_REAL                        147
+#define TK_ISNOT                          148
+#define TK_END_OF_FILE                    149
+#define TK_ILLEGAL                        150
+#define TK_SPACE                          151
+#define TK_UNCLOSED_STRING                152
+#define TK_FUNCTION                       153
+#define TK_COLUMN                         154
+#define TK_AGG_FUNCTION                   155
+#define TK_AGG_COLUMN                     156
+#define TK_UMINUS                         157
+#define TK_UPLUS                          158
+#define TK_REGISTER                       159
 
-/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
-** following values.
-**
-** NOTE:  These values must match the corresponding PAGER_ values in
-** pager.h.
-*/
-#define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
-#define BTREE_MEMORY        2  /* This is an in-memory DB */
-#define BTREE_SINGLE        4  /* The file contains at most 1 b-tree */
-#define BTREE_UNORDERED     8  /* Use of a hash implementation is OK */
+/************** End of parse.h ***********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stddef.h>
 
-SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
-SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
-SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
-SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
-SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
-SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
-SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*);
-#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
-SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
+/*
+** If compiling for a processor that lacks floating point support,
+** substitute integer for floating-point
+*/
+#ifdef SQLITE_OMIT_FLOATING_POINT
+# define double sqlite_int64
+# define float sqlite_int64
+# define LONGDOUBLE_TYPE sqlite_int64
+# ifndef SQLITE_BIG_DBL
+#   define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
+# endif
+# define SQLITE_OMIT_DATETIME_FUNCS 1
+# define SQLITE_OMIT_TRACE 1
+# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+# undef SQLITE_HAVE_ISNAN
+#endif
+#ifndef SQLITE_BIG_DBL
+# define SQLITE_BIG_DBL (1e99)
 #endif
-SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
-SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
-SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
-SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
-SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int);
-SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int);
-SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
-SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags);
-SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*);
-SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
-SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree);
-SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
-SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int);
 
-SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *);
-SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *);
-SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *);
+/*
+** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0
+** afterward. Having this macro allows us to cause the C compiler 
+** to omit code used by TEMP tables without messy #ifndef statements.
+*/
+#ifdef SQLITE_OMIT_TEMPDB
+#define OMIT_TEMPDB 1
+#else
+#define OMIT_TEMPDB 0
+#endif
 
-SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
+/*
+** The "file format" number is an integer that is incremented whenever
+** the VDBE-level file format changes.  The following macros define the
+** the default file format for new databases and the maximum file format
+** that the library can read.
+*/
+#define SQLITE_MAX_FILE_FORMAT 4
+#ifndef SQLITE_DEFAULT_FILE_FORMAT
+# define SQLITE_DEFAULT_FILE_FORMAT 4
+#endif
 
-/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
-** of the flags shown below.
-**
-** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set.
-** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data
-** is stored in the leaves.  (BTREE_INTKEY is used for SQL tables.)  With
-** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored
-** anywhere - the key is the content.  (BTREE_BLOBKEY is used for SQL
-** indices.)
+/*
+** Determine whether triggers are recursive by default.  This can be
+** changed at run-time using a pragma.
 */
-#define BTREE_INTKEY     1    /* Table has only 64-bit signed integer keys */
-#define BTREE_BLOBKEY    2    /* Table has keys only - no data */
+#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
+# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0
+#endif
 
-SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
-SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);
-SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);
+/*
+** Provide a default value for SQLITE_TEMP_STORE in case it is not specified
+** on the command-line
+*/
+#ifndef SQLITE_TEMP_STORE
+# define SQLITE_TEMP_STORE 1
+# define SQLITE_TEMP_STORE_xc 1  /* Exclude from ctime.c */
+#endif
 
-SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
-SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
+/*
+** GCC does not define the offsetof() macro so we'll have to do it
+** ourselves.
+*/
+#ifndef offsetof
+#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
 
-SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
+/*
+** Macros to compute minimum and maximum of two numbers.
+*/
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#define MAX(A,B) ((A)>(B)?(A):(B))
 
 /*
-** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
-** should be one of the following values. The integer values are assigned 
-** to constants so that the offset of the corresponding field in an
-** SQLite database header may be found using the following formula:
+** Check to see if this machine uses EBCDIC.  (Yes, believe it or
+** not, there are still machines out there that use EBCDIC.)
+*/
+#if 'A' == '\301'
+# define SQLITE_EBCDIC 1
+#else
+# define SQLITE_ASCII 1
+#endif
+
+/*
+** Integers of known sizes.  These typedefs might change for architectures
+** where the sizes very.  Preprocessor macros are available so that the
+** types can be conveniently redefined at compile-type.  Like this:
+**
+**         cc '-DUINTPTR_TYPE=long long int' ...
+*/
+#ifndef UINT32_TYPE
+# ifdef HAVE_UINT32_T
+#  define UINT32_TYPE uint32_t
+# else
+#  define UINT32_TYPE unsigned int
+# endif
+#endif
+#ifndef UINT16_TYPE
+# ifdef HAVE_UINT16_T
+#  define UINT16_TYPE uint16_t
+# else
+#  define UINT16_TYPE unsigned short int
+# endif
+#endif
+#ifndef INT16_TYPE
+# ifdef HAVE_INT16_T
+#  define INT16_TYPE int16_t
+# else
+#  define INT16_TYPE short int
+# endif
+#endif
+#ifndef UINT8_TYPE
+# ifdef HAVE_UINT8_T
+#  define UINT8_TYPE uint8_t
+# else
+#  define UINT8_TYPE unsigned char
+# endif
+#endif
+#ifndef INT8_TYPE
+# ifdef HAVE_INT8_T
+#  define INT8_TYPE int8_t
+# else
+#  define INT8_TYPE signed char
+# endif
+#endif
+#ifndef LONGDOUBLE_TYPE
+# define LONGDOUBLE_TYPE long double
+#endif
+typedef sqlite_int64 i64;          /* 8-byte signed integer */
+typedef sqlite_uint64 u64;         /* 8-byte unsigned integer */
+typedef UINT32_TYPE u32;           /* 4-byte unsigned integer */
+typedef UINT16_TYPE u16;           /* 2-byte unsigned integer */
+typedef INT16_TYPE i16;            /* 2-byte signed integer */
+typedef UINT8_TYPE u8;             /* 1-byte unsigned integer */
+typedef INT8_TYPE i8;              /* 1-byte signed integer */
+
+/*
+** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value
+** that can be stored in a u32 without loss of data.  The value
+** is 0x00000000ffffffff.  But because of quirks of some compilers, we
+** have to specify the value in the less intuitive manner shown:
+*/
+#define SQLITE_MAX_U32  ((((u64)1)<<32)-1)
+
+/*
+** The datatype used to store estimates of the number of rows in a
+** table or index.  This is an unsigned integer type.  For 99.9% of
+** the world, a 32-bit integer is sufficient.  But a 64-bit integer
+** can be used at compile-time if desired.
+*/
+#ifdef SQLITE_64BIT_STATS
+ typedef u64 tRowcnt;    /* 64-bit only if requested at compile-time */
+#else
+ typedef u32 tRowcnt;    /* 32-bit is the default */
+#endif
+
+/*
+** Estimated quantities used for query planning are stored as 16-bit
+** logarithms.  For quantity X, the value stored is 10*log2(X).  This
+** gives a possible range of values of approximately 1.0e986 to 1e-986.
+** But the allowed values are "grainy".  Not every value is representable.
+** For example, quantities 16 and 17 are both represented by a LogEst
+** of 40.  However, since LogEst quantaties are suppose to be estimates,
+** not exact values, this imprecision is not a problem.
+**
+** "LogEst" is short for "Logarithmic Estimate".
+**
+** Examples:
+**      1 -> 0              20 -> 43          10000 -> 132
+**      2 -> 10             25 -> 46          25000 -> 146
+**      3 -> 16            100 -> 66        1000000 -> 199
+**      4 -> 20           1000 -> 99        1048576 -> 200
+**     10 -> 33           1024 -> 100    4294967296 -> 320
+**
+** The LogEst can be negative to indicate fractional values. 
+** Examples:
+**
+**    0.5 -> -10           0.1 -> -33        0.0625 -> -40
+*/
+typedef INT16_TYPE LogEst;
+
+/*
+** Macros to determine whether the machine is big or little endian,
+** and whether or not that determination is run-time or compile-time.
+**
+** For best performance, an attempt is made to guess at the byte-order
+** using C-preprocessor macros.  If that is unsuccessful, or if
+** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
+** at run-time.
+*/
+#ifdef SQLITE_AMALGAMATION
+SQLITE_PRIVATE const int sqlite3one = 1;
+#else
+SQLITE_PRIVATE const int sqlite3one;
+#endif
+#if (defined(i386)     || defined(__i386__)   || defined(_M_IX86) ||    \
+     defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)  ||    \
+     defined(_M_AMD64) || defined(_M_ARM)     || defined(__x86)   ||    \
+     defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
+# define SQLITE_BYTEORDER    1234
+# define SQLITE_BIGENDIAN    0
+# define SQLITE_LITTLEENDIAN 1
+# define SQLITE_UTF16NATIVE  SQLITE_UTF16LE
+#endif
+#if (defined(sparc)    || defined(__ppc__))  \
+    && !defined(SQLITE_RUNTIME_BYTEORDER)
+# define SQLITE_BYTEORDER    4321
+# define SQLITE_BIGENDIAN    1
+# define SQLITE_LITTLEENDIAN 0
+# define SQLITE_UTF16NATIVE  SQLITE_UTF16BE
+#endif
+#if !defined(SQLITE_BYTEORDER)
+# define SQLITE_BYTEORDER    0     /* 0 means "unknown at compile-time" */
+# define SQLITE_BIGENDIAN    (*(char *)(&sqlite3one)==0)
+# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
+# define SQLITE_UTF16NATIVE  (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
+#endif
+
+/*
+** Constants for the largest and smallest possible 64-bit signed integers.
+** These macros are designed to work correctly on both 32-bit and 64-bit
+** compilers.
+*/
+#define LARGEST_INT64  (0xffffffff|(((i64)0x7fffffff)<<32))
+#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
+
+/* 
+** Round up a number to the next larger multiple of 8.  This is used
+** to force 8-byte alignment on 64-bit architectures.
+*/
+#define ROUND8(x)     (((x)+7)&~7)
+
+/*
+** Round down to the nearest multiple of 8
+*/
+#define ROUNDDOWN8(x) ((x)&~7)
+
+/*
+** Assert that the pointer X is aligned to an 8-byte boundary.  This
+** macro is used only within assert() to verify that the code gets
+** all alignment restrictions correct.
+**
+** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the
+** underlying malloc() implemention might return us 4-byte aligned
+** pointers.  In that case, only verify 4-byte alignment.
+*/
+#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
+# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&3)==0)
+#else
+# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&7)==0)
+#endif
+
+/*
+** Disable MMAP on platforms where it is known to not work
+*/
+#if defined(__OpenBSD__) || defined(__QNXNTO__)
+# undef SQLITE_MAX_MMAP_SIZE
+# define SQLITE_MAX_MMAP_SIZE 0
+#endif
+
+/*
+** Default maximum size of memory used by memory-mapped I/O in the VFS
+*/
+#ifdef __APPLE__
+# include <TargetConditionals.h>
+# if TARGET_OS_IPHONE
+#   undef SQLITE_MAX_MMAP_SIZE
+#   define SQLITE_MAX_MMAP_SIZE 0
+# endif
+#endif
+#ifndef SQLITE_MAX_MMAP_SIZE
+# if defined(__linux__) \
+  || defined(_WIN32) \
+  || (defined(__APPLE__) && defined(__MACH__)) \
+  || defined(__sun)
+#   define SQLITE_MAX_MMAP_SIZE 0x7fff0000  /* 2147418112 */
+# else
+#   define SQLITE_MAX_MMAP_SIZE 0
+# endif
+# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */
+#endif
+
+/*
+** The default MMAP_SIZE is zero on all platforms.  Or, even if a larger
+** default MMAP_SIZE is specified at compile-time, make sure that it does
+** not exceed the maximum mmap size.
+*/
+#ifndef SQLITE_DEFAULT_MMAP_SIZE
+# define SQLITE_DEFAULT_MMAP_SIZE 0
+# define SQLITE_DEFAULT_MMAP_SIZE_xc 1  /* Exclude from ctime.c */
+#endif
+#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
+# undef SQLITE_DEFAULT_MMAP_SIZE
+# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
+#endif
+
+/*
+** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined.
+** Priority is given to SQLITE_ENABLE_STAT4.  If either are defined, also
+** define SQLITE_ENABLE_STAT3_OR_STAT4
+*/
+#ifdef SQLITE_ENABLE_STAT4
+# undef SQLITE_ENABLE_STAT3
+# define SQLITE_ENABLE_STAT3_OR_STAT4 1
+#elif SQLITE_ENABLE_STAT3
+# define SQLITE_ENABLE_STAT3_OR_STAT4 1
+#elif SQLITE_ENABLE_STAT3_OR_STAT4
+# undef SQLITE_ENABLE_STAT3_OR_STAT4
+#endif
+
+/*
+** An instance of the following structure is used to store the busy-handler
+** callback for a given sqlite handle. 
+**
+** The sqlite.busyHandler member of the sqlite struct contains the busy
+** callback for the database handle. Each pager opened via the sqlite
+** handle is passed a pointer to sqlite.busyHandler. The busy-handler
+** callback is currently invoked only from within pager.c.
+*/
+typedef struct BusyHandler BusyHandler;
+struct BusyHandler {
+  int (*xFunc)(void *,int);  /* The busy callback */
+  void *pArg;                /* First arg to busy callback */
+  int nBusy;                 /* Incremented with each busy call */
+};
+
+/*
+** Name of the master database table.  The master database table
+** is a special table that holds the names and attributes of all
+** user tables and indices.
+*/
+#define MASTER_NAME       "sqlite_master"
+#define TEMP_MASTER_NAME  "sqlite_temp_master"
+
+/*
+** The root-page of the master database table.
+*/
+#define MASTER_ROOT       1
+
+/*
+** The name of the schema table.
+*/
+#define SCHEMA_TABLE(x)  ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME)
+
+/*
+** A convenience macro that returns the number of elements in
+** an array.
+*/
+#define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))
+
+/*
+** Determine if the argument is a power of two
+*/
+#define IsPowerOfTwo(X) (((X)&((X)-1))==0)
+
+/*
+** The following value as a destructor means to use sqlite3DbFree().
+** The sqlite3DbFree() routine requires two parameters instead of the 
+** one parameter that destructors normally want.  So we have to introduce 
+** this magic value that the code knows to handle differently.  Any 
+** pointer will work here as long as it is distinct from SQLITE_STATIC
+** and SQLITE_TRANSIENT.
+*/
+#define SQLITE_DYNAMIC   ((sqlite3_destructor_type)sqlite3MallocSize)
+
+/*
+** When SQLITE_OMIT_WSD is defined, it means that the target platform does
+** not support Writable Static Data (WSD) such as global and static variables.
+** All variables must either be on the stack or dynamically allocated from
+** the heap.  When WSD is unsupported, the variable declarations scattered
+** throughout the SQLite code must become constants instead.  The SQLITE_WSD
+** macro is used for this purpose.  And instead of referencing the variable
+** directly, we use its constant as a key to lookup the run-time allocated
+** buffer that holds real variable.  The constant is also the initializer
+** for the run-time allocated buffer.
+**
+** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL
+** macros become no-ops and have zero performance impact.
+*/
+#ifdef SQLITE_OMIT_WSD
+  #define SQLITE_WSD const
+  #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v)))
+  #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config)
+SQLITE_API   int sqlite3_wsd_init(int N, int J);
+SQLITE_API   void *sqlite3_wsd_find(void *K, int L);
+#else
+  #define SQLITE_WSD 
+  #define GLOBAL(t,v) v
+  #define sqlite3GlobalConfig sqlite3Config
+#endif
+
+/*
+** The following macros are used to suppress compiler warnings and to
+** make it clear to human readers when a function parameter is deliberately 
+** left unused within the body of a function. This usually happens when
+** a function is called via a function pointer. For example the 
+** implementation of an SQL aggregate step callback may not use the
+** parameter indicating the number of arguments passed to the aggregate,
+** if it knows that this is enforced elsewhere.
+**
+** When a function parameter is not used at all within the body of a function,
+** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
+** However, these macros may also be used to suppress warnings related to
+** parameters that may or may not be used depending on compilation options.
+** For example those parameters only used in assert() statements. In these
+** cases the parameters are named as per the usual conventions.
+*/
+#define UNUSED_PARAMETER(x) (void)(x)
+#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
+
+/*
+** Forward references to structures
+*/
+typedef struct AggInfo AggInfo;
+typedef struct AuthContext AuthContext;
+typedef struct AutoincInfo AutoincInfo;
+typedef struct Bitvec Bitvec;
+typedef struct CollSeq CollSeq;
+typedef struct Column Column;
+typedef struct Db Db;
+typedef struct Schema Schema;
+typedef struct Expr Expr;
+typedef struct ExprList ExprList;
+typedef struct ExprSpan ExprSpan;
+typedef struct FKey FKey;
+typedef struct FuncDestructor FuncDestructor;
+typedef struct FuncDef FuncDef;
+typedef struct FuncDefHash FuncDefHash;
+typedef struct IdList IdList;
+typedef struct Index Index;
+typedef struct IndexSample IndexSample;
+typedef struct KeyClass KeyClass;
+typedef struct KeyInfo KeyInfo;
+typedef struct Lookaside Lookaside;
+typedef struct LookasideSlot LookasideSlot;
+typedef struct Module Module;
+typedef struct NameContext NameContext;
+typedef struct Parse Parse;
+typedef struct PrintfArguments PrintfArguments;
+typedef struct RowSet RowSet;
+typedef struct Savepoint Savepoint;
+typedef struct Select Select;
+typedef struct SelectDest SelectDest;
+typedef struct SrcList SrcList;
+typedef struct StrAccum StrAccum;
+typedef struct Table Table;
+typedef struct TableLock TableLock;
+typedef struct Token Token;
+typedef struct Trigger Trigger;
+typedef struct TriggerPrg TriggerPrg;
+typedef struct TriggerStep TriggerStep;
+typedef struct UnpackedRecord UnpackedRecord;
+typedef struct VTable VTable;
+typedef struct VtabCtx VtabCtx;
+typedef struct Walker Walker;
+typedef struct WhereInfo WhereInfo;
+typedef struct With With;
+
+/*
+** Defer sourcing vdbe.h and btree.h until after the "u8" and 
+** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
+** pointer types (i.e. FuncDef) defined above.
+*/
+/************** Include btree.h in the middle of sqliteInt.h *****************/
+/************** Begin file btree.h *******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the sqlite B-Tree file
+** subsystem.  See comments in the source code for a detailed description
+** of what each interface routine does.
+*/
+#ifndef _BTREE_H_
+#define _BTREE_H_
+
+/* TODO: This definition is just included so other modules compile. It
+** needs to be revisited.
+*/
+#define SQLITE_N_BTREE_META 10
+
+/*
+** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
+** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
+*/
+#ifndef SQLITE_DEFAULT_AUTOVACUUM
+  #define SQLITE_DEFAULT_AUTOVACUUM 0
+#endif
+
+#define BTREE_AUTOVACUUM_NONE 0        /* Do not do auto-vacuum */
+#define BTREE_AUTOVACUUM_FULL 1        /* Do full auto-vacuum */
+#define BTREE_AUTOVACUUM_INCR 2        /* Incremental vacuum */
+
+/*
+** Forward declarations of structure
+*/
+typedef struct Btree Btree;
+typedef struct BtCursor BtCursor;
+typedef struct BtShared BtShared;
+
+
+SQLITE_PRIVATE int sqlite3BtreeOpen(
+  sqlite3_vfs *pVfs,       /* VFS to use with this b-tree */
+  const char *zFilename,   /* Name of database file to open */
+  sqlite3 *db,             /* Associated database connection */
+  Btree **ppBtree,         /* Return open Btree* here */
+  int flags,               /* Flags */
+  int vfsFlags             /* Flags passed through to VFS open */
+);
+
+/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
+** following values.
+**
+** NOTE:  These values must match the corresponding PAGER_ values in
+** pager.h.
+*/
+#define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
+#define BTREE_MEMORY        2  /* This is an in-memory DB */
+#define BTREE_SINGLE        4  /* The file contains at most 1 b-tree */
+#define BTREE_UNORDERED     8  /* Use of a hash implementation is OK */
+
+SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
+#if SQLITE_MAX_MMAP_SIZE>0
+SQLITE_PRIVATE   int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
+#endif
+SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
+SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
+SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
+SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*);
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
+SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
+#endif
+SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
+SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
+SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
+SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int);
+SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags);
+SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*);
+SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
+SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree);
+SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
+SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int);
+
+SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *);
+SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *);
+SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *);
+
+SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
+
+/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
+** of the flags shown below.
+**
+** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set.
+** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data
+** is stored in the leaves.  (BTREE_INTKEY is used for SQL tables.)  With
+** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored
+** anywhere - the key is the content.  (BTREE_BLOBKEY is used for SQL
+** indices.)
+*/
+#define BTREE_INTKEY     1    /* Table has only 64-bit signed integer keys */
+#define BTREE_BLOBKEY    2    /* Table has keys only - no data */
+
+SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
+SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);
+SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*);
+SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);
+
+SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
+SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
+
+SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
+
+/*
+** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
+** should be one of the following values. The integer values are assigned 
+** to constants so that the offset of the corresponding field in an
+** SQLite database header may be found using the following formula:
 **
 **   offset = 36 + (idx * 4)
 **
@@ -8669,21 +9012,20 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
 SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes);
 SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor*, i64 *pSize);
 SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
-SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt);
-SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt);
+SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, u32 *pAmt);
+SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, u32 *pAmt);
 SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
 SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
-SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64);
-SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor*);
 
 SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
 SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
 
 SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
-SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *);
+SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *);
 SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *);
 SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
 SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
+SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt);
 
 #ifndef NDEBUG
 SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
@@ -8779,7 +9121,6 @@ typedef struct Vdbe Vdbe;
 ** The names of the following types declared in vdbeInt.h are required
 ** for the VdbeOp definition.
 */
-typedef struct VdbeFunc VdbeFunc;
 typedef struct Mem Mem;
 typedef struct SubProgram SubProgram;
 
@@ -8803,7 +9144,6 @@ struct VdbeOp {
     i64 *pI64;             /* Used when p4type is P4_INT64 */
     double *pReal;         /* Used when p4type is P4_REAL */
     FuncDef *pFunc;        /* Used when p4type is P4_FUNCDEF */
-    VdbeFunc *pVdbeFunc;   /* Used when p4type is P4_VDBEFUNC */
     CollSeq *pColl;        /* Used when p4type is P4_COLLSEQ */
     Mem *pMem;             /* Used when p4type is P4_MEM */
     VTable *pVtab;         /* Used when p4type is P4_VTAB */
@@ -8812,13 +9152,16 @@ struct VdbeOp {
     SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */
     int (*xAdvance)(BtCursor *, int *);
   } p4;
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
   char *zComment;          /* Comment to improve readability */
 #endif
 #ifdef VDBE_PROFILE
-  int cnt;                 /* Number of times this instruction was executed */
+  u32 cnt;                 /* Number of times this instruction was executed */
   u64 cycles;              /* Total time spent executing this instruction */
 #endif
+#ifdef SQLITE_VDBE_COVERAGE
+  int iSrcLine;            /* Source-code line that generated this opcode */
+#endif
 };
 typedef struct VdbeOp VdbeOp;
 
@@ -8857,7 +9200,6 @@ typedef struct VdbeOpList VdbeOpList;
 #define P4_COLLSEQ  (-4)  /* P4 is a pointer to a CollSeq structure */
 #define P4_FUNCDEF  (-5)  /* P4 is a pointer to a FuncDef structure */
 #define P4_KEYINFO  (-6)  /* P4 is a pointer to a KeyInfo structure */
-#define P4_VDBEFUNC (-7)  /* P4 is a pointer to a VdbeFunc structure */
 #define P4_MEM      (-8)  /* P4 is a pointer to a Mem*    structure */
 #define P4_TRANSIENT  0   /* P4 is a pointer to a transient string */
 #define P4_VTAB     (-10) /* P4 is a pointer to an sqlite3_vtab structure */
@@ -8869,15 +9211,11 @@ typedef struct VdbeOpList VdbeOpList;
 #define P4_SUBPROGRAM  (-18) /* P4 is a pointer to a SubProgram structure */
 #define P4_ADVANCE  (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
 
-/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
-** is made.  That copy is freed when the Vdbe is finalized.  But if the
-** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used.  It still
-** gets freed when the Vdbe is finalized so it still should be obtained
-** from a single sqliteMalloc().  But no copy is made and the calling
-** function should *not* try to free the KeyInfo.
-*/
-#define P4_KEYINFO_HANDOFF (-16)
-#define P4_KEYINFO_STATIC  (-17)
+/* Error message codes for OP_Halt */
+#define P5_ConstraintNotNull 1
+#define P5_ConstraintUnique  2
+#define P5_ConstraintCheck   3
+#define P5_ConstraintFK      4
 
 /*
 ** The Vdbe.aColName array contains 5n Mem structures, where n is the 
@@ -8914,156 +9252,164 @@ typedef struct VdbeOpList VdbeOpList;
 /************** Begin file opcodes.h *****************************************/
 /* Automatically generated.  Do not edit */
 /* See the mkopcodeh.awk script for details */
-#define OP_Goto                                 1
-#define OP_Gosub                                2
-#define OP_Return                               3
-#define OP_Yield                                4
-#define OP_HaltIfNull                           5
-#define OP_Halt                                 6
-#define OP_Integer                              7
-#define OP_Int64                                8
-#define OP_Real                               130   /* same as TK_FLOAT    */
-#define OP_String8                             94   /* same as TK_STRING   */
-#define OP_String                               9
-#define OP_Null                                10
-#define OP_Blob                                11
-#define OP_Variable                            12
-#define OP_Move                                13
-#define OP_Copy                                14
-#define OP_SCopy                               15
-#define OP_ResultRow                           16
-#define OP_Concat                              91   /* same as TK_CONCAT   */
-#define OP_Add                                 86   /* same as TK_PLUS     */
-#define OP_Subtract                            87   /* same as TK_MINUS    */
-#define OP_Multiply                            88   /* same as TK_STAR     */
-#define OP_Divide                              89   /* same as TK_SLASH    */
-#define OP_Remainder                           90   /* same as TK_REM      */
-#define OP_CollSeq                             17
-#define OP_Function                            18
-#define OP_BitAnd                              82   /* same as TK_BITAND   */
-#define OP_BitOr                               83   /* same as TK_BITOR    */
-#define OP_ShiftLeft                           84   /* same as TK_LSHIFT   */
-#define OP_ShiftRight                          85   /* same as TK_RSHIFT   */
-#define OP_AddImm                              20
-#define OP_MustBeInt                           21
-#define OP_RealAffinity                        22
-#define OP_ToText                             141   /* same as TK_TO_TEXT  */
-#define OP_ToBlob                             142   /* same as TK_TO_BLOB  */
-#define OP_ToNumeric                          143   /* same as TK_TO_NUMERIC*/
-#define OP_ToInt                              144   /* same as TK_TO_INT   */
-#define OP_ToReal                             145   /* same as TK_TO_REAL  */
-#define OP_Eq                                  76   /* same as TK_EQ       */
-#define OP_Ne                                  75   /* same as TK_NE       */
-#define OP_Lt                                  79   /* same as TK_LT       */
-#define OP_Le                                  78   /* same as TK_LE       */
-#define OP_Gt                                  77   /* same as TK_GT       */
-#define OP_Ge                                  80   /* same as TK_GE       */
-#define OP_Permutation                         23
-#define OP_Compare                             24
-#define OP_Jump                                25
-#define OP_And                                 69   /* same as TK_AND      */
-#define OP_Or                                  68   /* same as TK_OR       */
-#define OP_Not                                 19   /* same as TK_NOT      */
-#define OP_BitNot                              93   /* same as TK_BITNOT   */
-#define OP_Once                                26
-#define OP_If                                  27
-#define OP_IfNot                               28
-#define OP_IsNull                              73   /* same as TK_ISNULL   */
-#define OP_NotNull                             74   /* same as TK_NOTNULL  */
-#define OP_Column                              29
-#define OP_Affinity                            30
-#define OP_MakeRecord                          31
-#define OP_Count                               32
-#define OP_Savepoint                           33
-#define OP_AutoCommit                          34
-#define OP_Transaction                         35
-#define OP_ReadCookie                          36
-#define OP_SetCookie                           37
-#define OP_VerifyCookie                        38
-#define OP_OpenRead                            39
-#define OP_OpenWrite                           40
-#define OP_OpenAutoindex                       41
-#define OP_OpenEphemeral                       42
-#define OP_SorterOpen                          43
-#define OP_OpenPseudo                          44
-#define OP_Close                               45
-#define OP_SeekLt                              46
-#define OP_SeekLe                              47
-#define OP_SeekGe                              48
-#define OP_SeekGt                              49
-#define OP_Seek                                50
-#define OP_NotFound                            51
-#define OP_Found                               52
-#define OP_IsUnique                            53
-#define OP_NotExists                           54
-#define OP_Sequence                            55
-#define OP_NewRowid                            56
-#define OP_Insert                              57
-#define OP_InsertInt                           58
-#define OP_Delete                              59
-#define OP_ResetCount                          60
-#define OP_SorterCompare                       61
-#define OP_SorterData                          62
-#define OP_RowKey                              63
-#define OP_RowData                             64
-#define OP_Rowid                               65
-#define OP_NullRow                             66
-#define OP_Last                                67
-#define OP_SorterSort                          70
-#define OP_Sort                                71
-#define OP_Rewind                              72
-#define OP_SorterNext                          81
-#define OP_Prev                                92
-#define OP_Next                                95
-#define OP_SorterInsert                        96
-#define OP_IdxInsert                           97
-#define OP_IdxDelete                           98
-#define OP_IdxRowid                            99
-#define OP_IdxLT                              100
-#define OP_IdxGE                              101
-#define OP_Destroy                            102
-#define OP_Clear                              103
-#define OP_CreateIndex                        104
-#define OP_CreateTable                        105
-#define OP_ParseSchema                        106
-#define OP_LoadAnalysis                       107
-#define OP_DropTable                          108
-#define OP_DropIndex                          109
-#define OP_DropTrigger                        110
-#define OP_IntegrityCk                        111
-#define OP_RowSetAdd                          112
-#define OP_RowSetRead                         113
-#define OP_RowSetTest                         114
-#define OP_Program                            115
-#define OP_Param                              116
-#define OP_FkCounter                          117
-#define OP_FkIfZero                           118
-#define OP_MemMax                             119
-#define OP_IfPos                              120
-#define OP_IfNeg                              121
-#define OP_IfZero                             122
-#define OP_AggStep                            123
-#define OP_AggFinal                           124
-#define OP_Checkpoint                         125
-#define OP_JournalMode                        126
-#define OP_Vacuum                             127
-#define OP_IncrVacuum                         128
-#define OP_Expire                             129
-#define OP_TableLock                          131
-#define OP_VBegin                             132
-#define OP_VCreate                            133
-#define OP_VDestroy                           134
-#define OP_VOpen                              135
-#define OP_VFilter                            136
-#define OP_VColumn                            137
-#define OP_VNext                              138
-#define OP_VRename                            139
-#define OP_VUpdate                            140
-#define OP_Pagecount                          146
-#define OP_MaxPgcnt                           147
-#define OP_Trace                              148
-#define OP_Noop                               149
-#define OP_Explain                            150
+#define OP_Function        1 /* synopsis: r[P3]=func(r[P2 at P5])             */
+#define OP_Savepoint       2
+#define OP_AutoCommit      3
+#define OP_Transaction     4
+#define OP_SorterNext      5
+#define OP_PrevIfOpen      6
+#define OP_NextIfOpen      7
+#define OP_Prev            8
+#define OP_Next            9
+#define OP_AggStep        10 /* synopsis: accum=r[P3] step(r[P2 at P5])       */
+#define OP_Checkpoint     11
+#define OP_JournalMode    12
+#define OP_Vacuum         13
+#define OP_VFilter        14 /* synopsis: iplan=r[P3] zplan='P4'           */
+#define OP_VUpdate        15 /* synopsis: data=r[P3 at P2]                    */
+#define OP_Goto           16
+#define OP_Gosub          17
+#define OP_Return         18
+#define OP_Not            19 /* same as TK_NOT, synopsis: r[P2]= !r[P1]    */
+#define OP_InitCoroutine  20
+#define OP_EndCoroutine   21
+#define OP_Yield          22
+#define OP_HaltIfNull     23 /* synopsis: if r[P3]=null halt               */
+#define OP_Halt           24
+#define OP_Integer        25 /* synopsis: r[P2]=P1                         */
+#define OP_Int64          26 /* synopsis: r[P2]=P4                         */
+#define OP_String         27 /* synopsis: r[P2]='P4' (len=P1)              */
+#define OP_Null           28 /* synopsis: r[P2..P3]=NULL                   */
+#define OP_SoftNull       29 /* synopsis: r[P1]=NULL                       */
+#define OP_Blob           30 /* synopsis: r[P2]=P4 (len=P1)                */
+#define OP_Variable       31 /* synopsis: r[P2]=parameter(P1,P4)           */
+#define OP_Move           32 /* synopsis: r[P2 at P3]=r[P1 at P3]                */
+#define OP_Copy           33 /* synopsis: r[P2 at P3+1]=r[P1 at P3+1]            */
+#define OP_SCopy          34 /* synopsis: r[P2]=r[P1]                      */
+#define OP_ResultRow      35 /* synopsis: output=r[P1 at P2]                  */
+#define OP_CollSeq        36
+#define OP_AddImm         37 /* synopsis: r[P1]=r[P1]+P2                   */
+#define OP_MustBeInt      38
+#define OP_RealAffinity   39
+#define OP_Permutation    40
+#define OP_Compare        41 /* synopsis: r[P1 at P3] <-> r[P2 at P3]            */
+#define OP_Jump           42
+#define OP_Once           43
+#define OP_If             44
+#define OP_IfNot          45
+#define OP_Column         46 /* synopsis: r[P3]=PX                         */
+#define OP_Affinity       47 /* synopsis: affinity(r[P1 at P2])               */
+#define OP_MakeRecord     48 /* synopsis: r[P3]=mkrec(r[P1 at P2])            */
+#define OP_Count          49 /* synopsis: r[P2]=count()                    */
+#define OP_ReadCookie     50
+#define OP_SetCookie      51
+#define OP_ReopenIdx      52 /* synopsis: root=P2 iDb=P3                   */
+#define OP_OpenRead       53 /* synopsis: root=P2 iDb=P3                   */
+#define OP_OpenWrite      54 /* synopsis: root=P2 iDb=P3                   */
+#define OP_OpenAutoindex  55 /* synopsis: nColumn=P2                       */
+#define OP_OpenEphemeral  56 /* synopsis: nColumn=P2                       */
+#define OP_SorterOpen     57
+#define OP_OpenPseudo     58 /* synopsis: P3 columns in r[P2]              */
+#define OP_Close          59
+#define OP_SeekLT         60 /* synopsis: key=r[P3 at P4]                     */
+#define OP_SeekLE         61 /* synopsis: key=r[P3 at P4]                     */
+#define OP_SeekGE         62 /* synopsis: key=r[P3 at P4]                     */
+#define OP_SeekGT         63 /* synopsis: key=r[P3 at P4]                     */
+#define OP_Seek           64 /* synopsis: intkey=r[P2]                     */
+#define OP_NoConflict     65 /* synopsis: key=r[P3 at P4]                     */
+#define OP_NotFound       66 /* synopsis: key=r[P3 at P4]                     */
+#define OP_Found          67 /* synopsis: key=r[P3 at P4]                     */
+#define OP_NotExists      68 /* synopsis: intkey=r[P3]                     */
+#define OP_Sequence       69 /* synopsis: r[P2]=cursor[P1].ctr++           */
+#define OP_NewRowid       70 /* synopsis: r[P2]=rowid                      */
+#define OP_Or             71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
+#define OP_And            72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
+#define OP_Insert         73 /* synopsis: intkey=r[P3] data=r[P2]          */
+#define OP_InsertInt      74 /* synopsis: intkey=P3 data=r[P2]             */
+#define OP_Delete         75
+#define OP_IsNull         76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+#define OP_NotNull        77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+#define OP_Ne             78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */
+#define OP_Eq             79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */
+#define OP_Gt             80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */
+#define OP_Le             81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */
+#define OP_Lt             82 /* same as TK_LT, synopsis: if r[P1]<r[P3] goto P2 */
+#define OP_Ge             83 /* same as TK_GE, synopsis: if r[P1]>=r[P3] goto P2 */
+#define OP_ResetCount     84
+#define OP_BitAnd         85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr          86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft      87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
+#define OP_ShiftRight     88 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
+#define OP_Add            89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract       90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply       91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide         92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder      93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat         94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_SorterCompare  95 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_BitNot         96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
+#define OP_String8        97 /* same as TK_STRING, synopsis: r[P2]='P4'    */
+#define OP_SorterData     98 /* synopsis: r[P2]=data                       */
+#define OP_RowKey         99 /* synopsis: r[P2]=key                        */
+#define OP_RowData       100 /* synopsis: r[P2]=data                       */
+#define OP_Rowid         101 /* synopsis: r[P2]=rowid                      */
+#define OP_NullRow       102
+#define OP_Last          103
+#define OP_SorterSort    104
+#define OP_Sort          105
+#define OP_Rewind        106
+#define OP_SorterInsert  107
+#define OP_IdxInsert     108 /* synopsis: key=r[P2]                        */
+#define OP_IdxDelete     109 /* synopsis: key=r[P2 at P3]                     */
+#define OP_IdxRowid      110 /* synopsis: r[P2]=rowid                      */
+#define OP_IdxLE         111 /* synopsis: key=r[P3 at P4]                     */
+#define OP_IdxGT         112 /* synopsis: key=r[P3 at P4]                     */
+#define OP_IdxLT         113 /* synopsis: key=r[P3 at P4]                     */
+#define OP_IdxGE         114 /* synopsis: key=r[P3 at P4]                     */
+#define OP_Destroy       115
+#define OP_Clear         116
+#define OP_ResetSorter   117
+#define OP_CreateIndex   118 /* synopsis: r[P2]=root iDb=P1                */
+#define OP_CreateTable   119 /* synopsis: r[P2]=root iDb=P1                */
+#define OP_ParseSchema   120
+#define OP_LoadAnalysis  121
+#define OP_DropTable     122
+#define OP_DropIndex     123
+#define OP_DropTrigger   124
+#define OP_IntegrityCk   125
+#define OP_RowSetAdd     126 /* synopsis: rowset(P1)=r[P2]                 */
+#define OP_RowSetRead    127 /* synopsis: r[P3]=rowset(P1)                 */
+#define OP_RowSetTest    128 /* synopsis: if r[P3] in rowset(P1) goto P2   */
+#define OP_Program       129
+#define OP_Param         130
+#define OP_FkCounter     131 /* synopsis: fkctr[P1]+=P2                    */
+#define OP_FkIfZero      132 /* synopsis: if fkctr[P1]==0 goto P2          */
+#define OP_Real          133 /* same as TK_FLOAT, synopsis: r[P2]=P4       */
+#define OP_MemMax        134 /* synopsis: r[P1]=max(r[P1],r[P2])           */
+#define OP_IfPos         135 /* synopsis: if r[P1]>0 goto P2               */
+#define OP_IfNeg         136 /* synopsis: r[P1]+=P3, if r[P1]<0 goto P2    */
+#define OP_IfZero        137 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2   */
+#define OP_AggFinal      138 /* synopsis: accum=r[P1] N=P2                 */
+#define OP_IncrVacuum    139
+#define OP_Expire        140
+#define OP_TableLock     141 /* synopsis: iDb=P1 root=P2 write=P3          */
+#define OP_VBegin        142
+#define OP_ToText        143 /* same as TK_TO_TEXT                         */
+#define OP_ToBlob        144 /* same as TK_TO_BLOB                         */
+#define OP_ToNumeric     145 /* same as TK_TO_NUMERIC                      */
+#define OP_ToInt         146 /* same as TK_TO_INT                          */
+#define OP_ToReal        147 /* same as TK_TO_REAL                         */
+#define OP_VCreate       148
+#define OP_VDestroy      149
+#define OP_VOpen         150
+#define OP_VColumn       151 /* synopsis: r[P3]=vcolumn(P2)                */
+#define OP_VNext         152
+#define OP_VRename       153
+#define OP_Pagecount     154
+#define OP_MaxPgcnt      155
+#define OP_Init          156 /* synopsis: Start at P2                      */
+#define OP_Noop          157
+#define OP_Explain       158
 
 
 /* Properties such as "out2" or "jump" that are specified in
@@ -9078,25 +9424,26 @@ typedef struct VdbeOpList VdbeOpList;
 #define OPFLG_OUT2            0x0020  /* out2:  P2 is an output */
 #define OPFLG_OUT3            0x0040  /* out3:  P3 is an output */
 #define OPFLG_INITIALIZER {\
-/*   0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\
-/*   8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x24,\
-/*  16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
-/*  24 */ 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00,\
-/*  32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
-/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\
-/*  48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\
-/*  56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/*  64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\
-/*  72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
-/*  80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
-/*  88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
-/*  96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
-/* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
-/* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\
-/* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\
-/* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,}
+/*   0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,\
+/*   8 */ 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,\
+/*  16 */ 0x01, 0x01, 0x04, 0x24, 0x01, 0x04, 0x05, 0x10,\
+/*  24 */ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\
+/*  32 */ 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x05, 0x04,\
+/*  40 */ 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00,\
+/*  48 */ 0x00, 0x02, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,\
+/*  56 */ 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,\
+/*  64 */ 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x4c,\
+/*  72 */ 0x4c, 0x00, 0x00, 0x00, 0x05, 0x05, 0x15, 0x15,\
+/*  80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\
+/*  88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\
+/*  96 */ 0x24, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,\
+/* 104 */ 0x01, 0x01, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01,\
+/* 112 */ 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02,\
+/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45,\
+/* 128 */ 0x15, 0x01, 0x02, 0x00, 0x01, 0x02, 0x08, 0x05,\
+/* 136 */ 0x05, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04,\
+/* 144 */ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,\
+/* 152 */ 0x01, 0x00, 0x02, 0x02, 0x01, 0x00, 0x00,}
 
 /************** End of opcodes.h *********************************************/
 /************** Continuing where we left off in vdbe.h ***********************/
@@ -9105,14 +9452,14 @@ typedef struct VdbeOpList VdbeOpList;
 ** Prototypes for the VDBE interface.  See comments on the implementation
 ** for a description of what each of these routines does.
 */
-SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3*);
+SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*);
 SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int);
 SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int);
 SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
 SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
 SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
 SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
-SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
+SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
 SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
 SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
 SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
@@ -9120,7 +9467,9 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
 SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
 SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
 SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
+SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
 SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
+SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
 SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
 SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
 SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
@@ -9133,7 +9482,6 @@ SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
 SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*);
 #ifdef SQLITE_DEBUG
 SQLITE_PRIVATE   int sqlite3VdbeAssertMayAbort(Vdbe *, int);
-SQLITE_PRIVATE   void sqlite3VdbeTrace(Vdbe*,FILE*);
 #endif
 SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*);
 SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*);
@@ -9145,29 +9493,82 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
 SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int);
 SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
 SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
-SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8);
+SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
 SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
 #ifndef SQLITE_OMIT_TRACE
 SQLITE_PRIVATE   char *sqlite3VdbeExpandSql(Vdbe*, const char*);
 #endif
+SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
 
 SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
-SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
+SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int);
 SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
 
+typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int);
+SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
+
 #ifndef SQLITE_OMIT_TRIGGER
 SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
 #endif
 
-
-#ifndef NDEBUG
+/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
+** each VDBE opcode.
+**
+** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
+** comments in VDBE programs that show key decision points in the code
+** generator.
+*/
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
 SQLITE_PRIVATE   void sqlite3VdbeComment(Vdbe*, const char*, ...);
 # define VdbeComment(X)  sqlite3VdbeComment X
 SQLITE_PRIVATE   void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
 # define VdbeNoopComment(X)  sqlite3VdbeNoopComment X
+# ifdef SQLITE_ENABLE_MODULE_COMMENTS
+#   define VdbeModuleComment(X)  sqlite3VdbeNoopComment X
+# else
+#   define VdbeModuleComment(X)
+# endif
 #else
 # define VdbeComment(X)
 # define VdbeNoopComment(X)
+# define VdbeModuleComment(X)
+#endif
+
+/*
+** The VdbeCoverage macros are used to set a coverage testing point
+** for VDBE branch instructions.  The coverage testing points are line
+** numbers in the sqlite3.c source file.  VDBE branch coverage testing
+** only works with an amalagmation build.  That's ok since a VDBE branch
+** coverage build designed for testing the test suite only.  No application
+** should ever ship with VDBE branch coverage measuring turned on.
+**
+**    VdbeCoverage(v)                  // Mark the previously coded instruction
+**                                     // as a branch
+**
+**    VdbeCoverageIf(v, conditional)   // Mark previous if conditional true
+**
+**    VdbeCoverageAlwaysTaken(v)       // Previous branch is always taken
+**
+**    VdbeCoverageNeverTaken(v)        // Previous branch is never taken
+**
+** Every VDBE branch operation must be tagged with one of the macros above.
+** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and
+** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch()
+** routine in vdbe.c, alerting the developer to the missed tag.
+*/
+#ifdef SQLITE_VDBE_COVERAGE
+SQLITE_PRIVATE   void sqlite3VdbeSetLineNumber(Vdbe*,int);
+# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__)
+# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
+# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2);
+# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1);
+# define VDBE_OFFSET_LINENO(x) (__LINE__+x)
+#else
+# define VdbeCoverage(v)
+# define VdbeCoverageIf(v,x)
+# define VdbeCoverageAlwaysTaken(v)
+# define VdbeCoverageNeverTaken(v)
+# define VDBE_OFFSET_LINENO(x) 0
 #endif
 
 #endif
@@ -9259,8 +9660,20 @@ typedef struct PgHdr DbPage;
 /*
 ** Flags that make up the mask passed to sqlite3PagerAcquire().
 */
-#define PAGER_ACQUIRE_NOCONTENT     0x01  /* Do not load data from disk */
-#define PAGER_ACQUIRE_READONLY      0x02  /* Read-only page is acceptable */
+#define PAGER_GET_NOCONTENT     0x01  /* Do not load data from disk */
+#define PAGER_GET_READONLY      0x02  /* Read-only page is acceptable */
+
+/*
+** Flags for sqlite3PagerSetFlags()
+*/
+#define PAGER_SYNCHRONOUS_OFF       0x01  /* PRAGMA synchronous=OFF */
+#define PAGER_SYNCHRONOUS_NORMAL    0x02  /* PRAGMA synchronous=NORMAL */
+#define PAGER_SYNCHRONOUS_FULL      0x03  /* PRAGMA synchronous=FULL */
+#define PAGER_SYNCHRONOUS_MASK      0x03  /* Mask for three values above */
+#define PAGER_FULLFSYNC             0x04  /* PRAGMA fullfsync=ON */
+#define PAGER_CKPT_FULLFSYNC        0x08  /* PRAGMA checkpoint_fullfsync=ON */
+#define PAGER_CACHESPILL            0x10  /* PRAGMA cache_spill=ON */
+#define PAGER_FLAGS_MASK            0x1c  /* All above except SYNCHRONOUS */
 
 /*
 ** The remainder of this file contains the declarations of the functions
@@ -9288,7 +9701,7 @@ SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
 SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
 SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
 SQLITE_PRIVATE void sqlite3PagerShrink(Pager*);
-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int);
+SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned);
 SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
 SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int);
 SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*);
@@ -9302,6 +9715,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage
 SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
 SQLITE_PRIVATE void sqlite3PagerRef(DbPage*);
 SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*);
+SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*);
 
 /* Operations on page references. */
 SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*);
@@ -9316,7 +9730,7 @@ SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*);
 SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int);
 SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
 SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*);
-SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster);
 SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*);
 SQLITE_PRIVATE int sqlite3PagerRollback(Pager*);
 SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
@@ -9568,83 +9982,71 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
 #define _SQLITE_OS_H_
 
 /*
-** Figure out if we are dealing with Unix, Windows, or some other
-** operating system.  After the following block of preprocess macros,
-** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER 
-** will defined to either 1 or 0.  One of the four will be 1.  The other 
-** three will be 0.
+** Attempt to automatically detect the operating system and setup the
+** necessary pre-processor macros for it.
 */
-#if defined(SQLITE_OS_OTHER)
-# if SQLITE_OS_OTHER==1
-#   undef SQLITE_OS_UNIX
-#   define SQLITE_OS_UNIX 0
-#   undef SQLITE_OS_WIN
-#   define SQLITE_OS_WIN 0
-# else
-#   undef SQLITE_OS_OTHER
-# endif
-#endif
-#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
-# define SQLITE_OS_OTHER 0
-# ifndef SQLITE_OS_WIN
-#   if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
-#     define SQLITE_OS_WIN 1
-#     define SQLITE_OS_UNIX 0
-#   else
-#     define SQLITE_OS_WIN 0
-#     define SQLITE_OS_UNIX 1
-#  endif
-# else
-#  define SQLITE_OS_UNIX 0
-# endif
-#else
-# ifndef SQLITE_OS_WIN
-#  define SQLITE_OS_WIN 0
-# endif
-#endif
-
-#if SQLITE_OS_WIN
-# include <windows.h>
-#endif
-
+/************** Include os_setup.h in the middle of os.h *********************/
+/************** Begin file os_setup.h ****************************************/
 /*
-** Determine if we are dealing with Windows NT.
-**
-** We ought to be able to determine if we are compiling for win98 or winNT
-** using the _WIN32_WINNT macro as follows:
+** 2013 November 25
 **
-** #if defined(_WIN32_WINNT)
-** # define SQLITE_OS_WINNT 1
-** #else
-** # define SQLITE_OS_WINNT 0
-** #endif
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
 **
-** However, vs2005 does not set _WIN32_WINNT by default, as it ought to,
-** so the above test does not work.  We'll just assume that everything is
-** winNT unless the programmer explicitly says otherwise by setting
-** SQLITE_OS_WINNT to 0.
+**    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 pre-processor directives related to operating system
+** detection and/or setup.
 */
-#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
-# define SQLITE_OS_WINNT 1
-#endif
+#ifndef _OS_SETUP_H_
+#define _OS_SETUP_H_
 
 /*
-** Determine if we are dealing with WindowsCE - which has a much
-** reduced API.
+** Figure out if we are dealing with Unix, Windows, or some other operating
+** system.
+**
+** After the following block of preprocess macros, all of SQLITE_OS_UNIX,
+** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0.  One of
+** the three will be 1.  The other two will be 0.
 */
-#if defined(_WIN32_WCE)
-# define SQLITE_OS_WINCE 1
+#if defined(SQLITE_OS_OTHER)
+#  if SQLITE_OS_OTHER==1
+#    undef SQLITE_OS_UNIX
+#    define SQLITE_OS_UNIX 0
+#    undef SQLITE_OS_WIN
+#    define SQLITE_OS_WIN 0
+#  else
+#    undef SQLITE_OS_OTHER
+#  endif
+#endif
+#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
+#  define SQLITE_OS_OTHER 0
+#  ifndef SQLITE_OS_WIN
+#    if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
+        defined(__MINGW32__) || defined(__BORLANDC__)
+#      define SQLITE_OS_WIN 1
+#      define SQLITE_OS_UNIX 0
+#    else
+#      define SQLITE_OS_WIN 0
+#      define SQLITE_OS_UNIX 1
+#    endif
+#  else
+#    define SQLITE_OS_UNIX 0
+#  endif
 #else
-# define SQLITE_OS_WINCE 0
+#  ifndef SQLITE_OS_WIN
+#    define SQLITE_OS_WIN 0
+#  endif
 #endif
 
-/*
-** Determine if we are dealing with WinRT, which provides only a subset of
-** the full Win32 API.
-*/
-#if !defined(SQLITE_OS_WINRT)
-# define SQLITE_OS_WINRT 0
-#endif
+#endif /* _OS_SETUP_H_ */
+
+/************** End of os_setup.h ********************************************/
+/************** Continuing where we left off in os.h *************************/
 
 /* If the SET_FULLSYNC macro is not defined above, then make it
 ** a no-op
@@ -9917,7 +10319,6 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *);
 struct Db {
   char *zName;         /* Name of this database */
   Btree *pBt;          /* The B*Tree structure for this database file */
-  u8 inTrans;          /* 0: not writable.  1: Transaction.  2: Checkpoint */
   u8 safety_level;     /* How aggressive at syncing data to disk */
   Schema *pSchema;     /* Pointer to database schema (possibly shared) */
 };
@@ -9949,7 +10350,7 @@ struct Schema {
   Table *pSeqTab;      /* The sqlite_sequence table used by AUTOINCREMENT */
   u8 file_format;      /* Schema format version for this file */
   u8 enc;              /* Text encoding used by this database */
-  u16 flags;           /* Flags associated with this schema */
+  u16 schemaFlags;     /* Flags associated with this schema */
   int cache_size;      /* Number of pages to use in the cache */
 };
 
@@ -9957,10 +10358,10 @@ struct Schema {
 ** These macros can be used to test, set, or clear bits in the 
 ** Db.pSchema->flags field.
 */
-#define DbHasProperty(D,I,P)     (((D)->aDb[I].pSchema->flags&(P))==(P))
-#define DbHasAnyProperty(D,I,P)  (((D)->aDb[I].pSchema->flags&(P))!=0)
-#define DbSetProperty(D,I,P)     (D)->aDb[I].pSchema->flags|=(P)
-#define DbClearProperty(D,I,P)   (D)->aDb[I].pSchema->flags&=~(P)
+#define DbHasProperty(D,I,P)     (((D)->aDb[I].pSchema->schemaFlags&(P))==(P))
+#define DbHasAnyProperty(D,I,P)  (((D)->aDb[I].pSchema->schemaFlags&(P))!=0)
+#define DbSetProperty(D,I,P)     (D)->aDb[I].pSchema->schemaFlags|=(P)
+#define DbClearProperty(D,I,P)   (D)->aDb[I].pSchema->schemaFlags&=~(P)
 
 /*
 ** Allowed values for the DB.pSchema->flags field.
@@ -10063,9 +10464,10 @@ struct sqlite3 {
     u8 busy;                    /* TRUE if currently initializing */
     u8 orphanTrigger;           /* Last statement is orphaned TEMP trigger */
   } init;
-  int activeVdbeCnt;            /* Number of VDBEs currently executing */
-  int writeVdbeCnt;             /* Number of active VDBEs that are writing */
-  int vdbeExecCnt;              /* Number of nested calls to VdbeExec() */
+  int nVdbeActive;              /* Number of VDBEs currently running */
+  int nVdbeRead;                /* Number of active VDBEs that read or write */
+  int nVdbeWrite;               /* Number of active VDBEs that read and write */
+  int nVdbeExec;                /* Number of nested calls to VdbeExec() */
   int nExtension;               /* Number of loaded extensions */
   void **aExtension;            /* Array of shared library handles */
   void (*xTrace)(void*,const char*);        /* Trace function */
@@ -10086,8 +10488,6 @@ struct sqlite3 {
   void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
   void *pCollNeededArg;
   sqlite3_value *pErr;          /* Most recent error message */
-  char *zErrMsg;                /* Most recent error message (UTF-8 encoded) */
-  char *zErrMsg16;              /* Most recent error message (UTF-16 encoded) */
   union {
     volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
     double notUsed1;            /* Spacer */
@@ -10101,7 +10501,7 @@ struct sqlite3 {
 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
   int (*xProgress)(void *);     /* The progress callback */
   void *pProgressArg;           /* Argument to the progress callback */
-  int nProgressOps;             /* Number of opcodes for progress callback */
+  unsigned nProgressOps;        /* Number of opcodes for progress callback */
 #endif
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   int nVTrans;                  /* Allocated size of aVTrans */
@@ -10119,6 +10519,7 @@ struct sqlite3 {
   int nSavepoint;               /* Number of non-transaction savepoints */
   int nStatement;               /* Number of nested statement-transactions  */
   i64 nDeferredCons;            /* Net deferred constraints this transaction. */
+  i64 nDeferredImmCons;         /* Net deferred immediate constraints */
   int *pnBytesFreed;            /* If not NULL, increment this in DbFree() */
 
 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
@@ -10150,30 +10551,35 @@ struct sqlite3 {
 */
 #define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
 #define SQLITE_InternChanges  0x00000002  /* Uncommitted Hash table changes */
-#define SQLITE_FullColNames   0x00000004  /* Show full column names on SELECT */
-#define SQLITE_ShortColNames  0x00000008  /* Show short columns names */
-#define SQLITE_CountRows      0x00000010  /* Count rows changed by INSERT, */
+#define SQLITE_FullFSync      0x00000004  /* Use full fsync on the backend */
+#define SQLITE_CkptFullFSync  0x00000008  /* Use full fsync for checkpoint */
+#define SQLITE_CacheSpill     0x00000010  /* OK to spill pager cache */
+#define SQLITE_FullColNames   0x00000020  /* Show full column names on SELECT */
+#define SQLITE_ShortColNames  0x00000040  /* Show short columns names */
+#define SQLITE_CountRows      0x00000080  /* Count rows changed by INSERT, */
                                           /*   DELETE, or UPDATE and return */
                                           /*   the count using a callback. */
-#define SQLITE_NullCallback   0x00000020  /* Invoke the callback once if the */
+#define SQLITE_NullCallback   0x00000100  /* Invoke the callback once if the */
                                           /*   result set is empty */
-#define SQLITE_SqlTrace       0x00000040  /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing    0x00000080  /* Debug listings of VDBE programs */
-#define SQLITE_WriteSchema    0x00000100  /* OK to update SQLITE_MASTER */
-#define SQLITE_VdbeAddopTrace 0x00000200  /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_IgnoreChecks   0x00000400  /* Do not enforce check constraints */
-#define SQLITE_ReadUncommitted 0x0000800  /* For shared-cache mode */
-#define SQLITE_LegacyFileFmt  0x00001000  /* Create new databases in format 1 */
-#define SQLITE_FullFSync      0x00002000  /* Use full fsync on the backend */
-#define SQLITE_CkptFullFSync  0x00004000  /* Use full fsync for checkpoint */
-#define SQLITE_RecoveryMode   0x00008000  /* Ignore schema errors */
-#define SQLITE_ReverseOrder   0x00010000  /* Reverse unordered SELECTs */
-#define SQLITE_RecTriggers    0x00020000  /* Enable recursive triggers */
-#define SQLITE_ForeignKeys    0x00040000  /* Enforce foreign key constraints  */
-#define SQLITE_AutoIndex      0x00080000  /* Enable automatic indexes */
-#define SQLITE_PreferBuiltin  0x00100000  /* Preference to built-in funcs */
-#define SQLITE_LoadExtension  0x00200000  /* Enable load_extension */
-#define SQLITE_EnableTrigger  0x00400000  /* True to enable triggers */
+#define SQLITE_SqlTrace       0x00000200  /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing    0x00000400  /* Debug listings of VDBE programs */
+#define SQLITE_WriteSchema    0x00000800  /* OK to update SQLITE_MASTER */
+#define SQLITE_VdbeAddopTrace 0x00001000  /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_IgnoreChecks   0x00002000  /* Do not enforce check constraints */
+#define SQLITE_ReadUncommitted 0x0004000  /* For shared-cache mode */
+#define SQLITE_LegacyFileFmt  0x00008000  /* Create new databases in format 1 */
+#define SQLITE_RecoveryMode   0x00010000  /* Ignore schema errors */
+#define SQLITE_ReverseOrder   0x00020000  /* Reverse unordered SELECTs */
+#define SQLITE_RecTriggers    0x00040000  /* Enable recursive triggers */
+#define SQLITE_ForeignKeys    0x00080000  /* Enforce foreign key constraints  */
+#define SQLITE_AutoIndex      0x00100000  /* Enable automatic indexes */
+#define SQLITE_PreferBuiltin  0x00200000  /* Preference to built-in funcs */
+#define SQLITE_LoadExtension  0x00400000  /* Enable load_extension */
+#define SQLITE_EnableTrigger  0x00800000  /* True to enable triggers */
+#define SQLITE_DeferFKs       0x01000000  /* Defer all FK constraints */
+#define SQLITE_QueryOnly      0x02000000  /* Disable database changes */
+#define SQLITE_VdbeEQP        0x04000000  /* Debug EXPLAIN QUERY PLAN */
+
 
 /*
 ** Bits of the sqlite3.dbOptFlags field that are used by the
@@ -10184,12 +10590,15 @@ struct sqlite3 {
 #define SQLITE_ColumnCache    0x0002   /* Column cache */
 #define SQLITE_GroupByOrder   0x0004   /* GROUPBY cover of ORDERBY */
 #define SQLITE_FactorOutConst 0x0008   /* Constant factoring */
-#define SQLITE_IdxRealAsInt   0x0010   /* Store REAL as INT in indices */
+/*                not used    0x0010   // Was: SQLITE_IdxRealAsInt */
 #define SQLITE_DistinctOpt    0x0020   /* DISTINCT using indexes */
 #define SQLITE_CoverIdxScan   0x0040   /* Covering index scans */
 #define SQLITE_OrderByIdxJoin 0x0080   /* ORDER BY of joins via index */
 #define SQLITE_SubqCoroutine  0x0100   /* Evaluate subqueries as coroutines */
 #define SQLITE_Transitive     0x0200   /* Transitive constraints */
+#define SQLITE_OmitNoopJoin   0x0400   /* Omit unused tables in joins */
+#define SQLITE_Stat3          0x0800   /* Use the SQLITE_STAT3 table */
+#define SQLITE_AdjustOutEst   0x1000   /* Adjust output estimates using WHERE */
 #define SQLITE_AllOpts        0xffff   /* All optimizations */
 
 /*
@@ -10204,6 +10613,12 @@ struct sqlite3 {
 #endif
 
 /*
+** Return true if it OK to factor constant expressions into the initialization
+** code. The argument is a Parse object for the code generator.
+*/
+#define ConstFactorOk(P) ((P)->okConstFactor)
+
+/*
 ** Possible values for the sqlite.magic field.
 ** The numbers are obtained at random and have no special meaning, other
 ** than being distinct from one another.
@@ -10223,8 +10638,7 @@ struct sqlite3 {
 */
 struct FuncDef {
   i16 nArg;            /* Number of arguments.  -1 means unlimited */
-  u8 iPrefEnc;         /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */
-  u8 flags;            /* Some combination of SQLITE_FUNC_* */
+  u16 funcFlags;       /* Some combination of SQLITE_FUNC_* */
   void *pUserData;     /* User data parameter */
   FuncDef *pNext;      /* Next function with same name */
   void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */
@@ -10260,14 +10674,17 @@ struct FuncDestructor {
 ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG.  There
 ** are assert() statements in the code to verify this.
 */
-#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 /* Ephemeral.  Delete with VDBE */
-#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
-#define SQLITE_FUNC_COUNT    0x10 /* Built-in count(*) aggregate */
-#define SQLITE_FUNC_COALESCE 0x20 /* Built-in coalesce() or ifnull() function */
-#define SQLITE_FUNC_LENGTH   0x40 /* Built-in length() function */
-#define SQLITE_FUNC_TYPEOF   0x80 /* Built-in typeof() function */
+#define SQLITE_FUNC_ENCMASK  0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
+#define SQLITE_FUNC_LIKE     0x004 /* Candidate for the LIKE optimization */
+#define SQLITE_FUNC_CASE     0x008 /* Case-sensitive LIKE-type function */
+#define SQLITE_FUNC_EPHEM    0x010 /* Ephemeral.  Delete with VDBE */
+#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */
+#define SQLITE_FUNC_LENGTH   0x040 /* Built-in length() function */
+#define SQLITE_FUNC_TYPEOF   0x080 /* Built-in typeof() function */
+#define SQLITE_FUNC_COUNT    0x100 /* Built-in count(*) aggregate */
+#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */
+#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */
+#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */
 
 /*
 ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -10280,6 +10697,9 @@ struct FuncDestructor {
 **     as the user-data (sqlite3_user_data()) for the function. If 
 **     argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set.
 **
+**   VFUNCTION(zName, nArg, iArg, bNC, xFunc)
+**     Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
+**
 **   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
@@ -10295,18 +10715,22 @@ struct FuncDestructor {
 **     parameter.
 */
 #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
-  {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL), \
+  {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
+   SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
+#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
+  {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
    SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
 #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
-  {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
+  {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
    SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
 #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
-  {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \
+  {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
    pArg, 0, xFunc, 0, 0, #zName, 0, 0}
 #define LIKEFUNC(zName, nArg, arg, flags) \
-  {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0}
+  {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
+   (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0}
 #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
-  {nArg, SQLITE_UTF8, nc*SQLITE_FUNC_NEEDCOLL, \
+  {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
    SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0}
 
 /*
@@ -10318,6 +10742,7 @@ struct FuncDestructor {
 struct Savepoint {
   char *zName;                        /* Savepoint name (nul-terminated) */
   i64 nDeferredCons;                  /* Number of deferred fk violations */
+  i64 nDeferredImmCons;               /* Number of deferred imm fk. */
   Savepoint *pNext;                   /* Parent savepoint (if any) */
 };
 
@@ -10354,7 +10779,8 @@ struct Column {
   char *zColl;     /* Collating sequence.  If NULL, use the default */
   u8 notNull;      /* An OE_ code for handling a NOT NULL constraint */
   char affinity;   /* One of the SQLITE_AFF_... values */
-  u16 colFlags;    /* Boolean properties.  See COLFLAG_ defines below */
+  u8 szEst;        /* Estimated size of this column.  INT==1 */
+  u8 colFlags;     /* Boolean properties.  See COLFLAG_ defines below */
 };
 
 /* Allowed values for Column.colFlags:
@@ -10416,10 +10842,16 @@ struct CollSeq {
 /*
 ** Additional bit values that can be ORed with an affinity without
 ** changing the affinity.
+**
+** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL.
+** It causes an assert() to fire if either operand to a comparison
+** operator is NULL.  It is added to certain comparison operators to
+** prove that the operands are always NOT NULL.
 */
 #define SQLITE_JUMPIFNULL   0x08  /* jumps if either operand is NULL */
 #define SQLITE_STOREP2      0x10  /* Store result in reg[P2] rather than jump */
 #define SQLITE_NULLEQ       0x80  /* NULL=NULL */
+#define SQLITE_NOTNULL      0x88  /* Assert that operands are never NULL */
 
 /*
 ** An object of this type is created for each virtual table present in
@@ -10513,11 +10945,15 @@ struct Table {
 #ifndef SQLITE_OMIT_CHECK
   ExprList *pCheck;    /* All CHECK constraints */
 #endif
-  tRowcnt nRowEst;     /* Estimated rows in table - from sqlite_stat1 table */
+  LogEst nRowLogEst;   /* Estimated rows in table - from sqlite_stat1 table */
   int tnum;            /* Root BTree node for this table (see note above) */
   i16 iPKey;           /* If not negative, use aCol[iPKey] as the primary key */
   i16 nCol;            /* Number of columns in this table */
   u16 nRef;            /* Number of pointers to this Table */
+  LogEst szTabRow;     /* Estimated size of each table row in bytes */
+#ifdef SQLITE_ENABLE_COSTMULT
+  LogEst costMult;     /* Cost multiplier for using this table */
+#endif
   u8 tabFlags;         /* Mask of TF_* values */
   u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */
 #ifndef SQLITE_OMIT_ALTERTABLE
@@ -10534,13 +10970,14 @@ struct Table {
 };
 
 /*
-** Allowed values for Tabe.tabFlags.
+** Allowed values for Table.tabFlags.
 */
 #define TF_Readonly        0x01    /* Read-only system table */
 #define TF_Ephemeral       0x02    /* An ephemeral 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_WithoutRowid    0x20    /* No rowid used. PRIMARY KEY is the key */
 
 
 /*
@@ -10556,6 +10993,9 @@ struct Table {
 #  define IsHiddenColumn(X) 0
 #endif
 
+/* Does the table have a rowid */
+#define HasRowid(X)     (((X)->tabFlags & TF_WithoutRowid)==0)
+
 /*
 ** Each foreign key constraint is an instance of the following structure.
 **
@@ -10570,26 +11010,35 @@ struct Table {
 **     );
 **
 ** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2".
+** Equivalent names:
+**
+**     from-table == child-table
+**       to-table == parent-table
 **
 ** Each REFERENCES clause generates an instance of the following structure
 ** which is attached to the from-table.  The to-table need not exist when
 ** the from-table is created.  The existence of the to-table is not checked.
+**
+** The list of all parents for child Table X is held at X.pFKey.
+**
+** A list of all children for a table named Z (which might not even exist)
+** is held in Schema.fkeyHash with a hash key of Z.
 */
 struct FKey {
   Table *pFrom;     /* Table containing the REFERENCES clause (aka: Child) */
-  FKey *pNextFrom;  /* Next foreign key in pFrom */
+  FKey *pNextFrom;  /* Next FKey with the same in pFrom. Next parent of pFrom */
   char *zTo;        /* Name of table that the key points to (aka: Parent) */
-  FKey *pNextTo;    /* Next foreign key on table named zTo */
-  FKey *pPrevTo;    /* Previous foreign key on table named zTo */
+  FKey *pNextTo;    /* Next with the same zTo. Next child of zTo. */
+  FKey *pPrevTo;    /* Previous with the same zTo */
   int nCol;         /* Number of columns in this key */
   /* EV: R-30323-21917 */
-  u8 isDeferred;    /* True if constraint checking is deferred till COMMIT */
-  u8 aAction[2];          /* ON DELETE and ON UPDATE actions, respectively */
-  Trigger *apTrigger[2];  /* Triggers for aAction[] actions */
-  struct sColMap {  /* Mapping of columns in pFrom to columns in zTo */
-    int iFrom;         /* Index of column in pFrom */
-    char *zCol;        /* Name of column in zTo.  If 0 use PRIMARY KEY */
-  } aCol[1];        /* One entry for each of nCol column s */
+  u8 isDeferred;       /* True if constraint checking is deferred till COMMIT */
+  u8 aAction[2];        /* ON DELETE and ON UPDATE actions, respectively */
+  Trigger *apTrigger[2];/* Triggers for aAction[] actions */
+  struct sColMap {      /* Mapping of columns in pFrom to columns in zTo */
+    int iFrom;            /* Index of column in pFrom */
+    char *zCol;           /* Name of column in zTo.  If NULL use PRIMARY KEY */
+  } aCol[1];            /* One entry for each of nCol columns */
 };
 
 /*
@@ -10629,19 +11078,25 @@ struct FKey {
 #define OE_SetDflt  8   /* Set the foreign key value to its default */
 #define OE_Cascade  9   /* Cascade the changes */
 
-#define OE_Default  99  /* Do whatever the default action is */
+#define OE_Default  10  /* Do whatever the default action is */
 
 
 /*
 ** 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.
+**
+** Note that aSortOrder[] and aColl[] have nField+1 slots.  There
+** are nField slots for the columns of an index then one extra slot
+** for the rowid at the end.
 */
 struct KeyInfo {
-  sqlite3 *db;        /* The database connection */
+  u32 nRef;           /* Number of references to this KeyInfo object */
   u8 enc;             /* Text encoding - one of the SQLITE_UTF* values */
-  u16 nField;         /* Number of entries in aColl[] */
-  u8 *aSortOrder;     /* Sort order for each column.  May be NULL */
+  u16 nField;         /* Number of key columns in the index */
+  u16 nXField;        /* Number of columns beyond the key columns */
+  sqlite3 *db;        /* The database connection */
+  u8 *aSortOrder;     /* Sort order for each column. */
   CollSeq *aColl[1];  /* Collating sequence for each term of the key */
 };
 
@@ -10658,21 +11113,20 @@ struct KeyInfo {
 **
 ** This structure holds a record that has already been disassembled
 ** into its constituent fields.
+**
+** The r1 and r2 member variables are only used by the optimized comparison
+** functions vdbeRecordCompareInt() and vdbeRecordCompareString().
 */
 struct UnpackedRecord {
   KeyInfo *pKeyInfo;  /* Collation and sort-order information */
   u16 nField;         /* Number of entries in apMem[] */
-  u8 flags;           /* Boolean settings.  UNPACKED_... below */
-  i64 rowid;          /* Used by UNPACKED_PREFIX_SEARCH */
+  i8 default_rc;      /* Comparison result if keys are equal */
+  u8 isCorrupt;       /* Corruption detected by xRecordCompare() */
   Mem *aMem;          /* Values */
+  int r1;             /* Value to return if (lhs > rhs) */
+  int r2;             /* Value to return if (rhs < lhs) */
 };
 
-/*
-** Allowed values of UnpackedRecord.flags
-*/
-#define UNPACKED_INCRKEY       0x01  /* Make this key an epsilon larger */
-#define UNPACKED_PREFIX_MATCH  0x02  /* A prefix match is considered OK */
-#define UNPACKED_PREFIX_SEARCH 0x04  /* Ignore final (rowid) field */
 
 /*
 ** Each SQL index is represented in memory by an
@@ -10702,42 +11156,58 @@ struct UnpackedRecord {
 */
 struct Index {
   char *zName;             /* Name of this index */
-  int *aiColumn;           /* Which columns are used by this index.  1st is 0 */
-  tRowcnt *aiRowEst;       /* From ANALYZE: Est. rows selected by each column */
+  i16 *aiColumn;           /* Which columns are used by this index.  1st is 0 */
+  LogEst *aiRowLogEst;     /* From ANALYZE: Est. rows selected by each column */
   Table *pTable;           /* The SQL table being indexed */
   char *zColAff;           /* String defining the affinity of each column */
   Index *pNext;            /* The next index associated with the same table */
   Schema *pSchema;         /* Schema containing this index */
   u8 *aSortOrder;          /* for each column: True==DESC, False==ASC */
   char **azColl;           /* Array of collation sequence names for index */
+  Expr *pPartIdxWhere;     /* WHERE clause for partial indices */
+  KeyInfo *pKeyInfo;       /* A KeyInfo object suitable for this index */
   int tnum;                /* DB Page containing root of this index */
-  u16 nColumn;             /* Number of columns in table used by this index */
+  LogEst szIdxRow;         /* Estimated average row size in bytes */
+  u16 nKeyCol;             /* Number of columns forming the key */
+  u16 nColumn;             /* Number of columns stored in the index */
   u8 onError;              /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
-  unsigned autoIndex:2;    /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
+  unsigned idxType:2;      /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
   unsigned bUnordered:1;   /* Use this index for == or IN queries only */
-#ifdef SQLITE_ENABLE_STAT3
+  unsigned uniqNotNull:1;  /* True if UNIQUE and NOT NULL for all columns */
+  unsigned isResized:1;    /* True if resizeIndexObject() has been called */
+  unsigned isCovering:1;   /* True if this is a covering index */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
   int nSample;             /* Number of elements in aSample[] */
-  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
+  int nSampleCol;          /* Size of IndexSample.anEq[] and so on */
+  tRowcnt *aAvgEq;         /* Average nEq values for keys not in aSample */
   IndexSample *aSample;    /* Samples of the left-most key */
 #endif
 };
 
 /*
+** Allowed values for Index.idxType
+*/
+#define SQLITE_IDXTYPE_APPDEF      0   /* Created using CREATE INDEX */
+#define SQLITE_IDXTYPE_UNIQUE      1   /* Implements a UNIQUE constraint */
+#define SQLITE_IDXTYPE_PRIMARYKEY  2   /* Is the PRIMARY KEY for the table */
+
+/* Return true if index X is a PRIMARY KEY index */
+#define IsPrimaryKeyIndex(X)  ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
+
+/* Return true if index X is a UNIQUE index */
+#define IsUniqueIndex(X)      ((X)->onError!=OE_None)
+
+/*
 ** Each sample stored in the sqlite_stat3 table is represented in memory 
 ** using a structure of this type.  See documentation at the top of the
 ** analyze.c source file for additional information.
 */
 struct IndexSample {
-  union {
-    char *z;        /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */
-    double r;       /* Value if eType is SQLITE_FLOAT */
-    i64 i;          /* Value if eType is SQLITE_INTEGER */
-  } u;
-  u8 eType;         /* SQLITE_NULL, SQLITE_INTEGER ... etc. */
-  int nByte;        /* Size in byte of text or blob. */
-  tRowcnt nEq;      /* Est. number of rows where the key equals this sample */
-  tRowcnt nLt;      /* Est. number of rows where key is less than this sample */
-  tRowcnt nDLt;     /* Est. number of distinct keys less than this sample */
+  void *p;          /* Pointer to sampled record */
+  int n;            /* Size of record in bytes */
+  tRowcnt *anEq;    /* Est. number of rows where the key equals this sample */
+  tRowcnt *anLt;    /* Est. number of rows where key is less than this sample */
+  tRowcnt *anDLt;   /* Est. number of distinct keys less than this sample */
 };
 
 /*
@@ -10774,6 +11244,7 @@ struct AggInfo {
   int sortingIdx;         /* Cursor number of the sorting index */
   int sortingIdxPTab;     /* Cursor number of pseudo-table */
   int nSortingColumn;     /* Number of columns in the sorting index */
+  int mnReg, mxReg;       /* Range of registers allocated for aCol and aFunc */
   ExprList *pGroupBy;     /* The group by clause */
   struct AggInfo_col {    /* For each column used in source tables */
     Table *pTab;             /* Source table */
@@ -10878,7 +11349,7 @@ typedef int ynVar;
 struct Expr {
   u8 op;                 /* Operation performed by this node */
   char affinity;         /* The affinity of the column or 0 if not a column */
-  u16 flags;             /* Various flags.  EP_* See below */
+  u32 flags;             /* Various flags.  EP_* See below */
   union {
     char *zToken;          /* Token value. Zero terminated and dequoted */
     int iValue;            /* Non-negative integer value if EP_IntValue */
@@ -10892,8 +11363,8 @@ struct Expr {
   Expr *pLeft;           /* Left subnode */
   Expr *pRight;          /* Right subnode */
   union {
-    ExprList *pList;     /* Function arguments or in "<expr> IN (<expr-list)" */
-    Select *pSelect;     /* Used for sub-selects and "<expr> IN (<select>)" */
+    ExprList *pList;     /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
+    Select *pSelect;     /* EP_xIsSelect and op = IN, EXISTS, SELECT */
   } x;
 
   /* If the EP_Reduced flag is set in the Expr.flags mask, then no
@@ -10906,12 +11377,12 @@ struct Expr {
 #endif
   int iTable;            /* TK_COLUMN: cursor number of table holding column
                          ** TK_REGISTER: register number
-                         ** TK_TRIGGER: 1 -> new, 0 -> old */
+                         ** TK_TRIGGER: 1 -> new, 0 -> old
+                         ** EP_Unlikely:  1000 times likelihood */
   ynVar iColumn;         /* TK_COLUMN: column index.  -1 for rowid.
                          ** TK_VARIABLE: variable number (always >= 1). */
   i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
   i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
-  u8 flags2;             /* Second set of flags.  EP2_... */
   u8 op2;                /* TK_REGISTER: original value of Expr.op
                          ** TK_COLUMN: the value of p5 for OP_Column
                          ** TK_AGG_FUNCTION: nesting depth */
@@ -10922,51 +11393,47 @@ struct Expr {
 /*
 ** The following are the meanings of bits in the Expr.flags field.
 */
-#define EP_FromJoin   0x0001  /* Originated in ON or USING clause of a join */
-#define EP_Agg        0x0002  /* Contains one or more aggregate functions */
-#define EP_Resolved   0x0004  /* IDs have been resolved to COLUMNs */
-#define EP_Error      0x0008  /* Expression contains one or more errors */
-#define EP_Distinct   0x0010  /* Aggregate function with DISTINCT keyword */
-#define EP_VarSelect  0x0020  /* pSelect is correlated, not constant */
-#define EP_DblQuoted  0x0040  /* token.z was originally in "..." */
-#define EP_InfixFunc  0x0080  /* True for an infix function: LIKE, GLOB, etc */
-#define EP_Collate    0x0100  /* Tree contains a TK_COLLATE opeartor */
-#define EP_FixedDest  0x0200  /* Result needed in a specific register */
-#define EP_IntValue   0x0400  /* Integer value contained in u.iValue */
-#define EP_xIsSelect  0x0800  /* x.pSelect is valid (otherwise x.pList is) */
-#define EP_Hint       0x1000  /* Not used */
-#define EP_Reduced    0x2000  /* Expr struct is EXPR_REDUCEDSIZE bytes only */
-#define EP_TokenOnly  0x4000  /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
-#define EP_Static     0x8000  /* Held in memory not obtained from malloc() */
+#define EP_FromJoin  0x000001 /* Originated in ON or USING clause of a join */
+#define EP_Agg       0x000002 /* Contains one or more aggregate functions */
+#define EP_Resolved  0x000004 /* IDs have been resolved to COLUMNs */
+#define EP_Error     0x000008 /* Expression contains one or more errors */
+#define EP_Distinct  0x000010 /* Aggregate function with DISTINCT keyword */
+#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
+#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
+#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
+#define EP_Collate   0x000100 /* Tree contains a TK_COLLATE operator */
+#define EP_Generic   0x000200 /* Ignore COLLATE or affinity on this tree */
+#define EP_IntValue  0x000400 /* Integer value contained in u.iValue */
+#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
+#define EP_Skip      0x001000 /* COLLATE, AS, or UNLIKELY */
+#define EP_Reduced   0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
+#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
+#define EP_Static    0x008000 /* Held in memory not obtained from malloc() */
+#define EP_MemToken  0x010000 /* Need to sqlite3DbFree() Expr.zToken */
+#define EP_NoReduce  0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
+#define EP_Unlikely  0x040000 /* unlikely() or likelihood() function */
+#define EP_Constant  0x080000 /* Node is a constant */
 
 /*
-** The following are the meanings of bits in the Expr.flags2 field.
+** These macros can be used to test, set, or clear bits in the 
+** Expr.flags field.
 */
-#define EP2_MallocedToken  0x0001  /* Need to sqlite3DbFree() Expr.zToken */
-#define EP2_Irreducible    0x0002  /* Cannot EXPRDUP_REDUCE this Expr */
+#define ExprHasProperty(E,P)     (((E)->flags&(P))!=0)
+#define ExprHasAllProperty(E,P)  (((E)->flags&(P))==(P))
+#define ExprSetProperty(E,P)     (E)->flags|=(P)
+#define ExprClearProperty(E,P)   (E)->flags&=~(P)
 
-/*
-** The pseudo-routine sqlite3ExprSetIrreducible sets the EP2_Irreducible
-** flag on an expression structure.  This flag is used for VV&A only.  The
-** routine is implemented as a macro that only works when in debugging mode,
-** so as not to burden production code.
+/* The ExprSetVVAProperty() macro is used for Verification, Validation,
+** and Accreditation only.  It works like ExprSetProperty() during VVA
+** processes but is a no-op for delivery.
 */
 #ifdef SQLITE_DEBUG
-# define ExprSetIrreducible(X)  (X)->flags2 |= EP2_Irreducible
+# define ExprSetVVAProperty(E,P)  (E)->flags|=(P)
 #else
-# define ExprSetIrreducible(X)
+# define ExprSetVVAProperty(E,P)
 #endif
 
 /*
-** These macros can be used to test, set, or clear bits in the 
-** Expr.flags field.
-*/
-#define ExprHasProperty(E,P)     (((E)->flags&(P))==(P))
-#define ExprHasAnyProperty(E,P)  (((E)->flags&(P))!=0)
-#define ExprSetProperty(E,P)     (E)->flags|=(P)
-#define ExprClearProperty(E,P)   (E)->flags&=~(P)
-
-/*
 ** Macros to determine the number of bytes required by a normal Expr 
 ** struct, an Expr struct with the EP_Reduced flag set in Expr.flags 
 ** and an Expr struct with the EP_TokenOnly flag set.
@@ -10999,7 +11466,6 @@ struct Expr {
 */
 struct ExprList {
   int nExpr;             /* Number of expressions on the list */
-  int iECursor;          /* VDBE Cursor associated with this ExprList */
   struct ExprList_item { /* For each expression in the list */
     Expr *pExpr;            /* The list of expressions */
     char *zName;            /* Token associated with this expression */
@@ -11007,8 +11473,14 @@ struct ExprList {
     u8 sortOrder;           /* 1 for DESC or 0 for ASC */
     unsigned done :1;       /* A flag to indicate when processing is finished */
     unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
-    u16 iOrderByCol;        /* For ORDER BY, column number in result set */
-    u16 iAlias;             /* Index into Parse.aAlias[] for zName */
+    unsigned reusable :1;   /* Constant expression is reusable */
+    union {
+      struct {
+        u16 iOrderByCol;      /* For ORDER BY, column number in result set */
+        u16 iAlias;           /* Index into Parse.aAlias[] for zName */
+      } x;
+      int iConstExprReg;      /* Register in which Expr value is cached */
+    } u;
   } *a;                  /* Alloc a power of two greater or equal to nExpr */
 };
 
@@ -11061,6 +11533,12 @@ typedef u64 Bitmask;
 #define BMS  ((int)(sizeof(Bitmask)*8))
 
 /*
+** A bit in a Bitmask
+*/
+#define MASKBIT(n)   (((Bitmask)1)<<(n))
+#define MASKBIT32(n) (((unsigned int)1)<<(n))
+
+/*
 ** The following structure describes the FROM clause of a SELECT statement.
 ** Each table or subquery in the FROM clause is a separate element of
 ** the SrcList.a[] array.
@@ -11080,8 +11558,8 @@ typedef u64 Bitmask;
 ** contains more than 63 columns and the 64-th or later column is used.
 */
 struct SrcList {
-  i16 nSrc;        /* Number of tables or subqueries in the FROM clause */
-  i16 nAlloc;      /* Number of entries allocated in a[] below */
+  int nSrc;        /* Number of tables or subqueries in the FROM clause */
+  u32 nAlloc;      /* Number of entries allocated in a[] below */
   struct SrcList_item {
     Schema *pSchema;  /* Schema to which this item is fixed */
     char *zDatabase;  /* Name of database holding this table */
@@ -11091,10 +11569,12 @@ struct SrcList {
     Select *pSelect;  /* A SELECT statement used in place of a table name */
     int addrFillSub;  /* Address of subroutine to manifest a subquery */
     int regReturn;    /* Register holding return address of addrFillSub */
+    int regResult;    /* Registers holding results of a co-routine */
     u8 jointype;      /* Type of join between this able and the previous */
     unsigned notIndexed :1;    /* True if there is a NOT INDEXED clause */
     unsigned isCorrelated :1;  /* True if sub-query is correlated */
     unsigned viaCoroutine :1;  /* Implemented as a co-routine */
+    unsigned isRecursive :1;   /* True for recursive reference in WITH */
 #ifndef SQLITE_OMIT_EXPLAIN
     u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
 #endif
@@ -11120,79 +11600,6 @@ struct SrcList {
 
 
 /*
-** A WherePlan object holds information that describes a lookup
-** strategy.
-**
-** This object is intended to be opaque outside of the where.c module.
-** It is included here only so that that compiler will know how big it
-** is.  None of the fields in this object should be used outside of
-** the where.c module.
-**
-** Within the union, pIdx is only used when wsFlags&WHERE_INDEXED is true.
-** pTerm is only used when wsFlags&WHERE_MULTI_OR is true.  And pVtabIdx
-** is only used when wsFlags&WHERE_VIRTUALTABLE is true.  It is never the
-** case that more than one of these conditions is true.
-*/
-struct WherePlan {
-  u32 wsFlags;                   /* WHERE_* flags that describe the strategy */
-  u16 nEq;                       /* Number of == constraints */
-  u16 nOBSat;                    /* Number of ORDER BY terms satisfied */
-  double nRow;                   /* Estimated number of rows (for EQP) */
-  union {
-    Index *pIdx;                   /* Index when WHERE_INDEXED is true */
-    struct WhereTerm *pTerm;       /* WHERE clause term for OR-search */
-    sqlite3_index_info *pVtabIdx;  /* Virtual table index to use */
-  } u;
-};
-
-/*
-** For each nested loop in a WHERE clause implementation, the WhereInfo
-** structure contains a single instance of this structure.  This structure
-** is intended to be private to the where.c module and should not be
-** access or modified by other modules.
-**
-** The pIdxInfo field is used to help pick the best index on a
-** virtual table.  The pIdxInfo pointer contains indexing
-** information for the i-th table in the FROM clause before reordering.
-** All the pIdxInfo pointers are freed by whereInfoFree() in where.c.
-** All other information in the i-th WhereLevel object for the i-th table
-** after FROM clause ordering.
-*/
-struct WhereLevel {
-  WherePlan plan;       /* query plan for this element of the FROM clause */
-  int iLeftJoin;        /* Memory cell used to implement LEFT OUTER JOIN */
-  int iTabCur;          /* The VDBE cursor used to access the table */
-  int iIdxCur;          /* The VDBE cursor used to access pIdx */
-  int addrBrk;          /* Jump here to break out of the loop */
-  int addrNxt;          /* Jump here to start the next IN combination */
-  int addrCont;         /* Jump here to continue with the next loop cycle */
-  int addrFirst;        /* First instruction of interior of the loop */
-  u8 iFrom;             /* Which entry in the FROM clause */
-  u8 op, p5;            /* Opcode and P5 of the opcode that ends the loop */
-  int p1, p2;           /* Operands of the opcode used to ends the loop */
-  union {               /* Information that depends on plan.wsFlags */
-    struct {
-      int nIn;              /* Number of entries in aInLoop[] */
-      struct InLoop {
-        int iCur;              /* The VDBE cursor used by this IN operator */
-        int addrInTop;         /* Top of the IN loop */
-        u8 eEndLoopOp;         /* IN Loop terminator. OP_Next or OP_Prev */
-      } *aInLoop;           /* Information about each nested IN operator */
-    } in;                 /* Used when plan.wsFlags&WHERE_IN_ABLE */
-    Index *pCovidx;       /* Possible covering index for WHERE_MULTI_OR */
-  } u;
-  double rOptCost;      /* "Optimal" cost for this level */
-
-  /* The following field is really not part of the current level.  But
-  ** we need a place to cache virtual table index information for each
-  ** virtual table in the FROM clause and the WhereLevel structure is
-  ** a convenient place since there is one WhereLevel for each FROM clause
-  ** element.
-  */
-  sqlite3_index_info *pIdxInfo;  /* Index info for n-th source table */
-};
-
-/*
 ** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
 ** and the WhereInfo.wctrlFlags member.
 */
@@ -11205,33 +11612,14 @@ struct WhereLevel {
 #define WHERE_FORCE_TABLE      0x0020 /* Do not use an index-only search */
 #define WHERE_ONETABLE_ONLY    0x0040 /* Only code the 1st table in pTabList */
 #define WHERE_AND_ONLY         0x0080 /* Don't use indices for OR terms */
+#define WHERE_GROUPBY          0x0100 /* pOrderBy is really a GROUP BY */
+#define WHERE_DISTINCTBY       0x0200 /* pOrderby is really a DISTINCT clause */
+#define WHERE_WANT_DISTINCT    0x0400 /* All output needs to be distinct */
+#define WHERE_SORTBYGROUP      0x0800 /* Support sqlite3WhereIsSorted() */
+#define WHERE_REOPEN_IDX       0x1000 /* Try to use OP_ReopenIdx */
 
-/*
-** The WHERE clause processing routine has two halves.  The
-** first part does the start of the WHERE loop and the second
-** half does the tail of the WHERE loop.  An instance of
-** this structure is returned by the first half and passed
-** into the second half to give some continuity.
+/* Allowed return values from sqlite3WhereIsDistinct()
 */
-struct WhereInfo {
-  Parse *pParse;            /* Parsing and code generating context */
-  SrcList *pTabList;        /* List of tables in the join */
-  u16 nOBSat;               /* Number of ORDER BY terms satisfied by indices */
-  u16 wctrlFlags;           /* Flags originally passed to sqlite3WhereBegin() */
-  u8 okOnePass;             /* Ok to use one-pass algorithm for UPDATE/DELETE */
-  u8 untestedTerms;         /* Not all WHERE terms resolved by outer loop */
-  u8 eDistinct;             /* One of the WHERE_DISTINCT_* values below */
-  int iTop;                 /* The very beginning of the WHERE loop */
-  int iContinue;            /* Jump here to continue with next record */
-  int iBreak;               /* Jump here to break out of the loop */
-  int nLevel;               /* Number of nested loop */
-  struct WhereClause *pWC;  /* Decomposition of the WHERE clause */
-  double savedNQueryLoop;   /* pParse->nQueryLoop outside the WHERE loop */
-  double nRowOut;           /* Estimated number of output rows */
-  WhereLevel a[1];          /* Information about each nest loop in WHERE */
-};
-
-/* Allowed values for WhereInfo.eDistinct and DistinctCtx.eTnctType */
 #define WHERE_DISTINCT_NOOP      0  /* DISTINCT keyword not used */
 #define WHERE_DISTINCT_UNIQUE    1  /* No duplicates */
 #define WHERE_DISTINCT_ORDERED   2  /* All duplicates are adjacent */
@@ -11261,7 +11649,7 @@ struct WhereInfo {
 struct NameContext {
   Parse *pParse;       /* The parser */
   SrcList *pSrcList;   /* One or more tables used to resolve names */
-  ExprList *pEList;    /* Optional list of named expressions */
+  ExprList *pEList;    /* Optional list of result-set columns */
   AggInfo *pAggInfo;   /* Information about aggregates at this level */
   NameContext *pNext;  /* Next outer name context.  NULL for outermost */
   int nRef;            /* Number of names resolved by this context */
@@ -11276,8 +11664,7 @@ struct NameContext {
 #define NC_HasAgg    0x02    /* One or more aggregate functions seen */
 #define NC_IsCheck   0x04    /* True if resolving names in a CHECK constraint */
 #define NC_InAggFunc 0x08    /* True if analyzing arguments to an agg func */
-#define NC_AsMaybe   0x10    /* Resolve to AS terms of the result set only
-                             ** if no other resolution is available */
+#define NC_PartIdx   0x10    /* True if resolving a partial index WHERE */
 
 /*
 ** An instance of the following structure contains all information
@@ -11304,8 +11691,8 @@ struct Select {
   u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
   u16 selFlags;          /* Various SF_* values */
   int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
-  int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this select */
-  double nSelectRow;     /* Estimated number of result rows */
+  int addrOpenEphm[2];   /* OP_OpenEphem opcodes related to this select */
+  u64 nSelectRow;        /* Estimated number of result rows */
   SrcList *pSrc;         /* The FROM clause */
   Expr *pWhere;          /* The WHERE clause */
   ExprList *pGroupBy;    /* The GROUP BY clause */
@@ -11313,9 +11700,9 @@ struct Select {
   ExprList *pOrderBy;    /* The ORDER BY clause */
   Select *pPrior;        /* Prior select in a compound select statement */
   Select *pNext;         /* Next select to the left in a compound */
-  Select *pRightmost;    /* Right-most select in a compound select statement */
   Expr *pLimit;          /* LIMIT expression. NULL means not used. */
   Expr *pOffset;         /* OFFSET expression. NULL means not used. */
+  With *pWith;           /* WITH clause attached to this select. Or NULL. */
 };
 
 /*
@@ -11328,41 +11715,109 @@ struct Select {
 #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 */
-#define SF_UseSorter       0x0040  /* Sort using a sorter */
+                    /*     0x0040  NOT USED */
 #define SF_Values          0x0080  /* Synthesized from VALUES clause */
-#define SF_Materialize     0x0100  /* Force materialization of views */
+                    /*     0x0100  NOT USED */
 #define SF_NestedFrom      0x0200  /* Part of a parenthesized FROM clause */
+#define SF_MaybeConvert    0x0400  /* Need convertCompoundSelectToSubquery() */
+#define SF_Recursive       0x0800  /* The recursive part of a recursive CTE */
+#define SF_Compound        0x1000  /* Part of a compound query */
 
 
 /*
-** The results of a select can be distributed in several ways.  The
-** "SRT" prefix means "SELECT Result Type".
+** The results of a SELECT can be distributed in several ways, as defined
+** by one of the following macros.  The "SRT" prefix means "SELECT Result
+** Type".
+**
+**     SRT_Union       Store results as a key in a temporary index 
+**                     identified by pDest->iSDParm.
+**
+**     SRT_Except      Remove results from the temporary index pDest->iSDParm.
+**
+**     SRT_Exists      Store a 1 in memory cell pDest->iSDParm if the result
+**                     set is not empty.
+**
+**     SRT_Discard     Throw the results away.  This is used by SELECT
+**                     statements within triggers whose only purpose is
+**                     the side-effects of functions.
+**
+** All of the above are free to ignore their ORDER BY clause. Those that
+** follow must honor the ORDER BY clause.
+**
+**     SRT_Output      Generate a row of output (using the OP_ResultRow
+**                     opcode) for each row in the result set.
+**
+**     SRT_Mem         Only valid if the result is a single column.
+**                     Store the first column of the first result row
+**                     in register pDest->iSDParm 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->iSDParm. 
+**                     Apply the affinity pDest->affSdst before storing
+**                     results.  Used to implement "IN (SELECT ...)".
+**
+**     SRT_EphemTab    Create an temporary table pDest->iSDParm and store
+**                     the result there. The cursor is left open after
+**                     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->iSDParm
+**                     and the result row is stored in pDest->nDest registers
+**                     starting with pDest->iSdst.
+**
+**     SRT_Table       Store results in temporary table pDest->iSDParm.
+**     SRT_Fifo        This is like SRT_EphemTab except that the table
+**                     is assumed to already be open.  SRT_Fifo has
+**                     the additional property of being able to ignore
+**                     the ORDER BY clause.
+**
+**     SRT_DistFifo    Store results in a temporary table pDest->iSDParm.
+**                     But also use temporary table pDest->iSDParm+1 as
+**                     a record of all prior results and ignore any duplicate
+**                     rows.  Name means:  "Distinct Fifo".
+**
+**     SRT_Queue       Store results in priority queue pDest->iSDParm (really
+**                     an index).  Append a sequence number so that all entries
+**                     are distinct.
+**
+**     SRT_DistQueue   Store results in priority queue pDest->iSDParm only if
+**                     the same record has never been stored before.  The
+**                     index at pDest->iSDParm+1 hold all prior stores.
 */
 #define SRT_Union        1  /* Store result as keys in an index */
 #define SRT_Except       2  /* Remove result from a UNION index */
 #define SRT_Exists       3  /* Store 1 if the result is not empty */
 #define SRT_Discard      4  /* Do not save the results anywhere */
+#define SRT_Fifo         5  /* Store result as data with an automatic rowid */
+#define SRT_DistFifo     6  /* Like SRT_Fifo, but unique results only */
+#define SRT_Queue        7  /* Store result in an queue */
+#define SRT_DistQueue    8  /* Like SRT_Queue, but unique results only */
 
 /* The ORDER BY clause is ignored for all of the above */
-#define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard)
+#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue)
 
-#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 */
-#define SRT_EphemTab     9  /* Create transient tab and store like SRT_Table */
-#define SRT_Coroutine   10  /* Generate a single row of result */
+#define SRT_Output       9  /* Output each row of result */
+#define SRT_Mem         10  /* Store result in a memory cell */
+#define SRT_Set         11  /* Store results as keys in an index */
+#define SRT_EphemTab    12  /* Create transient tab and store like SRT_Table */
+#define SRT_Coroutine   13  /* Generate a single row of result */
+#define SRT_Table       14  /* Store result as data with an automatic rowid */
 
 /*
 ** An instance of this object describes where to put of the results of
 ** a SELECT statement.
 */
 struct SelectDest {
-  u8 eDest;         /* How to dispose of the results.  On of SRT_* above. */
-  char affSdst;     /* Affinity used when eDest==SRT_Set */
-  int iSDParm;      /* A parameter used by the eDest disposal method */
-  int iSdst;        /* Base register where results are written */
-  int nSdst;        /* Number of registers allocated */
+  u8 eDest;            /* How to dispose of the results.  On of SRT_* above. */
+  char affSdst;        /* Affinity used when eDest==SRT_Set */
+  int iSDParm;         /* A parameter used by the eDest disposal method */
+  int iSdst;           /* Base register where results are written */
+  int nSdst;           /* Number of registers allocated */
+  ExprList *pOrderBy;  /* Key columns for SRT_Queue and SRT_DistQueue */
 };
 
 /*
@@ -11418,9 +11873,19 @@ struct TriggerPrg {
 ** The yDbMask datatype for the bitmask of all attached databases.
 */
 #if SQLITE_MAX_ATTACHED>30
-  typedef sqlite3_uint64 yDbMask;
+  typedef unsigned char yDbMask[(SQLITE_MAX_ATTACHED+9)/8];
+# define DbMaskTest(M,I)    (((M)[(I)/8]&(1<<((I)&7)))!=0)
+# define DbMaskZero(M)      memset((M),0,sizeof(M))
+# define DbMaskSet(M,I)     (M)[(I)/8]|=(1<<((I)&7))
+# define DbMaskAllZero(M)   sqlite3DbMaskAllZero(M)
+# define DbMaskNonZero(M)   (sqlite3DbMaskAllZero(M)==0)
 #else
   typedef unsigned int yDbMask;
+# define DbMaskTest(M,I)    (((M)&(((yDbMask)1)<<(I)))!=0)
+# define DbMaskZero(M)      (M)=0
+# define DbMaskSet(M,I)     (M)|=(((yDbMask)1)<<(I))
+# define DbMaskAllZero(M)   (M)==0
+# define DbMaskNonZero(M)   (M)!=0
 #endif
 
 /*
@@ -11448,11 +11913,10 @@ struct Parse {
   u8 checkSchema;      /* Causes schema cookie check after an error */
   u8 nested;           /* Number of nested calls to the parser/code generator */
   u8 nTempReg;         /* Number of temporary registers in aTempReg[] */
-  u8 nTempInUse;       /* Number of aTempReg[] currently checked out */
-  u8 nColCache;        /* Number of entries in aColCache[] */
-  u8 iColCache;        /* Next entry in aColCache[] to replace */
   u8 isMultiWrite;     /* True if statement may modify/insert multiple rows */
   u8 mayAbort;         /* True if statement may throw an ABORT exception */
+  u8 hasCompound;      /* Need to invoke convertCompoundSelectToSubquery() */
+  u8 okConstFactor;    /* OK to factor out constants */
   int aTempReg[8];     /* Holding area for temporary registers */
   int nRangeReg;       /* Size of the temporary register block */
   int iRangeReg;       /* First register in temporary register block */
@@ -11461,25 +11925,30 @@ struct Parse {
   int nMem;            /* Number of memory cells used so far */
   int nSet;            /* Number of sets used so far */
   int nOnce;           /* Number of OP_Once instructions so far */
+  int nOpAlloc;        /* Number of slots allocated for Vdbe.aOp[] */
+  int iFixedOp;        /* Never back out opcodes iFixedOp-1 or earlier */
   int ckBase;          /* Base register of data during check constraints */
+  int iPartIdxTab;     /* Table corresponding to a partial index */
   int iCacheLevel;     /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
   int iCacheCnt;       /* Counter used to generate aColCache[].lru values */
+  int nLabel;          /* Number of labels used */
+  int *aLabel;         /* Space to hold the labels */
   struct yColCache {
     int iTable;           /* Table cursor number */
-    int iColumn;          /* Table column number */
+    i16 iColumn;          /* Table column number */
     u8 tempReg;           /* iReg is a temp register that needs to be freed */
     int iLevel;           /* Nesting level */
     int iReg;             /* Reg with value of this column. 0 means none. */
     int lru;              /* Least recently used entry has the smallest value */
   } aColCache[SQLITE_N_COLCACHE];  /* One for each column cache entry */
+  ExprList *pConstExpr;/* Constant expressions */
+  Token constraintName;/* Name of the constraint currently being parsed */
   yDbMask writeMask;   /* Start a write transaction on these databases */
   yDbMask cookieMask;  /* Bitmask of schema verified databases */
-  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
   int cookieValue[SQLITE_MAX_ATTACHED+2];  /* Values of cookies to verify */
   int regRowid;        /* Register holding rowid of CREATE TABLE entry */
   int regRoot;         /* Register holding root page number for new objects */
   int nMaxArg;         /* Max args passed to user function by sub-program */
-  Token constraintName;/* Name of the constraint currently being parsed */
 #ifndef SQLITE_OMIT_SHARED_CACHE
   int nTableLock;        /* Number of locks in aTableLock */
   TableLock *aTableLock; /* Required table locks for shared-cache mode */
@@ -11489,18 +11958,26 @@ struct Parse {
   /* Information used while coding trigger programs. */
   Parse *pToplevel;    /* Parse structure for main program (or NULL) */
   Table *pTriggerTab;  /* Table triggers are being coded for */
-  double nQueryLoop;   /* Estimated number of iterations of a query */
+  int addrCrTab;       /* Address of OP_CreateTable opcode on CREATE TABLE */
+  int addrSkipPK;      /* Address of instruction to skip PRIMARY KEY index */
+  u32 nQueryLoop;      /* Est number of iterations of a query (10*log2(N)) */
   u32 oldmask;         /* Mask of old.* columns referenced */
   u32 newmask;         /* Mask of new.* columns referenced */
   u8 eTriggerOp;       /* TK_UPDATE, TK_INSERT or TK_DELETE */
   u8 eOrconf;          /* Default ON CONFLICT policy for trigger steps */
   u8 disableTriggers;  /* True to disable triggers */
 
-  /* Above is constant between recursions.  Below is reset before and after
-  ** each recursion */
+  /************************************************************************
+  ** Above is constant between recursions.  Below is reset before and after
+  ** each recursion.  The boundary between these two regions is determined
+  ** using offsetof(Parse,nVar) so the nVar field must be the first field
+  ** in the recursive region.
+  ************************************************************************/
 
   int nVar;                 /* Number of '?' variables seen in the SQL so far */
   int nzVar;                /* Number of available slots in azVar[] */
+  u8 iPkSortOrder;          /* ASC or DESC for INTEGER PRIMARY KEY */
+  u8 bFreeWith;             /* True if pWith should be freed with parser */
   u8 explain;               /* True if the EXPLAIN flag is found on the query */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   u8 declareVtab;           /* True if inside sqlite3_declare_vtab() */
@@ -11514,7 +11991,6 @@ struct Parse {
 #endif
   char **azVar;             /* Pointers to names of parameters */
   Vdbe *pReprepare;         /* VM being reprepared (sqlite3Reprepare()) */
-  int *aAlias;              /* Register used to hold aliased result */
   const char *zTail;        /* All SQL text past the last semicolon parsed */
   Table *pNewTable;         /* A table being constructed by CREATE TABLE */
   Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
@@ -11527,6 +12003,7 @@ struct Parse {
 #endif
   Table *pZombieTab;        /* List of Table objects to delete after code gen */
   TriggerPrg *pTriggerPrg;  /* Linked list of coded triggers */
+  With *pWith;              /* Current WITH clause, or NULL */
 };
 
 /*
@@ -11646,7 +12123,7 @@ struct TriggerStep {
   Select *pSelect;     /* SELECT statment or RHS of INSERT INTO .. SELECT ... */
   Token target;        /* Target table for DELETE, UPDATE, INSERT */
   Expr *pWhere;        /* The WHERE clause for DELETE or UPDATE steps */
-  ExprList *pExprList; /* SET clause for UPDATE.  VALUES clause for INSERT */
+  ExprList *pExprList; /* SET clause for UPDATE. */
   IdList *pIdList;     /* Column names for INSERT */
   TriggerStep *pNext;  /* Next in the link-list */
   TriggerStep *pLast;  /* Last element in link-list. Valid for 1st elem only */
@@ -11661,6 +12138,7 @@ typedef struct DbFixer DbFixer;
 struct DbFixer {
   Parse *pParse;      /* The parsing context.  Error messages written here */
   Schema *pSchema;    /* Fix items to this schema */
+  int bVarOnly;       /* Check for variable references only */
   const char *zDb;    /* Make sure all objects are contained in this database */
   const char *zType;  /* Type of the container - used for error messages */
   const Token *pName; /* Name of the container - used for error messages */
@@ -11677,10 +12155,11 @@ struct StrAccum {
   int  nChar;          /* Length of the string so far */
   int  nAlloc;         /* Amount of space allocated in zText */
   int  mxAlloc;        /* Maximum allowed string length */
-  u8   mallocFailed;   /* Becomes true if any memory allocation fails */
   u8   useMalloc;      /* 0: none,  1: sqlite3DbMalloc,  2: sqlite3_malloc */
-  u8   tooBig;         /* Becomes true if string size exceeds limits */
+  u8   accError;       /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
 };
+#define STRACCUM_NOMEM   1
+#define STRACCUM_TOOBIG  2
 
 /*
 ** A pointer to this structure is used to communicate information
@@ -11705,6 +12184,7 @@ struct Sqlite3Config {
   int bOpenUri;                     /* True to interpret filenames as URIs */
   int bUseCis;                      /* Use covering indices for full-scans */
   int mxStrlen;                     /* Maximum string length */
+  int neverCorrupt;                 /* Database is always well-formed */
   int szLookaside;                  /* Default lookaside buffer size */
   int nLookaside;                   /* Default lookaside buffer count */
   sqlite3_mem_methods m;            /* Low-level memory allocation interface */
@@ -11730,26 +12210,54 @@ struct Sqlite3Config {
   int isMutexInit;                  /* True after mutexes are initialized */
   int isMallocInit;                 /* True after malloc is initialized */
   int isPCacheInit;                 /* True after malloc is initialized */
-  sqlite3_mutex *pInitMutex;        /* Mutex used by sqlite3_initialize() */
   int nRefInitMutex;                /* Number of users of pInitMutex */
+  sqlite3_mutex *pInitMutex;        /* Mutex used by sqlite3_initialize() */
   void (*xLog)(void*,int,const char*); /* Function for logging */
   void *pLogArg;                       /* First argument to xLog() */
-  int bLocaltimeFault;              /* True to fail localtime() calls */
 #ifdef SQLITE_ENABLE_SQLLOG
   void(*xSqllog)(void*,sqlite3*,const char*, int);
   void *pSqllogArg;
 #endif
+#ifdef SQLITE_VDBE_COVERAGE
+  /* The following callback (if not NULL) is invoked on every VDBE branch
+  ** operation.  Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
+  */
+  void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx);  /* Callback */
+  void *pVdbeBranchArg;                                     /* 1st argument */
+#endif
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+  int (*xTestCallback)(int);        /* Invoked by sqlite3FaultSim() */
+#endif
+  int bLocaltimeFault;              /* True to fail localtime() calls */
 };
 
 /*
+** This macro is used inside of assert() statements to indicate that
+** the assert is only valid on a well-formed database.  Instead of:
+**
+**     assert( X );
+**
+** One writes:
+**
+**     assert( X || CORRUPT_DB );
+**
+** CORRUPT_DB is true during normal operation.  CORRUPT_DB does not indicate
+** that the database is definitely corrupt, only that it might be corrupt.
+** For most test cases, CORRUPT_DB is set to false using a special
+** sqlite3_test_control().  This enables assert() statements to prove
+** things that are always true for well-formed databases.
+*/
+#define CORRUPT_DB  (sqlite3Config.neverCorrupt==0)
+
+/*
 ** Context pointer passed down through the tree-walk.
 */
 struct Walker {
   int (*xExprCallback)(Walker*, Expr*);     /* Callback for expressions */
   int (*xSelectCallback)(Walker*,Select*);  /* Callback for SELECTs */
+  void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
   Parse *pParse;                            /* Parser context.  */
   int walkerDepth;                          /* Number of subqueries */
-  u8 bSelectDepthFirst;                     /* Do subqueries first */
   union {                                   /* Extra data for callback */
     NameContext *pNC;                          /* Naming context */
     int i;                                     /* Integer value */
@@ -11774,6 +12282,21 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
 #define WRC_Abort       2   /* Abandon the tree walk */
 
 /*
+** An instance of this structure represents a set of one or more CTEs
+** (common table expressions) created by a single WITH clause.
+*/
+struct With {
+  int nCte;                       /* Number of CTEs in the WITH clause */
+  With *pOuter;                   /* Containing WITH clause, or NULL */
+  struct Cte {                    /* For each CTE in the WITH clause.... */
+    char *zName;                    /* Name of this CTE */
+    ExprList *pCols;                /* List of explicit column names, or NULL */
+    Select *pSelect;                /* The definition of this CTE */
+    const char *zErr;               /* Error message for circular references */
+  } a[1];
+};
+
+/*
 ** 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.
 */
@@ -11912,10 +12435,20 @@ SQLITE_PRIVATE   int sqlite3IsNaN(double);
 # define sqlite3IsNaN(X)  0
 #endif
 
-SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
-#ifndef SQLITE_OMIT_TRACE
-SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...);
-#endif
+/*
+** An instance of the following structure holds information about SQL
+** functions arguments that are the parameters to the printf() function.
+*/
+struct PrintfArguments {
+  int nArg;                /* Total number of arguments */
+  int nUsed;               /* Number of arguments used so far */
+  sqlite3_value **apArg;   /* The argument values */
+};
+
+#define SQLITE_PRINTF_INTERNAL 0x01
+#define SQLITE_PRINTF_SQLFUNC  0x02
+SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list);
+SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, u32, const char*, ...);
 SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...);
 SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
 SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
@@ -11981,6 +12514,8 @@ SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
 SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
 SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
 SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
+SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
+SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16);
 SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
 SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*);
 SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
@@ -11989,12 +12524,18 @@ SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
 SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*);
 SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
 SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
-SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
+SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
 SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
                     sqlite3_vfs**,char**,char **);
 SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
 SQLITE_PRIVATE int sqlite3CodeOnce(Parse *);
 
+#ifdef SQLITE_OMIT_BUILTIN_TEST
+# define sqlite3FaultSim(X) SQLITE_OK
+#else
+SQLITE_PRIVATE   int sqlite3FaultSim(int);
+#endif
+
 SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
 SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
 SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
@@ -12006,7 +12547,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);
 SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
 SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*);
 SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64);
-SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, u8 iBatch, i64);
+SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, int iBatch, i64);
 SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*);
 
 SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
@@ -12017,6 +12558,9 @@ SQLITE_PRIVATE   int sqlite3ViewGetColumnNames(Parse*,Table*);
 # define sqlite3ViewGetColumnNames(A,B) 0
 #endif
 
+#if SQLITE_MAX_ATTACHED>30
+SQLITE_PRIVATE   int sqlite3DbMaskAllZero(yDbMask);
+#endif
 SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int);
 SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int);
 SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*);
@@ -12027,8 +12571,7 @@ SQLITE_PRIVATE   void sqlite3AutoincrementEnd(Parse *pParse);
 # define sqlite3AutoincrementBegin(X)
 # define sqlite3AutoincrementEnd(X)
 #endif
-SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*);
-SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
+SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int);
 SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
 SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
 SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
@@ -12042,8 +12585,9 @@ SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*);
 SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
 SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
 SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
+SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
 SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
-                        Token*, int, int);
+                          Expr*, int, int);
 SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
 SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
 SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
@@ -12059,21 +12603,31 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
 SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
 SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
+SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*);
 SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
 SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
 SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
 SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
-SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int);
+SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*);
 SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int);
 SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*);
 SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
-SQLITE_PRIVATE int sqlite3ExprCode(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
 SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
 SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
-SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int);
-SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse*, Expr*);
-SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int);
+SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8);
+#define SQLITE_ECEL_DUP      0x01  /* Deep, not shallow copies */
+#define SQLITE_ECEL_FACTOR   0x02  /* Factor out constant terms */
 SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
 SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
 SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*);
@@ -12085,15 +12639,15 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
 SQLITE_PRIVATE void sqlite3Vacuum(Parse*);
 SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*);
 SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
-SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*);
-SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*);
+SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int);
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
 SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
 SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
 SQLITE_PRIVATE void sqlite3PrngSaveState(void);
 SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
-SQLITE_PRIVATE void sqlite3PrngResetState(void);
 SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int);
 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
 SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
@@ -12108,20 +12662,22 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
 SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*);
 SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
 SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
-SQLITE_PRIVATE void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
 SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
 SQLITE_PRIVATE int sqlite3IsRowid(const char*);
-SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, int);
-SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
-SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int);
-SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
-                                     int*,int,int,int,int,int*);
-SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
-SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
+SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
+SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*);
+SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
+SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int);
+SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
+                                     u8,u8,int,int*);
+SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
+SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*);
 SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
 SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
 SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
-SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, int);
+SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8);
+SQLITE_PRIVATE void sqlite3UniqueConstraint(Parse*, int, Index*);
+SQLITE_PRIVATE void sqlite3RowidConstraint(Parse*, int, Table*);
 SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
 SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
 SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
@@ -12155,7 +12711,7 @@ SQLITE_PRIVATE   void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, i
 SQLITE_PRIVATE   void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
 SQLITE_PRIVATE   TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
 SQLITE_PRIVATE   TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
-                                        ExprList*,Select*,u8);
+                                        Select*,u8);
 SQLITE_PRIVATE   TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8);
 SQLITE_PRIVATE   TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
 SQLITE_PRIVATE   void sqlite3DeleteTrigger(sqlite3*, Trigger*);
@@ -12191,7 +12747,7 @@ SQLITE_PRIVATE   int sqlite3AuthReadCol(Parse*, const char *, const char *, int)
 #endif
 SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
 SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
-SQLITE_PRIVATE int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
+SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
 SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
 SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
 SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
@@ -12203,6 +12759,12 @@ SQLITE_PRIVATE int sqlite3Atoi(const char*);
 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
 SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
+SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
+SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
+#endif
+SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
 
 /*
 ** Routines to read and write variable-length integers.  These used to
@@ -12244,18 +12806,18 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
 
 
 SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *);
-SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *);
+SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int);
 SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
 SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
 SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
+SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*);
 SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...);
 SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
 SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
 SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
 
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \
-    defined(SQLITE_DEBUG_OS_TRACE)
+#if defined(SQLITE_TEST) 
 SQLITE_PRIVATE const char *sqlite3ErrName(int);
 #endif
 
@@ -12264,7 +12826,7 @@ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
 SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
 SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
-SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*);
 SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
 SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
@@ -12279,18 +12841,16 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
 #else
 # define sqlite3FileSuffix3(X,Y)
 #endif
-SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,int);
+SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8);
 
 SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
 SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
 SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, 
                         void(*)(void*));
+SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*);
 SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
 SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
 SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
-#ifdef SQLITE_ENABLE_STAT3
-SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
-#endif
 SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
 SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
 #ifndef SQLITE_AMALGAMATION
@@ -12316,12 +12876,13 @@ SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
 SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
 SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
 SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
 SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
 SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
 SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
-SQLITE_PRIVATE char sqlite3AffinityType(const char*);
+SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*);
 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
 SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
@@ -12335,7 +12896,13 @@ SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse*, int, int);
 SQLITE_PRIVATE void sqlite3SchemaClear(void *);
 SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
 SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
-SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *);
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
+SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*);
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*);
+#endif
 SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, 
   void (*)(sqlite3_context*,int,sqlite3_value **),
   void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*),
@@ -12346,6 +12913,7 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *);
 
 SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, char*, int, int);
 SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int);
+SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*);
 SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum*,int);
 SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*);
 SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*);
@@ -12355,6 +12923,14 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
 SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *);
 SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);
 
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void);
+SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(Parse*,Index*,UnpackedRecord**,Expr*,u8,int,int*);
+SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**);
+SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord*);
+SQLITE_PRIVATE int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**);
+#endif
+
 /*
 ** The interface to the LEMON-generated parser
 */
@@ -12396,13 +12972,14 @@ SQLITE_PRIVATE   int sqlite3Utf8To8(unsigned char*);
 #else
 SQLITE_PRIVATE    void sqlite3VtabClear(sqlite3 *db, Table*);
 SQLITE_PRIVATE    void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
-SQLITE_PRIVATE    int sqlite3VtabSync(sqlite3 *db, char **);
+SQLITE_PRIVATE    int sqlite3VtabSync(sqlite3 *db, Vdbe*);
 SQLITE_PRIVATE    int sqlite3VtabRollback(sqlite3 *db);
 SQLITE_PRIVATE    int sqlite3VtabCommit(sqlite3 *db);
 SQLITE_PRIVATE    void sqlite3VtabLock(VTable *);
 SQLITE_PRIVATE    void sqlite3VtabUnlock(VTable *);
 SQLITE_PRIVATE    void sqlite3VtabUnlockList(sqlite3*);
 SQLITE_PRIVATE    int sqlite3VtabSavepoint(sqlite3 *, int, int);
+SQLITE_PRIVATE    void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
 SQLITE_PRIVATE    VTable *sqlite3GetVTable(sqlite3*, Table*);
 #  define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
 #endif
@@ -12417,8 +12994,10 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
 SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *);
 SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
 SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
+SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
 SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
 SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
+SQLITE_PRIVATE void sqlite3ParserReset(Parse*);
 SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
 SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
 SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
@@ -12428,6 +13007,14 @@ SQLITE_PRIVATE const char *sqlite3JournalModename(int);
 SQLITE_PRIVATE   int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
 SQLITE_PRIVATE   int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
 #endif
+#ifndef SQLITE_OMIT_CTE
+SQLITE_PRIVATE   With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
+SQLITE_PRIVATE   void sqlite3WithDelete(sqlite3*,With*);
+SQLITE_PRIVATE   void sqlite3WithPush(Parse*, With*, u8);
+#else
+#define sqlite3WithPush(x,y,z)
+#define sqlite3WithDelete(x,y)
+#endif
 
 /* Declarations for functions in fkey.c. All of these are replaced by
 ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
@@ -12437,18 +13024,18 @@ SQLITE_PRIVATE   int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
 ** provided (enforcement of FK constraints requires the triggers sub-system).
 */
 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-SQLITE_PRIVATE   void sqlite3FkCheck(Parse*, Table*, int, int);
+SQLITE_PRIVATE   void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
 SQLITE_PRIVATE   void sqlite3FkDropTable(Parse*, SrcList *, Table*);
-SQLITE_PRIVATE   void sqlite3FkActions(Parse*, Table*, ExprList*, int);
+SQLITE_PRIVATE   void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
 SQLITE_PRIVATE   int sqlite3FkRequired(Parse*, Table*, int*, int);
 SQLITE_PRIVATE   u32 sqlite3FkOldmask(Parse*, Table*);
 SQLITE_PRIVATE   FKey *sqlite3FkReferences(Table *);
 #else
-  #define sqlite3FkActions(a,b,c,d)
-  #define sqlite3FkCheck(a,b,c,d)
+  #define sqlite3FkActions(a,b,c,d,e,f)
+  #define sqlite3FkCheck(a,b,c,d,e,f)
   #define sqlite3FkDropTable(a,b,c)
-  #define sqlite3FkOldmask(a,b)      0
-  #define sqlite3FkRequired(a,b,c,d) 0
+  #define sqlite3FkOldmask(a,b)         0
+  #define sqlite3FkRequired(a,b,c,d)    0
 #endif
 #ifndef SQLITE_OMIT_FOREIGN_KEY
 SQLITE_PRIVATE   void sqlite3FkDelete(sqlite3 *, Table*);
@@ -12478,11 +13065,21 @@ SQLITE_PRIVATE   void sqlite3EndBenignMalloc(void);
   #define sqlite3EndBenignMalloc()
 #endif
 
-#define IN_INDEX_ROWID           1
-#define IN_INDEX_EPH             2
-#define IN_INDEX_INDEX_ASC       3
-#define IN_INDEX_INDEX_DESC      4
-SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*);
+/*
+** Allowed return values from sqlite3FindInIndex()
+*/
+#define IN_INDEX_ROWID        1   /* Search the rowid of the table */
+#define IN_INDEX_EPH          2   /* Search an ephemeral b-tree */
+#define IN_INDEX_INDEX_ASC    3   /* Existing index ASCENDING */
+#define IN_INDEX_INDEX_DESC   4   /* Existing index DESCENDING */
+#define IN_INDEX_NOOP         5   /* No table available. Use comparisons */
+/*
+** Allowed flags for the 3rd parameter to sqlite3FindInIndex().
+*/
+#define IN_INDEX_NOOP_OK     0x0001  /* OK to return IN_INDEX_NOOP */
+#define IN_INDEX_MEMBERSHIP  0x0002  /* IN operator used for membership test */
+#define IN_INDEX_LOOP        0x0004  /* IN operator used as a loop */
+SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*);
 
 #ifdef SQLITE_ENABLE_ATOMIC_WRITE
 SQLITE_PRIVATE   int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
@@ -12735,6 +13332,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
    SQLITE_USE_URI,            /* bOpenUri */
    SQLITE_ALLOW_COVERING_INDEX_SCAN,   /* bUseCis */
    0x7ffffffe,                /* mxStrlen */
+   0,                         /* neverCorrupt */
    128,                       /* szLookaside */
    500,                       /* nLookaside */
    {0,0,0,0,0,0,0,0},         /* m */
@@ -12759,18 +13357,24 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
    0,                         /* isMutexInit */
    0,                         /* isMallocInit */
    0,                         /* isPCacheInit */
-   0,                         /* pInitMutex */
    0,                         /* nRefInitMutex */
+   0,                         /* pInitMutex */
    0,                         /* xLog */
    0,                         /* pLogArg */
-   0,                         /* bLocaltimeFault */
 #ifdef SQLITE_ENABLE_SQLLOG
    0,                         /* xSqllog */
-   0                          /* pSqllogArg */
+   0,                         /* pSqllogArg */
+#endif
+#ifdef SQLITE_VDBE_COVERAGE
+   0,                         /* xVdbeBranch */
+   0,                         /* pVbeBranchArg */
+#endif
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+   0,                         /* xTestCallback */
 #endif
+   0                          /* bLocaltimeFault */
 };
 
-
 /*
 ** Hash table for global functions - functions common to all
 ** database connections.  After initialization, this table is
@@ -12937,7 +13541,9 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_ENABLE_RTREE
   "ENABLE_RTREE",
 #endif
-#ifdef SQLITE_ENABLE_STAT3
+#if defined(SQLITE_ENABLE_STAT4)
+  "ENABLE_STAT4",
+#elif defined(SQLITE_ENABLE_STAT3)
   "ENABLE_STAT3",
 #endif
 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
@@ -13033,6 +13639,9 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_OMIT_COMPOUND_SELECT
   "OMIT_COMPOUND_SELECT",
 #endif
+#ifdef SQLITE_OMIT_CTE
+  "OMIT_CTE",
+#endif
 #ifdef SQLITE_OMIT_DATETIME_FUNCS
   "OMIT_DATETIME_FUNCS",
 #endif
@@ -13165,6 +13774,9 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_SOUNDEX
   "SOUNDEX",
 #endif
+#ifdef SQLITE_SYSTEM_MALLOC
+  "SYSTEM_MALLOC",
+#endif
 #ifdef SQLITE_TCL
   "TCL",
 #endif
@@ -13180,6 +13792,9 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_USE_ALLOCA
   "USE_ALLOCA",
 #endif
+#ifdef SQLITE_WIN32_MALLOC
+  "WIN32_MALLOC",
+#endif
 #ifdef SQLITE_ZERO_MALLOC
   "ZERO_MALLOC"
 #endif
@@ -13279,7 +13894,7 @@ typedef struct VdbeOp Op;
 /*
 ** Boolean values
 */
-typedef unsigned char Bool;
+typedef unsigned Bool;
 
 /* Opaque type used by code in vdbesort.c */
 typedef struct VdbeSorter VdbeSorter;
@@ -13287,12 +13902,18 @@ typedef struct VdbeSorter VdbeSorter;
 /* Opaque type used by the explainer */
 typedef struct Explain Explain;
 
+/* Elements of the linked list at Vdbe.pAuxData */
+typedef struct AuxData AuxData;
+
 /*
 ** A cursor is a pointer into a single BTree within a database file.
 ** The cursor can seek to a BTree entry with a particular key, or
 ** loop over all entries of the Btree.  You can also insert new BTree
 ** entries or retrieve the key or data from the entry that the cursor
 ** is currently pointing to.
+**
+** Cursors can also point to virtual tables, sorters, or "pseudo-tables".
+** A pseudo-table is a single-row table implemented by registers.
 ** 
 ** Every cursor that the virtual machine has open is represented by an
 ** instance of the following structure.
@@ -13301,31 +13922,28 @@ struct VdbeCursor {
   BtCursor *pCursor;    /* The cursor structure of the backend */
   Btree *pBt;           /* Separate file holding temporary table */
   KeyInfo *pKeyInfo;    /* Info about index keys needed by index cursors */
-  int iDb;              /* Index of cursor database in db->aDb[] (or -1) */
+  int seekResult;       /* Result of previous sqlite3BtreeMoveto() */
   int pseudoTableReg;   /* Register holding pseudotable content. */
-  int nField;           /* Number of fields in the header */
-  Bool zeroed;          /* True if zeroed out and ready for reuse */
-  Bool rowidIsValid;    /* True if lastRowid is valid */
-  Bool atFirst;         /* True if pointing to first entry */
-  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */
-  Bool nullRow;         /* True if pointing to a row with no data */
-  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 */
-  Bool isOrdered;       /* True if the underlying table is BTREE_UNORDERED */
-  Bool isSorter;        /* True if a new-style sorter */
-  Bool multiPseudo;     /* Multi-register pseudo-cursor */
+  i16 nField;           /* Number of fields in the header */
+  u16 nHdrParsed;       /* Number of header fields parsed so far */
+#ifdef SQLITE_DEBUG
+  u8 seekOp;            /* Most recent seek operation on this cursor */
+#endif
+  i8 iDb;               /* Index of cursor database in db->aDb[] (or -1) */
+  u8 nullRow;           /* True if pointing to a row with no data */
+  u8 rowidIsValid;      /* True if lastRowid is valid */
+  u8 deferredMoveto;    /* A call to sqlite3BtreeMoveto() is needed */
+  Bool isEphemeral:1;   /* True for an ephemeral table */
+  Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
+  Bool isTable:1;       /* True if a table requiring integer keys */
+  Bool isOrdered:1;     /* True if the underlying table is BTREE_UNORDERED */
+  Pgno pgnoRoot;        /* Root page of the open btree cursor */
   sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
-  const sqlite3_module *pModule;     /* Module for cursor pVtabCursor */
   i64 seqCount;         /* Sequence counter */
   i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
-  i64 lastRowid;        /* Last rowid from a Next or NextIdx operation */
+  i64 lastRowid;        /* Rowid being deleted by OP_Delete */
   VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
 
-  /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or 
-  ** OP_IsUnique opcode on this cursor. */
-  int seekResult;
-
   /* Cached information about the header for the data record that the
   ** cursor is currently pointing to.  Only valid if cacheStatus matches
   ** Vdbe.cacheCtr.  Vdbe.cacheCtr will never take on the value of
@@ -13336,10 +13954,14 @@ struct VdbeCursor {
   ** be NULL.
   */
   u32 cacheStatus;      /* Cache is valid if this matches Vdbe.cacheCtr */
-  int payloadSize;      /* Total number of bytes in the record */
-  u32 *aType;           /* Type values for all entries in the record */
-  u32 *aOffset;         /* Cached offsets to the start of each columns data */
-  u8 *aRow;             /* Data for the current row, if all on one page */
+  u32 payloadSize;      /* Total number of bytes in the record */
+  u32 szRow;            /* Byte available in aRow */
+  u32 iHdrOffset;       /* Offset to next unparsed byte of the header */
+  const u8 *aRow;       /* Data for the current row, if all on one page */
+  u32 aType[1];         /* Type values for all entries in the record */
+  /* 2*nField extra array elements allocated for aType[], beyond the one
+  ** static element declared in the structure.  nField total array slots for
+  ** aType[] and nField+1 array slots for aOffset[] */
 };
 typedef struct VdbeCursor VdbeCursor;
 
@@ -13409,7 +14031,6 @@ struct Mem {
   } u;
   int n;              /* Number of characters in string value, excluding '\0' */
   u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
-  u8  type;           /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
   u8  enc;            /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
 #ifdef SQLITE_DEBUG
   Mem *pScopyFrom;    /* This Mem is a shallow copy of pScopyFrom */
@@ -13436,9 +14057,10 @@ struct Mem {
 #define MEM_Int       0x0004   /* Value is an integer */
 #define MEM_Real      0x0008   /* Value is a real number */
 #define MEM_Blob      0x0010   /* Value is a BLOB */
+#define MEM_AffMask   0x001f   /* Mask of affinity bits */
 #define MEM_RowSet    0x0020   /* Value is a RowSet object */
 #define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
-#define MEM_Invalid   0x0080   /* Value is undefined */
+#define MEM_Undefined 0x0080   /* Value is undefined */
 #define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
 #define MEM_TypeMask  0x01ff   /* Mask of type bits */
 
@@ -13449,7 +14071,7 @@ struct Mem {
 ** string is \000 or \u0000 terminated
 */
 #define MEM_Term      0x0200   /* String rep is nul terminated */
-#define MEM_Dyn       0x0400   /* Need to call sqliteFree() on Mem.z */
+#define MEM_Dyn       0x0400   /* Need to call Mem.xDel() on Mem.z */
 #define MEM_Static    0x0800   /* Mem.z points to a static string */
 #define MEM_Ephem     0x1000   /* Mem.z points to an ephemeral string */
 #define MEM_Agg       0x2000   /* Mem.z points to an agg function context */
@@ -13470,26 +14092,22 @@ struct Mem {
 ** is for use inside assert() statements only.
 */
 #ifdef SQLITE_DEBUG
-#define memIsValid(M)  ((M)->flags & MEM_Invalid)==0
-#endif
-
-
-/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
-** additional information about auxiliary information bound to arguments
-** of the function.  This is used to implement the sqlite3_get_auxdata()
-** and sqlite3_set_auxdata() APIs.  The "auxdata" is some auxiliary data
-** that can be associated with a constant argument to a function.  This
-** allows functions such as "regexp" to compile their constant regular
-** expression argument once and reused the compiled code for multiple
-** invocations.
-*/
-struct VdbeFunc {
-  FuncDef *pFunc;               /* The definition of the function */
-  int nAux;                     /* Number of entries allocated for apAux[] */
-  struct AuxData {
-    void *pAux;                   /* Aux data for the i-th argument */
-    void (*xDelete)(void *);      /* Destructor for the aux data */
-  } apAux[1];                   /* One slot for each function argument */
+#define memIsValid(M)  ((M)->flags & MEM_Undefined)==0
+#endif
+
+/*
+** Each auxilliary data pointer stored by a user defined function 
+** implementation calling sqlite3_set_auxdata() is stored in an instance
+** of this structure. All such structures associated with a single VM
+** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
+** when the VM is halted (if not before).
+*/
+struct AuxData {
+  int iOp;                        /* Instruction number of OP_Function opcode */
+  int iArg;                       /* Index of function argument. */
+  void *pAux;                     /* Aux data pointer */
+  void (*xDelete)(void *);        /* Destructor for the aux data */
+  AuxData *pNext;                 /* Next element in list */
 };
 
 /*
@@ -13507,12 +14125,14 @@ struct VdbeFunc {
 */
 struct sqlite3_context {
   FuncDef *pFunc;       /* Pointer to function information.  MUST BE FIRST */
-  VdbeFunc *pVdbeFunc;  /* Auxilary data, if created. */
   Mem s;                /* The return value is stored here */
   Mem *pMem;            /* Memory cell used to store aggregate context */
   CollSeq *pColl;       /* Collating sequence */
+  Vdbe *pVdbe;          /* The VM that owns this context */
+  int iOp;              /* Instruction number of OP_Function */
   int isError;          /* Error code returned by the function. */
-  int skipFlag;         /* Skip skip accumulator loading if true */
+  u8 skipFlag;          /* Skip skip accumulator loading if true */
+  u8 fErrorOrAux;       /* isError!=0 or pVdbe->pAuxData modified */
 };
 
 /*
@@ -13554,12 +14174,9 @@ struct Vdbe {
   Mem **apArg;            /* Arguments to currently executing user function */
   Mem *aColName;          /* Column names to return */
   Mem *pResultSet;        /* Pointer to an array of results */
+  Parse *pParse;          /* Parsing context used to create this Vdbe */
   int nMem;               /* Number of memory locations currently allocated */
   int nOp;                /* Number of instructions in the program */
-  int nOpAlloc;           /* Number of slots allocated for aOp[] */
-  int nLabel;             /* Number of labels used */
-  int *aLabel;            /* Space to hold the labels */
-  u16 nResColumn;         /* Number of columns in one row of the result set */
   int nCursor;            /* Number of slots in apCsr[] */
   u32 magic;              /* Magic number for sanity checking */
   char *zErrMsg;          /* Error message written here */
@@ -13572,6 +14189,7 @@ struct Vdbe {
   u32 cacheCtr;           /* VdbeCursor row cache generation counter */
   int pc;                 /* The program counter */
   int rc;                 /* Value to return */
+  u16 nResColumn;         /* Number of columns in one row of the result set */
   u8 errorAction;         /* Recovery action to do in case of an error */
   u8 minWriteFileFormat;  /* Minimum file format for writable database files */
   bft explain:2;          /* True if EXPLAIN present on SQL command */
@@ -13580,24 +14198,24 @@ struct Vdbe {
   bft expired:1;          /* True if the VM needs to be recompiled */
   bft runOnlyOnce:1;      /* Automatically expire on reset */
   bft usesStmtJournal:1;  /* True if uses a statement journal */
-  bft readOnly:1;         /* True for read-only statements */
+  bft readOnly:1;         /* True for statements that do not write */
+  bft bIsReader:1;        /* True for statements that read */
   bft isPrepareV2:1;      /* True if prepared with prepare_v2() */
   bft doingRerun:1;       /* True if rerunning after an auto-reprepare */
   int nChange;            /* Number of db changes made since last reset */
   yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
   yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
   int iStatement;         /* Statement number (or 0 if has not opened stmt) */
-  int aCounter[3];        /* Counters used by sqlite3_stmt_status() */
+  u32 aCounter[5];        /* Counters used by sqlite3_stmt_status() */
 #ifndef SQLITE_OMIT_TRACE
   i64 startTime;          /* Time when query started - used for profiling */
 #endif
+  i64 iCurrentTime;       /* Value of julianday('now') for this statement */
   i64 nFkConstraint;      /* Number of imm. FK constraints this VM */
   i64 nStmtDefCons;       /* Number of def. constraints when stmt started */
+  i64 nStmtDefImmCons;    /* Number of def. imm constraints when stmt started */
   char *zSql;             /* Text of the SQL statement that generated this */
   void *pFree;            /* Free this when deleting the vdbe */
-#ifdef SQLITE_DEBUG
-  FILE *trace;            /* Write an execution trace here, if not NULL */
-#endif
 #ifdef SQLITE_ENABLE_TREE_EXPLAIN
   Explain *pExplain;      /* The explainer */
   char *zExplain;         /* Explanation of data structures */
@@ -13609,6 +14227,7 @@ struct Vdbe {
   SubProgram *pProgram;   /* Linked list of all sub-programs used by VM */
   int nOnceFlag;          /* Size of array aOnceFlag[] */
   u8 *aOnceFlag;          /* Flags for OP_Once */
+  AuxData *pAuxData;      /* Linked list of auxdata allocations */
 };
 
 /*
@@ -13630,14 +14249,13 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*);
 #endif
 SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
 SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
-SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
+SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
 SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
-SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
 
 int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
 SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
 SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
-SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
 SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
 SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
 SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
@@ -13665,28 +14283,29 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
 SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
 SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
 SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
-SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*);
 SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
 SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
+#define VdbeMemDynamic(X)  \
+  (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0)
 #define VdbeMemRelease(X)  \
-  if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
-    sqlite3VdbeMemReleaseExternal(X);
+  if( VdbeMemDynamic(X) ) sqlite3VdbeMemReleaseExternal(X);
 SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
 SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
 SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
 SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
 SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
 SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
-SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
 SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
 
 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
+SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
 SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
 SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
-SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
+SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
 
 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
 SQLITE_PRIVATE   void sqlite3VdbeEnter(Vdbe*);
@@ -13698,6 +14317,7 @@ SQLITE_PRIVATE   void sqlite3VdbeLeave(Vdbe*);
 
 #ifdef SQLITE_DEBUG
 SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
+SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*);
 #endif
 
 #ifndef SQLITE_OMIT_FOREIGN_KEY
@@ -13953,6 +14573,16 @@ SQLITE_API int sqlite3_db_status(
       break;
     }
 
+    /* Set *pCurrent to non-zero if there are unresolved deferred foreign
+    ** key constraints.  Set *pCurrent to zero if all foreign key constraints
+    ** have been satisfied.  The *pHighwater is always set to zero.
+    */
+    case SQLITE_DBSTATUS_DEFERRED_FKS: {
+      *pHighwater = 0;
+      *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
+      break;
+    }
+
     default: {
       rc = SQLITE_ERROR;
     }
@@ -14258,8 +14888,8 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
 ** Return the number of errors.
 */
 static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
-  sqlite3 *db = sqlite3_context_db_handle(context);
-  if( sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD)==SQLITE_OK ){
+  p->iJD = sqlite3StmtCurrentTime(context);
+  if( p->iJD>0 ){
     p->validJD = 1;
     return 0;
   }else{
@@ -14390,6 +15020,10 @@ static void clearYMD_HMS_TZ(DateTime *p){
 **
 ** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
 ** routine will always fail.
+**
+** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
+** library function localtime_r() is used to assist in the calculation of
+** local time.
 */
 static int osLocaltime(time_t *t, struct tm *pTm){
   int rc;
@@ -14446,6 +15080,11 @@ static sqlite3_int64 localtimeOffset(
   x = *p;
   computeYMD_HMS(&x);
   if( x.Y<1971 || x.Y>=2038 ){
+    /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
+    ** works for years between 1970 and 2037. For dates outside this range,
+    ** SQLite attempts to map the year into an equivalent year within this
+    ** range, do the calculation, then map the year back.
+    */
     x.Y = 2000;
     x.M = 1;
     x.D = 1;
@@ -15042,8 +15681,8 @@ static void currentTimeFunc(
   UNUSED_PARAMETER(argc);
   UNUSED_PARAMETER(argv);
 
-  db = sqlite3_context_db_handle(context);
-  if( sqlite3OsCurrentTimeInt64(db->pVfs, &iT) ) return;
+  iT = sqlite3StmtCurrentTime(context);
+  if( iT<=0 ) return;
   t = iT/1000 - 10000*(sqlite3_int64)21086676;
 #ifdef HAVE_GMTIME_R
   pTm = gmtime_r(&t, &sNow);
@@ -15201,7 +15840,21 @@ SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
 ** routine has no return value since the return value would be meaningless.
 */
 SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
-  DO_OS_MALLOC_TEST(id);
+#ifdef SQLITE_TEST
+  if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){
+    /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
+    ** is using a regular VFS, it is called after the corresponding 
+    ** transaction has been committed. Injecting a fault at this point 
+    ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM
+    ** but the transaction is committed anyway.
+    **
+    ** The core must call OsFileControl() though, not OsFileControlHint(),
+    ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
+    ** means the commit really has failed and an error should be returned
+    ** to the user.  */
+    DO_OS_MALLOC_TEST(id);
+  }
+#endif
   return id->pMethods->xFileControl(id, op, pArg);
 }
 SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
@@ -15671,16 +16324,6 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
 ** macros.
 */
 #ifdef SQLITE_SYSTEM_MALLOC
-
-/*
-** The MSVCRT has malloc_usable_size() but it is called _msize().
-** The use of _msize() is automatic, but can be disabled by compiling
-** with -DSQLITE_WITHOUT_MSIZE
-*/
-#if defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
-# define SQLITE_MALLOCSIZE _msize
-#endif
-
 #if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
 
 /*
@@ -15703,22 +16346,48 @@ static malloc_zone_t* _sqliteZone_;
 ** Use standard C library malloc and free on non-Apple systems.  
 ** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
 */
-#define SQLITE_MALLOC(x)    malloc(x)
-#define SQLITE_FREE(x)      free(x)
-#define SQLITE_REALLOC(x,y) realloc((x),(y))
+#define SQLITE_MALLOC(x)             malloc(x)
+#define SQLITE_FREE(x)               free(x)
+#define SQLITE_REALLOC(x,y)          realloc((x),(y))
 
-#if (defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)) \
-      || (defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE))
-# include <malloc.h>    /* Needed for malloc_usable_size on linux */
-#endif
-#ifdef HAVE_MALLOC_USABLE_SIZE
-# ifndef SQLITE_MALLOCSIZE
-#  define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
-# endif
-#else
-# undef SQLITE_MALLOCSIZE
+/*
+** The malloc.h header file is needed for malloc_usable_size() function
+** on some systems (e.g. Linux).
+*/
+#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE)
+#  define SQLITE_USE_MALLOC_H
+#  define SQLITE_USE_MALLOC_USABLE_SIZE
+/*
+** The MSVCRT has malloc_usable_size(), but it is called _msize().  The
+** use of _msize() is automatic, but can be disabled by compiling with
+** -DSQLITE_WITHOUT_MSIZE.  Using the _msize() function also requires
+** the malloc.h header file.
+*/
+#elif defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
+#  define SQLITE_USE_MALLOC_H
+#  define SQLITE_USE_MSIZE
 #endif
 
+/*
+** Include the malloc.h header file, if necessary.  Also set define macro
+** SQLITE_MALLOCSIZE to the appropriate function name, which is _msize()
+** for MSVC and malloc_usable_size() for most other systems (e.g. Linux).
+** The memory size function can always be overridden manually by defining
+** the macro SQLITE_MALLOCSIZE to the desired function name.
+*/
+#if defined(SQLITE_USE_MALLOC_H)
+#  include <malloc.h>
+#  if defined(SQLITE_USE_MALLOC_USABLE_SIZE)
+#    if !defined(SQLITE_MALLOCSIZE)
+#      define SQLITE_MALLOCSIZE(x)   malloc_usable_size(x)
+#    endif
+#  elif defined(SQLITE_USE_MSIZE)
+#    if !defined(SQLITE_MALLOCSIZE)
+#      define SQLITE_MALLOCSIZE      _msize
+#    endif
+#  endif
+#endif /* defined(SQLITE_USE_MALLOC_H) */
+
 #endif /* __APPLE__ or not __APPLE__ */
 
 /*
@@ -16082,7 +16751,7 @@ static int sqlite3MemSize(void *p){
     return 0;
   }
   pHdr = sqlite3MemsysGetHeader(p);
-  return pHdr->iSize;
+  return (int)pHdr->iSize;
 }
 
 /*
@@ -16124,7 +16793,7 @@ static void randomFill(char *pBuf, int nByte){
   x = SQLITE_PTR_TO_INT(pBuf);
   y = nByte | 1;
   while( nByte >= 4 ){
-    x = (x>>1) ^ (-(x&1) & 0xd0000001);
+    x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
     y = y*1103515245 + 12345;
     r = x ^ y;
     *(int*)pBuf = r;
@@ -16132,7 +16801,7 @@ static void randomFill(char *pBuf, int nByte){
     nByte -= 4;
   }
   while( nByte-- > 0 ){
-    x = (x>>1) ^ (-(x&1) & 0xd0000001);
+    x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
     y = y*1103515245 + 12345;
     r = x ^ y;
     *(pBuf++) = r & 0xff;
@@ -16227,9 +16896,9 @@ static void sqlite3MemFree(void *pPrior){
   }
   z = (char*)pBt;
   z -= pHdr->nTitle;
-  adjustStats(pHdr->iSize, -1);
+  adjustStats((int)pHdr->iSize, -1);
   randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
-                pHdr->iSize + sizeof(int) + pHdr->nTitle);
+                (int)pHdr->iSize + sizeof(int) + pHdr->nTitle);
   free(z);
   sqlite3_mutex_leave(mem.mutex);  
 }
@@ -16251,9 +16920,9 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
   pOldHdr = sqlite3MemsysGetHeader(pPrior);
   pNew = sqlite3MemMalloc(nByte);
   if( pNew ){
-    memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
+    memcpy(pNew, pPrior, (int)(nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize));
     if( nByte>pOldHdr->iSize ){
-      randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
+      randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - (int)pOldHdr->iSize);
     }
     sqlite3MemFree(pPrior);
   }
@@ -16368,7 +17037,7 @@ SQLITE_PRIVATE void sqlite3MemdebugSync(){
   for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
     void **pBt = (void**)pHdr;
     pBt -= pHdr->nBacktraceSlots;
-    mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
+    mem.xBacktrace((int)pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
   }
 }
 
@@ -17252,13 +17921,13 @@ static SQLITE_WSD struct Mem5Global {
 } mem5;
 
 /*
-** Access the static variable through a macro for SQLITE_OMIT_WSD
+** Access the static variable through a macro for SQLITE_OMIT_WSD.
 */
 #define mem5 GLOBAL(struct Mem5Global, mem5)
 
 /*
 ** Assuming mem5.zPool is divided up into an array of Mem5Link
-** structures, return a pointer to the idx-th such lik.
+** structures, return a pointer to the idx-th such link.
 */
 #define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
 
@@ -17324,7 +17993,7 @@ static void memsys5Leave(void){
 static int memsys5Size(void *p){
   int iSize = 0;
   if( p ){
-    int i = ((u8 *)p-mem5.zPool)/mem5.szAtom;
+    int i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom);
     assert( i>=0 && i<mem5.nBlock );
     iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
   }
@@ -17332,29 +18001,10 @@ static int memsys5Size(void *p){
 }
 
 /*
-** Find the first entry on the freelist iLogsize.  Unlink that
-** entry and return its index. 
-*/
-static int memsys5UnlinkFirst(int iLogsize){
-  int i;
-  int iFirst;
-
-  assert( iLogsize>=0 && iLogsize<=LOGMAX );
-  i = iFirst = mem5.aiFreelist[iLogsize];
-  assert( iFirst>=0 );
-  while( i>0 ){
-    if( i<iFirst ) iFirst = i;
-    i = MEM5LINK(i)->next;
-  }
-  memsys5Unlink(iFirst, iLogsize);
-  return iFirst;
-}
-
-/*
 ** Return a block of memory of at least nBytes in size.
 ** Return NULL if unable.  Return NULL if nBytes==0.
 **
-** The caller guarantees that nByte positive.
+** The caller guarantees that nByte is positive.
 **
 ** The caller has obtained a mutex prior to invoking this
 ** routine so there is never any chance that two or more
@@ -17389,13 +18039,14 @@ static void *memsys5MallocUnsafe(int nByte){
   ** block.  If not, then split a block of the next larger power of
   ** two in order to create a new free block of size iLogsize.
   */
-  for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
+  for(iBin=iLogsize; iBin<=LOGMAX && mem5.aiFreelist[iBin]<0; iBin++){}
   if( iBin>LOGMAX ){
     testcase( sqlite3GlobalConfig.xLog!=0 );
     sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
     return 0;
   }
-  i = memsys5UnlinkFirst(iBin);
+  i = mem5.aiFreelist[iBin];
+  memsys5Unlink(i, iBin);
   while( iBin>iLogsize ){
     int newSize;
 
@@ -17415,6 +18066,12 @@ static void *memsys5MallocUnsafe(int nByte){
   if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
   if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
 
+#ifdef SQLITE_DEBUG
+  /* Make sure the allocated memory does not assume that it is set to zero
+  ** or retains a value from a previous allocation */
+  memset(&mem5.zPool[i*mem5.szAtom], 0xAA, iFullSz);
+#endif
+
   /* Return a pointer to the allocated memory. */
   return (void*)&mem5.zPool[i*mem5.szAtom];
 }
@@ -17429,7 +18086,7 @@ static void memsys5FreeUnsafe(void *pOld){
   /* Set iBlock to the index of the block pointed to by pOld in 
   ** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
   */
-  iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom;
+  iBlock = (int)(((u8 *)pOld-mem5.zPool)/mem5.szAtom);
 
   /* Check that the pointer pOld points to a valid, non-free block. */
   assert( iBlock>=0 && iBlock<mem5.nBlock );
@@ -17472,11 +18129,18 @@ static void memsys5FreeUnsafe(void *pOld){
     }
     size *= 2;
   }
+
+#ifdef SQLITE_DEBUG
+  /* Overwrite freed memory with the 0x55 bit pattern to verify that it is
+  ** not used after being freed */
+  memset(&mem5.zPool[iBlock*mem5.szAtom], 0x55, size);
+#endif
+
   memsys5Link(iBlock, iLogsize);
 }
 
 /*
-** Allocate nBytes of memory
+** Allocate nBytes of memory.
 */
 static void *memsys5Malloc(int nBytes){
   sqlite3_int64 *p = 0;
@@ -17786,7 +18450,7 @@ SQLITE_PRIVATE int sqlite3MutexEnd(void){
 */
 SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
 #ifndef SQLITE_OMIT_AUTOINIT
-  if( sqlite3_initialize() ) return 0;
+  if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
 #endif
   return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
 }
@@ -17967,7 +18631,7 @@ static int debugMutexEnd(void){ return SQLITE_OK; }
 ** that means that a mutex could not be allocated. 
 */
 static sqlite3_mutex *debugMutexAlloc(int id){
-  static sqlite3_debug_mutex aStatic[6];
+  static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_APP3 - 1];
   sqlite3_debug_mutex *pNew = 0;
   switch( id ){
     case SQLITE_MUTEX_FAST:
@@ -18164,10 +18828,13 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
 ** <li>  SQLITE_MUTEX_RECURSIVE
 ** <li>  SQLITE_MUTEX_STATIC_MASTER
 ** <li>  SQLITE_MUTEX_STATIC_MEM
-** <li>  SQLITE_MUTEX_STATIC_MEM2
+** <li>  SQLITE_MUTEX_STATIC_OPEN
 ** <li>  SQLITE_MUTEX_STATIC_PRNG
 ** <li>  SQLITE_MUTEX_STATIC_LRU
 ** <li>  SQLITE_MUTEX_STATIC_PMEM
+** <li>  SQLITE_MUTEX_STATIC_APP1
+** <li>  SQLITE_MUTEX_STATIC_APP2
+** <li>  SQLITE_MUTEX_STATIC_APP3
 ** </ul>
 **
 ** The first two constants cause sqlite3_mutex_alloc() to create
@@ -18201,6 +18868,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
     SQLITE3_MUTEX_INITIALIZER,
     SQLITE3_MUTEX_INITIALIZER,
     SQLITE3_MUTEX_INITIALIZER,
+    SQLITE3_MUTEX_INITIALIZER,
+    SQLITE3_MUTEX_INITIALIZER,
+    SQLITE3_MUTEX_INITIALIZER,
     SQLITE3_MUTEX_INITIALIZER
   };
   sqlite3_mutex *p;
@@ -18431,12 +19101,303 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This file contains the C functions that implement mutexes for win32
+** This file contains the C functions that implement mutexes for Win32.
+*/
+
+#if SQLITE_OS_WIN
+/*
+** Include code that is common to all os_*.c files
+*/
+/************** Include os_common.h in the middle of mutex_w32.c *************/
+/************** Begin file os_common.h ***************************************/
+/*
+** 2004 May 22
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains macros and a little bit of code that is common to
+** all of the platform-specific files (os_*.c) and is #included into those
+** files.
+**
+** This file should be #included by the os_*.c files only.  It is not a
+** general purpose header file.
+*/
+#ifndef _OS_COMMON_H_
+#define _OS_COMMON_H_
+
+/*
+** At least two bugs have slipped in because we changed the MEMORY_DEBUG
+** macro to SQLITE_DEBUG and some older makefiles have not yet made the
+** switch.  The following code should catch this problem at compile-time.
+*/
+#ifdef MEMORY_DEBUG
+# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
+#endif
+
+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+# ifndef SQLITE_DEBUG_OS_TRACE
+#   define SQLITE_DEBUG_OS_TRACE 0
+# endif
+  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
+# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
+#else
+# define OSTRACE(X)
+#endif
+
+/*
+** Macros for performance tracing.  Normally turned off.  Only works
+** on i486 hardware.
+*/
+#ifdef SQLITE_PERFORMANCE_TRACE
+
+/* 
+** hwtime.h contains inline assembler code for implementing 
+** high-performance timing routines.
+*/
+/************** Include hwtime.h in the middle of os_common.h ****************/
+/************** Begin file hwtime.h ******************************************/
+/*
+** 2008 May 27
+**
+** 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 inline asm code for retrieving "high-performance"
+** counters for x86 class CPUs.
+*/
+#ifndef _HWTIME_H_
+#define _HWTIME_H_
+
+/*
+** The following routine only works on pentium-class (or newer) processors.
+** It uses the RDTSC opcode to read the cycle count value out of the
+** processor and returns that value.  This can be used for high-res
+** profiling.
+*/
+#if (defined(__GNUC__) || defined(_MSC_VER)) && \
+      (defined(i386) || defined(__i386__) || defined(_M_IX86))
+
+  #if defined(__GNUC__)
+
+  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+     unsigned int lo, hi;
+     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+     return (sqlite_uint64)hi << 32 | lo;
+  }
+
+  #elif defined(_MSC_VER)
+
+  __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
+     __asm {
+        rdtsc
+        ret       ; return value at EDX:EAX
+     }
+  }
+
+  #endif
+
+#elif (defined(__GNUC__) && defined(__x86_64__))
+
+  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+      unsigned long val;
+      __asm__ __volatile__ ("rdtsc" : "=A" (val));
+      return val;
+  }
+ 
+#elif (defined(__GNUC__) && defined(__ppc__))
+
+  __inline__ sqlite_uint64 sqlite3Hwtime(void){
+      unsigned long long retval;
+      unsigned long junk;
+      __asm__ __volatile__ ("\n\
+          1:      mftbu   %1\n\
+                  mftb    %L0\n\
+                  mftbu   %0\n\
+                  cmpw    %0,%1\n\
+                  bne     1b"
+                  : "=r" (retval), "=r" (junk));
+      return retval;
+  }
+
+#else
+
+  #error Need implementation of sqlite3Hwtime() for your platform.
+
+  /*
+  ** To compile without implementing sqlite3Hwtime() for your platform,
+  ** you can remove the above #error and use the following
+  ** stub function.  You will lose timing support for many
+  ** of the debugging and testing utilities, but it should at
+  ** least compile and run.
+  */
+SQLITE_PRIVATE   sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
+
+#endif
+
+#endif /* !defined(_HWTIME_H_) */
+
+/************** End of hwtime.h **********************************************/
+/************** Continuing where we left off in os_common.h ******************/
+
+static sqlite_uint64 g_start;
+static sqlite_uint64 g_elapsed;
+#define TIMER_START       g_start=sqlite3Hwtime()
+#define TIMER_END         g_elapsed=sqlite3Hwtime()-g_start
+#define TIMER_ELAPSED     g_elapsed
+#else
+#define TIMER_START
+#define TIMER_END
+#define TIMER_ELAPSED     ((sqlite_uint64)0)
+#endif
+
+/*
+** If we compile with the SQLITE_TEST macro set, then the following block
+** of code will give us the ability to simulate a disk I/O error.  This
+** is used for testing the I/O recovery logic.
 */
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_io_error_hit = 0;            /* Total number of I/O Errors */
+SQLITE_API int sqlite3_io_error_hardhit = 0;        /* Number of non-benign errors */
+SQLITE_API int sqlite3_io_error_pending = 0;        /* Count down to first I/O error */
+SQLITE_API int sqlite3_io_error_persist = 0;        /* True if I/O errors persist */
+SQLITE_API int sqlite3_io_error_benign = 0;         /* True if errors are benign */
+SQLITE_API int sqlite3_diskfull_pending = 0;
+SQLITE_API int sqlite3_diskfull = 0;
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
+#define SimulateIOError(CODE)  \
+  if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
+       || sqlite3_io_error_pending-- == 1 )  \
+              { local_ioerr(); CODE; }
+static void local_ioerr(){
+  IOTRACE(("IOERR\n"));
+  sqlite3_io_error_hit++;
+  if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
+}
+#define SimulateDiskfullError(CODE) \
+   if( sqlite3_diskfull_pending ){ \
+     if( sqlite3_diskfull_pending == 1 ){ \
+       local_ioerr(); \
+       sqlite3_diskfull = 1; \
+       sqlite3_io_error_hit = 1; \
+       CODE; \
+     }else{ \
+       sqlite3_diskfull_pending--; \
+     } \
+   }
+#else
+#define SimulateIOErrorBenign(X)
+#define SimulateIOError(A)
+#define SimulateDiskfullError(A)
+#endif
+
+/*
+** When testing, keep a count of the number of open files.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_open_file_count = 0;
+#define OpenCounter(X)  sqlite3_open_file_count+=(X)
+#else
+#define OpenCounter(X)
+#endif
+
+#endif /* !defined(_OS_COMMON_H_) */
+
+/************** End of os_common.h *******************************************/
+/************** Continuing where we left off in mutex_w32.c ******************/
+
+/*
+** Include the header file for the Windows VFS.
+*/
+/************** Include os_win.h in the middle of mutex_w32.c ****************/
+/************** Begin file os_win.h ******************************************/
+/*
+** 2013 November 25
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains code that is specific to Windows.
+*/
+#ifndef _OS_WIN_H_
+#define _OS_WIN_H_
+
+/*
+** Include the primary Windows SDK header file.
+*/
+#include "windows.h"
+
+#ifdef __CYGWIN__
+# include <sys/cygwin.h>
+# include <errno.h> /* amalgamator: dontcache */
+#endif
+
+/*
+** Determine if we are dealing with Windows NT.
+**
+** We ought to be able to determine if we are compiling for Windows 9x or
+** Windows NT using the _WIN32_WINNT macro as follows:
+**
+** #if defined(_WIN32_WINNT)
+** # define SQLITE_OS_WINNT 1
+** #else
+** # define SQLITE_OS_WINNT 0
+** #endif
+**
+** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as
+** it ought to, so the above test does not work.  We'll just assume that
+** everything is Windows NT unless the programmer explicitly says otherwise
+** by setting SQLITE_OS_WINNT to 0.
+*/
+#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
+# define SQLITE_OS_WINNT 1
+#endif
+
+/*
+** Determine if we are dealing with Windows CE - which has a much reduced
+** API.
+*/
+#if defined(_WIN32_WCE)
+# define SQLITE_OS_WINCE 1
+#else
+# define SQLITE_OS_WINCE 0
+#endif
+
+/*
+** Determine if we are dealing with WinRT, which provides only a subset of
+** the full Win32 API.
+*/
+#if !defined(SQLITE_OS_WINRT)
+# define SQLITE_OS_WINRT 0
+#endif
+
+#endif /* _OS_WIN_H_ */
+
+/************** End of os_win.h **********************************************/
+/************** Continuing where we left off in mutex_w32.c ******************/
+#endif
 
 /*
 ** The code in this file is only used if we are compiling multithreaded
-** on a win32 system.
+** on a Win32 system.
 */
 #ifdef SQLITE_MUTEX_W32
 
@@ -18449,48 +19410,22 @@ struct sqlite3_mutex {
 #ifdef SQLITE_DEBUG
   volatile int nRef;         /* Number of enterances */
   volatile DWORD owner;      /* Thread holding this mutex */
-  int trace;                 /* True to trace changes */
+  volatile int trace;        /* True to trace changes */
 #endif
 };
-#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
-#ifdef SQLITE_DEBUG
-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
-#else
-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
-#endif
 
 /*
-** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
-** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
-**
-** Here is an interesting observation:  Win95, Win98, and WinME lack
-** the LockFileEx() API.  But we can still statically link against that
-** API as long as we don't call it win running Win95/98/ME.  A call to
-** this routine is used to determine if the host is Win95/98/ME or
-** WinNT/2K/XP so that we will know whether or not we can safely call
-** the LockFileEx() API.
-**
-** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
-** which is only available if your application was compiled with 
-** _WIN32_WINNT defined to a value >= 0x0400.  Currently, the only
-** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef 
-** this out as well.
+** These are the initializer values used when declaring a "static" mutex
+** on Win32.  It should be noted that all mutexes require initialization
+** on the Win32 platform.
 */
-#if 0
-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
-# define mutexIsNT()  (1)
+#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
+
+#ifdef SQLITE_DEBUG
+#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \
+                                    0L, (DWORD)0, 0 }
 #else
-  static int mutexIsNT(void){
-    static int osType = 0;
-    if( osType==0 ){
-      OSVERSIONINFO sInfo;
-      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
-      GetVersionEx(&sInfo);
-      osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
-    }
-    return osType==2;
-  }
-#endif /* SQLITE_OS_WINCE */
+#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
 #endif
 
 #ifdef SQLITE_DEBUG
@@ -18501,20 +19436,24 @@ struct sqlite3_mutex {
 static int winMutexHeld(sqlite3_mutex *p){
   return p->nRef!=0 && p->owner==GetCurrentThreadId();
 }
+
 static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
   return p->nRef==0 || p->owner!=tid;
 }
+
 static int winMutexNotheld(sqlite3_mutex *p){
-  DWORD tid = GetCurrentThreadId(); 
+  DWORD tid = GetCurrentThreadId();
   return winMutexNotheld2(p, tid);
 }
 #endif
 
-
 /*
 ** Initialize and deinitialize the mutex subsystem.
 */
-static sqlite3_mutex winMutex_staticMutexes[6] = {
+static sqlite3_mutex winMutex_staticMutexes[] = {
+  SQLITE3_MUTEX_INITIALIZER,
+  SQLITE3_MUTEX_INITIALIZER,
+  SQLITE3_MUTEX_INITIALIZER,
   SQLITE3_MUTEX_INITIALIZER,
   SQLITE3_MUTEX_INITIALIZER,
   SQLITE3_MUTEX_INITIALIZER,
@@ -18522,17 +19461,20 @@ static sqlite3_mutex winMutex_staticMutexes[6] = {
   SQLITE3_MUTEX_INITIALIZER,
   SQLITE3_MUTEX_INITIALIZER
 };
+
 static int winMutex_isInit = 0;
-/* As winMutexInit() and winMutexEnd() are called as part
-** of the sqlite3_initialize and sqlite3_shutdown()
-** processing, the "interlocked" magic is probably not
-** strictly necessary.
+static int winMutex_isNt = -1; /* <0 means "need to query" */
+
+/* As the winMutexInit() and winMutexEnd() functions are called as part
+** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
+** "interlocked" magic used here is probably not strictly necessary.
 */
-static long winMutex_lock = 0;
+static LONG volatile winMutex_lock = 0;
 
+SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */
 SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
 
-static int winMutexInit(void){ 
+static int winMutexInit(void){
   /* The first to increment to 1 does actual initialization */
   if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
     int i;
@@ -18545,16 +19487,17 @@ static int winMutexInit(void){
     }
     winMutex_isInit = 1;
   }else{
-    /* Someone else is in the process of initing the static mutexes */
+    /* Another thread is (in the process of) initializing the static
+    ** mutexes */
     while( !winMutex_isInit ){
       sqlite3_win32_sleep(1);
     }
   }
-  return SQLITE_OK; 
+  return SQLITE_OK;
 }
 
-static int winMutexEnd(void){ 
-  /* The first to decrement to 0 does actual shutdown 
+static int winMutexEnd(void){
+  /* The first to decrement to 0 does actual shutdown
   ** (which should be the last to shutdown.) */
   if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
     if( winMutex_isInit==1 ){
@@ -18565,7 +19508,7 @@ static int winMutexEnd(void){
       winMutex_isInit = 0;
     }
   }
-  return SQLITE_OK; 
+  return SQLITE_OK;
 }
 
 /*
@@ -18580,10 +19523,13 @@ static int winMutexEnd(void){
 ** <li>  SQLITE_MUTEX_RECURSIVE
 ** <li>  SQLITE_MUTEX_STATIC_MASTER
 ** <li>  SQLITE_MUTEX_STATIC_MEM
-** <li>  SQLITE_MUTEX_STATIC_MEM2
+** <li>  SQLITE_MUTEX_STATIC_OPEN
 ** <li>  SQLITE_MUTEX_STATIC_PRNG
 ** <li>  SQLITE_MUTEX_STATIC_LRU
 ** <li>  SQLITE_MUTEX_STATIC_PMEM
+** <li>  SQLITE_MUTEX_STATIC_APP1
+** <li>  SQLITE_MUTEX_STATIC_APP2
+** <li>  SQLITE_MUTEX_STATIC_APP3
 ** </ul>
 **
 ** The first two constants cause sqlite3_mutex_alloc() to create
@@ -18606,7 +19552,7 @@ static int winMutexEnd(void){
 **
 ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
 ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-** returns a different mutex on every call.  But for the static 
+** returns a different mutex on every call.  But for the static
 ** mutex types, the same mutex is returned on every call that has
 ** the same type number.
 */
@@ -18617,9 +19563,12 @@ static sqlite3_mutex *winMutexAlloc(int iType){
     case SQLITE_MUTEX_FAST:
     case SQLITE_MUTEX_RECURSIVE: {
       p = sqlite3MallocZero( sizeof(*p) );
-      if( p ){  
+      if( p ){
 #ifdef SQLITE_DEBUG
         p->id = iType;
+#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC
+        p->trace = 1;
+#endif
 #endif
 #if SQLITE_OS_WINRT
         InitializeCriticalSectionEx(&p->mutex, 0, 0);
@@ -18630,12 +19579,15 @@ static sqlite3_mutex *winMutexAlloc(int iType){
       break;
     }
     default: {
-      assert( winMutex_isInit==1 );
       assert( iType-2 >= 0 );
       assert( iType-2 < ArraySize(winMutex_staticMutexes) );
+      assert( winMutex_isInit==1 );
       p = &winMutex_staticMutexes[iType-2];
 #ifdef SQLITE_DEBUG
       p->id = iType;
+#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
+      p->trace = 1;
+#endif
 #endif
       break;
     }
@@ -18651,8 +19603,11 @@ static sqlite3_mutex *winMutexAlloc(int iType){
 */
 static void winMutexFree(sqlite3_mutex *p){
   assert( p );
+#ifdef SQLITE_DEBUG
   assert( p->nRef==0 && p->owner==0 );
   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
+#endif
+  assert( winMutex_isInit==1 );
   DeleteCriticalSection(&p->mutex);
   sqlite3_free(p);
 }
@@ -18669,30 +19624,39 @@ static void winMutexFree(sqlite3_mutex *p){
 ** more than once, the behavior is undefined.
 */
 static void winMutexEnter(sqlite3_mutex *p){
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+  DWORD tid = GetCurrentThreadId();
+#endif
 #ifdef SQLITE_DEBUG
-  DWORD tid = GetCurrentThreadId(); 
+  assert( p );
   assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
+#else
+  assert( p );
 #endif
+  assert( winMutex_isInit==1 );
   EnterCriticalSection(&p->mutex);
 #ifdef SQLITE_DEBUG
   assert( p->nRef>0 || p->owner==0 );
-  p->owner = tid; 
+  p->owner = tid;
   p->nRef++;
   if( p->trace ){
-    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+    OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
+             tid, p, p->trace, p->nRef));
   }
 #endif
 }
+
 static int winMutexTry(sqlite3_mutex *p){
-#ifndef NDEBUG
-  DWORD tid = GetCurrentThreadId(); 
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+  DWORD tid = GetCurrentThreadId();
 #endif
   int rc = SQLITE_BUSY;
+  assert( p );
   assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
   /*
   ** The sqlite3_mutex_try() routine is very rarely used, and when it
   ** is used it is merely an optimization.  So it is OK for it to always
-  ** fail.  
+  ** fail.
   **
   ** The TryEnterCriticalSection() interface is only available on WinNT.
   ** And some windows compilers complain if you try to use it without
@@ -18700,18 +19664,27 @@ static int winMutexTry(sqlite3_mutex *p){
   ** For that reason, we will omit this optimization for now.  See
   ** ticket #2685.
   */
-#if 0
-  if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400
+  assert( winMutex_isInit==1 );
+  assert( winMutex_isNt>=-1 && winMutex_isNt<=1 );
+  if( winMutex_isNt<0 ){
+    winMutex_isNt = sqlite3_win32_is_nt();
+  }
+  assert( winMutex_isNt==0 || winMutex_isNt==1 );
+  if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){
+#ifdef SQLITE_DEBUG
     p->owner = tid;
     p->nRef++;
+#endif
     rc = SQLITE_OK;
   }
 #else
   UNUSED_PARAMETER(p);
 #endif
 #ifdef SQLITE_DEBUG
-  if( rc==SQLITE_OK && p->trace ){
-    printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+  if( p->trace ){
+    OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
+             tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
   }
 #endif
   return rc;
@@ -18724,18 +19697,23 @@ static int winMutexTry(sqlite3_mutex *p){
 ** is not currently allocated.  SQLite will never do either.
 */
 static void winMutexLeave(sqlite3_mutex *p){
-#ifndef NDEBUG
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
   DWORD tid = GetCurrentThreadId();
+#endif
+  assert( p );
+#ifdef SQLITE_DEBUG
   assert( p->nRef>0 );
   assert( p->owner==tid );
   p->nRef--;
   if( p->nRef==0 ) p->owner = 0;
   assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
 #endif
+  assert( winMutex_isInit==1 );
   LeaveCriticalSection(&p->mutex);
 #ifdef SQLITE_DEBUG
   if( p->trace ){
-    printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
+    OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
+             tid, p, p->trace, p->nRef));
   }
 #endif
 }
@@ -18757,9 +19735,9 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
     0
 #endif
   };
-
   return &sMutex;
 }
+
 #endif /* SQLITE_MUTEX_W32 */
 
 /************** End of mutex_w32.c *******************************************/
@@ -19198,7 +20176,7 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
 */
 #ifndef SQLITE_OMIT_LOOKASIDE
 static int isLookaside(sqlite3 *db, void *p){
-  return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
+  return p>=db->lookaside.pStart && p<db->lookaside.pEnd;
 }
 #else
 #define isLookaside(A,B) 0
@@ -19214,8 +20192,9 @@ SQLITE_PRIVATE int sqlite3MallocSize(void *p){
   return sqlite3GlobalConfig.m.xSize(p);
 }
 SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
-  assert( db==0 || sqlite3_mutex_held(db->mutex) );
-  if( db && isLookaside(db, p) ){
+  assert( db!=0 );
+  assert( sqlite3_mutex_held(db->mutex) );
+  if( isLookaside(db, p) ){
     return db->lookaside.sz;
   }else{
     assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
@@ -19249,6 +20228,7 @@ SQLITE_API void sqlite3_free(void *p){
 */
 SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
   assert( db==0 || sqlite3_mutex_held(db->mutex) );
+  if( p==0 ) return;
   if( db ){
     if( db->pnBytesFreed ){
       *db->pnBytesFreed += sqlite3DbMallocSize(db, p);
@@ -19684,20 +20664,31 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
 #endif /* SQLITE_OMIT_FLOATING_POINT */
 
 /*
-** Append N space characters to the given string buffer.
+** Set the StrAccum object to an error mode.
 */
-SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){
-  static const char zSpaces[] = "                             ";
-  while( N>=(int)sizeof(zSpaces)-1 ){
-    sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
-    N -= sizeof(zSpaces)-1;
-  }
-  if( N>0 ){
-    sqlite3StrAccumAppend(pAccum, zSpaces, N);
-  }
+static void setStrAccumError(StrAccum *p, u8 eError){
+  p->accError = eError;
+  p->nAlloc = 0;
 }
 
 /*
+** Extra argument values from a PrintfArguments object
+*/
+static sqlite3_int64 getIntArg(PrintfArguments *p){
+  if( p->nArg<=p->nUsed ) return 0;
+  return sqlite3_value_int64(p->apArg[p->nUsed++]);
+}
+static double getDoubleArg(PrintfArguments *p){
+  if( p->nArg<=p->nUsed ) return 0.0;
+  return sqlite3_value_double(p->apArg[p->nUsed++]);
+}
+static char *getTextArg(PrintfArguments *p){
+  if( p->nArg<=p->nUsed ) return 0;
+  return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
+}
+
+
+/*
 ** On machines with a small stack size, you can redefine the
 ** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
 */
@@ -19710,10 +20701,10 @@ SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){
 ** Render a string given by "fmt" into the StrAccum object.
 */
 SQLITE_PRIVATE void sqlite3VXPrintf(
-  StrAccum *pAccum,                  /* Accumulate results here */
-  int useExtended,                   /* Allow extended %-conversions */
-  const char *fmt,                   /* Format string */
-  va_list ap                         /* arguments */
+  StrAccum *pAccum,          /* Accumulate results here */
+  u32 bFlags,                /* SQLITE_PRINTF_* flags */
+  const char *fmt,           /* Format string */
+  va_list ap                 /* arguments */
 ){
   int c;                     /* Next character in the format string */
   char *bufpt;               /* Pointer to the conversion buffer */
@@ -19731,6 +20722,8 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
   etByte flag_longlong;      /* True if the "ll" flag is present */
   etByte done;               /* Loop termination flag */
   etByte xtype = 0;          /* Conversion paradigm */
+  u8 bArgList;               /* True for SQLITE_PRINTF_SQLFUNC */
+  u8 useIntern;              /* Ok to use internal conversions (ex: %T) */
   char prefix;               /* Prefix character.  "+" or "-" or " " or '\0'. */
   sqlite_uint64 longvalue;   /* Value for integer types */
   LONGDOUBLE_TYPE realvalue; /* Value for real types */
@@ -19745,16 +20738,23 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
   etByte flag_dp;            /* True if decimal point should be shown */
   etByte flag_rtz;           /* True if trailing zeros should be removed */
 #endif
+  PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
   char buf[etBUFSIZE];       /* Conversion buffer */
 
   bufpt = 0;
+  if( bFlags ){
+    if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){
+      pArgList = va_arg(ap, PrintfArguments*);
+    }
+    useIntern = bFlags & SQLITE_PRINTF_INTERNAL;
+  }else{
+    bArgList = useIntern = 0;
+  }
   for(; (c=(*fmt))!=0; ++fmt){
     if( c!='%' ){
-      int amt;
       bufpt = (char *)fmt;
-      amt = 1;
-      while( (c=(*++fmt))!='%' && c!=0 ) amt++;
-      sqlite3StrAccumAppend(pAccum, bufpt, amt);
+      while( (c=(*++fmt))!='%' && c!=0 ){};
+      sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt));
       if( c==0 ) break;
     }
     if( (c=(*++fmt))==0 ){
@@ -19779,7 +20779,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
     /* Get the field width */
     width = 0;
     if( c=='*' ){
-      width = va_arg(ap,int);
+      if( bArgList ){
+        width = (int)getIntArg(pArgList);
+      }else{
+        width = va_arg(ap,int);
+      }
       if( width<0 ){
         flag_leftjustify = 1;
         width = -width;
@@ -19796,7 +20800,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
       precision = 0;
       c = *++fmt;
       if( c=='*' ){
-        precision = va_arg(ap,int);
+        if( bArgList ){
+          precision = (int)getIntArg(pArgList);
+        }else{
+          precision = va_arg(ap,int);
+        }
         if( precision<0 ) precision = -precision;
         c = *++fmt;
       }else{
@@ -19827,7 +20835,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
     for(idx=0; idx<ArraySize(fmtinfo); idx++){
       if( c==fmtinfo[idx].fmttype ){
         infop = &fmtinfo[idx];
-        if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
+        if( useIntern || (infop->flags & FLAG_INTERN)==0 ){
           xtype = infop->type;
         }else{
           return;
@@ -19867,7 +20875,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
       case etRADIX:
         if( infop->flags & FLAG_SIGNED ){
           i64 v;
-          if( flag_longlong ){
+          if( bArgList ){
+            v = getIntArg(pArgList);
+          }else if( flag_longlong ){
             v = va_arg(ap,i64);
           }else if( flag_long ){
             v = va_arg(ap,long int);
@@ -19888,7 +20898,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
             else                       prefix = 0;
           }
         }else{
-          if( flag_longlong ){
+          if( bArgList ){
+            longvalue = (u64)getIntArg(pArgList);
+          }else if( flag_longlong ){
             longvalue = va_arg(ap,u64);
           }else if( flag_long ){
             longvalue = va_arg(ap,unsigned long int);
@@ -19908,7 +20920,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
           nOut = precision + 10;
           zOut = zExtra = sqlite3Malloc( nOut );
           if( zOut==0 ){
-            pAccum->mallocFailed = 1;
+            setStrAccumError(pAccum, STRACCUM_NOMEM);
             return;
           }
         }
@@ -19923,10 +20935,8 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
           *(--bufpt) = zOrd[x*2];
         }
         {
-          register const char *cset;      /* Use registers for speed */
-          register int base;
-          cset = &aDigits[infop->charset];
-          base = infop->base;
+          const char *cset = &aDigits[infop->charset];
+          u8 base = infop->base;
           do{                                           /* Convert to ascii */
             *(--bufpt) = cset[longvalue%base];
             longvalue = longvalue/base;
@@ -19948,7 +20958,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
       case etFLOAT:
       case etEXP:
       case etGENERIC:
-        realvalue = va_arg(ap,double);
+        if( bArgList ){
+          realvalue = getDoubleArg(pArgList);
+        }else{
+          realvalue = va_arg(ap,double);
+        }
 #ifdef SQLITE_OMIT_FLOATING_POINT
         length = 0;
 #else
@@ -19962,13 +20976,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
           else                         prefix = 0;
         }
         if( xtype==etGENERIC && precision>0 ) precision--;
-#if 0
-        /* Rounding works like BSD when the constant 0.4999 is used.  Wierd! */
-        for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
-#else
-        /* It makes more sense to use 0.5 */
         for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
-#endif
         if( xtype==etFLOAT ) realvalue += rounder;
         /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
         exp = 0;
@@ -20023,10 +21031,10 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
         }else{
           e2 = exp;
         }
-        if( e2+precision+width > etBUFSIZE - 15 ){
-          bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
+        if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){
+          bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 );
           if( bufpt==0 ){
-            pAccum->mallocFailed = 1;
+            setStrAccumError(pAccum, STRACCUM_NOMEM);
             return;
           }
         }
@@ -20109,7 +21117,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
 #endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
         break;
       case etSIZE:
-        *(va_arg(ap,int*)) = pAccum->nChar;
+        if( !bArgList ){
+          *(va_arg(ap,int*)) = pAccum->nChar;
+        }
         length = width = 0;
         break;
       case etPERCENT:
@@ -20118,7 +21128,12 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
         length = 1;
         break;
       case etCHARX:
-        c = va_arg(ap,int);
+        if( bArgList ){
+          bufpt = getTextArg(pArgList);
+          c = bufpt ? bufpt[0] : 0;
+        }else{
+          c = va_arg(ap,int);
+        }
         buf[0] = (char)c;
         if( precision>=0 ){
           for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
@@ -20130,10 +21145,14 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
         break;
       case etSTRING:
       case etDYNSTRING:
-        bufpt = va_arg(ap,char*);
+        if( bArgList ){
+          bufpt = getTextArg(pArgList);
+        }else{
+          bufpt = va_arg(ap,char*);
+        }
         if( bufpt==0 ){
           bufpt = "";
-        }else if( xtype==etDYNSTRING ){
+        }else if( xtype==etDYNSTRING && !bArgList ){
           zExtra = bufpt;
         }
         if( precision>=0 ){
@@ -20149,7 +21168,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
         int needQuote;
         char ch;
         char q = ((xtype==etSQLESCAPE3)?'"':'\'');   /* Quote character */
-        char *escarg = va_arg(ap,char*);
+        char *escarg;
+
+        if( bArgList ){
+          escarg = getTextArg(pArgList);
+        }else{
+          escarg = va_arg(ap,char*);
+        }
         isnull = escarg==0;
         if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
         k = precision;
@@ -20161,7 +21186,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
         if( n>etBUFSIZE ){
           bufpt = zExtra = sqlite3Malloc( n );
           if( bufpt==0 ){
-            pAccum->mallocFailed = 1;
+            setStrAccumError(pAccum, STRACCUM_NOMEM);
             return;
           }
         }else{
@@ -20184,7 +21209,8 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
       }
       case etTOKEN: {
         Token *pToken = va_arg(ap, Token*);
-        if( pToken ){
+        assert( bArgList==0 );
+        if( pToken && pToken->n ){
           sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
         }
         length = width = 0;
@@ -20194,12 +21220,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
         SrcList *pSrc = va_arg(ap, SrcList*);
         int k = va_arg(ap, int);
         struct SrcList_item *pItem = &pSrc->a[k];
+        assert( bArgList==0 );
         assert( k>=0 && k<pSrc->nSrc );
         if( pItem->zDatabase ){
-          sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1);
+          sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase);
           sqlite3StrAccumAppend(pAccum, ".", 1);
         }
-        sqlite3StrAccumAppend(pAccum, pItem->zName, -1);
+        sqlite3StrAccumAppendAll(pAccum, pItem->zName);
         length = width = 0;
         break;
       }
@@ -20213,77 +21240,99 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
     ** "length" characters long.  The field width is "width".  Do
     ** the output.
     */
-    if( !flag_leftjustify ){
-      register int nspace;
-      nspace = width-length;
-      if( nspace>0 ){
-        sqlite3AppendSpace(pAccum, nspace);
-      }
-    }
-    if( length>0 ){
-      sqlite3StrAccumAppend(pAccum, bufpt, length);
-    }
-    if( flag_leftjustify ){
-      register int nspace;
-      nspace = width-length;
-      if( nspace>0 ){
-        sqlite3AppendSpace(pAccum, nspace);
-      }
-    }
-    sqlite3_free(zExtra);
+    width -= length;
+    if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
+    sqlite3StrAccumAppend(pAccum, bufpt, length);
+    if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
+
+    if( zExtra ) sqlite3_free(zExtra);
   }/* End for loop over the format string */
 } /* End of function */
 
 /*
-** Append N bytes of text from z to the StrAccum object.
+** Enlarge the memory allocation on a StrAccum object so that it is
+** able to accept at least N more bytes of text.
+**
+** Return the number of bytes of text that StrAccum is able to accept
+** after the attempted enlargement.  The value returned might be zero.
 */
-SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
-  assert( z!=0 || N==0 );
-  if( p->tooBig | p->mallocFailed ){
-    testcase(p->tooBig);
-    testcase(p->mallocFailed);
-    return;
+static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
+  char *zNew;
+  assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */
+  if( p->accError ){
+    testcase(p->accError==STRACCUM_TOOBIG);
+    testcase(p->accError==STRACCUM_NOMEM);
+    return 0;
   }
-  assert( p->zText!=0 || p->nChar==0 );
-  if( N<0 ){
-    N = sqlite3Strlen30(z);
+  if( !p->useMalloc ){
+    N = p->nAlloc - p->nChar - 1;
+    setStrAccumError(p, STRACCUM_TOOBIG);
+    return N;
+  }else{
+    char *zOld = (p->zText==p->zBase ? 0 : p->zText);
+    i64 szNew = p->nChar;
+    szNew += N + 1;
+    if( szNew > p->mxAlloc ){
+      sqlite3StrAccumReset(p);
+      setStrAccumError(p, STRACCUM_TOOBIG);
+      return 0;
+    }else{
+      p->nAlloc = (int)szNew;
+    }
+    if( p->useMalloc==1 ){
+      zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
+    }else{
+      zNew = sqlite3_realloc(zOld, p->nAlloc);
+    }
+    if( zNew ){
+      assert( p->zText!=0 || p->nChar==0 );
+      if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
+      p->zText = zNew;
+    }else{
+      sqlite3StrAccumReset(p);
+      setStrAccumError(p, STRACCUM_NOMEM);
+      return 0;
+    }
   }
-  if( N==0 || NEVER(z==0) ){
-    return;
+  return N;
+}
+
+/*
+** Append N space characters to the given string buffer.
+*/
+SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *p, int N){
+  if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
+  while( (N--)>0 ) p->zText[p->nChar++] = ' ';
+}
+
+/*
+** The StrAccum "p" is not large enough to accept N new bytes of z[].
+** So enlarge if first, then do the append.
+**
+** This is a helper routine to sqlite3StrAccumAppend() that does special-case
+** work (enlarging the buffer) using tail recursion, so that the
+** sqlite3StrAccumAppend() routine can use fast calling semantics.
+*/
+static void enlargeAndAppend(StrAccum *p, const char *z, int N){
+  N = sqlite3StrAccumEnlarge(p, N);
+  if( N>0 ){
+    memcpy(&p->zText[p->nChar], z, N);
+    p->nChar += N;
   }
+}
+
+/*
+** Append N bytes of text from z to the StrAccum object.  Increase the
+** size of the memory allocation for StrAccum if necessary.
+*/
+SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
+  assert( z!=0 );
+  assert( p->zText!=0 || p->nChar==0 || p->accError );
+  assert( N>=0 );
+  assert( p->accError==0 || p->nAlloc==0 );
   if( p->nChar+N >= p->nAlloc ){
-    char *zNew;
-    if( !p->useMalloc ){
-      p->tooBig = 1;
-      N = p->nAlloc - p->nChar - 1;
-      if( N<=0 ){
-        return;
-      }
-    }else{
-      char *zOld = (p->zText==p->zBase ? 0 : p->zText);
-      i64 szNew = p->nChar;
-      szNew += N + 1;
-      if( szNew > p->mxAlloc ){
-        sqlite3StrAccumReset(p);
-        p->tooBig = 1;
-        return;
-      }else{
-        p->nAlloc = (int)szNew;
-      }
-      if( p->useMalloc==1 ){
-        zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
-      }else{
-        zNew = sqlite3_realloc(zOld, p->nAlloc);
-      }
-      if( zNew ){
-        if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
-        p->zText = zNew;
-      }else{
-        p->mallocFailed = 1;
-        sqlite3StrAccumReset(p);
-        return;
-      }
-    }
+    enlargeAndAppend(p,z,N);
+    return;
   }
   assert( p->zText );
   memcpy(&p->zText[p->nChar], z, N);
@@ -20291,6 +21340,14 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
 }
 
 /*
+** Append the complete text of zero-terminated string z[] to the p string.
+*/
+SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
+  sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z));
+}
+
+
+/*
 ** Finish off a string by making sure it is zero-terminated.
 ** Return a pointer to the resulting string.  Return a NULL
 ** pointer if any kind of error was encountered.
@@ -20307,7 +21364,7 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
       if( p->zText ){
         memcpy(p->zText, p->zBase, p->nChar+1);
       }else{
-        p->mallocFailed = 1;
+        setStrAccumError(p, STRACCUM_NOMEM);
       }
     }
   }
@@ -20338,8 +21395,7 @@ SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx)
   p->nAlloc = n;
   p->mxAlloc = mx;
   p->useMalloc = 1;
-  p->tooBig = 0;
-  p->mallocFailed = 0;
+  p->accError = 0;
 }
 
 /*
@@ -20354,9 +21410,9 @@ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list a
   sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
                       db->aLimit[SQLITE_LIMIT_LENGTH]);
   acc.db = db;
-  sqlite3VXPrintf(&acc, 1, zFormat, ap);
+  sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap);
   z = sqlite3StrAccumFinish(&acc);
-  if( acc.mallocFailed ){
+  if( acc.accError==STRACCUM_NOMEM ){
     db->mallocFailed = 1;
   }
   return z;
@@ -20510,17 +21566,15 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
 }
 #endif
 
-#ifndef SQLITE_OMIT_TRACE
 /*
 ** variable-argument wrapper around sqlite3VXPrintf().
 */
-SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
+SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){
   va_list ap;
   va_start(ap,zFormat);
-  sqlite3VXPrintf(p, 1, zFormat, ap);
+  sqlite3VXPrintf(p, bFlags, zFormat, ap);
   va_end(ap);
 }
-#endif
 
 /************** End of printf.c **********************************************/
 /************** Begin file random.c ******************************************/
@@ -20553,24 +21607,11 @@ static SQLITE_WSD struct sqlite3PrngType {
 } sqlite3Prng;
 
 /*
-** Get a single 8-bit random value from the RC4 PRNG.  The Mutex
-** must be held while executing this routine.
-**
-** Why not just use a library random generator like lrand48() for this?
-** Because the OP_NewRowid opcode in the VDBE depends on having a very
-** good source of random numbers.  The lrand48() library function may
-** well be good enough.  But maybe not.  Or maybe lrand48() has some
-** subtle problems on some systems that could cause problems.  It is hard
-** to know.  To minimize the risk of problems due to bad lrand48()
-** implementations, SQLite uses this random number generator based
-** on RC4, which we know works very well.
-**
-** (Later):  Actually, OP_NewRowid does not depend on a good source of
-** randomness any more.  But we will leave this code in all the same.
+** Return N random bytes.
 */
-static u8 randomByte(void){
+SQLITE_API void sqlite3_randomness(int N, void *pBuf){
   unsigned char t;
-
+  unsigned char *zBuf = pBuf;
 
   /* The "wsdPrng" macro will resolve to the pseudo-random number generator
   ** state vector.  If writable static data is unsupported on the target,
@@ -20585,6 +21626,16 @@ static u8 randomByte(void){
 # define wsdPrng sqlite3Prng
 #endif
 
+#if SQLITE_THREADSAFE
+  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
+  sqlite3_mutex_enter(mutex);
+#endif
+
+  if( N<=0 ){
+    wsdPrng.isInit = 0;
+    sqlite3_mutex_leave(mutex);
+    return;
+  }
 
   /* Initialize the state of the random number generator once,
   ** the first time this routine is called.  The seed value does
@@ -20613,29 +21664,16 @@ static u8 randomByte(void){
     wsdPrng.isInit = 1;
   }
 
-  /* Generate and return single random byte
-  */
-  wsdPrng.i++;
-  t = wsdPrng.s[wsdPrng.i];
-  wsdPrng.j += t;
-  wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
-  wsdPrng.s[wsdPrng.j] = t;
-  t += wsdPrng.s[wsdPrng.i];
-  return wsdPrng.s[t];
-}
-
-/*
-** Return N random bytes.
-*/
-SQLITE_API void sqlite3_randomness(int N, void *pBuf){
-  unsigned char *zBuf = pBuf;
-#if SQLITE_THREADSAFE
-  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
-#endif
-  sqlite3_mutex_enter(mutex);
-  while( N-- ){
-    *(zBuf++) = randomByte();
-  }
+  assert( N>0 );
+  do{
+    wsdPrng.i++;
+    t = wsdPrng.s[wsdPrng.i];
+    wsdPrng.j += t;
+    wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
+    wsdPrng.s[wsdPrng.j] = t;
+    t += wsdPrng.s[wsdPrng.i];
+    *(zBuf++) = wsdPrng.s[t];
+  }while( --N );
   sqlite3_mutex_leave(mutex);
 }
 
@@ -20664,9 +21702,6 @@ SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
     sizeof(sqlite3Prng)
   );
 }
-SQLITE_PRIVATE void sqlite3PrngResetState(void){
-  GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
-}
 #endif /* SQLITE_OMIT_BUILTIN_TEST */
 
 /************** End of random.c **********************************************/
@@ -20819,8 +21854,8 @@ static const unsigned char sqlite3Utf8Trans1[] = {
 **     and rendered as themselves even though they are technically
 **     invalid characters.
 **
-**  *  This routine accepts an infinite number of different UTF8 encodings
-**     for unicode values 0x80 and greater.  It do not change over-length
+**  *  This routine accepts over-length UTF8 encodings
+**     for unicode values 0x80 and greater.  It does not change over-length
 **     encodings to 0xfffd as some systems recommend.
 */
 #define READ_UTF8(zIn, zTerm, c)                           \
@@ -20988,7 +22023,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
   sqlite3VdbeMemRelease(pMem);
   pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
   pMem->enc = desiredEnc;
-  pMem->flags |= (MEM_Term|MEM_Dyn);
+  pMem->flags |= (MEM_Term);
   pMem->z = (char*)zOut;
   pMem->zMalloc = pMem->z;
 
@@ -21116,38 +22151,11 @@ SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 e
   }
   assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
   assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
-  assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
   assert( m.z || db->mallocFailed );
   return m.z;
 }
 
 /*
-** Convert a UTF-8 string to the UTF-16 encoding specified by parameter
-** enc. A pointer to the new string is returned, and the value of *pnOut
-** is set to the length of the returned string in bytes. The call should
-** arrange to call sqlite3DbFree() on the returned pointer when it is
-** no longer required.
-** 
-** If a malloc failure occurs, NULL is returned and the db.mallocFailed
-** flag set.
-*/
-#ifdef SQLITE_ENABLE_STAT3
-SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
-  Mem m;
-  memset(&m, 0, sizeof(m));
-  m.db = db;
-  sqlite3VdbeMemSetStr(&m, z, n, SQLITE_UTF8, SQLITE_STATIC);
-  if( sqlite3VdbeMemTranslate(&m, enc) ){
-    assert( db->mallocFailed );
-    return 0;
-  }
-  assert( m.z==m.zMalloc );
-  *pnOut = m.n;
-  return m.z;
-}
-#endif
-
-/*
 ** zIn is a UTF-16 encoded unicode string at least nChar characters long.
 ** Return the number of bytes in the first nChar unicode characters
 ** in pZ.  nChar must be non-negative.
@@ -21260,6 +22268,24 @@ SQLITE_PRIVATE void sqlite3Coverage(int x){
 }
 #endif
 
+/*
+** Give a callback to the test harness that can be used to simulate faults
+** in places where it is difficult or expensive to do so purely by means
+** of inputs.
+**
+** The intent of the integer argument is to let the fault simulator know
+** which of multiple sqlite3FaultSim() calls has been hit.
+**
+** Return whatever integer value the test callback returns, or return
+** SQLITE_OK if no test callback is installed.
+*/
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+SQLITE_PRIVATE int sqlite3FaultSim(int iTest){
+  int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback;
+  return xCallback ? xCallback(iTest) : SQLITE_OK;
+}
+#endif
+
 #ifndef SQLITE_OMIT_FLOATING_POINT
 /*
 ** Return true if the floating point value is Not a Number (NaN).
@@ -21344,18 +22370,17 @@ SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
 ** to NULL.
 */
 SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
-  if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
-    db->errCode = err_code;
-    if( zFormat ){
-      char *z;
-      va_list ap;
-      va_start(ap, zFormat);
-      z = sqlite3VMPrintf(db, zFormat, ap);
-      va_end(ap);
-      sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
-    }else{
-      sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
-    }
+  assert( db!=0 );
+  db->errCode = err_code;
+  if( zFormat && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
+    char *z;
+    va_list ap;
+    va_start(ap, zFormat);
+    z = sqlite3VMPrintf(db, zFormat, ap);
+    va_end(ap);
+    sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
+  }else if( db->pErr ){
+    sqlite3ValueSetNull(db->pErr);
   }
 }
 
@@ -21422,7 +22447,8 @@ SQLITE_PRIVATE int sqlite3Dequote(char *z){
     case '[':   quote = ']';  break;  /* For MS SqlServer compatibility */
     default:    return -1;
   }
-  for(i=1, j=0; ALWAYS(z[i]); i++){
+  for(i=1, j=0;; i++){
+    assert( z[i] );
     if( z[i]==quote ){
       if( z[i+1]==quote ){
         z[j++] = quote;
@@ -21686,19 +22712,19 @@ static int compare2pow63(const char *zNum, int incr){
   return c;
 }
 
-
 /*
-** Convert zNum to a 64-bit signed integer.
+** Convert zNum to a 64-bit signed integer.  zNum must be decimal. This
+** routine does *not* accept hexadecimal notation.
 **
 ** If the zNum value is representable as a 64-bit twos-complement 
 ** integer, then write that value into *pNum and return 0.
 **
-** If zNum is exactly 9223372036854665808, return 2.  This special
-** case is broken out because while 9223372036854665808 cannot be a 
-** signed 64-bit integer, its negative -9223372036854665808 can be.
+** If zNum is exactly 9223372036854775808, return 2.  This special
+** case is broken out because while 9223372036854775808 cannot be a 
+** signed 64-bit integer, its negative -9223372036854775808 can be.
 **
 ** If zNum is too big for a 64-bit integer and is not
-** 9223372036854665808  or if zNum contains any non-numeric text,
+** 9223372036854775808  or if zNum contains any non-numeric text,
 ** then return 1.
 **
 ** length is the number of bytes in the string (bytes, not characters).
@@ -21740,7 +22766,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
     u = u*10 + c - '0';
   }
   if( u>LARGEST_INT64 ){
-    *pNum = SMALLEST_INT64;
+    *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
   }else if( neg ){
     *pNum = -(i64)u;
   }else{
@@ -21771,16 +22797,49 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
       /* zNum is exactly 9223372036854775808.  Fits if negative.  The
       ** special case 2 overflow if positive */
       assert( u-1==LARGEST_INT64 );
-      assert( (*pNum)==SMALLEST_INT64 );
       return neg ? 0 : 2;
     }
   }
 }
 
 /*
+** Transform a UTF-8 integer literal, in either decimal or hexadecimal,
+** into a 64-bit signed integer.  This routine accepts hexadecimal literals,
+** whereas sqlite3Atoi64() does not.
+**
+** Returns:
+**
+**     0    Successful transformation.  Fits in a 64-bit signed integer.
+**     1    Integer too large for a 64-bit signed integer or is malformed
+**     2    Special case of 9223372036854775808
+*/
+SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
+#ifndef SQLITE_OMIT_HEX_INTEGER
+  if( z[0]=='0'
+   && (z[1]=='x' || z[1]=='X')
+   && sqlite3Isxdigit(z[2])
+  ){
+    u64 u = 0;
+    int i, k;
+    for(i=2; z[i]=='0'; i++){}
+    for(k=i; sqlite3Isxdigit(z[k]); k++){
+      u = u*16 + sqlite3HexToInt(z[k]);
+    }
+    memcpy(pOut, &u, 8);
+    return (z[k]==0 && k-i<=16) ? 0 : 1;
+  }else
+#endif /* SQLITE_OMIT_HEX_INTEGER */
+  {
+    return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8);
+  }
+}
+
+/*
 ** If zNum represents an integer that will fit in 32-bits, then set
 ** *pValue to that integer and return true.  Otherwise return false.
 **
+** This routine accepts both decimal and hexadecimal notation for integers.
+**
 ** Any non-numeric characters that following zNum are ignored.
 ** This is different from sqlite3Atoi64() which requires the
 ** input number to be zero-terminated.
@@ -21795,7 +22854,25 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
   }else if( zNum[0]=='+' ){
     zNum++;
   }
-  while( zNum[0]=='0' ) zNum++;
+#ifndef SQLITE_OMIT_HEX_INTEGER
+  else if( zNum[0]=='0'
+        && (zNum[1]=='x' || zNum[1]=='X')
+        && sqlite3Isxdigit(zNum[2])
+  ){
+    u32 u = 0;
+    zNum += 2;
+    while( zNum[0]=='0' ) zNum++;
+    for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){
+      u = u*16 + sqlite3HexToInt(zNum[i]);
+    }
+    if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){
+      memcpy(pValue, &u, 4);
+      return 1;
+    }else{
+      return 0;
+    }
+  }
+#endif
   for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
     v = v*10 + c;
   }
@@ -22231,7 +23308,8 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v){
 ** Read or write a four-byte big-endian integer value.
 */
 SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
-  return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
+  testcase( p[0]&0x80 );
+  return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
 }
 SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
   p[0] = (u8)(v>>24);
@@ -22352,13 +23430,12 @@ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
     testcase( iA>0 && LARGEST_INT64 - iA == iB );
     testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
     if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
-    *pA += iB;
   }else{
     testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
     testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
     if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
-    *pA += iB;
   }
+  *pA += iB;
   return 0; 
 }
 SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
@@ -22382,9 +23459,18 @@ SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
   iA0 = iA % TWOPOWER32;
   iB1 = iB/TWOPOWER32;
   iB0 = iB % TWOPOWER32;
-  if( iA1*iB1 != 0 ) return 1;
-  assert( iA1*iB0==0 || iA0*iB1==0 );
-  r = iA1*iB0 + iA0*iB1;
+  if( iA1==0 ){
+    if( iB1==0 ){
+      *pA *= iB;
+      return 0;
+    }
+    r = iA0*iB1;
+  }else if( iB1==0 ){
+    r = iA1*iB0;
+  }else{
+    /* If both iA1 and iB1 are non-zero, overflow will result */
+    return 1;
+  }
   testcase( r==(-TWOPOWER31)-1 );
   testcase( r==(-TWOPOWER31) );
   testcase( r==TWOPOWER31 );
@@ -22437,6 +23523,85 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
 }
 #endif
 
+/* 
+** Find (an approximate) sum of two LogEst values.  This computation is
+** not a simple "+" operator because LogEst is stored as a logarithmic
+** value.
+** 
+*/
+SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
+  static const unsigned char x[] = {
+     10, 10,                         /* 0,1 */
+      9, 9,                          /* 2,3 */
+      8, 8,                          /* 4,5 */
+      7, 7, 7,                       /* 6,7,8 */
+      6, 6, 6,                       /* 9,10,11 */
+      5, 5, 5,                       /* 12-14 */
+      4, 4, 4, 4,                    /* 15-18 */
+      3, 3, 3, 3, 3, 3,              /* 19-24 */
+      2, 2, 2, 2, 2, 2, 2,           /* 25-31 */
+  };
+  if( a>=b ){
+    if( a>b+49 ) return a;
+    if( a>b+31 ) return a+1;
+    return a+x[a-b];
+  }else{
+    if( b>a+49 ) return b;
+    if( b>a+31 ) return b+1;
+    return b+x[b-a];
+  }
+}
+
+/*
+** Convert an integer into a LogEst.  In other words, compute an
+** approximation for 10*log2(x).
+*/
+SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){
+  static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
+  LogEst y = 40;
+  if( x<8 ){
+    if( x<2 ) return 0;
+    while( x<8 ){  y -= 10; x <<= 1; }
+  }else{
+    while( x>255 ){ y += 40; x >>= 4; }
+    while( x>15 ){  y += 10; x >>= 1; }
+  }
+  return a[x&7] + y - 10;
+}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Convert a double into a LogEst
+** In other words, compute an approximation for 10*log2(x).
+*/
+SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){
+  u64 a;
+  LogEst e;
+  assert( sizeof(x)==8 && sizeof(a)==8 );
+  if( x<=1 ) return 0;
+  if( x<=2000000000 ) return sqlite3LogEst((u64)x);
+  memcpy(&a, &x, 8);
+  e = (a>>52) - 1022;
+  return e*10;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/*
+** Convert a LogEst into an integer.
+*/
+SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
+  u64 n;
+  if( x<10 ) return 1;
+  n = x%10;
+  x /= 10;
+  if( n>=5 ) n -= 2;
+  else if( n>=1 ) n -= 1;
+  if( x>=3 ){
+    return x>60 ? (u64)LARGEST_INT64 : (n+8)<<(x-3);
+  }
+  return (n+8)>>(3-x);
+}
+
 /************** End of util.c ************************************************/
 /************** Begin file hash.c ********************************************/
 /*
@@ -22493,7 +23658,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
 ** The hashing function.
 */
 static unsigned int strHash(const char *z, int nKey){
-  int h = 0;
+  unsigned int h = 0;
   assert( nKey>=0 );
   while( nKey > 0  ){
     h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
@@ -22724,159 +23889,172 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, voi
 /************** Begin file opcodes.c *****************************************/
 /* Automatically generated.  Do not edit */
 /* See the mkopcodec.awk script for details. */
-#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+#if !defined(SQLITE_OMIT_EXPLAIN) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) || defined(SQLITE_DEBUG)
+# define OpHelp(X) "\0" X
+#else
+# define OpHelp(X)
+#endif
 SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
  static const char *const azName[] = { "?",
-     /*   1 */ "Goto",
-     /*   2 */ "Gosub",
-     /*   3 */ "Return",
-     /*   4 */ "Yield",
-     /*   5 */ "HaltIfNull",
-     /*   6 */ "Halt",
-     /*   7 */ "Integer",
-     /*   8 */ "Int64",
-     /*   9 */ "String",
-     /*  10 */ "Null",
-     /*  11 */ "Blob",
-     /*  12 */ "Variable",
-     /*  13 */ "Move",
-     /*  14 */ "Copy",
-     /*  15 */ "SCopy",
-     /*  16 */ "ResultRow",
-     /*  17 */ "CollSeq",
-     /*  18 */ "Function",
-     /*  19 */ "Not",
-     /*  20 */ "AddImm",
-     /*  21 */ "MustBeInt",
-     /*  22 */ "RealAffinity",
-     /*  23 */ "Permutation",
-     /*  24 */ "Compare",
-     /*  25 */ "Jump",
-     /*  26 */ "Once",
-     /*  27 */ "If",
-     /*  28 */ "IfNot",
-     /*  29 */ "Column",
-     /*  30 */ "Affinity",
-     /*  31 */ "MakeRecord",
-     /*  32 */ "Count",
-     /*  33 */ "Savepoint",
-     /*  34 */ "AutoCommit",
-     /*  35 */ "Transaction",
-     /*  36 */ "ReadCookie",
-     /*  37 */ "SetCookie",
-     /*  38 */ "VerifyCookie",
-     /*  39 */ "OpenRead",
-     /*  40 */ "OpenWrite",
-     /*  41 */ "OpenAutoindex",
-     /*  42 */ "OpenEphemeral",
-     /*  43 */ "SorterOpen",
-     /*  44 */ "OpenPseudo",
-     /*  45 */ "Close",
-     /*  46 */ "SeekLt",
-     /*  47 */ "SeekLe",
-     /*  48 */ "SeekGe",
-     /*  49 */ "SeekGt",
-     /*  50 */ "Seek",
-     /*  51 */ "NotFound",
-     /*  52 */ "Found",
-     /*  53 */ "IsUnique",
-     /*  54 */ "NotExists",
-     /*  55 */ "Sequence",
-     /*  56 */ "NewRowid",
-     /*  57 */ "Insert",
-     /*  58 */ "InsertInt",
-     /*  59 */ "Delete",
-     /*  60 */ "ResetCount",
-     /*  61 */ "SorterCompare",
-     /*  62 */ "SorterData",
-     /*  63 */ "RowKey",
-     /*  64 */ "RowData",
-     /*  65 */ "Rowid",
-     /*  66 */ "NullRow",
-     /*  67 */ "Last",
-     /*  68 */ "Or",
-     /*  69 */ "And",
-     /*  70 */ "SorterSort",
-     /*  71 */ "Sort",
-     /*  72 */ "Rewind",
-     /*  73 */ "IsNull",
-     /*  74 */ "NotNull",
-     /*  75 */ "Ne",
-     /*  76 */ "Eq",
-     /*  77 */ "Gt",
-     /*  78 */ "Le",
-     /*  79 */ "Lt",
-     /*  80 */ "Ge",
-     /*  81 */ "SorterNext",
-     /*  82 */ "BitAnd",
-     /*  83 */ "BitOr",
-     /*  84 */ "ShiftLeft",
-     /*  85 */ "ShiftRight",
-     /*  86 */ "Add",
-     /*  87 */ "Subtract",
-     /*  88 */ "Multiply",
-     /*  89 */ "Divide",
-     /*  90 */ "Remainder",
-     /*  91 */ "Concat",
-     /*  92 */ "Prev",
-     /*  93 */ "BitNot",
-     /*  94 */ "String8",
-     /*  95 */ "Next",
-     /*  96 */ "SorterInsert",
-     /*  97 */ "IdxInsert",
-     /*  98 */ "IdxDelete",
-     /*  99 */ "IdxRowid",
-     /* 100 */ "IdxLT",
-     /* 101 */ "IdxGE",
-     /* 102 */ "Destroy",
-     /* 103 */ "Clear",
-     /* 104 */ "CreateIndex",
-     /* 105 */ "CreateTable",
-     /* 106 */ "ParseSchema",
-     /* 107 */ "LoadAnalysis",
-     /* 108 */ "DropTable",
-     /* 109 */ "DropIndex",
-     /* 110 */ "DropTrigger",
-     /* 111 */ "IntegrityCk",
-     /* 112 */ "RowSetAdd",
-     /* 113 */ "RowSetRead",
-     /* 114 */ "RowSetTest",
-     /* 115 */ "Program",
-     /* 116 */ "Param",
-     /* 117 */ "FkCounter",
-     /* 118 */ "FkIfZero",
-     /* 119 */ "MemMax",
-     /* 120 */ "IfPos",
-     /* 121 */ "IfNeg",
-     /* 122 */ "IfZero",
-     /* 123 */ "AggStep",
-     /* 124 */ "AggFinal",
-     /* 125 */ "Checkpoint",
-     /* 126 */ "JournalMode",
-     /* 127 */ "Vacuum",
-     /* 128 */ "IncrVacuum",
-     /* 129 */ "Expire",
-     /* 130 */ "Real",
-     /* 131 */ "TableLock",
-     /* 132 */ "VBegin",
-     /* 133 */ "VCreate",
-     /* 134 */ "VDestroy",
-     /* 135 */ "VOpen",
-     /* 136 */ "VFilter",
-     /* 137 */ "VColumn",
-     /* 138 */ "VNext",
-     /* 139 */ "VRename",
-     /* 140 */ "VUpdate",
-     /* 141 */ "ToText",
-     /* 142 */ "ToBlob",
-     /* 143 */ "ToNumeric",
-     /* 144 */ "ToInt",
-     /* 145 */ "ToReal",
-     /* 146 */ "Pagecount",
-     /* 147 */ "MaxPgcnt",
-     /* 148 */ "Trace",
-     /* 149 */ "Noop",
-     /* 150 */ "Explain",
+     /*   1 */ "Function"         OpHelp("r[P3]=func(r[P2 at P5])"),
+     /*   2 */ "Savepoint"        OpHelp(""),
+     /*   3 */ "AutoCommit"       OpHelp(""),
+     /*   4 */ "Transaction"      OpHelp(""),
+     /*   5 */ "SorterNext"       OpHelp(""),
+     /*   6 */ "PrevIfOpen"       OpHelp(""),
+     /*   7 */ "NextIfOpen"       OpHelp(""),
+     /*   8 */ "Prev"             OpHelp(""),
+     /*   9 */ "Next"             OpHelp(""),
+     /*  10 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2 at P5])"),
+     /*  11 */ "Checkpoint"       OpHelp(""),
+     /*  12 */ "JournalMode"      OpHelp(""),
+     /*  13 */ "Vacuum"           OpHelp(""),
+     /*  14 */ "VFilter"          OpHelp("iplan=r[P3] zplan='P4'"),
+     /*  15 */ "VUpdate"          OpHelp("data=r[P3 at P2]"),
+     /*  16 */ "Goto"             OpHelp(""),
+     /*  17 */ "Gosub"            OpHelp(""),
+     /*  18 */ "Return"           OpHelp(""),
+     /*  19 */ "Not"              OpHelp("r[P2]= !r[P1]"),
+     /*  20 */ "InitCoroutine"    OpHelp(""),
+     /*  21 */ "EndCoroutine"     OpHelp(""),
+     /*  22 */ "Yield"            OpHelp(""),
+     /*  23 */ "HaltIfNull"       OpHelp("if r[P3]=null halt"),
+     /*  24 */ "Halt"             OpHelp(""),
+     /*  25 */ "Integer"          OpHelp("r[P2]=P1"),
+     /*  26 */ "Int64"            OpHelp("r[P2]=P4"),
+     /*  27 */ "String"           OpHelp("r[P2]='P4' (len=P1)"),
+     /*  28 */ "Null"             OpHelp("r[P2..P3]=NULL"),
+     /*  29 */ "SoftNull"         OpHelp("r[P1]=NULL"),
+     /*  30 */ "Blob"             OpHelp("r[P2]=P4 (len=P1)"),
+     /*  31 */ "Variable"         OpHelp("r[P2]=parameter(P1,P4)"),
+     /*  32 */ "Move"             OpHelp("r[P2 at P3]=r[P1 at P3]"),
+     /*  33 */ "Copy"             OpHelp("r[P2 at P3+1]=r[P1 at P3+1]"),
+     /*  34 */ "SCopy"            OpHelp("r[P2]=r[P1]"),
+     /*  35 */ "ResultRow"        OpHelp("output=r[P1 at P2]"),
+     /*  36 */ "CollSeq"          OpHelp(""),
+     /*  37 */ "AddImm"           OpHelp("r[P1]=r[P1]+P2"),
+     /*  38 */ "MustBeInt"        OpHelp(""),
+     /*  39 */ "RealAffinity"     OpHelp(""),
+     /*  40 */ "Permutation"      OpHelp(""),
+     /*  41 */ "Compare"          OpHelp("r[P1 at P3] <-> r[P2 at P3]"),
+     /*  42 */ "Jump"             OpHelp(""),
+     /*  43 */ "Once"             OpHelp(""),
+     /*  44 */ "If"               OpHelp(""),
+     /*  45 */ "IfNot"            OpHelp(""),
+     /*  46 */ "Column"           OpHelp("r[P3]=PX"),
+     /*  47 */ "Affinity"         OpHelp("affinity(r[P1 at P2])"),
+     /*  48 */ "MakeRecord"       OpHelp("r[P3]=mkrec(r[P1 at P2])"),
+     /*  49 */ "Count"            OpHelp("r[P2]=count()"),
+     /*  50 */ "ReadCookie"       OpHelp(""),
+     /*  51 */ "SetCookie"        OpHelp(""),
+     /*  52 */ "ReopenIdx"        OpHelp("root=P2 iDb=P3"),
+     /*  53 */ "OpenRead"         OpHelp("root=P2 iDb=P3"),
+     /*  54 */ "OpenWrite"        OpHelp("root=P2 iDb=P3"),
+     /*  55 */ "OpenAutoindex"    OpHelp("nColumn=P2"),
+     /*  56 */ "OpenEphemeral"    OpHelp("nColumn=P2"),
+     /*  57 */ "SorterOpen"       OpHelp(""),
+     /*  58 */ "OpenPseudo"       OpHelp("P3 columns in r[P2]"),
+     /*  59 */ "Close"            OpHelp(""),
+     /*  60 */ "SeekLT"           OpHelp("key=r[P3 at P4]"),
+     /*  61 */ "SeekLE"           OpHelp("key=r[P3 at P4]"),
+     /*  62 */ "SeekGE"           OpHelp("key=r[P3 at P4]"),
+     /*  63 */ "SeekGT"           OpHelp("key=r[P3 at P4]"),
+     /*  64 */ "Seek"             OpHelp("intkey=r[P2]"),
+     /*  65 */ "NoConflict"       OpHelp("key=r[P3 at P4]"),
+     /*  66 */ "NotFound"         OpHelp("key=r[P3 at P4]"),
+     /*  67 */ "Found"            OpHelp("key=r[P3 at P4]"),
+     /*  68 */ "NotExists"        OpHelp("intkey=r[P3]"),
+     /*  69 */ "Sequence"         OpHelp("r[P2]=cursor[P1].ctr++"),
+     /*  70 */ "NewRowid"         OpHelp("r[P2]=rowid"),
+     /*  71 */ "Or"               OpHelp("r[P3]=(r[P1] || r[P2])"),
+     /*  72 */ "And"              OpHelp("r[P3]=(r[P1] && r[P2])"),
+     /*  73 */ "Insert"           OpHelp("intkey=r[P3] data=r[P2]"),
+     /*  74 */ "InsertInt"        OpHelp("intkey=P3 data=r[P2]"),
+     /*  75 */ "Delete"           OpHelp(""),
+     /*  76 */ "IsNull"           OpHelp("if r[P1]==NULL goto P2"),
+     /*  77 */ "NotNull"          OpHelp("if r[P1]!=NULL goto P2"),
+     /*  78 */ "Ne"               OpHelp("if r[P1]!=r[P3] goto P2"),
+     /*  79 */ "Eq"               OpHelp("if r[P1]==r[P3] goto P2"),
+     /*  80 */ "Gt"               OpHelp("if r[P1]>r[P3] goto P2"),
+     /*  81 */ "Le"               OpHelp("if r[P1]<=r[P3] goto P2"),
+     /*  82 */ "Lt"               OpHelp("if r[P1]<r[P3] goto P2"),
+     /*  83 */ "Ge"               OpHelp("if r[P1]>=r[P3] goto P2"),
+     /*  84 */ "ResetCount"       OpHelp(""),
+     /*  85 */ "BitAnd"           OpHelp("r[P3]=r[P1]&r[P2]"),
+     /*  86 */ "BitOr"            OpHelp("r[P3]=r[P1]|r[P2]"),
+     /*  87 */ "ShiftLeft"        OpHelp("r[P3]=r[P2]<<r[P1]"),
+     /*  88 */ "ShiftRight"       OpHelp("r[P3]=r[P2]>>r[P1]"),
+     /*  89 */ "Add"              OpHelp("r[P3]=r[P1]+r[P2]"),
+     /*  90 */ "Subtract"         OpHelp("r[P3]=r[P2]-r[P1]"),
+     /*  91 */ "Multiply"         OpHelp("r[P3]=r[P1]*r[P2]"),
+     /*  92 */ "Divide"           OpHelp("r[P3]=r[P2]/r[P1]"),
+     /*  93 */ "Remainder"        OpHelp("r[P3]=r[P2]%r[P1]"),
+     /*  94 */ "Concat"           OpHelp("r[P3]=r[P2]+r[P1]"),
+     /*  95 */ "SorterCompare"    OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+     /*  96 */ "BitNot"           OpHelp("r[P1]= ~r[P1]"),
+     /*  97 */ "String8"          OpHelp("r[P2]='P4'"),
+     /*  98 */ "SorterData"       OpHelp("r[P2]=data"),
+     /*  99 */ "RowKey"           OpHelp("r[P2]=key"),
+     /* 100 */ "RowData"          OpHelp("r[P2]=data"),
+     /* 101 */ "Rowid"            OpHelp("r[P2]=rowid"),
+     /* 102 */ "NullRow"          OpHelp(""),
+     /* 103 */ "Last"             OpHelp(""),
+     /* 104 */ "SorterSort"       OpHelp(""),
+     /* 105 */ "Sort"             OpHelp(""),
+     /* 106 */ "Rewind"           OpHelp(""),
+     /* 107 */ "SorterInsert"     OpHelp(""),
+     /* 108 */ "IdxInsert"        OpHelp("key=r[P2]"),
+     /* 109 */ "IdxDelete"        OpHelp("key=r[P2 at P3]"),
+     /* 110 */ "IdxRowid"         OpHelp("r[P2]=rowid"),
+     /* 111 */ "IdxLE"            OpHelp("key=r[P3 at P4]"),
+     /* 112 */ "IdxGT"            OpHelp("key=r[P3 at P4]"),
+     /* 113 */ "IdxLT"            OpHelp("key=r[P3 at P4]"),
+     /* 114 */ "IdxGE"            OpHelp("key=r[P3 at P4]"),
+     /* 115 */ "Destroy"          OpHelp(""),
+     /* 116 */ "Clear"            OpHelp(""),
+     /* 117 */ "ResetSorter"      OpHelp(""),
+     /* 118 */ "CreateIndex"      OpHelp("r[P2]=root iDb=P1"),
+     /* 119 */ "CreateTable"      OpHelp("r[P2]=root iDb=P1"),
+     /* 120 */ "ParseSchema"      OpHelp(""),
+     /* 121 */ "LoadAnalysis"     OpHelp(""),
+     /* 122 */ "DropTable"        OpHelp(""),
+     /* 123 */ "DropIndex"        OpHelp(""),
+     /* 124 */ "DropTrigger"      OpHelp(""),
+     /* 125 */ "IntegrityCk"      OpHelp(""),
+     /* 126 */ "RowSetAdd"        OpHelp("rowset(P1)=r[P2]"),
+     /* 127 */ "RowSetRead"       OpHelp("r[P3]=rowset(P1)"),
+     /* 128 */ "RowSetTest"       OpHelp("if r[P3] in rowset(P1) goto P2"),
+     /* 129 */ "Program"          OpHelp(""),
+     /* 130 */ "Param"            OpHelp(""),
+     /* 131 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),
+     /* 132 */ "FkIfZero"         OpHelp("if fkctr[P1]==0 goto P2"),
+     /* 133 */ "Real"             OpHelp("r[P2]=P4"),
+     /* 134 */ "MemMax"           OpHelp("r[P1]=max(r[P1],r[P2])"),
+     /* 135 */ "IfPos"            OpHelp("if r[P1]>0 goto P2"),
+     /* 136 */ "IfNeg"            OpHelp("r[P1]+=P3, if r[P1]<0 goto P2"),
+     /* 137 */ "IfZero"           OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
+     /* 138 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),
+     /* 139 */ "IncrVacuum"       OpHelp(""),
+     /* 140 */ "Expire"           OpHelp(""),
+     /* 141 */ "TableLock"        OpHelp("iDb=P1 root=P2 write=P3"),
+     /* 142 */ "VBegin"           OpHelp(""),
+     /* 143 */ "ToText"           OpHelp(""),
+     /* 144 */ "ToBlob"           OpHelp(""),
+     /* 145 */ "ToNumeric"        OpHelp(""),
+     /* 146 */ "ToInt"            OpHelp(""),
+     /* 147 */ "ToReal"           OpHelp(""),
+     /* 148 */ "VCreate"          OpHelp(""),
+     /* 149 */ "VDestroy"         OpHelp(""),
+     /* 150 */ "VOpen"            OpHelp(""),
+     /* 151 */ "VColumn"          OpHelp("r[P3]=vcolumn(P2)"),
+     /* 152 */ "VNext"            OpHelp(""),
+     /* 153 */ "VRename"          OpHelp(""),
+     /* 154 */ "Pagecount"        OpHelp(""),
+     /* 155 */ "MaxPgcnt"         OpHelp(""),
+     /* 156 */ "Init"             OpHelp("Start at P2"),
+     /* 157 */ "Noop"             OpHelp(""),
+     /* 158 */ "Explain"          OpHelp(""),
   };
   return azName[i];
 }
@@ -22931,13 +24109,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
 */
 #if SQLITE_OS_UNIX              /* This file is used on unix only */
 
-/* Use posix_fallocate() if it is available
-*/
-#if !defined(HAVE_POSIX_FALLOCATE) \
-      && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
-# define HAVE_POSIX_FALLOCATE 1
-#endif
-
 /*
 ** There are various methods for file locking used for concurrency
 ** control:
@@ -22976,32 +24147,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
 #endif
 
 /*
-** These #defines should enable >2GB file support on Posix if the
-** underlying operating system supports it.  If the OS lacks
-** large file support, these should be no-ops.
-**
-** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
-** on the compiler command line.  This is necessary if you are compiling
-** on a recent machine (ex: RedHat 7.2) but you want your code to work
-** on an older machine (ex: RedHat 6.0).  If you compile on RedHat 7.2
-** without this option, LFS is enable.  But LFS does not exist in the kernel
-** in RedHat 6.0, so the code won't work.  Hence, for maximum binary
-** portability you should omit LFS.
-**
-** The previous paragraph was written in 2005.  (This paragraph is written
-** on 2008-11-28.) These days, all Linux kernels support large files, so
-** you should probably leave LFS enabled.  But some embedded platforms might
-** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
-*/
-#ifndef SQLITE_DISABLE_LFS
-# define _LARGE_FILE       1
-# ifndef _FILE_OFFSET_BITS
-#   define _FILE_OFFSET_BITS 64
-# endif
-# define _LARGEFILE_SOURCE 1
-#endif
-
-/*
 ** standard include files.
 */
 #include <sys/types.h>
@@ -23012,11 +24157,10 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
 #include <sys/time.h>
 #include <errno.h>
 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
-#include <sys/mman.h>
+# include <sys/mman.h>
 #endif
 
-
-#if SQLITE_ENABLE_LOCKING_STYLE
+#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
 # include <sys/ioctl.h>
 # if OS_VXWORKS
 #  include <semaphore.h>
@@ -23110,11 +24254,13 @@ struct unixFile {
   const char *zPath;                  /* Name of the file */
   unixShm *pShm;                      /* Shared memory segment information */
   int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
+#if SQLITE_MAX_MMAP_SIZE>0
   int nFetchOut;                      /* Number of outstanding xFetch refs */
   sqlite3_int64 mmapSize;             /* Usable size of mapping at pMapRegion */
   sqlite3_int64 mmapSizeActual;       /* Actual size of mapping at pMapRegion */
   sqlite3_int64 mmapSizeMax;          /* Configured FCNTL_MMAP_SIZE value */
   void *pMapRegion;                   /* Memory mapped region */
+#endif
 #ifdef __QNXNTO__
   int sectorSize;                     /* Device sector size */
   int deviceCharacteristics;          /* Precomputed device characteristics */
@@ -23150,6 +24296,12 @@ struct unixFile {
 #endif
 };
 
+/* This variable holds the process id (pid) from when the xRandomness()
+** method was called.  If xOpen() is called from a different process id,
+** indicating that a fork() has occurred, the PRNG will be reset.
+*/
+static int randomnessPid = 0;
+
 /*
 ** Allowed values for the unixFile.ctrlFlags bitmask:
 */
@@ -23436,11 +24588,16 @@ static int posixOpen(const char *zFile, int flags, int mode){
 ** we are not running as root.
 */
 static int posixFchown(int fd, uid_t uid, gid_t gid){
+#if OS_VXWORKS
+  return 0;
+#else
   return geteuid() ? 0 : fchown(fd,uid,gid);
+#endif
 }
 
 /* Forward reference */
 static int openDirectory(const char*, int*);
+static int unixGetpagesize(void);
 
 /*
 ** Many system calls are accessed through pointer-to-functions so that
@@ -23491,7 +24648,7 @@ static struct unix_syscall {
   { "read",         (sqlite3_syscall_ptr)read,       0  },
 #define osRead      ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
 
-#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
+#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
   { "pread",        (sqlite3_syscall_ptr)pread,      0  },
 #else
   { "pread",        (sqlite3_syscall_ptr)0,          0  },
@@ -23508,7 +24665,7 @@ static struct unix_syscall {
   { "write",        (sqlite3_syscall_ptr)write,      0  },
 #define osWrite     ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
 
-#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
+#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
   { "pwrite",       (sqlite3_syscall_ptr)pwrite,     0  },
 #else
   { "pwrite",       (sqlite3_syscall_ptr)0,          0  },
@@ -23549,6 +24706,7 @@ static struct unix_syscall {
   { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
 #define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
 
+#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
   { "mmap",       (sqlite3_syscall_ptr)mmap,     0 },
 #define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)
 
@@ -23561,6 +24719,10 @@ static struct unix_syscall {
   { "mremap",       (sqlite3_syscall_ptr)0,               0 },
 #endif
 #define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
+  { "getpagesize",  (sqlite3_syscall_ptr)unixGetpagesize, 0 },
+#define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent)
+
+#endif
 
 }; /* End of the overrideable system calls */
 
@@ -23648,6 +24810,15 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
 }
 
 /*
+** Do not accept any file descriptor less than this value, in order to avoid
+** opening database file using file descriptors that are commonly used for 
+** standard input, output, and error.
+*/
+#ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR
+# define SQLITE_MINIMUM_FILE_DESCRIPTOR 3
+#endif
+
+/*
 ** Invoke open().  Do so multiple times, until it either succeeds or
 ** fails for some reason other than EINTR.
 **
@@ -23667,13 +24838,23 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
 static int robust_open(const char *z, int f, mode_t m){
   int fd;
   mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
-  do{
+  while(1){
 #if defined(O_CLOEXEC)
     fd = osOpen(z,f|O_CLOEXEC,m2);
 #else
     fd = osOpen(z,f,m2);
 #endif
-  }while( fd<0 && errno==EINTR );
+    if( fd<0 ){
+      if( errno==EINTR ) continue;
+      break;
+    }
+    if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
+    osClose(fd);
+    sqlite3_log(SQLITE_WARNING, 
+                "attempt to open \"%s\" as file descriptor %d", z, fd);
+    fd = -1;
+    if( osOpen("/dev/null", f, m)<0 ) break;
+  }
   if( fd>=0 ){
     if( m!=0 ){
       struct stat statbuf;
@@ -23854,16 +25035,6 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
   case EPERM: 
     return SQLITE_PERM;
     
-  /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
-  ** this module never makes such a call. And the code in SQLite itself 
-  ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
-  ** this case is also commented out. If the system does set errno to EDEADLK,
-  ** the default SQLITE_IOERR_XXX code will be returned. */
-#if 0
-  case EDEADLK:
-    return SQLITE_IOERR_BLOCKED;
-#endif
-    
 #if EOPNOTSUPP!=ENOTSUP
   case EOPNOTSUPP: 
     /* something went terribly awry, unless during file system support 
@@ -24392,6 +25563,19 @@ static int findInodeInfo(
   return SQLITE_OK;
 }
 
+/*
+** Return TRUE if pFile has been renamed or unlinked since it was first opened.
+*/
+static int fileHasMoved(unixFile *pFile){
+#if OS_VXWORKS
+  return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId;
+#else
+  struct stat buf;
+  return pFile->pInode!=0 &&
+      (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
+#endif
+}
+
 
 /*
 ** Check a unixFile that is a database.  Verify the following:
@@ -24426,10 +25610,7 @@ static void verifyDbFile(unixFile *pFile){
     pFile->ctrlFlags |= UNIXFILE_WARNED;
     return;
   }
-  if( pFile->pInode!=0
-   && ((rc = osStat(pFile->zPath, &buf))!=0
-       || buf.st_ino!=pFile->pInode->fileId.ino)
-  ){
+  if( fileHasMoved(pFile) ){
     sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
     pFile->ctrlFlags |= UNIXFILE_WARNED;
     return;
@@ -24967,12 +26148,16 @@ end_unlock:
 ** the requested locking level, this routine is a no-op.
 */
 static int unixUnlock(sqlite3_file *id, int eFileLock){
+#if SQLITE_MAX_MMAP_SIZE>0
   assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
+#endif
   return posixUnlock(id, eFileLock, 0);
 }
 
+#if SQLITE_MAX_MMAP_SIZE>0
 static int unixMapfile(unixFile *pFd, i64 nByte);
 static void unixUnmapfile(unixFile *pFd);
+#endif
 
 /*
 ** This function performs the parts of the "close file" operation 
@@ -24986,7 +26171,9 @@ static void unixUnmapfile(unixFile *pFd);
 */
 static int closeUnixFile(sqlite3_file *id){
   unixFile *pFile = (unixFile*)id;
+#if SQLITE_MAX_MMAP_SIZE>0
   unixUnmapfile(pFile);
+#endif
   if( pFile->h>=0 ){
     robust_close(pFile, pFile->h, __LINE__);
     pFile->h = -1;
@@ -25000,6 +26187,13 @@ static int closeUnixFile(sqlite3_file *id){
     pFile->pId = 0;
   }
 #endif
+#ifdef SQLITE_UNLINK_AFTER_CLOSE
+  if( pFile->ctrlFlags & UNIXFILE_DELETE ){
+    osUnlink(pFile->zPath);
+    sqlite3_free(*(char**)&pFile->zPath);
+    pFile->zPath = 0;
+  }
+#endif
   OSTRACE(("CLOSE   %-3d\n", pFile->h));
   OpenCounter(-1);
   sqlite3_free(pFile->pUnused);
@@ -25522,7 +26716,6 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
   /* Otherwise see if some other process holds it. */
   if( !reserved ){
     sem_t *pSem = pFile->pInode->pSem;
-    struct stat statBuf;
 
     if( sem_trywait(pSem)==-1 ){
       int tErrno = errno;
@@ -25575,7 +26768,6 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
 */
 static int semLock(sqlite3_file *id, int eFileLock) {
   unixFile *pFile = (unixFile*)id;
-  int fd;
   sem_t *pSem = pFile->pInode->pSem;
   int rc = SQLITE_OK;
 
@@ -26191,6 +27383,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
 #endif
   TIMER_START;
   assert( cnt==(cnt&0x1ffff) );
+  assert( id->h>2 );
   cnt &= 0x1ffff;
   do{
 #if defined(USE_PREAD)
@@ -26305,6 +27498,7 @@ static int seekAndWriteFd(
   int rc = 0;                     /* Value returned by system call */
 
   assert( nBuf==(nBuf&0x1ffff) );
+  assert( fd>2 );
   nBuf &= 0x1ffff;
   TIMER_START;
 
@@ -26690,6 +27884,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
     }
 #endif
 
+#if SQLITE_MAX_MMAP_SIZE>0
     /* If the file was just truncated to a size smaller than the currently
     ** mapped region, reduce the effective mapping size as well. SQLite will
     ** use read() and write() to access data beyond this point from now on.  
@@ -26697,6 +27892,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
     if( nByte<pFile->mmapSize ){
       pFile->mmapSize = nByte;
     }
+#endif
 
     return SQLITE_OK;
   }
@@ -26786,6 +27982,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
     }
   }
 
+#if SQLITE_MAX_MMAP_SIZE>0
   if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
     int rc;
     if( pFile->szChunk<=0 ){
@@ -26798,6 +27995,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
     rc = unixMapfile(pFile, nByte);
     return rc;
   }
+#endif
 
   return SQLITE_OK;
 }
@@ -26866,18 +28064,28 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
       }
       return SQLITE_OK;
     }
+    case SQLITE_FCNTL_HAS_MOVED: {
+      *(int*)pArg = fileHasMoved(pFile);
+      return SQLITE_OK;
+    }
+#if SQLITE_MAX_MMAP_SIZE>0
     case SQLITE_FCNTL_MMAP_SIZE: {
       i64 newLimit = *(i64*)pArg;
+      int rc = SQLITE_OK;
       if( newLimit>sqlite3GlobalConfig.mxMmap ){
         newLimit = sqlite3GlobalConfig.mxMmap;
       }
       *(i64*)pArg = pFile->mmapSizeMax;
-      if( newLimit>=0 ){
+      if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
         pFile->mmapSizeMax = newLimit;
-        if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit;
+        if( pFile->mmapSize>0 ){
+          unixUnmapfile(pFile);
+          rc = unixMapfile(pFile, -1);
+        }
       }
-      return SQLITE_OK;
+      return rc;
     }
+#endif
 #ifdef SQLITE_DEBUG
     /* The pager calls this method to signal that it has done
     ** a rollback and that the database is therefore unchanged and
@@ -27022,8 +28230,25 @@ static int unixDeviceCharacteristics(sqlite3_file *id){
   return rc;
 }
 
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
+
+/*
+** Return the system page size.
+**
+** This function should not be called directly by other code in this file. 
+** Instead, it should be called via macro osGetpagesize().
+*/
+static int unixGetpagesize(void){
+#if defined(_BSD_SOURCE)
+  return getpagesize();
+#else
+  return (int)sysconf(_SC_PAGESIZE);
+#endif
+}
 
+#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
+
+#ifndef SQLITE_OMIT_WAL
 
 /*
 ** Object used to represent an shared memory buffer.  
@@ -27140,7 +28365,7 @@ static int unixShmSystemLock(
 #ifdef SQLITE_DEBUG
   { u16 mask;
   OSTRACE(("SHM-LOCK "));
-  mask = (1<<(ofst+n)) - (1<<ofst);
+  mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
   if( rc==SQLITE_OK ){
     if( lockType==F_UNLCK ){
       OSTRACE(("unlock %d ok", ofst));
@@ -27174,6 +28399,22 @@ static int unixShmSystemLock(
   return rc;        
 }
 
+/*
+** Return the minimum number of 32KB shm regions that should be mapped at
+** a time, assuming that each mapping must be an integer multiple of the
+** current system page-size.
+**
+** Usually, this is 1. The exception seems to be systems that are configured
+** to use 64KB pages - in this case each mapping must cover at least two
+** shm regions.
+*/
+static int unixShmRegionPerMap(void){
+  int shmsz = 32*1024;            /* SHM region size */
+  int pgsz = osGetpagesize();   /* System page size */
+  assert( ((pgsz-1)&pgsz)==0 );   /* Page size must be a power of 2 */
+  if( pgsz<shmsz ) return 1;
+  return pgsz/shmsz;
+}
 
 /*
 ** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
@@ -27185,10 +28426,11 @@ static void unixShmPurge(unixFile *pFd){
   unixShmNode *p = pFd->pInode->pShmNode;
   assert( unixMutexHeld() );
   if( p && p->nRef==0 ){
+    int nShmPerMap = unixShmRegionPerMap();
     int i;
     assert( p->pInode==pFd->pInode );
     sqlite3_mutex_free(p->mutex);
-    for(i=0; i<p->nRegion; i++){
+    for(i=0; i<p->nRegion; i+=nShmPerMap){
       if( p->h>=0 ){
         osMunmap(p->apRegion[i], p->szRegion);
       }else{
@@ -27395,6 +28637,8 @@ static int unixShmMap(
   unixShm *p;
   unixShmNode *pShmNode;
   int rc = SQLITE_OK;
+  int nShmPerMap = unixShmRegionPerMap();
+  int nReqRegion;
 
   /* If the shared-memory file has not yet been opened, open it now. */
   if( pDbFd->pShm==0 ){
@@ -27410,9 +28654,12 @@ static int unixShmMap(
   assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
   assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
 
-  if( pShmNode->nRegion<=iRegion ){
+  /* Minimum number of regions required to be mapped. */
+  nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
+
+  if( pShmNode->nRegion<nReqRegion ){
     char **apNew;                      /* New apRegion[] array */
-    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
+    int nByte = nReqRegion*szRegion;   /* Minimum required file size */
     struct stat sStat;                 /* Used by fstat() */
 
     pShmNode->szRegion = szRegion;
@@ -27461,17 +28708,19 @@ static int unixShmMap(
 
     /* Map the requested memory region into this processes address space. */
     apNew = (char **)sqlite3_realloc(
-        pShmNode->apRegion, (iRegion+1)*sizeof(char *)
+        pShmNode->apRegion, nReqRegion*sizeof(char *)
     );
     if( !apNew ){
       rc = SQLITE_IOERR_NOMEM;
       goto shmpage_out;
     }
     pShmNode->apRegion = apNew;
-    while(pShmNode->nRegion<=iRegion){
+    while( pShmNode->nRegion<nReqRegion ){
+      int nMap = szRegion*nShmPerMap;
+      int i;
       void *pMem;
       if( pShmNode->h>=0 ){
-        pMem = osMmap(0, szRegion,
+        pMem = osMmap(0, nMap,
             pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
             MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
         );
@@ -27487,8 +28736,11 @@ static int unixShmMap(
         }
         memset(pMem, 0, szRegion);
       }
-      pShmNode->apRegion[pShmNode->nRegion] = pMem;
-      pShmNode->nRegion++;
+
+      for(i=0; i<nShmPerMap; i++){
+        pShmNode->apRegion[pShmNode->nRegion+i] = &((char*)pMem)[szRegion*i];
+      }
+      pShmNode->nRegion += nShmPerMap;
     }
   }
 
@@ -27688,37 +28940,20 @@ static int unixShmUnmap(
 # define unixShmUnmap   0
 #endif /* #ifndef SQLITE_OMIT_WAL */
 
+#if SQLITE_MAX_MMAP_SIZE>0
 /*
 ** If it is currently memory mapped, unmap file pFd.
 */
 static void unixUnmapfile(unixFile *pFd){
   assert( pFd->nFetchOut==0 );
-#if SQLITE_MAX_MMAP_SIZE>0
   if( pFd->pMapRegion ){
     osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
     pFd->pMapRegion = 0;
     pFd->mmapSize = 0;
     pFd->mmapSizeActual = 0;
   }
-#endif
-}
-
-#if SQLITE_MAX_MMAP_SIZE>0
-/*
-** Return the system page size.
-*/
-static int unixGetPagesize(void){
-#if HAVE_MREMAP
-  return 512;
-#elif defined(_BSD_SOURCE)
-  return getpagesize();
-#else
-  return (int)sysconf(_SC_PAGESIZE);
-#endif
 }
-#endif /* SQLITE_MAX_MMAP_SIZE>0 */
 
-#if SQLITE_MAX_MMAP_SIZE>0
 /*
 ** Attempt to set the size of the memory mapping maintained by file 
 ** descriptor pFd to nNew bytes. Any existing mapping is discarded.
@@ -27755,8 +28990,12 @@ static void unixRemapfile(
   if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
 
   if( pOrig ){
-    const int szSyspage = unixGetPagesize();
+#if HAVE_MREMAP
+    i64 nReuse = pFd->mmapSize;
+#else
+    const int szSyspage = osGetpagesize();
     i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
+#endif
     u8 *pReq = &pOrig[nReuse];
 
     /* Unmap any pages of the existing mapping that cannot be reused. */
@@ -27803,7 +29042,6 @@ static void unixRemapfile(
   pFd->pMapRegion = (void *)pNew;
   pFd->mmapSize = pFd->mmapSizeActual = nNew;
 }
-#endif
 
 /*
 ** Memory map or remap the file opened by file-descriptor pFd (if the file
@@ -27822,7 +29060,6 @@ static void unixRemapfile(
 ** code otherwise.
 */
 static int unixMapfile(unixFile *pFd, i64 nByte){
-#if SQLITE_MAX_MMAP_SIZE>0
   i64 nMap = nByte;
   int rc;
 
@@ -27848,10 +29085,10 @@ static int unixMapfile(unixFile *pFd, i64 nByte){
       unixUnmapfile(pFd);
     }
   }
-#endif
 
   return SQLITE_OK;
 }
+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
 
 /*
 ** If possible, return a pointer to a mapping of file fd starting at offset
@@ -27897,6 +29134,7 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
 ** may now be invalid and should be unmapped.
 */
 static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
+#if SQLITE_MAX_MMAP_SIZE>0
   unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
   UNUSED_PARAMETER(iOff);
 
@@ -27915,6 +29153,11 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
   }
 
   assert( pFd->nFetchOut>=0 );
+#else
+  UNUSED_PARAMETER(fd);
+  UNUSED_PARAMETER(p);
+  UNUSED_PARAMETER(iOff);
+#endif
   return SQLITE_OK;
 }
 
@@ -28246,7 +29489,9 @@ static int fillInUnixFile(
   pNew->pVfs = pVfs;
   pNew->zPath = zFilename;
   pNew->ctrlFlags = (u8)ctrlFlags;
+#if SQLITE_MAX_MMAP_SIZE>0
   pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
+#endif
   if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
                            "psow", SQLITE_POWERSAFE_OVERWRITE) ){
     pNew->ctrlFlags |= UNIXFILE_PSOW;
@@ -28403,6 +29648,7 @@ static const char *unixTempFileDir(void){
   static const char *azDirs[] = {
      0,
      0,
+     0,
      "/var/tmp",
      "/usr/tmp",
      "/tmp",
@@ -28413,7 +29659,8 @@ static const char *unixTempFileDir(void){
   const char *zDir = 0;
 
   azDirs[0] = sqlite3_temp_directory;
-  if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
+  if( !azDirs[1] ) azDirs[1] = getenv("SQLITE_TMPDIR");
+  if( !azDirs[2] ) azDirs[2] = getenv("TMPDIR");
   for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
     if( zDir==0 ) continue;
     if( osStat(zDir, &buf) ) continue;
@@ -28700,6 +29947,16 @@ static int unixOpen(
        || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
   );
 
+  /* Detect a pid change and reset the PRNG.  There is a race condition
+  ** here such that two or more threads all trying to open databases at
+  ** the same instant might all reset the PRNG.  But multiple resets
+  ** are harmless.
+  */
+  if( randomnessPid!=getpid() ){
+    randomnessPid = getpid();
+    sqlite3_randomness(0,0);
+  }
+
   memset(p, 0, sizeof(unixFile));
 
   if( eType==SQLITE_OPEN_MAIN_DB ){
@@ -28791,6 +30048,12 @@ static int unixOpen(
   if( isDelete ){
 #if OS_VXWORKS
     zPath = zName;
+#elif defined(SQLITE_UNLINK_AFTER_CLOSE)
+    zPath = sqlite3_mprintf("%s", zName);
+    if( zPath==0 ){
+      robust_close(p, fd, __LINE__);
+      return SQLITE_NOMEM;
+    }
 #else
     osUnlink(zName);
 #endif
@@ -28891,7 +30154,11 @@ static int unixDelete(
   UNUSED_PARAMETER(NotUsed);
   SimulateIOError(return SQLITE_IOERR_DELETE);
   if( osUnlink(zPath)==(-1) ){
-    if( errno==ENOENT ){
+    if( errno==ENOENT
+#if OS_VXWORKS
+        || errno==0x380003
+#endif
+    ){
       rc = SQLITE_IOERR_DELETE_NOENT;
     }else{
       rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
@@ -29087,18 +30354,18 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
   ** tests repeatable.
   */
   memset(zBuf, 0, nBuf);
+  randomnessPid = getpid();  
 #if !defined(SQLITE_TEST)
   {
-    int pid, fd, got;
+    int fd, got;
     fd = robust_open("/dev/urandom", O_RDONLY, 0);
     if( fd<0 ){
       time_t t;
       time(&t);
       memcpy(zBuf, &t, sizeof(t));
-      pid = getpid();
-      memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
-      assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
-      nBuf = sizeof(t) + sizeof(pid);
+      memcpy(&zBuf[sizeof(t)], &randomnessPid, sizeof(randomnessPid));
+      assert( sizeof(t)+sizeof(randomnessPid)<=(size_t)nBuf );
+      nBuf = sizeof(t) + sizeof(randomnessPid);
     }else{
       do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
       robust_close(0, fd, __LINE__);
@@ -30484,7 +31751,7 @@ SQLITE_API int sqlite3_os_init(void){
 
   /* Double-check that the aSyscall[] array has been constructed
   ** correctly.  See ticket [bb3a86e890c8e96ab] */
-  assert( ArraySize(aSyscall)==24 );
+  assert( ArraySize(aSyscall)==25 );
 
   /* Register all VFSes defined in the aVfs[] array */
   for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
@@ -30524,10 +31791,6 @@ SQLITE_API int sqlite3_os_end(void){
 */
 #if SQLITE_OS_WIN               /* This file is used for Windows only */
 
-#ifdef __CYGWIN__
-# include <sys/cygwin.h>
-#endif
-
 /*
 ** Include code that is common to all os_*.c files
 */
@@ -30742,11 +32005,15 @@ SQLITE_API int sqlite3_open_file_count = 0;
 /************** Continuing where we left off in os_win.c *********************/
 
 /*
+** Include the header file for the Windows VFS.
+*/
+
+/*
 ** Compiling and using WAL mode requires several APIs that are only
 ** available in Windows platforms based on the NT kernel.
 */
 #if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
-# error "WAL mode requires support from the Windows NT kernel, compile\
+#  error "WAL mode requires support from the Windows NT kernel, compile\
  with SQLITE_OMIT_WAL."
 #endif
 
@@ -30754,7 +32021,7 @@ SQLITE_API int sqlite3_open_file_count = 0;
 ** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
 ** based on the sub-platform)?
 */
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI)
 #  define SQLITE_WIN32_HAS_ANSI
 #endif
 
@@ -30762,11 +32029,122 @@ SQLITE_API int sqlite3_open_file_count = 0;
 ** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
 ** based on the sub-platform)?
 */
-#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
+#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \
+    !defined(SQLITE_WIN32_NO_WIDE)
 #  define SQLITE_WIN32_HAS_WIDE
 #endif
 
 /*
+** Make sure at least one set of Win32 APIs is available.
+*/
+#if !defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_WIN32_HAS_WIDE)
+#  error "At least one of SQLITE_WIN32_HAS_ANSI and SQLITE_WIN32_HAS_WIDE\
+ must be defined."
+#endif
+
+/*
+** Define the required Windows SDK version constants if they are not
+** already available.
+*/
+#ifndef NTDDI_WIN8
+#  define NTDDI_WIN8                        0x06020000
+#endif
+
+#ifndef NTDDI_WINBLUE
+#  define NTDDI_WINBLUE                     0x06030000
+#endif
+
+/*
+** Check to see if the GetVersionEx[AW] functions are deprecated on the
+** target system.  GetVersionEx was first deprecated in Win8.1.
+*/
+#ifndef SQLITE_WIN32_GETVERSIONEX
+#  if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
+#    define SQLITE_WIN32_GETVERSIONEX   0   /* GetVersionEx() is deprecated */
+#  else
+#    define SQLITE_WIN32_GETVERSIONEX   1   /* GetVersionEx() is current */
+#  endif
+#endif
+
+/*
+** This constant should already be defined (in the "WinDef.h" SDK file).
+*/
+#ifndef MAX_PATH
+#  define MAX_PATH                      (260)
+#endif
+
+/*
+** Maximum pathname length (in chars) for Win32.  This should normally be
+** MAX_PATH.
+*/
+#ifndef SQLITE_WIN32_MAX_PATH_CHARS
+#  define SQLITE_WIN32_MAX_PATH_CHARS   (MAX_PATH)
+#endif
+
+/*
+** This constant should already be defined (in the "WinNT.h" SDK file).
+*/
+#ifndef UNICODE_STRING_MAX_CHARS
+#  define UNICODE_STRING_MAX_CHARS      (32767)
+#endif
+
+/*
+** Maximum pathname length (in chars) for WinNT.  This should normally be
+** UNICODE_STRING_MAX_CHARS.
+*/
+#ifndef SQLITE_WINNT_MAX_PATH_CHARS
+#  define SQLITE_WINNT_MAX_PATH_CHARS   (UNICODE_STRING_MAX_CHARS)
+#endif
+
+/*
+** Maximum pathname length (in bytes) for Win32.  The MAX_PATH macro is in
+** characters, so we allocate 4 bytes per character assuming worst-case of
+** 4-bytes-per-character for UTF8.
+*/
+#ifndef SQLITE_WIN32_MAX_PATH_BYTES
+#  define SQLITE_WIN32_MAX_PATH_BYTES   (SQLITE_WIN32_MAX_PATH_CHARS*4)
+#endif
+
+/*
+** Maximum pathname length (in bytes) for WinNT.  This should normally be
+** UNICODE_STRING_MAX_CHARS * sizeof(WCHAR).
+*/
+#ifndef SQLITE_WINNT_MAX_PATH_BYTES
+#  define SQLITE_WINNT_MAX_PATH_BYTES   \
+                            (sizeof(WCHAR) * SQLITE_WINNT_MAX_PATH_CHARS)
+#endif
+
+/*
+** Maximum error message length (in chars) for WinRT.
+*/
+#ifndef SQLITE_WIN32_MAX_ERRMSG_CHARS
+#  define SQLITE_WIN32_MAX_ERRMSG_CHARS (1024)
+#endif
+
+/*
+** Returns non-zero if the character should be treated as a directory
+** separator.
+*/
+#ifndef winIsDirSep
+#  define winIsDirSep(a)                (((a) == '/') || ((a) == '\\'))
+#endif
+
+/*
+** This macro is used when a local variable is set to a value that is
+** [sometimes] not used by the code (e.g. via conditional compilation).
+*/
+#ifndef UNUSED_VARIABLE_VALUE
+#  define UNUSED_VARIABLE_VALUE(x)      (void)(x)
+#endif
+
+/*
+** Returns the character that should be used as the directory separator.
+*/
+#ifndef winGetDirSep
+#  define winGetDirSep()                '\\'
+#endif
+
+/*
 ** Do we need to manually define the Win32 file mapping APIs for use with WAL
 ** mode (e.g. these APIs are available in the Windows CE SDK; however, they
 ** are not present in the header file)?
@@ -30802,17 +32180,10 @@ WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
 #endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
 
 /*
-** Macro to find the minimum of two numeric values.
-*/
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
-/*
 ** Some Microsoft compilers lack this definition.
 */
 #ifndef INVALID_FILE_ATTRIBUTES
-# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
 #endif
 
 #ifndef FILE_FLAG_MASK
@@ -30824,7 +32195,7 @@ WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
 #endif
 
 #ifndef SQLITE_OMIT_WAL
-/* Forward references */
+/* Forward references to structures used for WAL */
 typedef struct winShm winShm;           /* A connection to shared-memory */
 typedef struct winShmNode winShmNode;   /* A region of shared-memory */
 #endif
@@ -30862,7 +32233,7 @@ struct winFile {
   int szChunk;            /* Chunk size configured by FCNTL_CHUNK_SIZE */
 #if SQLITE_OS_WINCE
   LPWSTR zDeleteOnClose;  /* Name of file to delete when closing */
-  HANDLE hMutex;          /* Mutex used to control access to shared lock */  
+  HANDLE hMutex;          /* Mutex used to control access to shared lock */
   HANDLE hShared;         /* Shared memory segment used for locking */
   winceLock local;        /* Locks obtained by this instance of winFile */
   winceLock *shared;      /* Global shared lock memory for the file  */
@@ -30954,6 +32325,7 @@ struct winFile {
 #  define SQLITE_WIN32_HEAP_FLAGS     (0)
 #endif
 
+
 /*
 ** The winMemData structure stores information required by the Win32-specific
 ** sqlite3_mem_methods implementation.
@@ -30961,30 +32333,41 @@ struct winFile {
 typedef struct winMemData winMemData;
 struct winMemData {
 #ifndef NDEBUG
-  u32 magic;    /* Magic number to detect structure corruption. */
+  u32 magic1;   /* Magic number to detect structure corruption. */
 #endif
   HANDLE hHeap; /* The handle to our heap. */
   BOOL bOwned;  /* Do we own the heap (i.e. destroy it on shutdown)? */
+#ifndef NDEBUG
+  u32 magic2;   /* Magic number to detect structure corruption. */
+#endif
 };
 
 #ifndef NDEBUG
-#define WINMEM_MAGIC     0x42b2830b
+#define WINMEM_MAGIC1     0x42b2830b
+#define WINMEM_MAGIC2     0xbd4d7cf4
 #endif
 
 static struct winMemData win_mem_data = {
 #ifndef NDEBUG
-  WINMEM_MAGIC,
+  WINMEM_MAGIC1,
 #endif
   NULL, FALSE
+#ifndef NDEBUG
+  ,WINMEM_MAGIC2
+#endif
 };
 
 #ifndef NDEBUG
-#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
+#define winMemAssertMagic1() assert( win_mem_data.magic1==WINMEM_MAGIC1 )
+#define winMemAssertMagic2() assert( win_mem_data.magic2==WINMEM_MAGIC2 )
+#define winMemAssertMagic()  winMemAssertMagic1(); winMemAssertMagic2();
 #else
 #define winMemAssertMagic()
 #endif
 
-#define winMemGetHeap() win_mem_data.hHeap
+#define winMemGetDataPtr()  &win_mem_data
+#define winMemGetHeap()     win_mem_data.hHeap
+#define winMemGetOwned()    win_mem_data.bOwned
 
 static void *winMemMalloc(int nBytes);
 static void winMemFree(void *pPrior);
@@ -31010,9 +32393,9 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
 ** can manually set this value to 1 to emulate Win98 behavior.
 */
 #ifdef SQLITE_TEST
-SQLITE_API int sqlite3_os_type = 0;
+SQLITE_API LONG volatile sqlite3_os_type = 0;
 #else
-static int sqlite3_os_type = 0;
+static LONG volatile sqlite3_os_type = 0;
 #endif
 
 #ifndef SYSCALL
@@ -31317,7 +32700,8 @@ static struct win_syscall {
 
 #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
 
-#if defined(SQLITE_WIN32_HAS_ANSI)
+#if defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_GETVERSIONEX) && \
+        SQLITE_WIN32_GETVERSIONEX
   { "GetVersionExA",           (SYSCALL)GetVersionExA,           0 },
 #else
   { "GetVersionExA",           (SYSCALL)0,                       0 },
@@ -31326,10 +32710,20 @@ static struct win_syscall {
 #define osGetVersionExA ((BOOL(WINAPI*)( \
         LPOSVERSIONINFOA))aSyscall[34].pCurrent)
 
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+        defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX
+  { "GetVersionExW",           (SYSCALL)GetVersionExW,           0 },
+#else
+  { "GetVersionExW",           (SYSCALL)0,                       0 },
+#endif
+
+#define osGetVersionExW ((BOOL(WINAPI*)( \
+        LPOSVERSIONINFOW))aSyscall[35].pCurrent)
+
   { "HeapAlloc",               (SYSCALL)HeapAlloc,               0 },
 
 #define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
-        SIZE_T))aSyscall[35].pCurrent)
+        SIZE_T))aSyscall[36].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "HeapCreate",              (SYSCALL)HeapCreate,              0 },
@@ -31338,7 +32732,7 @@ static struct win_syscall {
 #endif
 
 #define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
-        SIZE_T))aSyscall[36].pCurrent)
+        SIZE_T))aSyscall[37].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "HeapDestroy",             (SYSCALL)HeapDestroy,             0 },
@@ -31346,21 +32740,21 @@ static struct win_syscall {
   { "HeapDestroy",             (SYSCALL)0,                       0 },
 #endif
 
-#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
+#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent)
 
   { "HeapFree",                (SYSCALL)HeapFree,                0 },
 
-#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
+#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[39].pCurrent)
 
   { "HeapReAlloc",             (SYSCALL)HeapReAlloc,             0 },
 
 #define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
-        SIZE_T))aSyscall[39].pCurrent)
+        SIZE_T))aSyscall[40].pCurrent)
 
   { "HeapSize",                (SYSCALL)HeapSize,                0 },
 
 #define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
-        LPCVOID))aSyscall[40].pCurrent)
+        LPCVOID))aSyscall[41].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "HeapValidate",            (SYSCALL)HeapValidate,            0 },
@@ -31369,7 +32763,15 @@ static struct win_syscall {
 #endif
 
 #define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
-        LPCVOID))aSyscall[41].pCurrent)
+        LPCVOID))aSyscall[42].pCurrent)
+
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+  { "HeapCompact",             (SYSCALL)HeapCompact,             0 },
+#else
+  { "HeapCompact",             (SYSCALL)0,                       0 },
+#endif
+
+#define osHeapCompact ((UINT(WINAPI*)(HANDLE,DWORD))aSyscall[43].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
   { "LoadLibraryA",            (SYSCALL)LoadLibraryA,            0 },
@@ -31377,7 +32779,7 @@ static struct win_syscall {
   { "LoadLibraryA",            (SYSCALL)0,                       0 },
 #endif
 
-#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
+#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent)
 
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
         !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -31386,7 +32788,7 @@ static struct win_syscall {
   { "LoadLibraryW",            (SYSCALL)0,                       0 },
 #endif
 
-#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
+#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "LocalFree",               (SYSCALL)LocalFree,               0 },
@@ -31394,7 +32796,7 @@ static struct win_syscall {
   { "LocalFree",               (SYSCALL)0,                       0 },
 #endif
 
-#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
+#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent)
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   { "LockFile",                (SYSCALL)LockFile,                0 },
@@ -31404,7 +32806,7 @@ static struct win_syscall {
 
 #ifndef osLockFile
 #define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        DWORD))aSyscall[45].pCurrent)
+        DWORD))aSyscall[47].pCurrent)
 #endif
 
 #if !SQLITE_OS_WINCE
@@ -31415,7 +32817,7 @@ static struct win_syscall {
 
 #ifndef osLockFileEx
 #define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
-        LPOVERLAPPED))aSyscall[46].pCurrent)
+        LPOVERLAPPED))aSyscall[48].pCurrent)
 #endif
 
 #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
@@ -31425,26 +32827,26 @@ static struct win_syscall {
 #endif
 
 #define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        SIZE_T))aSyscall[47].pCurrent)
+        SIZE_T))aSyscall[49].pCurrent)
 
   { "MultiByteToWideChar",     (SYSCALL)MultiByteToWideChar,     0 },
 
 #define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
-        int))aSyscall[48].pCurrent)
+        int))aSyscall[50].pCurrent)
 
   { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
 
 #define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
-        LARGE_INTEGER*))aSyscall[49].pCurrent)
+        LARGE_INTEGER*))aSyscall[51].pCurrent)
 
   { "ReadFile",                (SYSCALL)ReadFile,                0 },
 
 #define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
-        LPOVERLAPPED))aSyscall[50].pCurrent)
+        LPOVERLAPPED))aSyscall[52].pCurrent)
 
   { "SetEndOfFile",            (SYSCALL)SetEndOfFile,            0 },
 
-#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
+#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "SetFilePointer",          (SYSCALL)SetFilePointer,          0 },
@@ -31453,7 +32855,7 @@ static struct win_syscall {
 #endif
 
 #define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
-        DWORD))aSyscall[52].pCurrent)
+        DWORD))aSyscall[54].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "Sleep",                   (SYSCALL)Sleep,                   0 },
@@ -31461,12 +32863,12 @@ static struct win_syscall {
   { "Sleep",                   (SYSCALL)0,                       0 },
 #endif
 
-#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
+#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent)
 
   { "SystemTimeToFileTime",    (SYSCALL)SystemTimeToFileTime,    0 },
 
 #define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
-        LPFILETIME))aSyscall[54].pCurrent)
+        LPFILETIME))aSyscall[56].pCurrent)
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   { "UnlockFile",              (SYSCALL)UnlockFile,              0 },
@@ -31476,7 +32878,7 @@ static struct win_syscall {
 
 #ifndef osUnlockFile
 #define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        DWORD))aSyscall[55].pCurrent)
+        DWORD))aSyscall[57].pCurrent)
 #endif
 
 #if !SQLITE_OS_WINCE
@@ -31486,7 +32888,7 @@ static struct win_syscall {
 #endif
 
 #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-        LPOVERLAPPED))aSyscall[56].pCurrent)
+        LPOVERLAPPED))aSyscall[58].pCurrent)
 
 #if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
   { "UnmapViewOfFile",         (SYSCALL)UnmapViewOfFile,         0 },
@@ -31494,17 +32896,17 @@ static struct win_syscall {
   { "UnmapViewOfFile",         (SYSCALL)0,                       0 },
 #endif
 
-#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
+#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[59].pCurrent)
 
   { "WideCharToMultiByte",     (SYSCALL)WideCharToMultiByte,     0 },
 
 #define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
-        LPCSTR,LPBOOL))aSyscall[58].pCurrent)
+        LPCSTR,LPBOOL))aSyscall[60].pCurrent)
 
   { "WriteFile",               (SYSCALL)WriteFile,               0 },
 
 #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
-        LPOVERLAPPED))aSyscall[59].pCurrent)
+        LPOVERLAPPED))aSyscall[61].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "CreateEventExW",          (SYSCALL)CreateEventExW,          0 },
@@ -31513,7 +32915,7 @@ static struct win_syscall {
 #endif
 
 #define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
-        DWORD,DWORD))aSyscall[60].pCurrent)
+        DWORD,DWORD))aSyscall[62].pCurrent)
 
 #if !SQLITE_OS_WINRT
   { "WaitForSingleObject",     (SYSCALL)WaitForSingleObject,     0 },
@@ -31522,7 +32924,7 @@ static struct win_syscall {
 #endif
 
 #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
-        DWORD))aSyscall[61].pCurrent)
+        DWORD))aSyscall[63].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "WaitForSingleObjectEx",   (SYSCALL)WaitForSingleObjectEx,   0 },
@@ -31531,7 +32933,7 @@ static struct win_syscall {
 #endif
 
 #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
-        BOOL))aSyscall[62].pCurrent)
+        BOOL))aSyscall[64].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "SetFilePointerEx",        (SYSCALL)SetFilePointerEx,        0 },
@@ -31540,7 +32942,7 @@ static struct win_syscall {
 #endif
 
 #define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
-        PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
+        PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
@@ -31549,7 +32951,7 @@ static struct win_syscall {
 #endif
 
 #define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
-        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
+        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
 
 #if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
   { "MapViewOfFileFromApp",    (SYSCALL)MapViewOfFileFromApp,    0 },
@@ -31558,7 +32960,7 @@ static struct win_syscall {
 #endif
 
 #define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
-        SIZE_T))aSyscall[65].pCurrent)
+        SIZE_T))aSyscall[67].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "CreateFile2",             (SYSCALL)CreateFile2,             0 },
@@ -31567,7 +32969,7 @@ static struct win_syscall {
 #endif
 
 #define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
-        LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
+        LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent)
 
 #if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
   { "LoadPackagedLibrary",     (SYSCALL)LoadPackagedLibrary,     0 },
@@ -31576,7 +32978,7 @@ static struct win_syscall {
 #endif
 
 #define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
-        DWORD))aSyscall[67].pCurrent)
+        DWORD))aSyscall[69].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "GetTickCount64",          (SYSCALL)GetTickCount64,          0 },
@@ -31584,7 +32986,7 @@ static struct win_syscall {
   { "GetTickCount64",          (SYSCALL)0,                       0 },
 #endif
 
-#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
+#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent)
 
 #if SQLITE_OS_WINRT
   { "GetNativeSystemInfo",     (SYSCALL)GetNativeSystemInfo,     0 },
@@ -31593,7 +32995,7 @@ static struct win_syscall {
 #endif
 
 #define osGetNativeSystemInfo ((VOID(WINAPI*)( \
-        LPSYSTEM_INFO))aSyscall[69].pCurrent)
+        LPSYSTEM_INFO))aSyscall[71].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_ANSI)
   { "OutputDebugStringA",      (SYSCALL)OutputDebugStringA,      0 },
@@ -31601,7 +33003,7 @@ static struct win_syscall {
   { "OutputDebugStringA",      (SYSCALL)0,                       0 },
 #endif
 
-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent)
 
 #if defined(SQLITE_WIN32_HAS_WIDE)
   { "OutputDebugStringW",      (SYSCALL)OutputDebugStringW,      0 },
@@ -31609,11 +33011,11 @@ static struct win_syscall {
   { "OutputDebugStringW",      (SYSCALL)0,                       0 },
 #endif
 
-#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
+#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent)
 
   { "GetProcessHeap",          (SYSCALL)GetProcessHeap,          0 },
 
-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent)
 
 #if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
   { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
@@ -31622,7 +33024,23 @@ static struct win_syscall {
 #endif
 
 #define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
-        LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
+        LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
+
+/*
+** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
+**       is really just a macro that uses a compiler intrinsic (e.g. x64).
+**       So do not try to make this is into a redefinable interface.
+*/
+#if defined(InterlockedCompareExchange)
+  { "InterlockedCompareExchange", (SYSCALL)0,                    0 },
+
+#define osInterlockedCompareExchange InterlockedCompareExchange
+#else
+  { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
+
+#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG volatile*, \
+        LONG,LONG))aSyscall[76].pCurrent)
+#endif /* defined(InterlockedCompareExchange) */
 
 }; /* End of the overrideable system calls */
 
@@ -31709,6 +33127,94 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
   return 0;
 }
 
+#ifdef SQLITE_WIN32_MALLOC
+/*
+** If a Win32 native heap has been configured, this function will attempt to
+** compact it.  Upon success, SQLITE_OK will be returned.  Upon failure, one
+** of SQLITE_NOMEM, SQLITE_ERROR, or SQLITE_NOTFOUND will be returned.  The
+** "pnLargest" argument, if non-zero, will be used to return the size of the
+** largest committed free block in the heap, in bytes.
+*/
+SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){
+  int rc = SQLITE_OK;
+  UINT nLargest = 0;
+  HANDLE hHeap;
+
+  winMemAssertMagic();
+  hHeap = winMemGetHeap();
+  assert( hHeap!=0 );
+  assert( hHeap!=INVALID_HANDLE_VALUE );
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+  assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+#endif
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+  if( (nLargest=osHeapCompact(hHeap, SQLITE_WIN32_HEAP_FLAGS))==0 ){
+    DWORD lastErrno = osGetLastError();
+    if( lastErrno==NO_ERROR ){
+      sqlite3_log(SQLITE_NOMEM, "failed to HeapCompact (no space), heap=%p",
+                  (void*)hHeap);
+      rc = SQLITE_NOMEM;
+    }else{
+      sqlite3_log(SQLITE_ERROR, "failed to HeapCompact (%lu), heap=%p",
+                  osGetLastError(), (void*)hHeap);
+      rc = SQLITE_ERROR;
+    }
+  }
+#else
+  sqlite3_log(SQLITE_NOTFOUND, "failed to HeapCompact, heap=%p",
+              (void*)hHeap);
+  rc = SQLITE_NOTFOUND;
+#endif
+  if( pnLargest ) *pnLargest = nLargest;
+  return rc;
+}
+
+/*
+** If a Win32 native heap has been configured, this function will attempt to
+** destroy and recreate it.  If the Win32 native heap is not isolated and/or
+** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will
+** be returned and no changes will be made to the Win32 native heap.
+*/
+SQLITE_API int sqlite3_win32_reset_heap(){
+  int rc;
+  MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
+  MUTEX_LOGIC( sqlite3_mutex *pMem; )    /* The memsys static mutex */
+  MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
+  MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
+  sqlite3_mutex_enter(pMaster);
+  sqlite3_mutex_enter(pMem);
+  winMemAssertMagic();
+  if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){
+    /*
+    ** At this point, there should be no outstanding memory allocations on
+    ** the heap.  Also, since both the master and memsys locks are currently
+    ** being held by us, no other function (i.e. from another thread) should
+    ** be able to even access the heap.  Attempt to destroy and recreate our
+    ** isolated Win32 native heap now.
+    */
+    assert( winMemGetHeap()!=NULL );
+    assert( winMemGetOwned() );
+    assert( sqlite3_memory_used()==0 );
+    winMemShutdown(winMemGetDataPtr());
+    assert( winMemGetHeap()==NULL );
+    assert( !winMemGetOwned() );
+    assert( sqlite3_memory_used()==0 );
+    rc = winMemInit(winMemGetDataPtr());
+    assert( rc!=SQLITE_OK || winMemGetHeap()!=NULL );
+    assert( rc!=SQLITE_OK || winMemGetOwned() );
+    assert( rc!=SQLITE_OK || sqlite3_memory_used()==0 );
+  }else{
+    /*
+    ** The Win32 native heap cannot be modified because it may be in use.
+    */
+    rc = SQLITE_BUSY;
+  }
+  sqlite3_mutex_leave(pMem);
+  sqlite3_mutex_leave(pMaster);
+  return rc;
+}
+#endif /* SQLITE_WIN32_MALLOC */
+
 /*
 ** This function outputs the specified (ANSI) string to the Win32 debugger
 ** (if available).
@@ -31778,21 +33284,46 @@ SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
 ** WinNT/2K/XP so that we will know whether or not we can safely call
 ** the LockFileEx() API.
 */
-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
-# define isNT()  (1)
+
+#if !defined(SQLITE_WIN32_GETVERSIONEX) || !SQLITE_WIN32_GETVERSIONEX
+# define osIsNT()  (1)
+#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
+# define osIsNT()  (1)
 #elif !defined(SQLITE_WIN32_HAS_WIDE)
-# define isNT()  (0)
+# define osIsNT()  (0)
 #else
-  static int isNT(void){
-    if( sqlite3_os_type==0 ){
-      OSVERSIONINFOA sInfo;
-      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
-      osGetVersionExA(&sInfo);
-      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
-    }
-    return sqlite3_os_type==2;
+# define osIsNT()  ((sqlite3_os_type==2) || sqlite3_win32_is_nt())
+#endif
+
+/*
+** This function determines if the machine is running a version of Windows
+** based on the NT kernel.
+*/
+SQLITE_API int sqlite3_win32_is_nt(void){
+#if defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX
+  if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+        defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
+    OSVERSIONINFOW sInfo;
+    sInfo.dwOSVersionInfoSize = sizeof(sInfo);
+    osGetVersionExW(&sInfo);
+    osInterlockedCompareExchange(&sqlite3_os_type,
+        (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
+#elif defined(SQLITE_WIN32_HAS_ANSI)
+    OSVERSIONINFOA sInfo;
+    sInfo.dwOSVersionInfoSize = sizeof(sInfo);
+    osGetVersionExA(&sInfo);
+    osInterlockedCompareExchange(&sqlite3_os_type,
+        (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
+#endif
   }
+  return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
+#elif SQLITE_TEST
+  return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
+#else
+  return 1;
 #endif
+}
 
 #ifdef SQLITE_WIN32_MALLOC
 /*
@@ -31807,12 +33338,12 @@ static void *winMemMalloc(int nBytes){
   assert( hHeap!=0 );
   assert( hHeap!=INVALID_HANDLE_VALUE );
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+  assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
 #endif
   assert( nBytes>=0 );
   p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
   if( !p ){
-    sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
+    sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p",
                 nBytes, osGetLastError(), (void*)hHeap);
   }
   return p;
@@ -31829,11 +33360,11 @@ static void winMemFree(void *pPrior){
   assert( hHeap!=0 );
   assert( hHeap!=INVALID_HANDLE_VALUE );
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+  assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
 #endif
   if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
   if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
-    sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
+    sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p",
                 pPrior, osGetLastError(), (void*)hHeap);
   }
 }
@@ -31850,7 +33381,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){
   assert( hHeap!=0 );
   assert( hHeap!=INVALID_HANDLE_VALUE );
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+  assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
 #endif
   assert( nBytes>=0 );
   if( !pPrior ){
@@ -31859,7 +33390,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){
     p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
   }
   if( !p ){
-    sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
+    sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p",
                 pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
                 (void*)hHeap);
   }
@@ -31878,12 +33409,12 @@ static int winMemSize(void *p){
   assert( hHeap!=0 );
   assert( hHeap!=INVALID_HANDLE_VALUE );
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+  assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) );
 #endif
   if( !p ) return 0;
   n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
   if( n==(SIZE_T)-1 ){
-    sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
+    sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p",
                 p, osGetLastError(), (void*)hHeap);
     return 0;
   }
@@ -31904,18 +33435,25 @@ static int winMemInit(void *pAppData){
   winMemData *pWinMemData = (winMemData *)pAppData;
 
   if( !pWinMemData ) return SQLITE_ERROR;
-  assert( pWinMemData->magic==WINMEM_MAGIC );
+  assert( pWinMemData->magic1==WINMEM_MAGIC1 );
+  assert( pWinMemData->magic2==WINMEM_MAGIC2 );
 
 #if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
   if( !pWinMemData->hHeap ){
+    DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE;
+    DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap;
+    if( dwMaximumSize==0 ){
+      dwMaximumSize = SQLITE_WIN32_HEAP_MAX_SIZE;
+    }else if( dwInitialSize>dwMaximumSize ){
+      dwInitialSize = dwMaximumSize;
+    }
     pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
-                                      SQLITE_WIN32_HEAP_INIT_SIZE,
-                                      SQLITE_WIN32_HEAP_MAX_SIZE);
+                                      dwInitialSize, dwMaximumSize);
     if( !pWinMemData->hHeap ){
       sqlite3_log(SQLITE_NOMEM,
-          "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
-          osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
-          SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
+          "failed to HeapCreate (%lu), flags=%u, initSize=%lu, maxSize=%lu",
+          osGetLastError(), SQLITE_WIN32_HEAP_FLAGS, dwInitialSize,
+          dwMaximumSize);
       return SQLITE_NOMEM;
     }
     pWinMemData->bOwned = TRUE;
@@ -31925,7 +33463,7 @@ static int winMemInit(void *pAppData){
   pWinMemData->hHeap = osGetProcessHeap();
   if( !pWinMemData->hHeap ){
     sqlite3_log(SQLITE_NOMEM,
-        "failed to GetProcessHeap (%d)", osGetLastError());
+        "failed to GetProcessHeap (%lu)", osGetLastError());
     return SQLITE_NOMEM;
   }
   pWinMemData->bOwned = FALSE;
@@ -31946,6 +33484,9 @@ static void winMemShutdown(void *pAppData){
   winMemData *pWinMemData = (winMemData *)pAppData;
 
   if( !pWinMemData ) return;
+  assert( pWinMemData->magic1==WINMEM_MAGIC1 );
+  assert( pWinMemData->magic2==WINMEM_MAGIC2 );
+
   if( pWinMemData->hHeap ){
     assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
@@ -31953,7 +33494,7 @@ static void winMemShutdown(void *pAppData){
 #endif
     if( pWinMemData->bOwned ){
       if( !osHeapDestroy(pWinMemData->hHeap) ){
-        sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
+        sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p",
                     osGetLastError(), (void*)pWinMemData->hHeap);
       }
       pWinMemData->bOwned = FALSE;
@@ -31990,11 +33531,11 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
 #endif /* SQLITE_WIN32_MALLOC */
 
 /*
-** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). 
+** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
 **
 ** Space to hold the returned string is obtained from malloc.
 */
-static LPWSTR utf8ToUnicode(const char *zFilename){
+static LPWSTR winUtf8ToUnicode(const char *zFilename){
   int nChar;
   LPWSTR zWideFilename;
 
@@ -32019,7 +33560,7 @@ static LPWSTR utf8ToUnicode(const char *zFilename){
 ** Convert Microsoft Unicode to UTF-8.  Space to hold the returned string is
 ** obtained from sqlite3_malloc().
 */
-static char *unicodeToUtf8(LPCWSTR zWideFilename){
+static char *winUnicodeToUtf8(LPCWSTR zWideFilename){
   int nByte;
   char *zFilename;
 
@@ -32043,11 +33584,11 @@ static char *unicodeToUtf8(LPCWSTR zWideFilename){
 /*
 ** Convert an ANSI string to Microsoft Unicode, based on the
 ** current codepage settings for file apis.
-** 
+**
 ** Space to hold the returned string is obtained
 ** from sqlite3_malloc.
 */
-static LPWSTR mbcsToUnicode(const char *zFilename){
+static LPWSTR winMbcsToUnicode(const char *zFilename){
   int nByte;
   LPWSTR zMbcsFilename;
   int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
@@ -32077,7 +33618,7 @@ static LPWSTR mbcsToUnicode(const char *zFilename){
 ** Space to hold the returned string is obtained from
 ** sqlite3_malloc().
 */
-static char *unicodeToMbcs(LPCWSTR zWideFilename){
+static char *winUnicodeToMbcs(LPCWSTR zWideFilename){
   int nByte;
   char *zFilename;
   int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
@@ -32107,28 +33648,28 @@ SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
   char *zFilenameUtf8;
   LPWSTR zTmpWide;
 
-  zTmpWide = mbcsToUnicode(zFilename);
+  zTmpWide = winMbcsToUnicode(zFilename);
   if( zTmpWide==0 ){
     return 0;
   }
-  zFilenameUtf8 = unicodeToUtf8(zTmpWide);
+  zFilenameUtf8 = winUnicodeToUtf8(zTmpWide);
   sqlite3_free(zTmpWide);
   return zFilenameUtf8;
 }
 
 /*
-** Convert UTF-8 to multibyte character string.  Space to hold the 
+** Convert UTF-8 to multibyte character string.  Space to hold the
 ** returned string is obtained from sqlite3_malloc().
 */
 SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
   char *zFilenameMbcs;
   LPWSTR zTmpWide;
 
-  zTmpWide = utf8ToUnicode(zFilename);
+  zTmpWide = winUtf8ToUnicode(zFilename);
   if( zTmpWide==0 ){
     return 0;
   }
-  zFilenameMbcs = unicodeToMbcs(zTmpWide);
+  zFilenameMbcs = winUnicodeToMbcs(zTmpWide);
   sqlite3_free(zTmpWide);
   return zFilenameMbcs;
 }
@@ -32158,7 +33699,7 @@ SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
   if( ppDirectory ){
     char *zValueUtf8 = 0;
     if( zValue && zValue[0] ){
-      zValueUtf8 = unicodeToUtf8(zValue);
+      zValueUtf8 = winUnicodeToUtf8(zValue);
       if ( zValueUtf8==0 ){
         return SQLITE_NOMEM;
       }
@@ -32171,11 +33712,11 @@ SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
 }
 
 /*
-** The return value of getLastErrorMsg
+** The return value of winGetLastErrorMsg
 ** is zero if the error message fits in the buffer, or non-zero
 ** otherwise (if the message was truncated).
 */
-static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
+static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
   /* FormatMessage returns 0 on failure.  Otherwise it
   ** returns the number of TCHARs written to the output
   ** buffer, excluding the terminating null char.
@@ -32183,16 +33724,16 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
   DWORD dwLen = 0;
   char *zOut = 0;
 
-  if( isNT() ){
+  if( osIsNT() ){
 #if SQLITE_OS_WINRT
-    WCHAR zTempWide[MAX_PATH+1]; /* NOTE: Somewhat arbitrary. */
+    WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1];
     dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
                              FORMAT_MESSAGE_IGNORE_INSERTS,
                              NULL,
                              lastErrno,
                              0,
                              zTempWide,
-                             MAX_PATH,
+                             SQLITE_WIN32_MAX_ERRMSG_CHARS,
                              0);
 #else
     LPWSTR zTempWide = NULL;
@@ -32209,7 +33750,7 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
     if( dwLen > 0 ){
       /* allocate a buffer and convert to UTF8 */
       sqlite3BeginBenignMalloc();
-      zOut = unicodeToUtf8(zTempWide);
+      zOut = winUnicodeToUtf8(zTempWide);
       sqlite3EndBenignMalloc();
 #if !SQLITE_OS_WINRT
       /* free the system buffer allocated by FormatMessage */
@@ -32257,11 +33798,11 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
 **
 ** This routine is invoked after an error occurs in an OS function.
 ** It logs a message using sqlite3_log() containing the current value of
-** error code and, if possible, the human-readable equivalent from 
+** error code and, if possible, the human-readable equivalent from
 ** FormatMessage.
 **
 ** The first argument passed to the macro should be the error code that
-** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). 
+** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
 ** The two subsequent arguments should be the name of the OS function that
 ** failed and the associated file-system path, if any.
 */
@@ -32277,7 +33818,7 @@ static int winLogErrorAtLine(
   int i;                          /* Loop counter */
 
   zMsg[0] = 0;
-  getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
+  winGetLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
   assert( errcode!=SQLITE_OK );
   if( zPath==0 ) zPath = "";
   for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
@@ -32292,7 +33833,7 @@ static int winLogErrorAtLine(
 
 /*
 ** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
-** will be retried following a locking error - probably caused by 
+** will be retried following a locking error - probably caused by
 ** antivirus software.  Also the initial delay before the first retry.
 ** The delay increases linearly with each retry.
 */
@@ -32302,29 +33843,60 @@ static int winLogErrorAtLine(
 #ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
 # define SQLITE_WIN32_IOERR_RETRY_DELAY 25
 #endif
-static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
-static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
+static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
+static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
+
+/*
+** The "winIoerrCanRetry1" macro is used to determine if a particular I/O
+** error code obtained via GetLastError() is eligible to be retried.  It
+** must accept the error code DWORD as its only argument and should return
+** non-zero if the error code is transient in nature and the operation
+** responsible for generating the original error might succeed upon being
+** retried.  The argument to this macro should be a variable.
+**
+** Additionally, a macro named "winIoerrCanRetry2" may be defined.  If it
+** is defined, it will be consulted only when the macro "winIoerrCanRetry1"
+** returns zero.  The "winIoerrCanRetry2" macro is completely optional and
+** may be used to include additional error codes in the set that should
+** result in the failing I/O operation being retried by the caller.  If
+** defined, the "winIoerrCanRetry2" macro must exhibit external semantics
+** identical to those of the "winIoerrCanRetry1" macro.
+*/
+#if !defined(winIoerrCanRetry1)
+#define winIoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED)        || \
+                              ((a)==ERROR_SHARING_VIOLATION)    || \
+                              ((a)==ERROR_LOCK_VIOLATION)       || \
+                              ((a)==ERROR_DEV_NOT_EXIST)        || \
+                              ((a)==ERROR_NETNAME_DELETED)      || \
+                              ((a)==ERROR_SEM_TIMEOUT)          || \
+                              ((a)==ERROR_NETWORK_UNREACHABLE))
+#endif
 
 /*
 ** If a ReadFile() or WriteFile() error occurs, invoke this routine
 ** to see if it should be retried.  Return TRUE to retry.  Return FALSE
 ** to give up with an error.
 */
-static int retryIoerr(int *pnRetry, DWORD *pError){
+static int winRetryIoerr(int *pnRetry, DWORD *pError){
   DWORD e = osGetLastError();
-  if( *pnRetry>=win32IoerrRetry ){
+  if( *pnRetry>=winIoerrRetry ){
     if( pError ){
       *pError = e;
     }
     return 0;
   }
-  if( e==ERROR_ACCESS_DENIED ||
-      e==ERROR_LOCK_VIOLATION ||
-      e==ERROR_SHARING_VIOLATION ){
-    sqlite3_win32_sleep(win32IoerrRetryDelay*(1+*pnRetry));
+  if( winIoerrCanRetry1(e) ){
+    sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
+    ++*pnRetry;
+    return 1;
+  }
+#if defined(winIoerrCanRetry2)
+  else if( winIoerrCanRetry2(e) ){
+    sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
     ++*pnRetry;
     return 1;
   }
+#endif
   if( pError ){
     *pError = e;
   }
@@ -32334,11 +33906,11 @@ static int retryIoerr(int *pnRetry, DWORD *pError){
 /*
 ** Log a I/O error retry episode.
 */
-static void logIoerr(int nRetry){
+static void winLogIoerr(int nRetry){
   if( nRetry ){
-    sqlite3_log(SQLITE_IOERR, 
+    sqlite3_log(SQLITE_IOERR,
       "delayed %dms for lock/sharing conflict",
-      win32IoerrRetryDelay*nRetry*(nRetry+1)/2
+      winIoerrRetryDelay*nRetry*(nRetry+1)/2
     );
   }
 }
@@ -32403,7 +33975,7 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){
   BOOL bLogged = FALSE;
   BOOL bInit = TRUE;
 
-  zName = utf8ToUnicode(zFilename);
+  zName = winUtf8ToUnicode(zFilename);
   if( zName==0 ){
     /* out of memory */
     return SQLITE_IOERR_NOMEM;
@@ -32423,25 +33995,24 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){
   pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
   if (!pFile->hMutex){
     pFile->lastErrno = osGetLastError();
-    winLogError(SQLITE_IOERR, pFile->lastErrno,
-                "winceCreateLock1", zFilename);
     sqlite3_free(zName);
-    return SQLITE_IOERR;
+    return winLogError(SQLITE_IOERR, pFile->lastErrno,
+                       "winceCreateLock1", zFilename);
   }
 
   /* Acquire the mutex before continuing */
   winceMutexAcquire(pFile->hMutex);
-  
-  /* Since the names of named mutexes, semaphores, file mappings etc are 
+
+  /* Since the names of named mutexes, semaphores, file mappings etc are
   ** case-sensitive, take advantage of that by uppercasing the mutex name
   ** and using that as the shared filemapping name.
   */
   osCharUpperW(zName);
   pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
                                         PAGE_READWRITE, 0, sizeof(winceLock),
-                                        zName);  
+                                        zName);
 
-  /* Set a flag that indicates we're the first to create the memory so it 
+  /* Set a flag that indicates we're the first to create the memory so it
   ** must be zero-initialized */
   lastErrno = osGetLastError();
   if (lastErrno == ERROR_ALREADY_EXISTS){
@@ -32452,7 +34023,7 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){
 
   /* If we succeeded in making the shared memory handle, map it. */
   if( pFile->hShared ){
-    pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, 
+    pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
              FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
     /* If mapping failed, close the shared memory handle and erase it */
     if( !pFile->shared ){
@@ -32478,7 +34049,7 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){
     pFile->hMutex = NULL;
     return SQLITE_IOERR;
   }
-  
+
   /* Initialize the shared memory if we're supposed to */
   if( bInit ){
     memset(pFile->shared, 0, sizeof(winceLock));
@@ -32516,13 +34087,13 @@ static void winceDestroyLock(winFile *pFile){
     osCloseHandle(pFile->hShared);
 
     /* Done with the mutex */
-    winceMutexRelease(pFile->hMutex);    
+    winceMutexRelease(pFile->hMutex);
     osCloseHandle(pFile->hMutex);
     pFile->hMutex = NULL;
   }
 }
 
-/* 
+/*
 ** An implementation of the LockFile() API of Windows for CE
 */
 static BOOL winceLockFile(
@@ -32676,7 +34247,7 @@ static BOOL winLockFile(
   return winceLockFile(phFile, offsetLow, offsetHigh,
                        numBytesLow, numBytesHigh);
 #else
-  if( isNT() ){
+  if( osIsNT() ){
     OVERLAPPED ovlp;
     memset(&ovlp, 0, sizeof(OVERLAPPED));
     ovlp.Offset = offsetLow;
@@ -32707,7 +34278,7 @@ static BOOL winUnlockFile(
   return winceUnlockFile(phFile, offsetLow, offsetHigh,
                          numBytesLow, numBytesHigh);
 #else
-  if( isNT() ){
+  if( osIsNT() ){
     OVERLAPPED ovlp;
     memset(&ovlp, 0, sizeof(OVERLAPPED));
     ovlp.Offset = offsetLow;
@@ -32733,11 +34304,11 @@ static BOOL winUnlockFile(
 #endif
 
 /*
-** Move the current position of the file handle passed as the first 
-** argument to offset iOffset within the file. If successful, return 0. 
+** Move the current position of the file handle passed as the first
+** argument to offset iOffset within the file. If successful, return 0.
 ** Otherwise, set pFile->lastErrno and return non-zero.
 */
-static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
+static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
 #if !SQLITE_OS_WINRT
   LONG upperBits;                 /* Most sig. 32 bits of new offset */
   LONG lowerBits;                 /* Least sig. 32 bits of new offset */
@@ -32749,11 +34320,11 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
   upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
   lowerBits = (LONG)(iOffset & 0xffffffff);
 
-  /* API oddity: If successful, SetFilePointer() returns a dword 
+  /* API oddity: If successful, SetFilePointer() returns a dword
   ** containing the lower 32-bits of the new file-offset. Or, if it fails,
-  ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, 
-  ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine 
-  ** whether an error has actually occurred, it is also necessary to call 
+  ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
+  ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
+  ** whether an error has actually occurred, it is also necessary to call
   ** GetLastError().
   */
   dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
@@ -32762,7 +34333,7 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
       && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
     pFile->lastErrno = lastErrno;
     winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
-             "seekWinFile", pFile->zPath);
+                "winSeekFile", pFile->zPath);
     OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
     return 1;
   }
@@ -32783,7 +34354,7 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
   if(!bRet){
     pFile->lastErrno = osGetLastError();
     winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
-             "seekWinFile", pFile->zPath);
+                "winSeekFile", pFile->zPath);
     OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
     return 1;
   }
@@ -32794,7 +34365,8 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
 }
 
 #if SQLITE_MAX_MMAP_SIZE>0
-/* Forward references to VFS methods */
+/* Forward references to VFS helper methods used for memory mapped files */
+static int winMapfile(winFile*, sqlite3_int64);
 static int winUnmapfile(winFile*);
 #endif
 
@@ -32821,8 +34393,7 @@ static int winClose(sqlite3_file *id){
   OSTRACE(("CLOSE file=%p\n", pFile->h));
 
 #if SQLITE_MAX_MMAP_SIZE>0
-  rc = winUnmapfile(pFile);
-  if( rc!=SQLITE_OK ) return rc;
+  winUnmapfile(pFile);
 #endif
 
   do{
@@ -32836,7 +34407,7 @@ static int winClose(sqlite3_file *id){
     int cnt = 0;
     while(
            osDeleteFileW(pFile->zDeleteOnClose)==0
-        && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff 
+        && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
         && cnt++ < WINCE_DELETION_ATTEMPTS
     ){
        sqlite3_win32_sleep(100);  /* Wait a little before trying again */
@@ -32898,7 +34469,7 @@ static int winRead(
 #endif
 
 #if SQLITE_OS_WINCE
-  if( seekWinFile(pFile, offset) ){
+  if( winSeekFile(pFile, offset) ){
     OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
     return SQLITE_FULL;
   }
@@ -32911,13 +34482,13 @@ static int winRead(
          osGetLastError()!=ERROR_HANDLE_EOF ){
 #endif
     DWORD lastErrno;
-    if( retryIoerr(&nRetry, &lastErrno) ) continue;
+    if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
     pFile->lastErrno = lastErrno;
     OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
     return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
-             "winRead", pFile->zPath);
+                       "winRead", pFile->zPath);
   }
-  logIoerr(nRetry);
+  winLogIoerr(nRetry);
   if( nRead<(DWORD)amt ){
     /* Unread parts of the buffer must be zero-filled */
     memset(&((char*)pBuf)[nRead], 0, amt-nRead);
@@ -32970,7 +34541,7 @@ static int winWrite(
 #endif
 
 #if SQLITE_OS_WINCE
-  rc = seekWinFile(pFile, offset);
+  rc = winSeekFile(pFile, offset);
   if( rc==0 ){
 #else
   {
@@ -32995,7 +34566,7 @@ static int winWrite(
 #else
       if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
 #endif
-        if( retryIoerr(&nRetry, &lastErrno) ) continue;
+        if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
         break;
       }
       assert( nWrite==0 || nWrite<=(DWORD)nRem );
@@ -33021,13 +34592,14 @@ static int winWrite(
     if(   ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
        || ( pFile->lastErrno==ERROR_DISK_FULL )){
       OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
-      return SQLITE_FULL;
+      return winLogError(SQLITE_FULL, pFile->lastErrno,
+                         "winWrite1", pFile->zPath);
     }
     OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
     return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
-             "winWrite", pFile->zPath);
+                       "winWrite2", pFile->zPath);
   }else{
-    logIoerr(nRetry);
+    winLogIoerr(nRetry);
   }
   OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
   return SQLITE_OK;
@@ -33056,7 +34628,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
   }
 
   /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
-  if( seekWinFile(pFile, nByte) ){
+  if( winSeekFile(pFile, nByte) ){
     rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
                      "winTruncate1", pFile->zPath);
   }else if( 0==osSetEndOfFile(pFile->h) &&
@@ -33137,6 +34709,7 @@ static int winSync(sqlite3_file *id, int flags){
   ** no-op
   */
 #ifdef SQLITE_NO_SYNC
+  OSTRACE(("SYNC-NOP file=%p, rc=SQLITE_OK\n", pFile->h));
   return SQLITE_OK;
 #else
   rc = osFlushFileBuffers(pFile->h);
@@ -33148,7 +34721,7 @@ static int winSync(sqlite3_file *id, int flags){
     pFile->lastErrno = osGetLastError();
     OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
     return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
-             "winSync", pFile->zPath);
+                       "winSync", pFile->zPath);
   }
 #endif
 }
@@ -33189,7 +34762,7 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
        && ((lastErrno = osGetLastError())!=NO_ERROR) ){
       pFile->lastErrno = lastErrno;
       rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
-             "winFileSize", pFile->zPath);
+                       "winFileSize", pFile->zPath);
     }
   }
 #endif
@@ -33234,10 +34807,10 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
 ** Different API routines are called depending on whether or not this
 ** is Win9x or WinNT.
 */
-static int getReadLock(winFile *pFile){
+static int winGetReadLock(winFile *pFile){
   int res;
   OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
-  if( isNT() ){
+  if( osIsNT() ){
 #if SQLITE_OS_WINCE
     /*
     ** NOTE: Windows CE is handled differently here due its lack of the Win32
@@ -33262,18 +34835,18 @@ static int getReadLock(winFile *pFile){
     pFile->lastErrno = osGetLastError();
     /* No need to log a failure to lock */
   }
-  OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
+  OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res));
   return res;
 }
 
 /*
 ** Undo a readlock
 */
-static int unlockReadLock(winFile *pFile){
+static int winUnlockReadLock(winFile *pFile){
   int res;
   DWORD lastErrno;
   OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
-  if( isNT() ){
+  if( osIsNT() ){
     res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
   }
 #ifdef SQLITE_WIN32_HAS_ANSI
@@ -33284,9 +34857,9 @@ static int unlockReadLock(winFile *pFile){
   if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
     pFile->lastErrno = lastErrno;
     winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
-             "unlockReadLock", pFile->zPath);
+                "winUnlockReadLock", pFile->zPath);
   }
-  OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
+  OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res));
   return res;
 }
 
@@ -33361,8 +34934,16 @@ static int winLock(sqlite3_file *id, int locktype){
       ** If you are using this code as a model for alternative VFSes, do not
       ** copy this retry logic.  It is a hack intended for Windows only.
       */
-      OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n",
-               pFile->h, cnt, sqlite3ErrName(res)));
+      lastErrno = osGetLastError();
+      OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
+               pFile->h, cnt, res));
+      if( lastErrno==ERROR_INVALID_HANDLE ){
+        pFile->lastErrno = lastErrno;
+        rc = SQLITE_IOERR_LOCK;
+        OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
+                 pFile->h, cnt, sqlite3ErrName(rc)));
+        return rc;
+      }
       if( cnt ) sqlite3_win32_sleep(1);
     }
     gotPendingLock = res;
@@ -33375,7 +34956,7 @@ static int winLock(sqlite3_file *id, int locktype){
   */
   if( locktype==SHARED_LOCK && res ){
     assert( pFile->locktype==NO_LOCK );
-    res = getReadLock(pFile);
+    res = winGetReadLock(pFile);
     if( res ){
       newLocktype = SHARED_LOCK;
     }else{
@@ -33406,14 +34987,14 @@ static int winLock(sqlite3_file *id, int locktype){
   */
   if( locktype==EXCLUSIVE_LOCK && res ){
     assert( pFile->locktype>=SHARED_LOCK );
-    res = unlockReadLock(pFile);
+    res = winUnlockReadLock(pFile);
     res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
                       SHARED_SIZE, 0);
     if( res ){
       newLocktype = EXCLUSIVE_LOCK;
     }else{
       lastErrno = osGetLastError();
-      getReadLock(pFile);
+      winGetReadLock(pFile);
     }
   }
 
@@ -33430,10 +35011,10 @@ static int winLock(sqlite3_file *id, int locktype){
   if( res ){
     rc = SQLITE_OK;
   }else{
-    OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
-             pFile->h, locktype, newLocktype));
     pFile->lastErrno = lastErrno;
     rc = SQLITE_BUSY;
+    OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
+             pFile->h, locktype, newLocktype));
   }
   pFile->locktype = (u8)newLocktype;
   OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n",
@@ -33447,7 +35028,7 @@ static int winLock(sqlite3_file *id, int locktype){
 ** non-zero, otherwise zero.
 */
 static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
-  int rc;
+  int res;
   winFile *pFile = (winFile*)id;
 
   SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
@@ -33455,17 +35036,17 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
 
   assert( id!=0 );
   if( pFile->locktype>=RESERVED_LOCK ){
-    rc = 1;
-    OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc));
+    res = 1;
+    OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res));
   }else{
-    rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
-    if( rc ){
+    res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
+    if( res ){
       winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
     }
-    rc = !rc;
-    OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc));
+    res = !res;
+    OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res));
   }
-  *pResOut = rc;
+  *pResOut = res;
   OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
            pFile->h, pResOut, *pResOut));
   return SQLITE_OK;
@@ -33493,18 +35074,18 @@ static int winUnlock(sqlite3_file *id, int locktype){
   type = pFile->locktype;
   if( type>=EXCLUSIVE_LOCK ){
     winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
-    if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
+    if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){
       /* This should never happen.  We should always be able to
       ** reacquire the read lock */
       rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
-               "winUnlock", pFile->zPath);
+                       "winUnlock", pFile->zPath);
     }
   }
   if( type>=RESERVED_LOCK ){
     winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
   }
   if( locktype==NO_LOCK && type>=SHARED_LOCK ){
-    unlockReadLock(pFile);
+    winUnlockReadLock(pFile);
   }
   if( type>=PENDING_LOCK ){
     winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
@@ -33531,8 +35112,10 @@ static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
   }
 }
 
-/* Forward declaration */
-static int getTempname(int nBuf, char *zBuf);
+/* Forward references to VFS helper methods used for temporary files */
+static int winGetTempname(sqlite3_vfs *, char **);
+static int winIsDir(const void *);
+static BOOL winIsDriveLetterAndColon(const char *);
 
 /*
 ** Control and query of the open file handle.
@@ -33585,44 +35168,62 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
       return SQLITE_OK;
     }
     case SQLITE_FCNTL_VFSNAME: {
-      *(char**)pArg = sqlite3_mprintf("win32");
+      *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
       OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
       return SQLITE_OK;
     }
     case SQLITE_FCNTL_WIN32_AV_RETRY: {
       int *a = (int*)pArg;
       if( a[0]>0 ){
-        win32IoerrRetry = a[0];
+        winIoerrRetry = a[0];
       }else{
-        a[0] = win32IoerrRetry;
+        a[0] = winIoerrRetry;
       }
       if( a[1]>0 ){
-        win32IoerrRetryDelay = a[1];
+        winIoerrRetryDelay = a[1];
       }else{
-        a[1] = win32IoerrRetryDelay;
+        a[1] = winIoerrRetryDelay;
       }
       OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
       return SQLITE_OK;
     }
+#ifdef SQLITE_TEST
+    case SQLITE_FCNTL_WIN32_SET_HANDLE: {
+      LPHANDLE phFile = (LPHANDLE)pArg;
+      HANDLE hOldFile = pFile->h;
+      pFile->h = *phFile;
+      *phFile = hOldFile;
+      OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n",
+               hOldFile, pFile->h));
+      return SQLITE_OK;
+    }
+#endif
     case SQLITE_FCNTL_TEMPFILENAME: {
-      char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
-      if( zTFile ){
-        getTempname(pFile->pVfs->mxPathname, zTFile);
+      char *zTFile = 0;
+      int rc = winGetTempname(pFile->pVfs, &zTFile);
+      if( rc==SQLITE_OK ){
         *(char**)pArg = zTFile;
       }
-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-      return SQLITE_OK;
+      OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
+      return rc;
     }
 #if SQLITE_MAX_MMAP_SIZE>0
     case SQLITE_FCNTL_MMAP_SIZE: {
       i64 newLimit = *(i64*)pArg;
+      int rc = SQLITE_OK;
       if( newLimit>sqlite3GlobalConfig.mxMmap ){
         newLimit = sqlite3GlobalConfig.mxMmap;
       }
       *(i64*)pArg = pFile->mmapSizeMax;
-      if( newLimit>=0 ) pFile->mmapSizeMax = newLimit;
-      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-      return SQLITE_OK;
+      if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
+        pFile->mmapSizeMax = newLimit;
+        if( pFile->mmapSize>0 ){
+          winUnmapfile(pFile);
+          rc = winMapfile(pFile, -1);
+        }
+      }
+      OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
+      return rc;
     }
 #endif
   }
@@ -33654,23 +35255,23 @@ static int winDeviceCharacteristics(sqlite3_file *id){
          ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
 }
 
-/* 
+/*
 ** Windows will only let you create file view mappings
 ** on allocation size granularity boundaries.
 ** During sqlite3_os_init() we do a GetSystemInfo()
 ** to get the granularity size.
 */
-SYSTEM_INFO winSysInfo;
+static SYSTEM_INFO winSysInfo;
 
 #ifndef SQLITE_OMIT_WAL
 
 /*
 ** Helper functions to obtain and relinquish the global mutex. The
-** global mutex is used to protect the winLockInfo objects used by 
+** global mutex is used to protect the winLockInfo objects used by
 ** this file, all of which may be shared by multiple threads.
 **
-** Function winShmMutexHeld() is used to assert() that the global mutex 
-** is held when required. This function is only used as part of assert() 
+** Function winShmMutexHeld() is used to assert() that the global mutex
+** is held when required. This function is only used as part of assert()
 ** statements. e.g.
 **
 **   winShmEnterMutex()
@@ -33683,7 +35284,7 @@ static void winShmEnterMutex(void){
 static void winShmLeaveMutex(void){
   sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
 }
-#ifdef SQLITE_DEBUG
+#ifndef NDEBUG
 static int winShmMutexHeld(void) {
   return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
 }
@@ -33700,10 +35301,10 @@ static int winShmMutexHeld(void) {
 ** this object or while reading or writing the following fields:
 **
 **      nRef
-**      pNext 
+**      pNext
 **
 ** The following fields are read-only after the object is created:
-** 
+**
 **      fid
 **      zFilename
 **
@@ -33799,7 +35400,7 @@ static int winShmSystemLock(
     if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
     rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
   }
-  
+
   if( rc!= 0 ){
     rc = SQLITE_OK;
   }else{
@@ -33827,7 +35428,6 @@ static int winDelete(sqlite3_vfs *,const char*,int);
 static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
   winShmNode **pp;
   winShmNode *p;
-  BOOL bRc;
   assert( winShmMutexHeld() );
   OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
            osGetCurrentProcessId(), deleteFlag));
@@ -33835,14 +35435,16 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
   while( (p = *pp)!=0 ){
     if( p->nRef==0 ){
       int i;
-      if( p->mutex ) sqlite3_mutex_free(p->mutex);
+      if( p->mutex ){ sqlite3_mutex_free(p->mutex); }
       for(i=0; i<p->nRegion; i++){
-        bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
+        BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
         OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
                  osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
+        UNUSED_VARIABLE_VALUE(bRc);
         bRc = osCloseHandle(p->aRegion[i].hMap);
         OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
                  osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
+        UNUSED_VARIABLE_VALUE(bRc);
       }
       if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
         SimulateIOErrorBenign(1);
@@ -33894,7 +35496,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
   }
   pNew->zFilename = (char*)&pNew[1];
   sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
-  sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); 
+  sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
 
   /* Look to see if there is an existing winShmNode that can be used.
   ** If no matching winShmNode currently exists, create a new one.
@@ -33931,13 +35533,13 @@ static int winOpenSharedMemory(winFile *pDbFd){
     }
 
     /* Check to see if another process is holding the dead-man switch.
-    ** If not, truncate the file to zero length. 
+    ** If not, truncate the file to zero length.
     */
     if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
       rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
       if( rc!=SQLITE_OK ){
         rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
-                 "winOpenShm", pDbFd->zPath);
+                         "winOpenShm", pDbFd->zPath);
       }
     }
     if( rc==SQLITE_OK ){
@@ -33960,7 +35562,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
   ** the cover of the winShmEnterMutex() mutex and the pointer from the
   ** new (struct winShm) object to the pShmNode has been set. All that is
   ** left to do is to link the new object into the linked list starting
-  ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex 
+  ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
   ** mutex.
   */
   sqlite3_mutex_enter(pShmNode->mutex);
@@ -33980,7 +35582,7 @@ shm_open_err:
 }
 
 /*
-** Close a connection to shared-memory.  Delete the underlying 
+** Close a connection to shared-memory.  Delete the underlying
 ** storage if deleteFlag is true.
 */
 static int winShmUnmap(
@@ -34069,7 +35671,7 @@ static int winShmLock(
     if( rc==SQLITE_OK ){
       p->exclMask &= ~mask;
       p->sharedMask &= ~mask;
-    } 
+    }
   }else if( flags & SQLITE_SHM_SHARED ){
     u16 allShared = 0;  /* Union of locks held by connections other than "p" */
 
@@ -34108,7 +35710,7 @@ static int winShmLock(
         break;
       }
     }
-  
+
     /* Get the exclusive locks at the system level.  Then if successful
     ** also mark the local connection as being locked.
     */
@@ -34128,7 +35730,7 @@ static int winShmLock(
 }
 
 /*
-** Implement a memory barrier or memory fence on shared memory.  
+** Implement a memory barrier or memory fence on shared memory.
 **
 ** All loads and stores begun before the barrier must complete before
 ** any load or store begun after the barrier.
@@ -34143,22 +35745,22 @@ static void winShmBarrier(
 }
 
 /*
-** This function is called to obtain a pointer to region iRegion of the 
-** shared-memory associated with the database file fd. Shared-memory regions 
-** are numbered starting from zero. Each shared-memory region is szRegion 
+** This function is called to obtain a pointer to region iRegion of the
+** shared-memory associated with the database file fd. Shared-memory regions
+** are numbered starting from zero. Each shared-memory region is szRegion
 ** bytes in size.
 **
 ** If an error occurs, an error code is returned and *pp is set to NULL.
 **
 ** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
 ** region has not been allocated (by any client, including one running in a
-** separate process), then *pp is set to NULL and SQLITE_OK returned. If 
-** isWrite is non-zero and the requested shared-memory region has not yet 
+** separate process), then *pp is set to NULL and SQLITE_OK returned. If
+** isWrite is non-zero and the requested shared-memory region has not yet
 ** been allocated, it is allocated by this function.
 **
 ** If the shared-memory region has already been allocated or is allocated by
-** this call as described above, then it is mapped into this processes 
-** address space (if it is not already), *pp is set to point to the mapped 
+** this call as described above, then it is mapped into this processes
+** address space (if it is not already), *pp is set to point to the mapped
 ** memory and SQLITE_OK returned.
 */
 static int winShmMap(
@@ -34197,7 +35799,7 @@ static int winShmMap(
     rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
     if( rc!=SQLITE_OK ){
       rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
-               "winShmMap1", pDbFd->zPath);
+                       "winShmMap1", pDbFd->zPath);
       goto shmpage_out;
     }
 
@@ -34212,7 +35814,7 @@ static int winShmMap(
       rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
       if( rc!=SQLITE_OK ){
         rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
-                 "winShmMap2", pDbFd->zPath);
+                         "winShmMap2", pDbFd->zPath);
         goto shmpage_out;
       }
     }
@@ -34230,17 +35832,17 @@ static int winShmMap(
     while( pShmNode->nRegion<=iRegion ){
       HANDLE hMap = NULL;         /* file-mapping handle */
       void *pMap = 0;             /* Mapped memory region */
-     
+
 #if SQLITE_OS_WINRT
       hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
           NULL, PAGE_READWRITE, nByte, NULL
       );
 #elif defined(SQLITE_WIN32_HAS_WIDE)
-      hMap = osCreateFileMappingW(pShmNode->hFile.h, 
+      hMap = osCreateFileMappingW(pShmNode->hFile.h,
           NULL, PAGE_READWRITE, 0, nByte, NULL
       );
 #elif defined(SQLITE_WIN32_HAS_ANSI)
-      hMap = osCreateFileMappingA(pShmNode->hFile.h, 
+      hMap = osCreateFileMappingA(pShmNode->hFile.h,
           NULL, PAGE_READWRITE, 0, nByte, NULL
       );
 #endif
@@ -34266,7 +35868,7 @@ static int winShmMap(
       if( !pMap ){
         pShmNode->lastErrno = osGetLastError();
         rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
-                 "winShmMap3", pDbFd->zPath);
+                         "winShmMap3", pDbFd->zPath);
         if( hMap ) osCloseHandle(hMap);
         goto shmpage_out;
       }
@@ -34314,7 +35916,7 @@ static int winUnmapfile(winFile *pFile){
                "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile,
                pFile->pMapRegion));
       return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
-                         "winUnmap1", pFile->zPath);
+                         "winUnmapfile1", pFile->zPath);
     }
     pFile->pMapRegion = 0;
     pFile->mmapSize = 0;
@@ -34326,7 +35928,7 @@ static int winUnmapfile(winFile *pFile){
       OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n",
                osGetCurrentProcessId(), pFile, pFile->hMap));
       return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
-                         "winUnmap2", pFile->zPath);
+                         "winUnmapfile2", pFile->zPath);
     }
     pFile->hMap = NULL;
   }
@@ -34337,14 +35939,14 @@ static int winUnmapfile(winFile *pFile){
 
 /*
 ** Memory map or remap the file opened by file-descriptor pFd (if the file
-** is already mapped, the existing mapping is replaced by the new). Or, if 
-** there already exists a mapping for this file, and there are still 
+** is already mapped, the existing mapping is replaced by the new). Or, if
+** there already exists a mapping for this file, and there are still
 ** outstanding xFetch() references to it, this function is a no-op.
 **
-** If parameter nByte is non-negative, then it is the requested size of 
-** the mapping to create. Otherwise, if nByte is less than zero, then the 
+** If parameter nByte is non-negative, then it is the requested size of
+** the mapping to create. Otherwise, if nByte is less than zero, then the
 ** requested size is the size of the file on disk. The actual size of the
-** created mapping is either the requested size or the value configured 
+** created mapping is either the requested size or the value configured
 ** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
 **
 ** SQLITE_OK is returned if no error occurs (even if the mapping is not
@@ -34373,7 +35975,7 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
     nMap = pFd->mmapSizeMax;
   }
   nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
- 
+
   if( nMap==0 && pFd->mmapSize>0 ){
     winUnmapfile(pFd);
   }
@@ -34401,27 +36003,28 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
     if( pFd->hMap==NULL ){
       pFd->lastErrno = osGetLastError();
       rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
-                       "winMapfile", pFd->zPath);
+                       "winMapfile1", pFd->zPath);
       /* Log the error, but continue normal operation using xRead/xWrite */
-      OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
-               osGetCurrentProcessId(), pFd));
+      OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=%s\n",
+               osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
       return SQLITE_OK;
     }
     assert( (nMap % winSysInfo.dwPageSize)==0 );
+    assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
 #if SQLITE_OS_WINRT
-    pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, nMap);
+    pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap);
 #else
-    assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
     pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
 #endif
     if( pNew==NULL ){
       osCloseHandle(pFd->hMap);
       pFd->hMap = NULL;
       pFd->lastErrno = osGetLastError();
-      winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
-                  "winMapfile", pFd->zPath);
-      OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
-               osGetCurrentProcessId(), pFd));
+      rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
+                       "winMapfile2", pFd->zPath);
+      /* Log the error, but continue normal operation using xRead/xWrite */
+      OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=%s\n",
+               osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
       return SQLITE_OK;
     }
     pFd->pMapRegion = pNew;
@@ -34444,7 +36047,7 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
 ** Finally, if an error does occur, return an SQLite error code. The final
 ** value of *pp is undefined in this case.
 **
-** If this function does return a pointer, the caller must eventually 
+** If this function does return a pointer, the caller must eventually
 ** release the reference by calling winUnfetch().
 */
 static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
@@ -34479,20 +36082,20 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
 }
 
 /*
-** If the third argument is non-NULL, then this function releases a 
+** If the third argument is non-NULL, then this function releases a
 ** reference obtained by an earlier call to winFetch(). The second
 ** argument passed to this function must be the same as the corresponding
-** argument that was passed to the winFetch() invocation. 
+** argument that was passed to the winFetch() invocation.
 **
-** Or, if the third argument is NULL, then this function is being called 
-** to inform the VFS layer that, according to POSIX, any existing mapping 
+** Or, if the third argument is NULL, then this function is being called
+** to inform the VFS layer that, according to POSIX, any existing mapping
 ** may now be invalid and should be unmapped.
 */
 static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
 #if SQLITE_MAX_MMAP_SIZE>0
   winFile *pFd = (winFile*)fd;   /* The underlying database file */
 
-  /* If p==0 (unmap the entire file) then there must be no outstanding 
+  /* If p==0 (unmap the entire file) then there must be no outstanding
   ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
   ** then there must be at least one outstanding.  */
   assert( (p==0)==(pFd->nFetchOut==0) );
@@ -34560,16 +36163,37 @@ static const sqlite3_io_methods winIoMethod = {
 ** sqlite3_vfs object.
 */
 
+#if defined(__CYGWIN__)
+/*
+** Convert a filename from whatever the underlying operating system
+** supports for filenames into UTF-8.  Space to hold the result is
+** obtained from malloc and must be freed by the calling function.
+*/
+static char *winConvertToUtf8Filename(const void *zFilename){
+  char *zConverted = 0;
+  if( osIsNT() ){
+    zConverted = winUnicodeToUtf8(zFilename);
+  }
+#ifdef SQLITE_WIN32_HAS_ANSI
+  else{
+    zConverted = sqlite3_win32_mbcs_to_utf8(zFilename);
+  }
+#endif
+  /* caller will handle out of memory */
+  return zConverted;
+}
+#endif
+
 /*
 ** Convert a UTF-8 filename into whatever form the underlying
 ** operating system wants filenames in.  Space to hold the result
 ** is obtained from malloc and must be freed by the calling
 ** function.
 */
-static void *convertUtf8Filename(const char *zFilename){
+static void *winConvertFromUtf8Filename(const char *zFilename){
   void *zConverted = 0;
-  if( isNT() ){
-    zConverted = utf8ToUnicode(zFilename);
+  if( osIsNT() ){
+    zConverted = winUtf8ToUnicode(zFilename);
   }
 #ifdef SQLITE_WIN32_HAS_ANSI
   else{
@@ -34581,39 +36205,180 @@ static void *convertUtf8Filename(const char *zFilename){
 }
 
 /*
-** Create a temporary file name in zBuf.  zBuf must be big enough to
-** hold at pVfs->mxPathname characters.
+** This function returns non-zero if the specified UTF-8 string buffer
+** ends with a directory separator character or one was successfully
+** added to it.
+*/
+static int winMakeEndInDirSep(int nBuf, char *zBuf){
+  if( zBuf ){
+    int nLen = sqlite3Strlen30(zBuf);
+    if( nLen>0 ){
+      if( winIsDirSep(zBuf[nLen-1]) ){
+        return 1;
+      }else if( nLen+1<nBuf ){
+        zBuf[nLen] = winGetDirSep();
+        zBuf[nLen+1] = '\0';
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+/*
+** Create a temporary file name and store the resulting pointer into pzBuf.
+** The pointer returned in pzBuf must be freed via sqlite3_free().
 */
-static int getTempname(int nBuf, char *zBuf){
+static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
   static char zChars[] =
     "abcdefghijklmnopqrstuvwxyz"
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     "0123456789";
   size_t i, j;
-  int nTempPath;
-  char zTempPath[MAX_PATH+2];
+  int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX);
+  int nMax, nBuf, nDir, nLen;
+  char *zBuf;
 
   /* It's odd to simulate an io-error here, but really this is just
   ** using the io-error infrastructure to test that SQLite handles this
-  ** function failing. 
+  ** function failing.
   */
   SimulateIOError( return SQLITE_IOERR );
 
-  memset(zTempPath, 0, MAX_PATH+2);
+  /* Allocate a temporary buffer to store the fully qualified file
+  ** name for the temporary file.  If this fails, we cannot continue.
+  */
+  nMax = pVfs->mxPathname; nBuf = nMax + 2;
+  zBuf = sqlite3MallocZero( nBuf );
+  if( !zBuf ){
+    OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+    return SQLITE_IOERR_NOMEM;
+  }
 
+  /* Figure out the effective temporary directory.  First, check if one
+  ** has been explicitly set by the application; otherwise, use the one
+  ** configured by the operating system.
+  */
+  nDir = nMax - (nPre + 15);
+  assert( nDir>0 );
   if( sqlite3_temp_directory ){
-    sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
+    int nDirLen = sqlite3Strlen30(sqlite3_temp_directory);
+    if( nDirLen>0 ){
+      if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){
+        nDirLen++;
+      }
+      if( nDirLen>nDir ){
+        sqlite3_free(zBuf);
+        OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
+        return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0);
+      }
+      sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory);
+    }
   }
-#if !SQLITE_OS_WINRT
-  else if( isNT() ){
+#if defined(__CYGWIN__)
+  else{
+    static const char *azDirs[] = {
+       0, /* getenv("SQLITE_TMPDIR") */
+       0, /* getenv("TMPDIR") */
+       0, /* getenv("TMP") */
+       0, /* getenv("TEMP") */
+       0, /* getenv("USERPROFILE") */
+       "/var/tmp",
+       "/usr/tmp",
+       "/tmp",
+       ".",
+       0        /* List terminator */
+    };
+    unsigned int i;
+    const char *zDir = 0;
+
+    if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
+    if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
+    if( !azDirs[2] ) azDirs[2] = getenv("TMP");
+    if( !azDirs[3] ) azDirs[3] = getenv("TEMP");
+    if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE");
+    for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
+      void *zConverted;
+      if( zDir==0 ) continue;
+      /* If the path starts with a drive letter followed by the colon
+      ** character, assume it is already a native Win32 path; otherwise,
+      ** it must be converted to a native Win32 path via the Cygwin API
+      ** prior to using it.
+      */
+      if( winIsDriveLetterAndColon(zDir) ){
+        zConverted = winConvertFromUtf8Filename(zDir);
+        if( !zConverted ){
+          sqlite3_free(zBuf);
+          OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+          return SQLITE_IOERR_NOMEM;
+        }
+        if( winIsDir(zConverted) ){
+          sqlite3_snprintf(nMax, zBuf, "%s", zDir);
+          sqlite3_free(zConverted);
+          break;
+        }
+        sqlite3_free(zConverted);
+      }else{
+        zConverted = sqlite3MallocZero( nMax+1 );
+        if( !zConverted ){
+          sqlite3_free(zBuf);
+          OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+          return SQLITE_IOERR_NOMEM;
+        }
+        if( cygwin_conv_path(
+                osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir,
+                zConverted, nMax+1)<0 ){
+          sqlite3_free(zConverted);
+          sqlite3_free(zBuf);
+          OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
+          return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
+                             "winGetTempname2", zDir);
+        }
+        if( winIsDir(zConverted) ){
+          /* At this point, we know the candidate directory exists and should
+          ** be used.  However, we may need to convert the string containing
+          ** its name into UTF-8 (i.e. if it is UTF-16 right now).
+          */
+          char *zUtf8 = winConvertToUtf8Filename(zConverted);
+          if( !zUtf8 ){
+            sqlite3_free(zConverted);
+            sqlite3_free(zBuf);
+            OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+            return SQLITE_IOERR_NOMEM;
+          }
+          sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
+          sqlite3_free(zUtf8);
+          sqlite3_free(zConverted);
+          break;
+        }
+        sqlite3_free(zConverted);
+      }
+    }
+  }
+#elif !SQLITE_OS_WINRT && !defined(__CYGWIN__)
+  else if( osIsNT() ){
     char *zMulti;
-    WCHAR zWidePath[MAX_PATH];
-    osGetTempPathW(MAX_PATH-30, zWidePath);
-    zMulti = unicodeToUtf8(zWidePath);
+    LPWSTR zWidePath = sqlite3MallocZero( nMax*sizeof(WCHAR) );
+    if( !zWidePath ){
+      sqlite3_free(zBuf);
+      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+      return SQLITE_IOERR_NOMEM;
+    }
+    if( osGetTempPathW(nMax, zWidePath)==0 ){
+      sqlite3_free(zWidePath);
+      sqlite3_free(zBuf);
+      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
+      return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(),
+                         "winGetTempname2", 0);
+    }
+    zMulti = winUnicodeToUtf8(zWidePath);
     if( zMulti ){
-      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
+      sqlite3_snprintf(nMax, zBuf, "%s", zMulti);
       sqlite3_free(zMulti);
+      sqlite3_free(zWidePath);
     }else{
+      sqlite3_free(zWidePath);
+      sqlite3_free(zBuf);
       OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
       return SQLITE_IOERR_NOMEM;
     }
@@ -34621,36 +36386,62 @@ static int getTempname(int nBuf, char *zBuf){
 #ifdef SQLITE_WIN32_HAS_ANSI
   else{
     char *zUtf8;
-    char zMbcsPath[MAX_PATH];
-    osGetTempPathA(MAX_PATH-30, zMbcsPath);
+    char *zMbcsPath = sqlite3MallocZero( nMax );
+    if( !zMbcsPath ){
+      sqlite3_free(zBuf);
+      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+      return SQLITE_IOERR_NOMEM;
+    }
+    if( osGetTempPathA(nMax, zMbcsPath)==0 ){
+      sqlite3_free(zBuf);
+      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
+      return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(),
+                         "winGetTempname3", 0);
+    }
     zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
     if( zUtf8 ){
-      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
+      sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
       sqlite3_free(zUtf8);
     }else{
+      sqlite3_free(zBuf);
       OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
       return SQLITE_IOERR_NOMEM;
     }
   }
-#endif
-#endif
+#endif /* SQLITE_WIN32_HAS_ANSI */
+#endif /* !SQLITE_OS_WINRT */
 
-  /* Check that the output buffer is large enough for the temporary file 
-  ** name. If it is not, return SQLITE_ERROR.
+  /*
+  ** Check to make sure the temporary directory ends with an appropriate
+  ** separator.  If it does not and there is not enough space left to add
+  ** one, fail.
   */
-  nTempPath = sqlite3Strlen30(zTempPath);
+  if( !winMakeEndInDirSep(nDir+1, zBuf) ){
+    sqlite3_free(zBuf);
+    OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
+    return winLogError(SQLITE_ERROR, 0, "winGetTempname4", 0);
+  }
 
-  if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
+  /*
+  ** Check that the output buffer is large enough for the temporary file
+  ** name in the following format:
+  **
+  **   "<temporary_directory>/etilqs_XXXXXXXXXXXXXXX\0\0"
+  **
+  ** If not, return SQLITE_ERROR.  The number 17 is used here in order to
+  ** account for the space used by the 15 character random suffix and the
+  ** two trailing NUL characters.  The final directory separator character
+  ** has already added if it was not already present.
+  */
+  nLen = sqlite3Strlen30(zBuf);
+  if( (nLen + nPre + 17) > nBuf ){
+    sqlite3_free(zBuf);
     OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
-    return SQLITE_ERROR;
+    return winLogError(SQLITE_ERROR, 0, "winGetTempname5", 0);
   }
 
-  for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){}
-  zTempPath[i] = 0;
+  sqlite3_snprintf(nBuf-16-nLen, zBuf+nLen, SQLITE_TEMP_FILE_PREFIX);
 
-  sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ?
-                       "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX,
-                   zTempPath);
   j = sqlite3Strlen30(zBuf);
   sqlite3_randomness(15, &zBuf[j]);
   for(i=0; i<15; i++, j++){
@@ -34658,6 +36449,7 @@ static int getTempname(int nBuf, char *zBuf){
   }
   zBuf[j] = 0;
   zBuf[j+1] = 0;
+  *pzBuf = zBuf;
 
   OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf));
   return SQLITE_OK;
@@ -34673,13 +36465,13 @@ static int winIsDir(const void *zConverted){
   int rc = 0;
   DWORD lastErrno;
 
-  if( isNT() ){
+  if( osIsNT() ){
     int cnt = 0;
     WIN32_FILE_ATTRIBUTE_DATA sAttrData;
     memset(&sAttrData, 0, sizeof(sAttrData));
     while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
                              GetFileExInfoStandard,
-                             &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
+                             &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
     if( !rc ){
       return 0; /* Invalid name? */
     }
@@ -34696,14 +36488,14 @@ static int winIsDir(const void *zConverted){
 ** Open a file.
 */
 static int winOpen(
-  sqlite3_vfs *pVfs,        /* Not used */
+  sqlite3_vfs *pVfs,        /* Used to get maximum path name length */
   const char *zName,        /* Name of the file (UTF-8) */
   sqlite3_file *id,         /* Write the SQLite file handle here */
   int flags,                /* Open mode flags */
   int *pOutFlags            /* Status return flags */
 ){
   HANDLE h;
-  DWORD lastErrno;
+  DWORD lastErrno = 0;
   DWORD dwDesiredAccess;
   DWORD dwShareMode;
   DWORD dwCreationDisposition;
@@ -34719,7 +36511,7 @@ static int winOpen(
   /* If argument zPath is a NULL pointer, this function is required to open
   ** a temporary file. Use this buffer to store the file name in.
   */
-  char zTmpname[MAX_PATH+2];     /* Buffer used to create temp filename */
+  char *zTmpname = 0; /* For temporary filename, if necessary. */
 
   int rc = SQLITE_OK;            /* Function Return Code */
 #if !defined(NDEBUG) || SQLITE_OS_WINCE
@@ -34734,8 +36526,8 @@ static int winOpen(
 
 #ifndef NDEBUG
   int isOpenJournal = (isCreate && (
-        eType==SQLITE_OPEN_MASTER_JOURNAL 
-     || eType==SQLITE_OPEN_MAIN_JOURNAL 
+        eType==SQLITE_OPEN_MASTER_JOURNAL
+     || eType==SQLITE_OPEN_MAIN_JOURNAL
      || eType==SQLITE_OPEN_WAL
   ));
 #endif
@@ -34743,9 +36535,9 @@ static int winOpen(
   OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
            zUtf8Name, id, flags, pOutFlags));
 
-  /* Check the following statements are true: 
+  /* Check the following statements are true:
   **
-  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
+  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and
   **   (b) if CREATE is set, then READWRITE must also be set, and
   **   (c) if EXCLUSIVE is set, then CREATE must also be set.
   **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
@@ -34755,7 +36547,7 @@ static int winOpen(
   assert(isExclusive==0 || isCreate);
   assert(isDelete==0 || isCreate);
 
-  /* The main DB, main journal, WAL file and master journal are never 
+  /* The main DB, main journal, WAL file and master journal are never
   ** automatically deleted. Nor are they ever temporary files.  */
   assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
   assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
@@ -34763,9 +36555,9 @@ static int winOpen(
   assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
 
   /* Assert that the upper layer has set one of the "file-type" flags. */
-  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
-       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
-       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
+  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB
+       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
+       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL
        || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
   );
 
@@ -34774,19 +36566,18 @@ static int winOpen(
   pFile->h = INVALID_HANDLE_VALUE;
 
 #if SQLITE_OS_WINRT
-  if( !sqlite3_temp_directory ){
+  if( !zUtf8Name && !sqlite3_temp_directory ){
     sqlite3_log(SQLITE_ERROR,
         "sqlite3_temp_directory variable should be set for WinRT");
   }
 #endif
 
-  /* If the second argument to this function is NULL, generate a 
-  ** temporary file name to use 
+  /* If the second argument to this function is NULL, generate a
+  ** temporary file name to use
   */
   if( !zUtf8Name ){
-    assert(isDelete && !isOpenJournal);
-    memset(zTmpname, 0, MAX_PATH+2);
-    rc = getTempname(MAX_PATH+2, zTmpname);
+    assert( isDelete && !isOpenJournal );
+    rc = winGetTempname(pVfs, &zTmpname);
     if( rc!=SQLITE_OK ){
       OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
       return rc;
@@ -34799,17 +36590,19 @@ static int winOpen(
   ** sqlite3_uri_parameter().
   */
   assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
-        zUtf8Name[strlen(zUtf8Name)+1]==0 );
+       zUtf8Name[sqlite3Strlen30(zUtf8Name)+1]==0 );
 
   /* Convert the filename to the system encoding. */
-  zConverted = convertUtf8Filename(zUtf8Name);
+  zConverted = winConvertFromUtf8Filename(zUtf8Name);
   if( zConverted==0 ){
+    sqlite3_free(zTmpname);
     OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
     return SQLITE_IOERR_NOMEM;
   }
 
   if( winIsDir(zConverted) ){
     sqlite3_free(zConverted);
+    sqlite3_free(zTmpname);
     OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
     return SQLITE_CANTOPEN_ISDIR;
   }
@@ -34820,8 +36613,8 @@ static int winOpen(
     dwDesiredAccess = GENERIC_READ;
   }
 
-  /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is 
-  ** created. SQLite doesn't use it to indicate "exclusive access" 
+  /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
+  ** created. SQLite doesn't use it to indicate "exclusive access"
   ** as it is usually understood.
   */
   if( isExclusive ){
@@ -34856,7 +36649,7 @@ static int winOpen(
   dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
 #endif
 
-  if( isNT() ){
+  if( osIsNT() ){
 #if SQLITE_OS_WINRT
     CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
     extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
@@ -34871,7 +36664,7 @@ static int winOpen(
                               dwShareMode,
                               dwCreationDisposition,
                               &extendedParameters))==INVALID_HANDLE_VALUE &&
-                              retryIoerr(&cnt, &lastErrno) ){
+                              winRetryIoerr(&cnt, &lastErrno) ){
                /* Noop */
     }
 #else
@@ -34881,7 +36674,7 @@ static int winOpen(
                               dwCreationDisposition,
                               dwFlagsAndAttributes,
                               NULL))==INVALID_HANDLE_VALUE &&
-                              retryIoerr(&cnt, &lastErrno) ){
+                              winRetryIoerr(&cnt, &lastErrno) ){
                /* Noop */
     }
 #endif
@@ -34894,12 +36687,12 @@ static int winOpen(
                               dwCreationDisposition,
                               dwFlagsAndAttributes,
                               NULL))==INVALID_HANDLE_VALUE &&
-                              retryIoerr(&cnt, &lastErrno) ){
+                              winRetryIoerr(&cnt, &lastErrno) ){
                /* Noop */
     }
   }
 #endif
-  logIoerr(cnt);
+  winLogIoerr(cnt);
 
   OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
            dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
@@ -34908,8 +36701,9 @@ static int winOpen(
     pFile->lastErrno = lastErrno;
     winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
     sqlite3_free(zConverted);
+    sqlite3_free(zTmpname);
     if( isReadWrite && !isExclusive ){
-      return winOpen(pVfs, zName, id, 
+      return winOpen(pVfs, zName, id,
          ((flags|SQLITE_OPEN_READONLY) &
                      ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
          pOutFlags);
@@ -34936,6 +36730,7 @@ static int winOpen(
   ){
     osCloseHandle(h);
     sqlite3_free(zConverted);
+    sqlite3_free(zTmpname);
     OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
     return rc;
   }
@@ -34947,6 +36742,7 @@ static int winOpen(
     sqlite3_free(zConverted);
   }
 
+  sqlite3_free(zTmpname);
   pFile->pMethod = &winIoMethod;
   pFile->pVfs = pVfs;
   pFile->h = h;
@@ -34990,7 +36786,7 @@ static int winDelete(
   int cnt = 0;
   int rc;
   DWORD attr;
-  DWORD lastErrno;
+  DWORD lastErrno = 0;
   void *zConverted;
   UNUSED_PARAMETER(pVfs);
   UNUSED_PARAMETER(syncDir);
@@ -34998,11 +36794,12 @@ static int winDelete(
   SimulateIOError(return SQLITE_IOERR_DELETE);
   OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir));
 
-  zConverted = convertUtf8Filename(zFilename);
+  zConverted = winConvertFromUtf8Filename(zFilename);
   if( zConverted==0 ){
+    OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
     return SQLITE_IOERR_NOMEM;
   }
-  if( isNT() ){
+  if( osIsNT() ){
     do {
 #if SQLITE_OS_WINRT
       WIN32_FILE_ATTRIBUTE_DATA sAttrData;
@@ -35041,7 +36838,7 @@ static int winDelete(
         rc = SQLITE_OK; /* Deleted OK. */
         break;
       }
-      if ( !retryIoerr(&cnt, &lastErrno) ){
+      if ( !winRetryIoerr(&cnt, &lastErrno) ){
         rc = SQLITE_ERROR; /* No more retries. */
         break;
       }
@@ -35069,7 +36866,7 @@ static int winDelete(
         rc = SQLITE_OK; /* Deleted OK. */
         break;
       }
-      if ( !retryIoerr(&cnt, &lastErrno) ){
+      if ( !winRetryIoerr(&cnt, &lastErrno) ){
         rc = SQLITE_ERROR; /* No more retries. */
         break;
       }
@@ -35077,10 +36874,9 @@ static int winDelete(
   }
 #endif
   if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
-    rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
-             "winDelete", zFilename);
+    rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename);
   }else{
-    logIoerr(cnt);
+    winLogIoerr(cnt);
   }
   sqlite3_free(zConverted);
   OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
@@ -35098,7 +36894,7 @@ static int winAccess(
 ){
   DWORD attr;
   int rc = 0;
-  DWORD lastErrno;
+  DWORD lastErrno = 0;
   void *zConverted;
   UNUSED_PARAMETER(pVfs);
 
@@ -35106,35 +36902,35 @@ static int winAccess(
   OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
            zFilename, flags, pResOut));
 
-  zConverted = convertUtf8Filename(zFilename);
+  zConverted = winConvertFromUtf8Filename(zFilename);
   if( zConverted==0 ){
     OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
     return SQLITE_IOERR_NOMEM;
   }
-  if( isNT() ){
+  if( osIsNT() ){
     int cnt = 0;
     WIN32_FILE_ATTRIBUTE_DATA sAttrData;
     memset(&sAttrData, 0, sizeof(sAttrData));
     while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
-                             GetFileExInfoStandard, 
-                             &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
+                             GetFileExInfoStandard,
+                             &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
     if( rc ){
       /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
       ** as if it does not exist.
       */
       if(    flags==SQLITE_ACCESS_EXISTS
-          && sAttrData.nFileSizeHigh==0 
+          && sAttrData.nFileSizeHigh==0
           && sAttrData.nFileSizeLow==0 ){
         attr = INVALID_FILE_ATTRIBUTES;
       }else{
         attr = sAttrData.dwFileAttributes;
       }
     }else{
-      logIoerr(cnt);
+      winLogIoerr(cnt);
       if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
-        winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
         sqlite3_free(zConverted);
-        return SQLITE_IOERR_ACCESS;
+        return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
+                           zFilename);
       }else{
         attr = INVALID_FILE_ATTRIBUTES;
       }
@@ -35164,6 +36960,15 @@ static int winAccess(
   return SQLITE_OK;
 }
 
+/*
+** Returns non-zero if the specified path name starts with a drive letter
+** followed by a colon character.
+*/
+static BOOL winIsDriveLetterAndColon(
+  const char *zPathname
+){
+  return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' );
+}
 
 /*
 ** Returns non-zero if the specified path name should be used verbatim.  If
@@ -35181,7 +36986,7 @@ static BOOL winIsVerbatimPathname(
   ** the final two cases; therefore, we return the safer return value of TRUE
   ** so that callers of this function will simply use it verbatim.
   */
-  if ( zPathname[0]=='/' || zPathname[0]=='\\' ){
+  if ( winIsDirSep(zPathname[0]) ){
     return TRUE;
   }
 
@@ -35191,7 +36996,7 @@ static BOOL winIsVerbatimPathname(
   ** attempt to treat it as a relative path name (i.e. they should simply use
   ** it verbatim).
   */
-  if ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ){
+  if ( winIsDriveLetterAndColon(zPathname) ){
     return TRUE;
   }
 
@@ -35213,11 +37018,10 @@ static int winFullPathname(
   int nFull,                    /* Size of output buffer in bytes */
   char *zFull                   /* Output buffer */
 ){
-  
+
 #if defined(__CYGWIN__)
   SimulateIOError( return SQLITE_ERROR );
   UNUSED_PARAMETER(nFull);
-  assert( pVfs->mxPathname>=MAX_PATH );
   assert( nFull>=pVfs->mxPathname );
   if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
     /*
@@ -35226,14 +37030,48 @@ static int winFullPathname(
     **       for converting the relative path name to an absolute
     **       one by prepending the data directory and a slash.
     */
-    char zOut[MAX_PATH+1];
-    memset(zOut, 0, MAX_PATH+1);
-    cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
-                     MAX_PATH+1);
-    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
-                     sqlite3_data_directory, zOut);
+    char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
+    if( !zOut ){
+      return SQLITE_IOERR_NOMEM;
+    }
+    if( cygwin_conv_path(
+            (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) |
+            CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){
+      sqlite3_free(zOut);
+      return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
+                         "winFullPathname1", zRelative);
+    }else{
+      char *zUtf8 = winConvertToUtf8Filename(zOut);
+      if( !zUtf8 ){
+        sqlite3_free(zOut);
+        return SQLITE_IOERR_NOMEM;
+      }
+      sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
+                       sqlite3_data_directory, winGetDirSep(), zUtf8);
+      sqlite3_free(zUtf8);
+      sqlite3_free(zOut);
+    }
   }else{
-    cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
+    char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
+    if( !zOut ){
+      return SQLITE_IOERR_NOMEM;
+    }
+    if( cygwin_conv_path(
+            (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A),
+            zRelative, zOut, pVfs->mxPathname+1)<0 ){
+      sqlite3_free(zOut);
+      return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
+                         "winFullPathname2", zRelative);
+    }else{
+      char *zUtf8 = winConvertToUtf8Filename(zOut);
+      if( !zUtf8 ){
+        sqlite3_free(zOut);
+        return SQLITE_IOERR_NOMEM;
+      }
+      sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
+      sqlite3_free(zUtf8);
+      sqlite3_free(zOut);
+    }
   }
   return SQLITE_OK;
 #endif
@@ -35249,8 +37087,8 @@ static int winFullPathname(
     **       for converting the relative path name to an absolute
     **       one by prepending the data directory and a backslash.
     */
-    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
-                     sqlite3_data_directory, zRelative);
+    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
+                     sqlite3_data_directory, winGetDirSep(), zRelative);
   }else{
     sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
   }
@@ -35265,7 +37103,7 @@ static int winFullPathname(
   /* If this path name begins with "/X:", where "X" is any alphabetic
   ** character, discard the initial "/" from the pathname.
   */
-  if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
+  if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){
     zRelative++;
   }
 
@@ -35282,22 +37120,21 @@ static int winFullPathname(
     **       for converting the relative path name to an absolute
     **       one by prepending the data directory and a backslash.
     */
-    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
-                     sqlite3_data_directory, zRelative);
+    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
+                     sqlite3_data_directory, winGetDirSep(), zRelative);
     return SQLITE_OK;
   }
-  zConverted = convertUtf8Filename(zRelative);
+  zConverted = winConvertFromUtf8Filename(zRelative);
   if( zConverted==0 ){
     return SQLITE_IOERR_NOMEM;
   }
-  if( isNT() ){
+  if( osIsNT() ){
     LPWSTR zTemp;
     nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
     if( nByte==0 ){
-      winLogError(SQLITE_ERROR, osGetLastError(),
-                  "GetFullPathNameW1", zConverted);
       sqlite3_free(zConverted);
-      return SQLITE_CANTOPEN_FULLPATH;
+      return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
+                         "winFullPathname1", zRelative);
     }
     nByte += 3;
     zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
@@ -35307,14 +37144,13 @@ static int winFullPathname(
     }
     nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
     if( nByte==0 ){
-      winLogError(SQLITE_ERROR, osGetLastError(),
-                  "GetFullPathNameW2", zConverted);
       sqlite3_free(zConverted);
       sqlite3_free(zTemp);
-      return SQLITE_CANTOPEN_FULLPATH;
+      return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
+                         "winFullPathname2", zRelative);
     }
     sqlite3_free(zConverted);
-    zOut = unicodeToUtf8(zTemp);
+    zOut = winUnicodeToUtf8(zTemp);
     sqlite3_free(zTemp);
   }
 #ifdef SQLITE_WIN32_HAS_ANSI
@@ -35322,10 +37158,9 @@ static int winFullPathname(
     char *zTemp;
     nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
     if( nByte==0 ){
-      winLogError(SQLITE_ERROR, osGetLastError(),
-                  "GetFullPathNameA1", zConverted);
       sqlite3_free(zConverted);
-      return SQLITE_CANTOPEN_FULLPATH;
+      return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
+                         "winFullPathname3", zRelative);
     }
     nByte += 3;
     zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
@@ -35335,11 +37170,10 @@ static int winFullPathname(
     }
     nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
     if( nByte==0 ){
-      winLogError(SQLITE_ERROR, osGetLastError(),
-                  "GetFullPathNameA2", zConverted);
       sqlite3_free(zConverted);
       sqlite3_free(zTemp);
-      return SQLITE_CANTOPEN_FULLPATH;
+      return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
+                         "winFullPathname4", zRelative);
     }
     sqlite3_free(zConverted);
     zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
@@ -35361,18 +37195,32 @@ static int winFullPathname(
 ** Interfaces for opening a shared library, finding entry points
 ** within the shared library, and closing the shared library.
 */
-/*
-** Interfaces for opening a shared library, finding entry points
-** within the shared library, and closing the shared library.
-*/
 static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
   HANDLE h;
-  void *zConverted = convertUtf8Filename(zFilename);
+#if defined(__CYGWIN__)
+  int nFull = pVfs->mxPathname+1;
+  char *zFull = sqlite3MallocZero( nFull );
+  void *zConverted = 0;
+  if( zFull==0 ){
+    OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
+    return 0;
+  }
+  if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
+    sqlite3_free(zFull);
+    OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
+    return 0;
+  }
+  zConverted = winConvertFromUtf8Filename(zFull);
+  sqlite3_free(zFull);
+#else
+  void *zConverted = winConvertFromUtf8Filename(zFilename);
   UNUSED_PARAMETER(pVfs);
+#endif
   if( zConverted==0 ){
+    OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
     return 0;
   }
-  if( isNT() ){
+  if( osIsNT() ){
 #if SQLITE_OS_WINRT
     h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
 #else
@@ -35384,20 +37232,26 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
     h = osLoadLibraryA((char*)zConverted);
   }
 #endif
+  OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h));
   sqlite3_free(zConverted);
   return (void*)h;
 }
 static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
   UNUSED_PARAMETER(pVfs);
-  getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
+  winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut);
 }
 static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
+  FARPROC proc;
   UNUSED_PARAMETER(pVfs);
-  return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
+  proc = osGetProcAddressA((HANDLE)pH, zSym);
+  OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n",
+           (void*)pH, zSym, (void*)proc));
+  return (void(*)(void))proc;
 }
 static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
   UNUSED_PARAMETER(pVfs);
   osFreeLibrary((HANDLE)pHandle);
+  OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle));
 }
 #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
   #define winDlOpen  0
@@ -35477,12 +37331,12 @@ SQLITE_API int sqlite3_current_time = 0;  /* Fake system time in seconds since 1
 ** epoch of noon in Greenwich on November 24, 4714 B.C according to the
 ** proleptic Gregorian calendar.
 **
-** On success, return SQLITE_OK.  Return SQLITE_ERROR if the time and date 
+** On success, return SQLITE_OK.  Return SQLITE_ERROR if the time and date
 ** cannot be found.
 */
 static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
-  /* FILETIME structure is a 64-bit value representing the number of 
-     100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). 
+  /* FILETIME structure is a 64-bit value representing the number of
+     100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
   */
   FILETIME ft;
   static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
@@ -35490,7 +37344,7 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
   static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
 #endif
   /* 2^32 - to avoid use of LL and warnings in gcc */
-  static const sqlite3_int64 max32BitValue = 
+  static const sqlite3_int64 max32BitValue =
       (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
       (sqlite3_int64)294967296;
 
@@ -35506,7 +37360,7 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
 #endif
 
   *piNow = winFiletimeEpoch +
-            ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + 
+            ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
                (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
 
 #ifdef SQLITE_TEST
@@ -35565,7 +37419,7 @@ static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
 */
 static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
   UNUSED_PARAMETER(pVfs);
-  return getLastErrorMsg(osGetLastError(), nBuf, zBuf);
+  return winGetLastErrorMsg(osGetLastError(), nBuf, zBuf);
 }
 
 /*
@@ -35575,7 +37429,7 @@ SQLITE_API int sqlite3_os_init(void){
   static sqlite3_vfs winVfs = {
     3,                   /* iVersion */
     sizeof(winFile),     /* szOsFile */
-    MAX_PATH,            /* mxPathname */
+    SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */
     0,                   /* pNext */
     "win32",             /* zName */
     0,                   /* pAppData */
@@ -35596,10 +37450,36 @@ SQLITE_API int sqlite3_os_init(void){
     winGetSystemCall,    /* xGetSystemCall */
     winNextSystemCall,   /* xNextSystemCall */
   };
+#if defined(SQLITE_WIN32_HAS_WIDE)
+  static sqlite3_vfs winLongPathVfs = {
+    3,                   /* iVersion */
+    sizeof(winFile),     /* szOsFile */
+    SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */
+    0,                   /* pNext */
+    "win32-longpath",    /* zName */
+    0,                   /* pAppData */
+    winOpen,             /* xOpen */
+    winDelete,           /* xDelete */
+    winAccess,           /* xAccess */
+    winFullPathname,     /* xFullPathname */
+    winDlOpen,           /* xDlOpen */
+    winDlError,          /* xDlError */
+    winDlSym,            /* xDlSym */
+    winDlClose,          /* xDlClose */
+    winRandomness,       /* xRandomness */
+    winSleep,            /* xSleep */
+    winCurrentTime,      /* xCurrentTime */
+    winGetLastError,     /* xGetLastError */
+    winCurrentTimeInt64, /* xCurrentTimeInt64 */
+    winSetSystemCall,    /* xSetSystemCall */
+    winGetSystemCall,    /* xGetSystemCall */
+    winNextSystemCall,   /* xNextSystemCall */
+  };
+#endif
 
   /* Double-check that the aSyscall[] array has been constructed
   ** correctly.  See ticket [bb3a86e890c8e96ab] */
-  assert( ArraySize(aSyscall)==74 );
+  assert( ArraySize(aSyscall)==77 );
 
   /* get memory map allocation granularity */
   memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
@@ -35612,10 +37492,15 @@ SQLITE_API int sqlite3_os_init(void){
   assert( winSysInfo.dwPageSize>0 );
 
   sqlite3_vfs_register(&winVfs, 1);
-  return SQLITE_OK; 
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+  sqlite3_vfs_register(&winLongPathVfs, 0);
+#endif
+
+  return SQLITE_OK;
 }
 
-SQLITE_API int sqlite3_os_end(void){ 
+SQLITE_API int sqlite3_os_end(void){
 #if SQLITE_OS_WINRT
   if( sleepObj!=NULL ){
     osCloseHandle(sleepObj);
@@ -36062,7 +37947,8 @@ struct PCache {
   int szCache;                        /* Configured cache size */
   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 */
+  u8 bPurgeable;                      /* True if pages are on backing store */
+  u8 eCreate;                         /* eCreate value for for xFetch() */
   int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
   void *pStress;                      /* Argument to xStress */
   sqlite3_pcache *pCache;             /* Pluggable cache module */
@@ -36129,6 +38015,10 @@ static void pcacheRemoveFromDirtyList(PgHdr *pPage){
   }else{
     assert( pPage==p->pDirty );
     p->pDirty = pPage->pDirtyNext;
+    if( p->pDirty==0 && p->bPurgeable ){
+      assert( p->eCreate==1 );
+      p->eCreate = 2;
+    }
   }
   pPage->pDirtyNext = 0;
   pPage->pDirtyPrev = 0;
@@ -36149,6 +38039,9 @@ static void pcacheAddToDirtyList(PgHdr *pPage){
   if( pPage->pDirtyNext ){
     assert( pPage->pDirtyNext->pDirtyPrev==0 );
     pPage->pDirtyNext->pDirtyPrev = pPage;
+  }else if( p->bPurgeable ){
+    assert( p->eCreate==2 );
+    p->eCreate = 1;
   }
   p->pDirty = pPage;
   if( !p->pDirtyTail ){
@@ -36218,6 +38111,7 @@ SQLITE_PRIVATE void sqlite3PcacheOpen(
   p->szPage = szPage;
   p->szExtra = szExtra;
   p->bPurgeable = bPurgeable;
+  p->eCreate = 2;
   p->xStress = xStress;
   p->pStress = pStress;
   p->szCache = 100;
@@ -36257,7 +38151,7 @@ SQLITE_PRIVATE int sqlite3PcacheFetch(
   int createFlag,       /* If true, create page if it does not exist already */
   PgHdr **ppPage        /* Write the page here */
 ){
-  sqlite3_pcache_page *pPage = 0;
+  sqlite3_pcache_page *pPage;
   PgHdr *pPgHdr = 0;
   int eCreate;
 
@@ -36268,8 +38162,12 @@ SQLITE_PRIVATE int sqlite3PcacheFetch(
   /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
   ** allocate it now.
   */
-  if( !pCache->pCache && createFlag ){
+  if( !pCache->pCache ){
     sqlite3_pcache *p;
+    if( !createFlag ){
+      *ppPage = 0;
+      return SQLITE_OK;
+    }
     p = sqlite3GlobalConfig.pcache2.xCreate(
         pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
     );
@@ -36280,11 +38178,16 @@ SQLITE_PRIVATE int sqlite3PcacheFetch(
     pCache->pCache = p;
   }
 
-  eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
-  if( pCache->pCache ){
-    pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
-  }
-
+  /* eCreate defines what to do if the page does not exist.
+  **    0     Do not allocate a new page.  (createFlag==0)
+  **    1     Allocate a new page if doing so is inexpensive.
+  **          (createFlag==1 AND bPurgeable AND pDirty)
+  **    2     Allocate a new page even it doing so is difficult.
+  **          (createFlag==1 AND !(bPurgeable AND pDirty)
+  */
+  eCreate = createFlag==0 ? 0 : pCache->eCreate;
+  assert( (createFlag*(1+(!pCache->bPurgeable||!pCache->pDirty)))==eCreate );
+  pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
   if( !pPage && eCreate==1 ){
     PgHdr *pPg;
 
@@ -36756,6 +38659,7 @@ struct PCache1 {
 struct PgHdr1 {
   sqlite3_pcache_page page;
   unsigned int iKey;             /* Key value (page number) */
+  u8 isPinned;                   /* Page in use, not on the LRU list */
   PgHdr1 *pNext;                 /* Next in hash table chain */
   PCache1 *pCache;               /* Cache that currently owns this page */
   PgHdr1 *pLruNext;              /* Next in LRU list of unpinned pages */
@@ -37084,34 +38988,32 @@ static int pcache1ResizeHash(PCache1 *p){
 ** LRU list, then this function is a no-op.
 **
 ** The PGroup mutex must be held when this function is called.
-**
-** If pPage is NULL then this routine is a no-op.
 */
 static void pcache1PinPage(PgHdr1 *pPage){
   PCache1 *pCache;
   PGroup *pGroup;
 
-  if( pPage==0 ) return;
+  assert( pPage!=0 );
+  assert( pPage->isPinned==0 );
   pCache = pPage->pCache;
   pGroup = pCache->pGroup;
+  assert( pPage->pLruNext || pPage==pGroup->pLruTail );
+  assert( pPage->pLruPrev || pPage==pGroup->pLruHead );
   assert( sqlite3_mutex_held(pGroup->mutex) );
-  if( pPage->pLruNext || pPage==pGroup->pLruTail ){
-    if( pPage->pLruPrev ){
-      pPage->pLruPrev->pLruNext = pPage->pLruNext;
-    }
-    if( pPage->pLruNext ){
-      pPage->pLruNext->pLruPrev = pPage->pLruPrev;
-    }
-    if( pGroup->pLruHead==pPage ){
-      pGroup->pLruHead = pPage->pLruNext;
-    }
-    if( pGroup->pLruTail==pPage ){
-      pGroup->pLruTail = pPage->pLruPrev;
-    }
-    pPage->pLruNext = 0;
-    pPage->pLruPrev = 0;
-    pPage->pCache->nRecyclable--;
+  if( pPage->pLruPrev ){
+    pPage->pLruPrev->pLruNext = pPage->pLruNext;
+  }else{
+    pGroup->pLruHead = pPage->pLruNext;
+  }
+  if( pPage->pLruNext ){
+    pPage->pLruNext->pLruPrev = pPage->pLruPrev;
+  }else{
+    pGroup->pLruTail = pPage->pLruPrev;
   }
+  pPage->pLruNext = 0;
+  pPage->pLruPrev = 0;
+  pPage->isPinned = 1;
+  pCache->nRecyclable--;
 }
 
 
@@ -37143,6 +39045,7 @@ static void pcache1EnforceMaxPage(PGroup *pGroup){
   while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
     PgHdr1 *p = pGroup->pLruTail;
     assert( p->pCache->pGroup==pGroup );
+    assert( p->isPinned==0 );
     pcache1PinPage(p);
     pcache1RemoveFromHash(p);
     pcache1FreePage(p);
@@ -37170,7 +39073,7 @@ static void pcache1TruncateUnsafe(
       if( pPage->iKey>=iLimit ){
         pCache->nPage--;
         *pp = pPage->pNext;
-        pcache1PinPage(pPage);
+        if( !pPage->isPinned ) pcache1PinPage(pPage);
         pcache1FreePage(pPage);
       }else{
         pp = &pPage->pNext;
@@ -37222,7 +39125,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
   int sz;               /* Bytes of memory required to allocate the new cache */
 
   /*
-  ** The seperateCache variable is true if each PCache has its own private
+  ** The separateCache variable is true if each PCache has its own private
   ** PGroup.  In other words, separateCache is true for mode (1) where no
   ** mutexing is required.
   **
@@ -37380,6 +39283,7 @@ static sqlite3_pcache_page *pcache1Fetch(
   PGroup *pGroup;
   PgHdr1 *pPage = 0;
 
+  assert( offsetof(PgHdr1,page)==0 );
   assert( pCache->bPurgeable || createFlag!=1 );
   assert( pCache->bPurgeable || pCache->nMin==0 );
   assert( pCache->bPurgeable==0 || pCache->nMin==10 );
@@ -37393,8 +39297,11 @@ static sqlite3_pcache_page *pcache1Fetch(
   }
 
   /* Step 2: Abort if no existing page is found and createFlag is 0 */
-  if( pPage || createFlag==0 ){
-    pcache1PinPage(pPage);
+  if( pPage ){
+    if( !pPage->isPinned ) pcache1PinPage(pPage);
+    goto fetch_out;
+  }
+  if( createFlag==0 ){
     goto fetch_out;
   }
 
@@ -37425,6 +39332,7 @@ static sqlite3_pcache_page *pcache1Fetch(
   if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
     goto fetch_out;
   }
+  assert( pCache->nHash>0 && pCache->apHash );
 
   /* Step 4. Try to recycle a page. */
   if( pCache->bPurgeable && pGroup->pLruTail && (
@@ -37434,6 +39342,7 @@ static sqlite3_pcache_page *pcache1Fetch(
   )){
     PCache1 *pOther;
     pPage = pGroup->pLruTail;
+    assert( pPage->isPinned==0 );
     pcache1RemoveFromHash(pPage);
     pcache1PinPage(pPage);
     pOther = pPage->pCache;
@@ -37470,6 +39379,7 @@ static sqlite3_pcache_page *pcache1Fetch(
     pPage->pCache = pCache;
     pPage->pLruPrev = 0;
     pPage->pLruNext = 0;
+    pPage->isPinned = 1;
     *(void **)pPage->page.pExtra = 0;
     pCache->apHash[h] = pPage;
   }
@@ -37479,7 +39389,7 @@ fetch_out:
     pCache->iMaxKey = iKey;
   }
   pcache1LeaveMutex(pGroup);
-  return &pPage->page;
+  return (sqlite3_pcache_page*)pPage;
 }
 
 
@@ -37505,6 +39415,7 @@ static void pcache1Unpin(
   */
   assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
   assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
+  assert( pPage->isPinned==1 );
 
   if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
     pcache1RemoveFromHash(pPage);
@@ -37520,6 +39431,7 @@ static void pcache1Unpin(
       pGroup->pLruHead = pPage;
     }
     pCache->nRecyclable++;
+    pPage->isPinned = 0;
   }
 
   pcache1LeaveMutex(pCache->pGroup);
@@ -37646,6 +39558,7 @@ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
 #ifdef SQLITE_PCACHE_SEPARATE_HEADER
       nFree += sqlite3MemSize(p);
 #endif
+      assert( p->isPinned==0 );
       pcache1PinPage(p);
       pcache1RemoveFromHash(p);
       pcache1FreePage(p);
@@ -37670,6 +39583,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats(
   PgHdr1 *p;
   int nRecyclable = 0;
   for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
+    assert( p->isPinned==0 );
     nRecyclable++;
   }
   *pnCurrent = pcache1.grp.nCurrentPage;
@@ -37794,8 +39708,8 @@ struct RowSet {
   struct RowSetEntry *pFresh;    /* Source of new entry objects */
   struct RowSetEntry *pForest;   /* List of binary trees of entries */
   u16 nFresh;                    /* Number of objects on pFresh */
-  u8 rsFlags;                    /* Various flags */
-  u8 iBatch;                     /* Current insert batch */
+  u16 rsFlags;                   /* Various flags */
+  int iBatch;                    /* Current insert batch */
 };
 
 /*
@@ -38129,7 +40043,7 @@ SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
 ** on pRowSet->pEntry, then sort those entires into the forest at
 ** pRowSet->pForest so that they can be tested.
 */
-SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){
+SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
   struct RowSetEntry *p, *pTree;
 
   /* This routine is never called after sqlite3RowSetNext() */
@@ -38786,6 +40700,13 @@ struct PagerSavepoint {
 };
 
 /*
+** Bits of the Pager.doNotSpill flag.  See further description below.
+*/
+#define SPILLFLAG_OFF         0x01      /* Never spill cache.  Set via pragma */
+#define SPILLFLAG_ROLLBACK    0x02      /* Current rolling back, so do not spill */
+#define SPILLFLAG_NOSYNC      0x04      /* Spill is ok, but do not sync */
+
+/*
 ** A open page cache is an instance of struct Pager. A description of
 ** some of the more important member variables follows:
 **
@@ -38851,19 +40772,21 @@ struct PagerSavepoint {
 **   journal file from being successfully finalized, the setMaster flag
 **   is cleared anyway (and the pager will move to ERROR state).
 **
-** doNotSpill, doNotSyncSpill
+** doNotSpill
 **
-**   These two boolean variables control the behavior of cache-spills
-**   (calls made by the pcache module to the pagerStress() routine to
-**   write cached data to the file-system in order to free up memory).
+**   This variables control the behavior of cache-spills  (calls made by
+**   the pcache module to the pagerStress() routine to write cached data
+**   to the file-system in order to free up memory).
 **
-**   When doNotSpill is non-zero, writing to the database from pagerStress()
-**   is disabled altogether. This is done in a very obscure case that
+**   When bits SPILLFLAG_OFF or SPILLFLAG_ROLLBACK of doNotSpill are set,
+**   writing to the database from pagerStress() is disabled altogether.
+**   The SPILLFLAG_ROLLBACK case is done in a very obscure case that
 **   comes up during savepoint rollback that requires the pcache module
 **   to allocate a new page to prevent the journal file from being written
-**   while it is being traversed by code in pager_playback().
+**   while it is being traversed by code in pager_playback().  The SPILLFLAG_OFF
+**   case is a user preference.
 ** 
-**   If doNotSyncSpill is non-zero, writing to the database from pagerStress()
+**   If the SPILLFLAG_NOSYNC bit is set, writing to the database from pagerStress()
 **   is permitted, but syncing the journal file is not. This flag is set
 **   by sqlite3PagerWrite() when the file-system sector-size is larger than
 **   the database page-size in order to prevent a journal sync from happening 
@@ -38949,7 +40872,8 @@ struct Pager {
   u8 ckptSyncFlags;           /* SYNC_NORMAL or SYNC_FULL for checkpoint */
   u8 walSyncFlags;            /* SYNC_NORMAL or SYNC_FULL for wal writes */
   u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
-  u8 tempFile;                /* zFilename is a temporary file */
+  u8 tempFile;                /* zFilename is a temporary or immutable file */
+  u8 noLock;                  /* Do not lock (except in WAL mode) */
   u8 readOnly;                /* True for a read-only database */
   u8 memDb;                   /* True to inhibit all file I/O */
 
@@ -38967,7 +40891,6 @@ struct Pager {
   u8 changeCountDone;         /* Set after incrementing the change-counter */
   u8 setMaster;               /* True if a m-j name has been written to jrnl */
   u8 doNotSpill;              /* Do not spill the cache when non-zero */
-  u8 doNotSyncSpill;          /* Do not do a spill that requires jrnl sync */
   u8 subjInMemory;            /* True to use in-memory sub-journals */
   Pgno dbSize;                /* Number of pages in the database */
   Pgno dbOrigSize;            /* dbSize before the current transaction */
@@ -39346,11 +41269,12 @@ static char *print_pager_state(Pager *p){
 **     PagerSavepoint.pInSavepoint.
 */
 static int subjRequiresPage(PgHdr *pPg){
-  Pgno pgno = pPg->pgno;
   Pager *pPager = pPg->pPager;
+  PagerSavepoint *p;
+  Pgno pgno = pPg->pgno;
   int i;
   for(i=0; i<pPager->nSavepoint; i++){
-    PagerSavepoint *p = &pPager->aSavepoint[i];
+    p = &pPager->aSavepoint[i];
     if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
       return 1;
     }
@@ -39361,8 +41285,8 @@ static int subjRequiresPage(PgHdr *pPg){
 /*
 ** Return true if the page is already in the journal file.
 */
-static int pageInJournal(PgHdr *pPg){
-  return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
+static int pageInJournal(Pager *pPager, PgHdr *pPg){
+  return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno);
 }
 
 /*
@@ -39414,7 +41338,7 @@ static int pagerUnlockDb(Pager *pPager, int eLock){
   assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
   if( isOpen(pPager->fd) ){
     assert( pPager->eLock>=eLock );
-    rc = sqlite3OsUnlock(pPager->fd, eLock);
+    rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
     if( pPager->eLock!=UNKNOWN_LOCK ){
       pPager->eLock = (u8)eLock;
     }
@@ -39438,7 +41362,7 @@ static int pagerLockDb(Pager *pPager, int eLock){
 
   assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
   if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
-    rc = sqlite3OsLock(pPager->fd, eLock);
+    rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock);
     if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
       pPager->eLock = (u8)eLock;
       IOTRACE(("LOCK %p %d\n", pPager, eLock))
@@ -39569,6 +41493,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
    || szJ<16
    || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
    || len>=nMaster 
+   || len==0 
    || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
    || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
    || memcmp(aMagic, aJournalMagic, 8)
@@ -39946,12 +41871,11 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
 
   if( !zMaster 
    || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
-   || pPager->journalMode==PAGER_JOURNALMODE_OFF 
+   || !isOpen(pPager->jfd)
   ){
     return SQLITE_OK;
   }
   pPager->setMaster = 1;
-  assert( isOpen(pPager->jfd) );
   assert( pPager->journalHdr <= pPager->journalOff );
 
   /* Calculate the length in bytes and the checksum of zMaster */
@@ -40005,7 +41929,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
 ** already in memory.
 */
 static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
-  PgHdr *p;                         /* Return value */
+  PgHdr *p = 0;                     /* Return value */
 
   /* It is not possible for a call to PcacheFetch() with createFlag==0 to
   ** fail, since no attempt to allocate dynamic memory will be made.
@@ -40144,6 +42068,7 @@ static void pager_unlock(Pager *pPager){
     pPager->changeCountDone = pPager->tempFile;
     pPager->eState = PAGER_OPEN;
     pPager->errCode = SQLITE_OK;
+    if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
   }
 
   pPager->journalOff = 0;
@@ -40308,7 +42233,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
     PgHdr *p = pager_lookup(pPager, 1);
     if( p ){
       p->pageHash = 0;
-      sqlite3PagerUnref(p);
+      sqlite3PagerUnrefNotNull(p);
     }
   }
 #endif
@@ -40337,6 +42262,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
     rc = pager_truncate(pPager, pPager->dbSize);
   }
 
+  if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){
+    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
+    if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
+  }
+
   if( !pPager->exclusiveMode 
    && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
   ){
@@ -40626,11 +42556,11 @@ static int pager_playback_one_page(
     ** requiring a journal-sync before it is written.
     */
     assert( isSavepnt );
-    assert( pPager->doNotSpill==0 );
-    pPager->doNotSpill++;
+    assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
+    pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
     rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
-    assert( pPager->doNotSpill==1 );
-    pPager->doNotSpill--;
+    assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
+    pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
     if( rc!=SQLITE_OK ) return rc;
     pPg->flags &= ~PGHDR_NEED_READ;
     sqlite3PcacheMakeDirty(pPg);
@@ -41150,7 +43080,7 @@ end_playback:
   if( rc==SQLITE_OK
    && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
   ){
-    rc = sqlite3PagerSync(pPager);
+    rc = sqlite3PagerSync(pPager, 0);
   }
   if( rc==SQLITE_OK ){
     rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
@@ -41197,12 +43127,6 @@ static int readDbPage(PgHdr *pPg, u32 iFrame){
   assert( pPager->eState>=PAGER_READER && !MEMDB );
   assert( isOpen(pPager->fd) );
 
-  if( NEVER(!isOpen(pPager->fd)) ){
-    assert( pPager->tempFile );
-    memset(pPg->pData, 0, pPager->pageSize);
-    return SQLITE_OK;
-  }
-
 #ifndef SQLITE_OMIT_WAL
   if( iFrame ){
     /* Try to pull the page from the write-ahead log. */
@@ -41302,7 +43226,7 @@ static int pagerUndoCallback(void *pCtx, Pgno iPg){
       if( rc==SQLITE_OK ){
         pPager->xReiniter(pPg);
       }
-      sqlite3PagerUnref(pPg);
+      sqlite3PagerUnrefNotNull(pPg);
     }
   }
 
@@ -41710,10 +43634,10 @@ SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
 static void pagerFixMaplimit(Pager *pPager){
 #if SQLITE_MAX_MMAP_SIZE>0
   sqlite3_file *fd = pPager->fd;
-  if( isOpen(fd) ){
+  if( isOpen(fd) && fd->pMethods->iVersion>=3 ){
     sqlite3_int64 sz;
-    pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->szMmap>0;
     sz = pPager->szMmap;
+    pPager->bUseFetch = (sz>0);
     sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
   }
 #endif
@@ -41735,9 +43659,12 @@ SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
 }
 
 /*
-** 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:
+** Adjust settings of the pager to those specified in the pgFlags parameter.
+**
+** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness
+** of the database to damage due to OS crashes or power failures by
+** changing the number of syncs()s when writing the journals.
+** There are three levels:
 **
 **    OFF       sqlite3OsSync() is never called.  This is the default
 **              for temporary and transient files.
@@ -41778,22 +43705,21 @@ SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
 ** and FULL=3.
 */
 #ifndef SQLITE_OMIT_PAGER_PRAGMAS
-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
+SQLITE_PRIVATE void sqlite3PagerSetFlags(
   Pager *pPager,        /* The pager to set safety level for */
-  int level,            /* PRAGMA synchronous.  1=OFF, 2=NORMAL, 3=FULL */  
-  int bFullFsync,       /* PRAGMA fullfsync */
-  int bCkptFullFsync    /* PRAGMA checkpoint_fullfsync */
+  unsigned pgFlags      /* Various flags */
 ){
+  unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
   assert( level>=1 && level<=3 );
   pPager->noSync =  (level==1 || pPager->tempFile) ?1:0;
   pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
   if( pPager->noSync ){
     pPager->syncFlags = 0;
     pPager->ckptSyncFlags = 0;
-  }else if( bFullFsync ){
+  }else if( pgFlags & PAGER_FULLFSYNC ){
     pPager->syncFlags = SQLITE_SYNC_FULL;
     pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
-  }else if( bCkptFullFsync ){
+  }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){
     pPager->syncFlags = SQLITE_SYNC_NORMAL;
     pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
   }else{
@@ -41804,6 +43730,11 @@ SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
   if( pPager->fullSync ){
     pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
   }
+  if( pgFlags & PAGER_CACHESPILL ){
+    pPager->doNotSpill &= ~SPILLFLAG_OFF;
+  }else{
+    pPager->doNotSpill |= SPILLFLAG_OFF;
+  }
 }
 #endif
 
@@ -42546,7 +44477,8 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
   */
   assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
   if( rc==SQLITE_OK 
-   && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize 
+   && pPager->dbHintSize<pPager->dbSize
+   && (pList->pDirty || pList->pgno>pPager->dbHintSize)
   ){
     sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
     sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
@@ -42649,7 +44581,7 @@ static int subjournalPage(PgHdr *pPg){
     assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
     assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
     assert( pagerUseWal(pPager) 
-         || pageInJournal(pPg) 
+         || pageInJournal(pPager, pPg) 
          || pPg->pgno>pPager->dbOrigSize 
     );
     rc = openSubJournal(pPager);
@@ -42703,13 +44635,14 @@ static int pagerStress(void *p, PgHdr *pPg){
   assert( pPg->pPager==pPager );
   assert( pPg->flags&PGHDR_DIRTY );
 
-  /* The doNotSyncSpill flag is set during times when doing a sync of
+  /* The doNotSpill NOSYNC bit is set during times when doing a sync of
   ** journal (and adding a new header) is not allowed.  This occurs
   ** during calls to sqlite3PagerWrite() while trying to journal multiple
   ** pages belonging to the same sector.
   **
-  ** The doNotSpill flag inhibits all cache spilling regardless of whether
-  ** or not a sync is required.  This is set during a rollback.
+  ** The doNotSpill ROLLBACK and OFF bits inhibits all cache spilling
+  ** regardless of whether or not a sync is required.  This is set during
+  ** a rollback or by user request, respectively.
   **
   ** Spilling is also prohibited when in an error state since that could
   ** lead to database corruption.   In the current implementaton it 
@@ -42719,8 +44652,13 @@ static int pagerStress(void *p, PgHdr *pPg){
   ** test for the error state as a safeguard against future changes.
   */
   if( NEVER(pPager->errCode) ) return SQLITE_OK;
-  if( pPager->doNotSpill ) return SQLITE_OK;
-  if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
+  testcase( pPager->doNotSpill & SPILLFLAG_ROLLBACK );
+  testcase( pPager->doNotSpill & SPILLFLAG_OFF );
+  testcase( pPager->doNotSpill & SPILLFLAG_NOSYNC );
+  if( pPager->doNotSpill
+   && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0
+      || (pPg->flags & PGHDR_NEED_SYNC)!=0)
+  ){
     return SQLITE_OK;
   }
 
@@ -42983,30 +44921,38 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
     **    + The value returned by sqlite3OsSectorSize()
     **    + The largest page size that can be written atomically.
     */
-    if( rc==SQLITE_OK && !readOnly ){
-      setSectorSize(pPager);
-      assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
-      if( szPageDflt<pPager->sectorSize ){
-        if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
-          szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
-        }else{
-          szPageDflt = (u32)pPager->sectorSize;
+    if( rc==SQLITE_OK ){
+      int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
+      if( !readOnly ){
+        setSectorSize(pPager);
+        assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
+        if( szPageDflt<pPager->sectorSize ){
+          if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
+            szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
+          }else{
+            szPageDflt = (u32)pPager->sectorSize;
+          }
         }
-      }
 #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;
+        {
+          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
+      }
+      pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
+      if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
+       || sqlite3_uri_boolean(zFilename, "immutable", 0) ){
+          vfsFlags |= SQLITE_OPEN_READONLY;
+          goto act_like_temp_file;
+      }
     }
   }else{
     /* If a temporary file is requested, it is not opened immediately.
@@ -43016,10 +44962,14 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
     ** This branch is also run for an in-memory database. An in-memory
     ** database is the same as a temp-file that is never written out to
     ** disk and uses an in-memory rollback journal.
+    **
+    ** This branch also runs for files marked as immutable.
     */ 
+act_like_temp_file:
     tempFile = 1;
-    pPager->eState = PAGER_READER;
-    pPager->eLock = EXCLUSIVE_LOCK;
+    pPager->eState = PAGER_READER;     /* Pretend we already have a lock */
+    pPager->eLock = EXCLUSIVE_LOCK;    /* Pretend we are in EXCLUSIVE locking mode */
+    pPager->noLock = 1;                /* Do no locking */
     readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
   }
 
@@ -43060,9 +45010,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
   /* pPager->nPage = 0; */
   pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
   /* pPager->state = PAGER_UNLOCK; */
-#if 0
-  assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
-#endif
   /* pPager->errMask = 0; */
   pPager->tempFile = (u8)tempFile;
   assert( tempFile==PAGER_LOCKINGMODE_NORMAL 
@@ -43108,6 +45055,30 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
 }
 
 
+/* Verify that the database file has not be deleted or renamed out from
+** under the pager.  Return SQLITE_OK if the database is still were it ought
+** to be on disk.  Return non-zero (SQLITE_READONLY_DBMOVED or some other error
+** code from sqlite3OsAccess()) if the database has gone missing.
+*/
+static int databaseIsUnmoved(Pager *pPager){
+  int bHasMoved = 0;
+  int rc;
+
+  if( pPager->tempFile ) return SQLITE_OK;
+  if( pPager->dbSize==0 ) return SQLITE_OK;
+  assert( pPager->zFilename && pPager->zFilename[0] );
+  rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
+  if( rc==SQLITE_NOTFOUND ){
+    /* If the HAS_MOVED file-control is unimplemented, assume that the file
+    ** has not been moved.  That is the historical behavior of SQLite: prior to
+    ** version 3.8.3, it never checked */
+    rc = SQLITE_OK;
+  }else if( rc==SQLITE_OK && bHasMoved ){
+    rc = SQLITE_READONLY_DBMOVED;
+  }
+  return rc;
+}
+
 
 /*
 ** This function is called after transitioning from PAGER_UNLOCK to
@@ -43173,15 +45144,17 @@ static int hasHotJournal(Pager *pPager, int *pExists){
     if( rc==SQLITE_OK && !locked ){
       Pgno nPage;                 /* Number of pages in database file */
 
-      /* Check the size of the database file. If it consists of 0 pages,
-      ** then delete the journal file. See the header comment above for 
-      ** the reasoning here.  Delete the obsolete journal file under
-      ** a RESERVED lock to avoid race conditions and to avoid violating
-      ** [H33020].
-      */
       rc = pagerPagecount(pPager, &nPage);
       if( rc==SQLITE_OK ){
-        if( nPage==0 ){
+        /* If the database is zero pages in size, that means that either (1) the
+        ** journal is a remnant from a prior database with the same name where
+        ** the database file but not the journal was deleted, or (2) the initial
+        ** transaction that populates a new database is being rolled back.
+        ** In either case, the journal file can be deleted.  However, take care
+        ** not to delete the journal file if it is already open due to
+        ** journal_mode=PERSIST.
+        */
+        if( nPage==0 && !jrnlOpen ){
           sqlite3BeginBenignMalloc();
           if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
             sqlite3OsDelete(pVfs, pPager->zJournal, 0);
@@ -43511,7 +45484,7 @@ static void pagerUnlockIfUnused(Pager *pPager){
 ** page is initialized to all zeros. 
 **
 ** If noContent is true, it means that we do not care about the contents
-** of the page. This occurs in two seperate scenarios:
+** of the page. This occurs in two scenarios:
 **
 **   a) When reading a free-list leaf page from the database, and
 **
@@ -43542,19 +45515,19 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
   Pager *pPager,      /* The pager open on the database file */
   Pgno pgno,          /* Page number to fetch */
   DbPage **ppPage,    /* Write a pointer to the page here */
-  int flags           /* PAGER_ACQUIRE_XXX flags */
+  int flags           /* PAGER_GET_XXX flags */
 ){
   int rc = SQLITE_OK;
   PgHdr *pPg = 0;
   u32 iFrame = 0;                 /* Frame to read from WAL file */
-  const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);
+  const int noContent = (flags & PAGER_GET_NOCONTENT);
 
   /* It is acceptable to use a read-only (mmap) page for any page except
   ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
   ** flag was specified by the caller. And so long as the db is not a 
   ** temporary or in-memory database.  */
   const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
-   && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
+   && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
 #ifdef SQLITE_HAS_CODEC
    && pPager->xCodec==0
 #endif
@@ -43579,7 +45552,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
       if( rc!=SQLITE_OK ) goto pager_acquire_err;
     }
 
-    if( iFrame==0 && bMmapOk ){
+    if( bMmapOk && iFrame==0 ){
       void *pData = 0;
 
       rc = sqlite3OsFetch(pPager->fd, 
@@ -43720,16 +45693,19 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
 ** are released, a rollback occurs and the lock on the database is
 ** removed.
 */
-SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
-  if( pPg ){
-    Pager *pPager = pPg->pPager;
-    if( pPg->flags & PGHDR_MMAP ){
-      pagerReleaseMapPage(pPg);
-    }else{
-      sqlite3PcacheRelease(pPg);
-    }
-    pagerUnlockIfUnused(pPager);
+SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){
+  Pager *pPager;
+  assert( pPg!=0 );
+  pPager = pPg->pPager;
+  if( pPg->flags & PGHDR_MMAP ){
+    pagerReleaseMapPage(pPg);
+  }else{
+    sqlite3PcacheRelease(pPg);
   }
+  pagerUnlockIfUnused(pPager);
+}
+SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
+  if( pPg ) sqlite3PagerUnrefNotNull(pPg);
 }
 
 /*
@@ -43784,13 +45760,19 @@ static int pager_open_journal(Pager *pPager){
             (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
             (SQLITE_OPEN_MAIN_JOURNAL)
           );
-  #ifdef SQLITE_ENABLE_ATOMIC_WRITE
-        rc = sqlite3JournalOpen(
-            pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
-        );
-  #else
-        rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
-  #endif
+
+        /* Verify that the database still has the same name as it did when
+        ** it was originally opened. */
+        rc = databaseIsUnmoved(pPager);
+        if( rc==SQLITE_OK ){
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+          rc = sqlite3JournalOpen(
+              pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
+          );
+#else
+          rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
+#endif
+        }
       }
       assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
     }
@@ -43911,9 +45893,9 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory
 ** of any open savepoints as appropriate.
 */
 static int pager_write(PgHdr *pPg){
-  void *pData = pPg->pData;
   Pager *pPager = pPg->pPager;
   int rc = SQLITE_OK;
+  int inJournal;
 
   /* This routine is not called unless a write-transaction has already 
   ** been started. The journal file may or may not be open at this point.
@@ -43924,14 +45906,8 @@ static int pager_write(PgHdr *pPg){
        || pPager->eState==PAGER_WRITER_DBMOD
   );
   assert( assert_pager_state(pPager) );
-
-  /* If an error has been previously detected, report the same error
-  ** again. This should not happen, but the check provides robustness. */
-  if( NEVER(pPager->errCode) )  return pPager->errCode;
-
-  /* Higher-level routines never call this function if database is not
-  ** writable.  But check anyway, just for robustness. */
-  if( NEVER(pPager->readOnly) ) return SQLITE_PERM;
+  assert( pPager->errCode==0 );
+  assert( pPager->readOnly==0 );
 
   CHECK_PAGE(pPg);
 
@@ -43955,7 +45931,8 @@ static int pager_write(PgHdr *pPg){
   ** to the journal then we can return right away.
   */
   sqlite3PcacheMakeDirty(pPg);
-  if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
+  inJournal = pageInJournal(pPager, pPg);
+  if( inJournal && (pPager->nSavepoint==0 || !subjRequiresPage(pPg)) ){
     assert( !pagerUseWal(pPager) );
   }else{
   
@@ -43963,7 +45940,7 @@ static int pager_write(PgHdr *pPg){
     ** EXCLUSIVE lock on the main database file.  Write the current page to
     ** the transaction journal if it is not there already.
     */
-    if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){
+    if( !inJournal && !pagerUseWal(pPager) ){
       assert( pagerUseWal(pPager)==0 );
       if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){
         u32 cksum;
@@ -43976,7 +45953,7 @@ static int pager_write(PgHdr *pPg){
         assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
 
         assert( pPager->journalHdr<=pPager->journalOff );
-        CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
+        CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
         cksum = pager_cksum(pPager, (u8*)pData2);
 
         /* Even if an IO or diskfull error occurs while journalling the
@@ -44028,7 +46005,7 @@ static int pager_write(PgHdr *pPg){
     ** the statement journal format differs from the standard journal format
     ** in that it omits the checksums and the header.
     */
-    if( subjRequiresPage(pPg) ){
+    if( pPager->nSavepoint>0 && subjRequiresPage(pPg) ){
       rc = subjournalPage(pPg);
     }
   }
@@ -44060,27 +46037,27 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
 
   PgHdr *pPg = pDbPage;
   Pager *pPager = pPg->pPager;
-  Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
 
   assert( (pPg->flags & PGHDR_MMAP)==0 );
   assert( pPager->eState>=PAGER_WRITER_LOCKED );
   assert( pPager->eState!=PAGER_ERROR );
   assert( assert_pager_state(pPager) );
 
-  if( nPagePerSector>1 ){
+  if( pPager->sectorSize > (u32)pPager->pageSize ){
     Pgno nPageCount;          /* Total number of pages in database file */
     Pgno pg1;                 /* First page of the sector pPg is located on. */
     int nPage = 0;            /* Number of pages starting at pg1 to journal */
     int ii;                   /* Loop counter */
     int needSync = 0;         /* True if any page has PGHDR_NEED_SYNC */
+    Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
 
-    /* Set the doNotSyncSpill flag to 1. This is because we cannot allow
+    /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
     ** a journal header to be written between the pages journaled by
     ** this function.
     */
     assert( !MEMDB );
-    assert( pPager->doNotSyncSpill==0 );
-    pPager->doNotSyncSpill++;
+    assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
+    pPager->doNotSpill |= SPILLFLAG_NOSYNC;
 
     /* This trick assumes that both the page-size and sector-size are
     ** an integer power of 2. It sets variable pg1 to the identifier
@@ -44111,14 +46088,14 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
             if( pPage->flags&PGHDR_NEED_SYNC ){
               needSync = 1;
             }
-            sqlite3PagerUnref(pPage);
+            sqlite3PagerUnrefNotNull(pPage);
           }
         }
       }else if( (pPage = pager_lookup(pPager, pg))!=0 ){
         if( pPage->flags&PGHDR_NEED_SYNC ){
           needSync = 1;
         }
-        sqlite3PagerUnref(pPage);
+        sqlite3PagerUnrefNotNull(pPage);
       }
     }
 
@@ -44134,13 +46111,13 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
         PgHdr *pPage = pager_lookup(pPager, pg1+ii);
         if( pPage ){
           pPage->flags |= PGHDR_NEED_SYNC;
-          sqlite3PagerUnref(pPage);
+          sqlite3PagerUnrefNotNull(pPage);
         }
       }
     }
 
-    assert( pPager->doNotSyncSpill==1 );
-    pPager->doNotSyncSpill--;
+    assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
+    pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
   }else{
     rc = pager_write(pDbPage);
   }
@@ -44287,17 +46264,17 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
 ** If successful, or if called on a pager for which it is a no-op, this
 ** function returns SQLITE_OK. Otherwise, an IO error code is returned.
 */
-SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){
   int rc = SQLITE_OK;
-  if( !pPager->noSync ){
+
+  if( isOpen(pPager->fd) ){
+    void *pArg = (void*)zMaster;
+    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
+    if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
+  }
+  if( rc==SQLITE_OK && !pPager->noSync ){
     assert( !MEMDB );
     rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
-  }else if( isOpen(pPager->fd) ){
-    assert( !MEMDB );
-    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0);
-    if( rc==SQLITE_NOTFOUND ){
-      rc = SQLITE_OK;
-    }
   }
   return rc;
 }
@@ -44496,7 +46473,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
   
       /* Finally, sync the database file. */
       if( !noSync ){
-        rc = sqlite3PagerSync(pPager);
+        rc = sqlite3PagerSync(pPager, zMaster);
       }
       IOTRACE(("DBSYNC %p\n", pPager))
     }
@@ -44625,7 +46602,9 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
 
   assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
   assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
-          || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
+          || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR 
+          || rc==SQLITE_CANTOPEN
+  );
 
   /* 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.
@@ -44921,7 +46900,27 @@ SQLITE_PRIVATE void sqlite3PagerSetCodec(
 SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
   return pPager->pCodec;
 }
-#endif
+
+/*
+** This function is called by the wal module when writing page content
+** into the log file.
+**
+** This function returns a pointer to a buffer containing the encrypted
+** page content. If a malloc fails, this function may return NULL.
+*/
+SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
+  void *aData = 0;
+  CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
+  return aData;
+}
+
+/*
+** Return the current pager state
+*/
+SQLITE_PRIVATE int sqlite3PagerState(Pager *pPager){
+  return pPager->eState;
+}
+#endif /* SQLITE_HAS_CODEC */
 
 #ifndef SQLITE_OMIT_AUTOVACUUM
 /*
@@ -45008,7 +47007,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
   if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
     needSyncPgno = pPg->pgno;
     assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
-            pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
+            pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize );
     assert( pPg->flags&PGHDR_DIRTY );
   }
 
@@ -45042,7 +47041,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
   if( MEMDB ){
     assert( pPgOld );
     sqlite3PcacheMove(pPgOld, origPgno);
-    sqlite3PagerUnref(pPgOld);
+    sqlite3PagerUnrefNotNull(pPgOld);
   }
 
   if( needSyncPgno ){
@@ -45071,7 +47070,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
     }
     pPgHdr->flags |= PGHDR_NEED_SYNC;
     sqlite3PcacheMakeDirty(pPgHdr);
-    sqlite3PagerUnref(pPgHdr);
+    sqlite3PagerUnrefNotNull(pPgHdr);
   }
 
   return SQLITE_OK;
@@ -45476,21 +47475,6 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
 }
 #endif
 
-#ifdef SQLITE_HAS_CODEC
-/*
-** This function is called by the wal module when writing page content
-** into the log file.
-**
-** This function returns a pointer to a buffer containing the encrypted
-** page content. If a malloc fails, this function may return NULL.
-*/
-SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
-  void *aData = 0;
-  CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
-  return aData;
-}
-#endif /* SQLITE_HAS_CODEC */
-
 #endif /* SQLITE_OMIT_DISKIO */
 
 /************** End of pager.c ***********************************************/
@@ -46802,7 +48786,7 @@ SQLITE_PRIVATE int sqlite3WalOpen(
     sqlite3OsClose(pRet->pWalFd);
     sqlite3_free(pRet);
   }else{
-    int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd);
+    int iDC = sqlite3OsDeviceCharacteristics(pDbFd);
     if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; }
     if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){
       pRet->padToSectorBoundary = 0;
@@ -47592,8 +49576,8 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
   ** calls to sqlite3OsSleep() have a delay of 1 microsecond.  Really this
   ** is more of a scheduler yield than an actual delay.  But on the 10th
   ** an subsequent retries, the delays start becoming longer and longer, 
-  ** so that on the 100th (and last) RETRY we delay for 21 milliseconds.
-  ** The total delay time before giving up is less than 1 second.
+  ** so that on the 100th (and last) RETRY we delay for 323 milliseconds.
+  ** The total delay time before giving up is less than 10 seconds.
   */
   if( cnt>5 ){
     int nDelay = 1;                      /* Pause time in microseconds */
@@ -47601,7 +49585,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
       VVA_ONLY( pWal->lockError = 1; )
       return SQLITE_PROTOCOL;
     }
-    if( cnt>=10 ) nDelay = (cnt-9)*238;  /* Max delay 21ms. Total delay 996ms */
+    if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39;
     sqlite3OsSleep(pWal->pVfs, nDelay);
   }
 
@@ -47959,7 +49943,7 @@ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
   if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
     walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
     pWal->writeLock = 0;
-    rc = SQLITE_BUSY;
+    rc = SQLITE_BUSY_SNAPSHOT;
   }
 
   return rc;
@@ -48173,7 +50157,7 @@ static int walWriteToLog(
     iAmt -= iFirstAmt;
     pContent = (void*)(iFirstAmt + (char*)pContent);
     assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) );
-    rc = sqlite3OsSync(p->pFd, p->syncFlags);
+    rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK);
     if( iAmt==0 || rc ) return rc;
   }
   rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
@@ -48668,13 +50652,13 @@ SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
 **
 **   OFFSET   SIZE    DESCRIPTION
 **      0      16     Header string: "SQLite format 3\000"
-**     16       2     Page size in bytes.  
+**     16       2     Page size in bytes.  (1 means 65536)
 **     18       1     File format write version
 **     19       1     File format read version
 **     20       1     Bytes of unused space at the end of each page
-**     21       1     Max embedded payload fraction
-**     22       1     Min embedded payload fraction
-**     23       1     Min leaf payload fraction
+**     21       1     Max embedded payload fraction (must be 64)
+**     22       1     Min embedded payload fraction (must be 32)
+**     23       1     Min leaf payload fraction (must be 32)
 **     24       4     File change counter
 **     28       4     Reserved for future use
 **     32       4     First freelist page
@@ -48688,9 +50672,10 @@ SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
 **     56       4     1=UTF-8 2=UTF16le 3=UTF16be
 **     60       4     User version
 **     64       4     Incremental vacuum mode
-**     68       4     unused
-**     72       4     unused
-**     76       4     unused
+**     68       4     Application-ID
+**     72      20     unused
+**     92       4     The version-valid-for number
+**     96       4     SQLITE_VERSION_NUMBER
 **
 ** All of the integer values are big-endian (most significant byte first).
 **
@@ -49106,22 +51091,15 @@ struct BtCursor {
   BtShared *pBt;            /* The BtShared this cursor points to */
   BtCursor *pNext, *pPrev;  /* Forms a linked list of all cursors */
   struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
-#ifndef SQLITE_OMIT_INCRBLOB
   Pgno *aOverflow;          /* Cache of overflow page locations */
-#endif
-  Pgno pgnoRoot;            /* The root page of this tree */
-  sqlite3_int64 cachedRowid; /* Next rowid cache.  0 means not valid */
   CellInfo info;            /* A parse of the cell we are pointing at */
-  i64 nKey;        /* Size of pKey, or last integer key */
-  void *pKey;      /* Saved key that was cursor's last known position */
+  i64 nKey;                 /* Size of pKey, or last integer key */
+  void *pKey;               /* Saved key that was cursor last known position */
+  Pgno pgnoRoot;            /* The root page of this tree */
+  int nOvflAlloc;           /* Allocated size of aOverflow[] array */
   int skipNext;    /* Prev() is noop if negative. Next() is noop if positive */
-  u8 wrFlag;                /* True if writable */
-  u8 atLast;                /* Cursor pointing to the last entry */
-  u8 validNKey;             /* True if info.nKey is valid */
+  u8 curFlags;              /* zero or more BTCF_* flags defined below */
   u8 eState;                /* One of the CURSOR_XXX constants (see below) */
-#ifndef SQLITE_OMIT_INCRBLOB
-  u8 isIncrblobHandle;      /* True if this cursor is an incr. io handle */
-#endif
   u8 hints;                             /* As configured by CursorSetHints() */
   i16 iPage;                            /* Index of current page in apPage */
   u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
@@ -49129,16 +51107,30 @@ struct BtCursor {
 };
 
 /*
+** Legal values for BtCursor.curFlags
+*/
+#define BTCF_WriteFlag    0x01   /* True if a write cursor */
+#define BTCF_ValidNKey    0x02   /* True if info.nKey is valid */
+#define BTCF_ValidOvfl    0x04   /* True if aOverflow is valid */
+#define BTCF_AtLast       0x08   /* Cursor is pointing ot the last entry */
+#define BTCF_Incrblob     0x10   /* True if an incremental I/O handle */
+
+/*
 ** Potential values for BtCursor.eState.
 **
-** CURSOR_VALID:
-**   Cursor points to a valid entry. getPayload() etc. may be called.
-**
 ** CURSOR_INVALID:
 **   Cursor does not point to a valid entry. This can happen (for example) 
 **   because the table is empty or because BtreeCursorFirst() has not been
 **   called.
 **
+** CURSOR_VALID:
+**   Cursor points to a valid entry. getPayload() etc. may be called.
+**
+** CURSOR_SKIPNEXT:
+**   Cursor is valid except that the Cursor.skipNext field is non-zero
+**   indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious()
+**   operation should be a no-op.
+**
 ** CURSOR_REQUIRESEEK:
 **   The table that this cursor was opened on still exists, but has been 
 **   modified since the cursor was last used. The cursor position is saved
@@ -49155,8 +51147,9 @@ struct BtCursor {
 */
 #define CURSOR_INVALID           0
 #define CURSOR_VALID             1
-#define CURSOR_REQUIRESEEK       2
-#define CURSOR_FAULT             3
+#define CURSOR_SKIPNEXT          2
+#define CURSOR_REQUIRESEEK       3
+#define CURSOR_FAULT             4
 
 /* 
 ** The database page the PENDING_BYTE occupies. This page is never used.
@@ -49708,7 +51701,7 @@ static int hasSharedCacheTableLock(
   ** the correct locks are held.  So do not bother - just return true.
   ** This case does not come up very often anyhow.
   */
-  if( isIndex && (!pSchema || (pSchema->flags&DB_SchemaLoaded)==0) ){
+  if( isIndex && (!pSchema || (pSchema->schemaFlags&DB_SchemaLoaded)==0) ){
     return 1;
   }
 
@@ -49992,16 +51985,11 @@ static int cursorHoldsMutex(BtCursor *p){
 }
 #endif
 
-
-#ifndef SQLITE_OMIT_INCRBLOB
 /*
-** Invalidate the overflow page-list cache for cursor pCur, if any.
+** Invalidate the overflow cache of the cursor passed as the first argument.
+** on the shared btree structure pBt.
 */
-static void invalidateOverflowCache(BtCursor *pCur){
-  assert( cursorHoldsMutex(pCur) );
-  sqlite3_free(pCur->aOverflow);
-  pCur->aOverflow = 0;
-}
+#define invalidateOverflowCache(pCur) (pCur->curFlags &= ~BTCF_ValidOvfl)
 
 /*
 ** Invalidate the overflow page-list cache for all cursors opened
@@ -50015,6 +52003,7 @@ static void invalidateAllOverflowCache(BtShared *pBt){
   }
 }
 
+#ifndef SQLITE_OMIT_INCRBLOB
 /*
 ** This function is called before modifying the contents of a table
 ** to invalidate any incrblob cursors that are open on the
@@ -50037,16 +52026,14 @@ static void invalidateIncrblobCursors(
   BtShared *pBt = pBtree->pBt;
   assert( sqlite3BtreeHoldsMutex(pBtree) );
   for(p=pBt->pCursor; p; p=p->pNext){
-    if( p->isIncrblobHandle && (isClearTable || p->info.nKey==iRow) ){
+    if( (p->curFlags & BTCF_Incrblob)!=0 && (isClearTable || p->info.nKey==iRow) ){
       p->eState = CURSOR_INVALID;
     }
   }
 }
 
 #else
-  /* Stub functions when INCRBLOB is omitted */
-  #define invalidateOverflowCache(x)
-  #define invalidateAllOverflowCache(x)
+  /* Stub function when INCRBLOB is omitted */
   #define invalidateIncrblobCursors(x,y,z)
 #endif /* SQLITE_OMIT_INCRBLOB */
 
@@ -50230,7 +52217,7 @@ static int btreeMoveto(
 ){
   int rc;                    /* Status code */
   UnpackedRecord *pIdxKey;   /* Unpacked index key */
-  char aSpace[150];          /* Temp space for pIdxKey - to avoid a malloc */
+  char aSpace[200];          /* Temp space for pIdxKey - to avoid a malloc */
   char *pFree = 0;
 
   if( pKey ){
@@ -50240,6 +52227,10 @@ static int btreeMoveto(
     );
     if( pIdxKey==0 ) return SQLITE_NOMEM;
     sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
+    if( pIdxKey->nField==0 ){
+      sqlite3DbFree(pCur->pKeyInfo->db, pFree);
+      return SQLITE_CORRUPT_BKPT;
+    }
   }else{
     pIdxKey = 0;
   }
@@ -50270,6 +52261,9 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
     sqlite3_free(pCur->pKey);
     pCur->pKey = 0;
     assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
+    if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
+      pCur->eState = CURSOR_SKIPNEXT;
+    }
   }
   return rc;
 }
@@ -50285,20 +52279,32 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
 ** at is deleted out from under them.
 **
 ** This routine returns an error code if something goes wrong.  The
-** integer *pHasMoved is set to one if the cursor has moved and 0 if not.
+** integer *pHasMoved is set as follows:
+**
+**    0:   The cursor is unchanged
+**    1:   The cursor is still pointing at the same row, but the pointers
+**         returned by sqlite3BtreeKeyFetch() or sqlite3BtreeDataFetch()
+**         might now be invalid because of a balance() or other change to the
+**         b-tree.
+**    2:   The cursor is no longer pointing to the row.  The row might have
+**         been deleted out from under the cursor.
 */
 SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
   int rc;
 
+  if( pCur->eState==CURSOR_VALID ){
+    *pHasMoved = 0;
+    return SQLITE_OK;
+  }
   rc = restoreCursorPosition(pCur);
   if( rc ){
-    *pHasMoved = 1;
+    *pHasMoved = 2;
     return rc;
   }
-  if( pCur->eState!=CURSOR_VALID || pCur->skipNext!=0 ){
-    *pHasMoved = 1;
+  if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
+    *pHasMoved = 2;
   }else{
-    *pHasMoved = 0;
+    *pHasMoved = 1;
   }
   return SQLITE_OK;
 }
@@ -50483,7 +52489,8 @@ static void btreeParseCellPtr(
   assert( n==4-4*pPage->leaf );
   if( pPage->intKey ){
     if( pPage->hasData ){
-      n += getVarint32(&pCell[n], nPayload);
+      assert( n==0 );
+      n = getVarint32(pCell, nPayload);
     }else{
       nPayload = 0;
     }
@@ -50761,7 +52768,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
   }else if( gap+2<=top ){
     /* Search the freelist looking for a free slot big enough to satisfy 
     ** the request. The allocation is made from the first free slot in 
-    ** the list that is large enough to accomadate it.
+    ** the list that is large enough to accommodate it.
     */
     int pc, addr;
     for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){
@@ -51080,13 +53087,12 @@ static void zeroPage(MemPage *pPage, int flags){
     memset(&data[hdr], 0, pBt->usableSize - hdr);
   }
   data[hdr] = (char)flags;
-  first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0);
+  first = hdr + ((flags&PTF_LEAF)==0 ? 12 : 8);
   memset(&data[hdr+1], 0, 4);
   data[hdr+7] = 0;
   put2byte(&data[hdr+5], pBt->usableSize);
   pPage->nFree = (u16)(pBt->usableSize - first);
   decodeFlags(pPage, flags);
-  pPage->hdrOffset = hdr;
   pPage->cellOffset = first;
   pPage->aDataEnd = &data[pBt->usableSize];
   pPage->aCellIdx = &data[first];
@@ -51127,15 +53133,12 @@ static int btreeGetPage(
   BtShared *pBt,       /* The btree */
   Pgno pgno,           /* Number of the page to fetch */
   MemPage **ppPage,    /* Return the page in this parameter */
-  int noContent,       /* Do not load page content if true */
-  int bReadonly        /* True if a read-only (mmap) page is ok */
+  int flags            /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */
 ){
   int rc;
   DbPage *pDbPage;
-  int flags = (noContent ? PAGER_ACQUIRE_NOCONTENT : 0) 
-            | (bReadonly ? PAGER_ACQUIRE_READONLY : 0);
 
-  assert( noContent==0 || bReadonly==0 );
+  assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY );
   assert( sqlite3_mutex_held(pBt->mutex) );
   rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
   if( rc ) return rc;
@@ -51168,7 +53171,7 @@ static Pgno btreePagecount(BtShared *pBt){
 SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
   assert( sqlite3BtreeHoldsMutex(p) );
   assert( ((p->pBt->nPage)&0x8000000)==0 );
-  return (int)btreePagecount(p->pBt);
+  return btreePagecount(p->pBt);
 }
 
 /*
@@ -51183,16 +53186,17 @@ static int getAndInitPage(
   BtShared *pBt,                  /* The database file */
   Pgno pgno,                      /* Number of the page to get */
   MemPage **ppPage,               /* Write the page pointer here */
-  int bReadonly                   /* True if a read-only (mmap) page is ok */
+  int bReadonly                   /* PAGER_GET_READONLY or 0 */
 ){
   int rc;
   assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( bReadonly==PAGER_GET_READONLY || bReadonly==0 );
 
   if( pgno>btreePagecount(pBt) ){
     rc = SQLITE_CORRUPT_BKPT;
   }else{
-    rc = btreeGetPage(pBt, pgno, ppPage, 0, bReadonly);
-    if( rc==SQLITE_OK ){
+    rc = btreeGetPage(pBt, pgno, ppPage, bReadonly);
+    if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
       rc = btreeInitPage(*ppPage);
       if( rc!=SQLITE_OK ){
         releasePage(*ppPage);
@@ -51213,10 +53217,11 @@ static void releasePage(MemPage *pPage){
   if( pPage ){
     assert( pPage->aData );
     assert( pPage->pBt );
+    assert( pPage->pDbPage!=0 );
     assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
     assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
     assert( sqlite3_mutex_held(pPage->pBt->mutex) );
-    sqlite3PagerUnref(pPage->pDbPage);
+    sqlite3PagerUnrefNotNull(pPage->pDbPage);
   }
 }
 
@@ -51596,6 +53601,18 @@ static int removeFromSharingList(BtShared *pBt){
 static void allocateTempSpace(BtShared *pBt){
   if( !pBt->pTmpSpace ){
     pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
+
+    /* One of the uses of pBt->pTmpSpace is to format cells before
+    ** inserting them into a leaf page (function fillInCell()). If
+    ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
+    ** by the various routines that manipulate binary cells. Which
+    ** can mean that fillInCell() only initializes the first 2 or 3
+    ** bytes of pTmpSpace, but that the first 4 bytes are copied from
+    ** it into a database page. This is not actually a problem, but it
+    ** does cause a valgrind error when the 1 or 2 bytes of unitialized 
+    ** data is passed to system call write(). So to avoid this error,
+    ** zero the first 4 bytes of temp space here.  */
+    if( pBt->pTmpSpace ) memset(pBt->pTmpSpace, 0, 4);
   }
 }
 
@@ -51689,6 +53706,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
   return SQLITE_OK;
 }
 
+#if SQLITE_MAX_MMAP_SIZE>0
 /*
 ** Change the limit on the amount of the database file that may be
 ** memory mapped.
@@ -51701,6 +53719,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
   sqlite3BtreeLeave(p);
   return SQLITE_OK;
 }
+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
 
 /*
 ** Change the way data is synced to disk in order to increase or decrease
@@ -51711,17 +53730,14 @@ SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
 ** probability of damage to near zero but with a write performance reduction.
 */
 #ifndef SQLITE_OMIT_PAGER_PRAGMAS
-SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(
+SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(
   Btree *p,              /* The btree to set the safety level on */
-  int level,             /* PRAGMA synchronous.  1=OFF, 2=NORMAL, 3=FULL */
-  int fullSync,          /* PRAGMA fullfsync. */
-  int ckptFullSync       /* PRAGMA checkpoint_fullfync */
+  unsigned pgFlags       /* Various PAGER_* flags */
 ){
   BtShared *pBt = p->pBt;
   assert( sqlite3_mutex_held(p->db->mutex) );
-  assert( level>=1 && level<=3 );
   sqlite3BtreeEnter(p);
-  sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync, ckptFullSync);
+  sqlite3PagerSetFlags(pBt->pPager, pgFlags);
   sqlite3BtreeLeave(p);
   return SQLITE_OK;
 }
@@ -51927,7 +53943,7 @@ static int lockBtree(BtShared *pBt){
   assert( pBt->pPage1==0 );
   rc = sqlite3PagerSharedLock(pBt->pPager);
   if( rc!=SQLITE_OK ) return rc;
-  rc = btreeGetPage(pBt, 1, &pPage1, 0, 0);
+  rc = btreeGetPage(pBt, 1, &pPage1, 0);
   if( rc!=SQLITE_OK ) return rc;
 
   /* Do some checking to help insure the file we opened really is
@@ -52080,7 +54096,8 @@ static int countValidCursors(BtShared *pBt, int wrOnly){
   BtCursor *pCur;
   int r = 0;
   for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-    if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++; 
+    if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0)
+     && pCur->eState!=CURSOR_FAULT ) r++; 
   }
   return r;
 }
@@ -52214,7 +54231,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
   if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
     goto trans_begun;
   }
-  assert( IfNotOmitAV(pBt->bDoTruncate)==0 );
+  assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
 
   /* Write transactions are not possible on a read-only database */
   if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
@@ -52509,7 +54526,7 @@ static int relocatePage(
   ** iPtrPage.
   */
   if( eType!=PTRMAP_ROOTPAGE ){
-    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0, 0);
+    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
     if( rc!=SQLITE_OK ){
       return rc;
     }
@@ -52593,7 +54610,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
       u8 eMode = BTALLOC_ANY;   /* Mode parameter for allocateBtreePage() */
       Pgno iNear = 0;           /* nearby parameter for allocateBtreePage() */
 
-      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0, 0);
+      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
       if( rc!=SQLITE_OK ){
         return rc;
       }
@@ -52704,7 +54721,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
 
 /*
 ** This routine is called prior to sqlite3PagerCommit when a transaction
-** is commited for an auto-vacuum database.
+** is committed for an auto-vacuum database.
 **
 ** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
 ** the database file should be truncated to during the commit process. 
@@ -52819,12 +54836,13 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
 */
 static void btreeEndTransaction(Btree *p){
   BtShared *pBt = p->pBt;
+  sqlite3 *db = p->db;
   assert( sqlite3BtreeHoldsMutex(p) );
 
 #ifndef SQLITE_OMIT_AUTOVACUUM
   pBt->bDoTruncate = 0;
 #endif
-  if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
+  if( p->inTrans>TRANS_NONE && db->nVdbeRead>1 ){
     /* If there are other active statements that belong to this database
     ** handle, downgrade to a read-only transaction. The other statements
     ** may still be reading from the database.  */
@@ -52991,7 +55009,7 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){
     /* The rollback may have destroyed the pPage1->aData value.  So
     ** call btreeGetPage() on page 1 again to make
     ** sure pPage1->aData is set correctly. */
-    if( btreeGetPage(pBt, 1, &pPage1, 0, 0)==SQLITE_OK ){
+    if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
       int nPage = get4byte(28+(u8*)pPage1->aData);
       testcase( nPage==0 );
       if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
@@ -53154,14 +55172,14 @@ static int btreeCursor(
   pCur->pKeyInfo = pKeyInfo;
   pCur->pBtree = p;
   pCur->pBt = pBt;
-  pCur->wrFlag = (u8)wrFlag;
+  assert( wrFlag==0 || wrFlag==BTCF_WriteFlag );
+  pCur->curFlags = wrFlag;
   pCur->pNext = pBt->pCursor;
   if( pCur->pNext ){
     pCur->pNext->pPrev = pCur;
   }
   pBt->pCursor = pCur;
   pCur->eState = CURSOR_INVALID;
-  pCur->cachedRowid = 0;
   return SQLITE_OK;
 }
 SQLITE_PRIVATE int sqlite3BtreeCursor(
@@ -53203,36 +55221,6 @@ SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){
 }
 
 /*
-** Set the cached rowid value of every cursor in the same database file
-** as pCur and having the same root page number as pCur.  The value is
-** set to iRowid.
-**
-** Only positive rowid values are considered valid for this cache.
-** The cache is initialized to zero, indicating an invalid cache.
-** A btree will work fine with zero or negative rowids.  We just cannot
-** cache zero or negative rowids, which means tables that use zero or
-** negative rowids might run a little slower.  But in practice, zero
-** or negative rowids are very uncommon so this should not be a problem.
-*/
-SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor *pCur, sqlite3_int64 iRowid){
-  BtCursor *p;
-  for(p=pCur->pBt->pCursor; p; p=p->pNext){
-    if( p->pgnoRoot==pCur->pgnoRoot ) p->cachedRowid = iRowid;
-  }
-  assert( pCur->cachedRowid==iRowid );
-}
-
-/*
-** Return the cached rowid for the given cursor.  A negative or zero
-** return value indicates that the rowid cache is invalid and should be
-** ignored.  If the rowid cache has never before been set, then a
-** zero is returned.
-*/
-SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor *pCur){
-  return pCur->cachedRowid;
-}
-
-/*
 ** Close a cursor.  The read lock on the database file is released
 ** when the last cursor is closed.
 */
@@ -53255,7 +55243,7 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
       releasePage(pCur->apPage[i]);
     }
     unlockBtreeIfUnused(pBt);
-    invalidateOverflowCache(pCur);
+    sqlite3DbFree(pBtree->db, pCur->aOverflow);
     /* sqlite3_free(pCur); */
     sqlite3BtreeLeave(pBtree);
   }
@@ -53283,7 +55271,7 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
     int iPage = pCur->iPage;
     memset(&info, 0, sizeof(info));
     btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info);
-    assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
+    assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 );
   }
 #else
   #define assertCellInfo(x)
@@ -53294,7 +55282,7 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
     if( pCur->info.nSize==0 ){
       int iPage = pCur->iPage;
       btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
-      pCur->validNKey = 1;
+      pCur->curFlags |= BTCF_ValidNKey;
     }else{
       assertCellInfo(pCur);
     }
@@ -53304,8 +55292,8 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
 #define getCellInfo(pCur)                                                      \
   if( pCur->info.nSize==0 ){                                                   \
     int iPage = pCur->iPage;                                                   \
-    btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \
-    pCur->validNKey = 1;                                                       \
+    btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);        \
+    pCur->curFlags |= BTCF_ValidNKey;                                          \
   }else{                                                                       \
     assertCellInfo(pCur);                                                      \
   }
@@ -53426,7 +55414,7 @@ static int getOverflowPage(
 
   assert( next==0 || rc==SQLITE_DONE );
   if( rc==SQLITE_OK ){
-    rc = btreeGetPage(pBt, ovfl, &pPage, 0, (ppPage==0));
+    rc = btreeGetPage(pBt, ovfl, &pPage, (ppPage==0) ? PAGER_GET_READONLY : 0);
     assert( rc==SQLITE_OK || pPage==0 );
     if( rc==SQLITE_OK ){
       next = get4byte(pPage->aData);
@@ -53476,10 +55464,12 @@ static int copyPayload(
 
 /*
 ** This function is used to read or overwrite payload information
-** for the entry that the pCur cursor is pointing to. If the eOp
-** parameter is 0, this is a read operation (data copied into
-** buffer pBuf). If it is non-zero, a write (data copied from
-** buffer pBuf).
+** for the entry that the pCur cursor is pointing to. The eOp
+** argument is interpreted as follows:
+**
+**   0: The operation is a read. Populate the overflow cache.
+**   1: The operation is a write. Populate the overflow cache.
+**   2: The operation is a read. Do not populate the overflow cache.
 **
 ** A total of "amt" bytes are read or written beginning at "offset".
 ** Data is read to or from the buffer pBuf.
@@ -53487,11 +55477,11 @@ static int copyPayload(
 ** The content being read or written might appear on the main page
 ** or be scattered out on multiple overflow pages.
 **
-** If the BtCursor.isIncrblobHandle flag is set, and the current
-** cursor entry uses one or more overflow pages, this function
-** allocates space for and lazily popluates the overflow page-list 
-** cache array (BtCursor.aOverflow). Subsequent calls use this
-** cache to make seeking to the supplied offset more efficient.
+** If the current cursor entry uses one or more overflow pages and the
+** eOp argument is not 2, this function may allocate space for and lazily 
+** popluates the overflow page-list cache array (BtCursor.aOverflow). 
+** Subsequent calls use this cache to make seeking to the supplied offset 
+** more efficient.
 **
 ** Once an overflow page-list cache has been allocated, it may be
 ** invalidated if some other cursor writes to the same table, or if
@@ -53515,15 +55505,22 @@ static int accessPayload(
   int iIdx = 0;
   MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
   BtShared *pBt = pCur->pBt;                  /* Btree this cursor belongs to */
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+  int bEnd;                                   /* True if reading to end of data */
+#endif
 
   assert( pPage );
   assert( pCur->eState==CURSOR_VALID );
   assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
   assert( cursorHoldsMutex(pCur) );
+  assert( eOp!=2 || offset==0 );      /* Always start from beginning for eOp==2 */
 
   getCellInfo(pCur);
   aPayload = pCur->info.pCell + pCur->info.nHeader;
   nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey);
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+  bEnd = (offset+amt==nKey+pCur->info.nData);
+#endif
 
   if( NEVER(offset+amt > nKey+pCur->info.nData) 
    || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
@@ -53538,7 +55535,7 @@ static int accessPayload(
     if( a+offset>pCur->info.nLocal ){
       a = pCur->info.nLocal - offset;
     }
-    rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
+    rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage);
     offset = 0;
     pBuf += a;
     amt -= a;
@@ -53552,21 +55549,30 @@ static int accessPayload(
 
     nextPage = get4byte(&aPayload[pCur->info.nLocal]);
 
-#ifndef SQLITE_OMIT_INCRBLOB
-    /* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[]
-    ** has not been allocated, allocate it now. The array is sized at
-    ** one entry for each overflow page in the overflow chain. The
-    ** page number of the first overflow page is stored in aOverflow[0],
-    ** etc. A value of 0 in the aOverflow[] array means "not yet known"
-    ** (the cache is lazily populated).
+    /* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
+    ** Except, do not allocate aOverflow[] for eOp==2.
+    **
+    ** The aOverflow[] array is sized at one entry for each overflow page
+    ** in the overflow chain. The page number of the first overflow page is
+    ** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
+    ** means "not yet known" (the cache is lazily populated).
     */
-    if( pCur->isIncrblobHandle && !pCur->aOverflow ){
+    if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
       int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
-      pCur->aOverflow = (Pgno *)sqlite3MallocZero(sizeof(Pgno)*nOvfl);
-      /* nOvfl is always positive.  If it were zero, fetchPayload would have
-      ** been used instead of this routine. */
-      if( ALWAYS(nOvfl) && !pCur->aOverflow ){
-        rc = SQLITE_NOMEM;
+      if( nOvfl>pCur->nOvflAlloc ){
+        Pgno *aNew = (Pgno*)sqlite3DbRealloc(
+            pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno)
+        );
+        if( aNew==0 ){
+          rc = SQLITE_NOMEM;
+        }else{
+          pCur->nOvflAlloc = nOvfl*2;
+          pCur->aOverflow = aNew;
+        }
+      }
+      if( rc==SQLITE_OK ){
+        memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
+        pCur->curFlags |= BTCF_ValidOvfl;
       }
     }
 
@@ -53574,22 +55580,19 @@ static int accessPayload(
     ** entry for the first required overflow page is valid, skip
     ** directly to it.
     */
-    if( pCur->aOverflow && pCur->aOverflow[offset/ovflSize] ){
+    if( (pCur->curFlags & BTCF_ValidOvfl)!=0 && pCur->aOverflow[offset/ovflSize] ){
       iIdx = (offset/ovflSize);
       nextPage = pCur->aOverflow[iIdx];
       offset = (offset%ovflSize);
     }
-#endif
 
     for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){
 
-#ifndef SQLITE_OMIT_INCRBLOB
       /* If required, populate the overflow page-list cache. */
-      if( pCur->aOverflow ){
+      if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
         assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage);
         pCur->aOverflow[iIdx] = nextPage;
       }
-#endif
 
       if( offset>=ovflSize ){
         /* The only reason to read this page is to obtain the page
@@ -53597,13 +55600,17 @@ static int accessPayload(
         ** data is not required. So first try to lookup the overflow
         ** page-list cache, if any, then fall back to the getOverflowPage()
         ** function.
+        **
+        ** Note that the aOverflow[] array must be allocated because eOp!=2
+        ** here.  If eOp==2, then offset==0 and this branch is never taken.
         */
-#ifndef SQLITE_OMIT_INCRBLOB
-        if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){
+        assert( eOp!=2 );
+        assert( pCur->curFlags & BTCF_ValidOvfl );
+        if( pCur->aOverflow[iIdx+1] ){
           nextPage = pCur->aOverflow[iIdx+1];
-        } else 
-#endif
+        }else{
           rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
+        }
         offset -= ovflSize;
       }else{
         /* Need to read this page properly. It contains some of the
@@ -53625,13 +55632,15 @@ static int accessPayload(
         **   3) the database is file-backed, and
         **   4) there is no open write-transaction, and
         **   5) the database is not a WAL database,
+        **   6) all data from the page is being read.
         **
         ** then data can be read directly from the database file into the
         ** output buffer, bypassing the page-cache altogether. This speeds
         ** up loading large records that span many overflow pages.
         */
-        if( eOp==0                                             /* (1) */
+        if( (eOp&0x01)==0                                      /* (1) */
          && offset==0                                          /* (2) */
+         && (bEnd || a==ovflSize)                              /* (6) */
          && pBt->inTransaction==TRANS_READ                     /* (4) */
          && (fd = sqlite3PagerFile(pBt->pPager))->pMethods     /* (3) */
          && pBt->pPage1->aData[19]==0x01                       /* (5) */
@@ -53648,12 +55657,12 @@ static int accessPayload(
         {
           DbPage *pDbPage;
           rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
-              (eOp==0 ? PAGER_ACQUIRE_READONLY : 0)
+              ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
           );
           if( rc==SQLITE_OK ){
             aPayload = sqlite3PagerGetData(pDbPage);
             nextPage = get4byte(aPayload);
-            rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
+            rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage);
             sqlite3PagerUnref(pDbPage);
             offset = 0;
           }
@@ -53722,10 +55731,10 @@ SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *p
 /*
 ** Return a pointer to payload information from the entry that the 
 ** pCur cursor is pointing to.  The pointer is to the beginning of
-** the key if skipKey==0 and it points to the beginning of data if
-** skipKey==1.  The number of bytes of available key/data is written
-** into *pAmt.  If *pAmt==0, then the value returned will not be
-** a valid pointer.
+** the key if index btrees (pPage->intKey==0) and is the data for
+** table btrees (pPage->intKey==1). The number of bytes of available
+** key/data is written into *pAmt.  If *pAmt==0, then the value
+** returned will not be a valid pointer.
 **
 ** This routine is an optimization.  It is common for the entire key
 ** and data to fit on the local page and for there to be no overflow
@@ -53738,41 +55747,18 @@ SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *p
 ** page of the database.  The data might change or move the next time
 ** any btree routine is called.
 */
-static const unsigned char *fetchPayload(
+static const void *fetchPayload(
   BtCursor *pCur,      /* Cursor pointing to entry to read from */
-  int *pAmt,           /* Write the number of available bytes here */
-  int skipKey          /* read beginning at data if this is true */
+  u32 *pAmt            /* Write the number of available bytes here */
 ){
-  unsigned char *aPayload;
-  MemPage *pPage;
-  u32 nKey;
-  u32 nLocal;
-
   assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
   assert( pCur->eState==CURSOR_VALID );
+  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
   assert( cursorHoldsMutex(pCur) );
-  pPage = pCur->apPage[pCur->iPage];
-  assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
-  if( NEVER(pCur->info.nSize==0) ){
-    btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
-                   &pCur->info);
-  }
-  aPayload = pCur->info.pCell;
-  aPayload += pCur->info.nHeader;
-  if( pPage->intKey ){
-    nKey = 0;
-  }else{
-    nKey = (int)pCur->info.nKey;
-  }
-  if( skipKey ){
-    aPayload += nKey;
-    nLocal = pCur->info.nLocal - nKey;
-  }else{
-    nLocal = pCur->info.nLocal;
-    assert( nLocal<=nKey );
-  }
-  *pAmt = nLocal;
-  return aPayload;
+  assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
+  assert( pCur->info.nSize>0 );
+  *pAmt = pCur->info.nLocal;
+  return (void*)(pCur->info.pCell + pCur->info.nHeader);
 }
 
 
@@ -53790,23 +55776,11 @@ static const unsigned char *fetchPayload(
 ** These routines is used to get quick access to key and data
 ** in the common case where no overflow pages are used.
 */
-SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){
-  const void *p = 0;
-  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
-  assert( cursorHoldsMutex(pCur) );
-  if( ALWAYS(pCur->eState==CURSOR_VALID) ){
-    p = (const void*)fetchPayload(pCur, pAmt, 0);
-  }
-  return p;
+SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){
+  return fetchPayload(pCur, pAmt);
 }
-SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){
-  const void *p = 0;
-  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
-  assert( cursorHoldsMutex(pCur) );
-  if( ALWAYS(pCur->eState==CURSOR_VALID) ){
-    p = (const void*)fetchPayload(pCur, pAmt, 1);
-  }
-  return p;
+SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){
+  return fetchPayload(pCur, pAmt);
 }
 
 
@@ -53832,14 +55806,15 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
   if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
     return SQLITE_CORRUPT_BKPT;
   }
-  rc = getAndInitPage(pBt, newPgno, &pNewPage, (pCur->wrFlag==0));
+  rc = getAndInitPage(pBt, newPgno, &pNewPage,
+               (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0);
   if( rc ) return rc;
   pCur->apPage[i+1] = pNewPage;
   pCur->aiIdx[i+1] = 0;
   pCur->iPage++;
 
   pCur->info.nSize = 0;
-  pCur->validNKey = 0;
+  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
   if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){
     return SQLITE_CORRUPT_BKPT;
   }
@@ -53897,7 +55872,7 @@ static void moveToParent(BtCursor *pCur){
   releasePage(pCur->apPage[pCur->iPage]);
   pCur->iPage--;
   pCur->info.nSize = 0;
-  pCur->validNKey = 0;
+  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
 }
 
 /*
@@ -53924,8 +55899,6 @@ static void moveToParent(BtCursor *pCur){
 static int moveToRoot(BtCursor *pCur){
   MemPage *pRoot;
   int rc = SQLITE_OK;
-  Btree *p = pCur->pBtree;
-  BtShared *pBt = p->pBt;
 
   assert( cursorHoldsMutex(pCur) );
   assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
@@ -53940,55 +55913,51 @@ static int moveToRoot(BtCursor *pCur){
   }
 
   if( pCur->iPage>=0 ){
-    int i;
-    for(i=1; i<=pCur->iPage; i++){
-      releasePage(pCur->apPage[i]);
-    }
-    pCur->iPage = 0;
+    while( pCur->iPage ) releasePage(pCur->apPage[pCur->iPage--]);
   }else if( pCur->pgnoRoot==0 ){
     pCur->eState = CURSOR_INVALID;
     return SQLITE_OK;
   }else{
-    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0);
+    rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
+                 (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0);
     if( rc!=SQLITE_OK ){
       pCur->eState = CURSOR_INVALID;
       return rc;
     }
     pCur->iPage = 0;
-
-    /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
-    ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
-    ** NULL, the caller expects a table b-tree. If this is not the case,
-    ** return an SQLITE_CORRUPT error.  */
-    assert( pCur->apPage[0]->intKey==1 || pCur->apPage[0]->intKey==0 );
-    if( (pCur->pKeyInfo==0)!=pCur->apPage[0]->intKey ){
-      return SQLITE_CORRUPT_BKPT;
-    }
   }
-
-  /* Assert that the root page is of the correct type. This must be the
-  ** case as the call to this function that loaded the root-page (either
-  ** this call or a previous invocation) would have detected corruption 
-  ** if the assumption were not true, and it is not possible for the flags 
-  ** byte to have been modified while this cursor is holding a reference
-  ** to the page.  */
   pRoot = pCur->apPage[0];
   assert( pRoot->pgno==pCur->pgnoRoot );
-  assert( pRoot->isInit && (pCur->pKeyInfo==0)==pRoot->intKey );
+
+  /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
+  ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
+  ** NULL, the caller expects a table b-tree. If this is not the case,
+  ** return an SQLITE_CORRUPT error. 
+  **
+  ** Earlier versions of SQLite assumed that this test could not fail
+  ** if the root page was already loaded when this function was called (i.e.
+  ** if pCur->iPage>=0). But this is not so if the database is corrupted 
+  ** in such a way that page pRoot is linked into a second b-tree table 
+  ** (or the freelist).  */
+  assert( pRoot->intKey==1 || pRoot->intKey==0 );
+  if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
+    return SQLITE_CORRUPT_BKPT;
+  }
 
   pCur->aiIdx[0] = 0;
   pCur->info.nSize = 0;
-  pCur->atLast = 0;
-  pCur->validNKey = 0;
+  pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
 
-  if( pRoot->nCell==0 && !pRoot->leaf ){
+  if( pRoot->nCell>0 ){
+    pCur->eState = CURSOR_VALID;
+  }else if( !pRoot->leaf ){
     Pgno subpage;
     if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
     subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
     pCur->eState = CURSOR_VALID;
     rc = moveToChild(pCur, subpage);
   }else{
-    pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID);
+    pCur->eState = CURSOR_INVALID;
   }
   return rc;
 }
@@ -54040,7 +56009,7 @@ static int moveToRightmost(BtCursor *pCur){
   if( rc==SQLITE_OK ){
     pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
     pCur->info.nSize = 0;
-    pCur->validNKey = 0;
+    pCur->curFlags &= ~BTCF_ValidNKey;
   }
   return rc;
 }
@@ -54079,7 +56048,7 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
   assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
 
   /* If the cursor already points to the last entry, this is a no-op. */
-  if( CURSOR_VALID==pCur->eState && pCur->atLast ){
+  if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
 #ifdef SQLITE_DEBUG
     /* This block serves to assert() that the cursor really does point 
     ** to the last entry in the b-tree. */
@@ -54102,7 +56071,12 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
       assert( pCur->eState==CURSOR_VALID );
       *pRes = 0;
       rc = moveToRightmost(pCur);
-      pCur->atLast = rc==SQLITE_OK ?1:0;
+      if( rc==SQLITE_OK ){
+        pCur->curFlags |= BTCF_AtLast;
+      }else{
+        pCur->curFlags &= ~BTCF_AtLast;
+      }
+   
     }
   }
   return rc;
@@ -54144,6 +56118,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
   int *pRes                /* Write search results here */
 ){
   int rc;
+  RecordCompare xRecordCompare;
 
   assert( cursorHoldsMutex(pCur) );
   assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
@@ -54152,19 +56127,30 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
 
   /* 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 
+  if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
    && pCur->apPage[0]->intKey 
   ){
     if( pCur->info.nKey==intKey ){
       *pRes = 0;
       return SQLITE_OK;
     }
-    if( pCur->atLast && pCur->info.nKey<intKey ){
+    if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
       *pRes = -1;
       return SQLITE_OK;
     }
   }
 
+  if( pIdxKey ){
+    xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
+    pIdxKey->isCorrupt = 0;
+    assert( pIdxKey->default_rc==1 
+         || pIdxKey->default_rc==0 
+         || pIdxKey->default_rc==-1
+    );
+  }else{
+    xRecordCompare = 0; /* All keys are integers */
+  }
+
   rc = moveToRoot(pCur);
   if( rc ){
     return rc;
@@ -54179,10 +56165,10 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
   }
   assert( pCur->apPage[0]->intKey || pIdxKey );
   for(;;){
-    int lwr, upr, idx;
+    int lwr, upr, idx, c;
     Pgno chldPg;
     MemPage *pPage = pCur->apPage[pCur->iPage];
-    int c;
+    u8 *pCell;                          /* Pointer to current cell in pPage */
 
     /* pPage->nCell must be greater than zero. If this is the root-page
     ** the cursor would have been INVALID above and this for(;;) loop
@@ -54194,35 +56180,47 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
     assert( pPage->intKey==(pIdxKey==0) );
     lwr = 0;
     upr = pPage->nCell-1;
-    if( biasRight ){
-      pCur->aiIdx[pCur->iPage] = (u16)(idx = upr);
-    }else{
-      pCur->aiIdx[pCur->iPage] = (u16)(idx = (upr+lwr)/2);
-    }
-    for(;;){
-      u8 *pCell;                          /* Pointer to current cell in pPage */
-
-      assert( idx==pCur->aiIdx[pCur->iPage] );
-      pCur->info.nSize = 0;
-      pCell = findCell(pPage, idx) + pPage->childPtrSize;
-      if( pPage->intKey ){
+    assert( biasRight==0 || biasRight==1 );
+    idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
+    pCur->aiIdx[pCur->iPage] = (u16)idx;
+    if( xRecordCompare==0 ){
+      for(;;){
         i64 nCellKey;
+        pCell = findCell(pPage, idx) + pPage->childPtrSize;
         if( pPage->hasData ){
-          u32 dummy;
-          pCell += getVarint32(pCell, dummy);
+          while( 0x80 <= *(pCell++) ){
+            if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
+          }
         }
         getVarint(pCell, (u64*)&nCellKey);
-        if( nCellKey==intKey ){
-          c = 0;
-        }else if( nCellKey<intKey ){
-          c = -1;
+        if( nCellKey<intKey ){
+          lwr = idx+1;
+          if( lwr>upr ){ c = -1; break; }
+        }else if( nCellKey>intKey ){
+          upr = idx-1;
+          if( lwr>upr ){ c = +1; break; }
         }else{
-          assert( nCellKey>intKey );
-          c = +1;
+          assert( nCellKey==intKey );
+          pCur->curFlags |= BTCF_ValidNKey;
+          pCur->info.nKey = nCellKey;
+          pCur->aiIdx[pCur->iPage] = (u16)idx;
+          if( !pPage->leaf ){
+            lwr = idx;
+            goto moveto_next_layer;
+          }else{
+            *pRes = 0;
+            rc = SQLITE_OK;
+            goto moveto_finish;
+          }
         }
-        pCur->validNKey = 1;
-        pCur->info.nKey = nCellKey;
-      }else{
+        assert( lwr+upr>=0 );
+        idx = (lwr+upr)>>1;  /* idx = (lwr+upr)/2; */
+      }
+    }else{
+      for(;;){
+        int nCell;
+        pCell = findCell(pPage, idx) + pPage->childPtrSize;
+
         /* The maximum supported page-size is 65536 bytes. This means that
         ** the maximum number of record bytes stored on an index B-Tree
         ** page is less than 16384 bytes and may be stored as a 2-byte
@@ -54231,23 +56229,20 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
         ** stored entirely within the b-tree page by inspecting the first 
         ** 2 bytes of the cell.
         */
-        int nCell = pCell[0];
-        if( nCell<=pPage->max1bytePayload
-         /* && (pCell+nCell)<pPage->aDataEnd */
-        ){
+        nCell = pCell[0];
+        if( nCell<=pPage->max1bytePayload ){
           /* This branch runs if the record-size field of the cell is a
           ** single byte varint and the record fits entirely on the main
           ** b-tree page.  */
           testcase( pCell+nCell+1==pPage->aDataEnd );
-          c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
+          c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey, 0);
         }else if( !(pCell[1] & 0x80) 
           && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
-          /* && (pCell+nCell+2)<=pPage->aDataEnd */
         ){
           /* The record-size field is a 2 byte varint and the record 
           ** fits entirely on the main b-tree page.  */
           testcase( pCell+nCell+2==pPage->aDataEnd );
-          c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
+          c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey, 0);
         }else{
           /* The record flows over onto one or more overflow pages. In
           ** this case the whole cell needs to be parsed, a buffer allocated
@@ -54262,57 +56257,55 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
             rc = SQLITE_NOMEM;
             goto moveto_finish;
           }
-          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
+          pCur->aiIdx[pCur->iPage] = (u16)idx;
+          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
           if( rc ){
             sqlite3_free(pCellKey);
             goto moveto_finish;
           }
-          c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
+          c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
           sqlite3_free(pCellKey);
         }
-      }
-      if( c==0 ){
-        if( pPage->intKey && !pPage->leaf ){
-          lwr = idx;
-          break;
+        assert( pIdxKey->isCorrupt==0 || c==0 );
+        if( c<0 ){
+          lwr = idx+1;
+        }else if( c>0 ){
+          upr = idx-1;
         }else{
+          assert( c==0 );
           *pRes = 0;
           rc = SQLITE_OK;
+          pCur->aiIdx[pCur->iPage] = (u16)idx;
+          if( pIdxKey->isCorrupt ) rc = SQLITE_CORRUPT;
           goto moveto_finish;
         }
+        if( lwr>upr ) break;
+        assert( lwr+upr>=0 );
+        idx = (lwr+upr)>>1;  /* idx = (lwr+upr)/2 */
       }
-      if( c<0 ){
-        lwr = idx+1;
-      }else{
-        upr = idx-1;
-      }
-      if( lwr>upr ){
-        break;
-      }
-      pCur->aiIdx[pCur->iPage] = (u16)(idx = (lwr+upr)/2);
     }
     assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
     assert( pPage->isInit );
     if( pPage->leaf ){
-      chldPg = 0;
-    }else if( lwr>=pPage->nCell ){
-      chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
-    }else{
-      chldPg = get4byte(findCell(pPage, lwr));
-    }
-    if( chldPg==0 ){
       assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
+      pCur->aiIdx[pCur->iPage] = (u16)idx;
       *pRes = c;
       rc = SQLITE_OK;
       goto moveto_finish;
     }
+moveto_next_layer:
+    if( lwr>=pPage->nCell ){
+      chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+    }else{
+      chldPg = get4byte(findCell(pPage, lwr));
+    }
     pCur->aiIdx[pCur->iPage] = (u16)lwr;
-    pCur->info.nSize = 0;
-    pCur->validNKey = 0;
     rc = moveToChild(pCur, chldPg);
-    if( rc ) goto moveto_finish;
+    if( rc ) break;
   }
 moveto_finish:
+  pCur->info.nSize = 0;
+  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
   return rc;
 }
 
@@ -54337,6 +56330,15 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){
 ** successful then set *pRes=0.  If the cursor
 ** was already pointing to the last entry in the database before
 ** this routine was called, then set *pRes=1.
+**
+** The calling function will set *pRes to 0 or 1.  The initial *pRes value
+** will be 1 if the cursor being stepped corresponds to an SQL index and
+** if this routine could have been skipped if that SQL index had been
+** a unique index.  Otherwise the caller will have set *pRes to zero.
+** Zero is the common case. The btree implementation is free to use the
+** initial *pRes value as a hint to improve performance, but the current
+** SQLite btree implementation does not. (Note that the comdb2 btree
+** implementation does use this hint, however.)
 */
 SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
   int rc;
@@ -54344,21 +56346,31 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
   MemPage *pPage;
 
   assert( cursorHoldsMutex(pCur) );
-  rc = restoreCursorPosition(pCur);
-  if( rc!=SQLITE_OK ){
-    return rc;
-  }
   assert( pRes!=0 );
-  if( CURSOR_INVALID==pCur->eState ){
-    *pRes = 1;
-    return SQLITE_OK;
-  }
-  if( pCur->skipNext>0 ){
-    pCur->skipNext = 0;
-    *pRes = 0;
-    return SQLITE_OK;
+  assert( *pRes==0 || *pRes==1 );
+  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
+  if( pCur->eState!=CURSOR_VALID ){
+    invalidateOverflowCache(pCur);
+    rc = restoreCursorPosition(pCur);
+    if( rc!=SQLITE_OK ){
+      *pRes = 0;
+      return rc;
+    }
+    if( CURSOR_INVALID==pCur->eState ){
+      *pRes = 1;
+      return SQLITE_OK;
+    }
+    if( pCur->skipNext ){
+      assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+      pCur->eState = CURSOR_VALID;
+      if( pCur->skipNext>0 ){
+        pCur->skipNext = 0;
+        *pRes = 0;
+        return SQLITE_OK;
+      }
+      pCur->skipNext = 0;
+    }
   }
-  pCur->skipNext = 0;
 
   pPage = pCur->apPage[pCur->iPage];
   idx = ++pCur->aiIdx[pCur->iPage];
@@ -54372,11 +56384,14 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
   testcase( idx>pPage->nCell );
 
   pCur->info.nSize = 0;
-  pCur->validNKey = 0;
+  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
   if( idx>=pPage->nCell ){
     if( !pPage->leaf ){
       rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
-      if( rc ) return rc;
+      if( rc ){
+        *pRes = 0;
+        return rc;
+      }
       rc = moveToLeftmost(pCur);
       *pRes = 0;
       return rc;
@@ -54412,27 +56427,48 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
 ** successful then set *pRes=0.  If the cursor
 ** was already pointing to the first entry in the database before
 ** this routine was called, then set *pRes=1.
+**
+** The calling function will set *pRes to 0 or 1.  The initial *pRes value
+** will be 1 if the cursor being stepped corresponds to an SQL index and
+** if this routine could have been skipped if that SQL index had been
+** a unique index.  Otherwise the caller will have set *pRes to zero.
+** Zero is the common case. The btree implementation is free to use the
+** initial *pRes value as a hint to improve performance, but the current
+** SQLite btree implementation does not. (Note that the comdb2 btree
+** implementation does use this hint, however.)
 */
 SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
   int rc;
   MemPage *pPage;
 
   assert( cursorHoldsMutex(pCur) );
-  rc = restoreCursorPosition(pCur);
-  if( rc!=SQLITE_OK ){
-    return rc;
-  }
-  pCur->atLast = 0;
-  if( CURSOR_INVALID==pCur->eState ){
-    *pRes = 1;
-    return SQLITE_OK;
-  }
-  if( pCur->skipNext<0 ){
-    pCur->skipNext = 0;
-    *pRes = 0;
-    return SQLITE_OK;
+  assert( pRes!=0 );
+  assert( *pRes==0 || *pRes==1 );
+  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
+  pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl);
+  if( pCur->eState!=CURSOR_VALID ){
+    if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
+      rc = btreeRestoreCursorPosition(pCur);
+      if( rc!=SQLITE_OK ){
+        *pRes = 0;
+        return rc;
+      }
+    }
+    if( CURSOR_INVALID==pCur->eState ){
+      *pRes = 1;
+      return SQLITE_OK;
+    }
+    if( pCur->skipNext ){
+      assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+      pCur->eState = CURSOR_VALID;
+      if( pCur->skipNext<0 ){
+        pCur->skipNext = 0;
+        *pRes = 0;
+        return SQLITE_OK;
+      }
+      pCur->skipNext = 0;
+    }
   }
-  pCur->skipNext = 0;
 
   pPage = pCur->apPage[pCur->iPage];
   assert( pPage->isInit );
@@ -54440,6 +56476,7 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
     int idx = pCur->aiIdx[pCur->iPage];
     rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
     if( rc ){
+      *pRes = 0;
       return rc;
     }
     rc = moveToRightmost(pCur);
@@ -54453,7 +56490,7 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
       moveToParent(pCur);
     }
     pCur->info.nSize = 0;
-    pCur->validNKey = 0;
+    pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
 
     pCur->aiIdx[pCur->iPage]--;
     pPage = pCur->apPage[pCur->iPage];
@@ -54563,7 +56600,7 @@ static int allocateBtreePage(
       if( iTrunk>mxPage ){
         rc = SQLITE_CORRUPT_BKPT;
       }else{
-        rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
+        rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
       }
       if( rc ){
         pTrunk = 0;
@@ -54627,7 +56664,7 @@ static int allocateBtreePage(
             goto end_allocate_page;
           }
           testcase( iNewTrunk==mxPage );
-          rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0, 0);
+          rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0);
           if( rc!=SQLITE_OK ){
             goto end_allocate_page;
           }
@@ -54706,8 +56743,8 @@ static int allocateBtreePage(
             memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
           }
           put4byte(&aData[4], k-1);
-          noContent = !btreeGetHasContent(pBt, *pPgno);
-          rc = btreeGetPage(pBt, *pPgno, ppPage, noContent, 0);
+          noContent = !btreeGetHasContent(pBt, *pPgno) ? PAGER_GET_NOCONTENT : 0;
+          rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
           if( rc==SQLITE_OK ){
             rc = sqlite3PagerWrite((*ppPage)->pDbPage);
             if( rc!=SQLITE_OK ){
@@ -54739,7 +56776,7 @@ static int allocateBtreePage(
     ** here are confined to those pages that lie between the end of the
     ** database image and the end of the database file.
     */
-    int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate));
+    int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate)) ? PAGER_GET_NOCONTENT : 0;
 
     rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
     if( rc ) return rc;
@@ -54755,7 +56792,7 @@ static int allocateBtreePage(
       MemPage *pPg = 0;
       TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
       assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
-      rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent, 0);
+      rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
       if( rc==SQLITE_OK ){
         rc = sqlite3PagerWrite(pPg->pDbPage);
         releasePage(pPg);
@@ -54769,7 +56806,7 @@ static int allocateBtreePage(
     *pPgno = pBt->nPage;
 
     assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
-    rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent, 0);
+    rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
     if( rc ) return rc;
     rc = sqlite3PagerWrite((*ppPage)->pDbPage);
     if( rc!=SQLITE_OK ){
@@ -54786,6 +56823,7 @@ end_allocate_page:
   if( rc==SQLITE_OK ){
     if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
       releasePage(*ppPage);
+      *ppPage = 0;
       return SQLITE_CORRUPT_BKPT;
     }
     (*ppPage)->isInit = 0;
@@ -54837,7 +56875,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
     /* If the secure_delete option is enabled, then
     ** always fully overwrite deleted information with zeros.
     */
-    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0, 0))!=0) )
+    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
      ||            ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
     ){
       goto freepage_out;
@@ -54864,7 +56902,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
     u32 nLeaf;                /* Initial number of leaf cells on trunk page */
 
     iTrunk = get4byte(&pPage1->aData[32]);
-    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
+    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
     if( rc!=SQLITE_OK ){
       goto freepage_out;
     }
@@ -54910,7 +56948,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
   ** first trunk in the free-list is full. Either way, the page being freed
   ** will become the new first trunk page in the free-list.
   */
-  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0, 0)) ){
+  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
     goto freepage_out;
   }
   rc = sqlite3PagerWrite(pPage->pDbPage);
@@ -55047,7 +57085,7 @@ static int fillInCell(
     nHeader += 4;
   }
   if( pPage->hasData ){
-    nHeader += putVarint(&pCell[nHeader], nData+nZero);
+    nHeader += putVarint32(&pCell[nHeader], nData+nZero);
   }else{
     nData = nZero = 0;
   }
@@ -55175,7 +57213,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
   u32 pc;         /* Offset to cell content of cell being deleted */
   u8 *data;       /* pPage->aData */
   u8 *ptr;        /* Used to move bytes around within data[] */
-  u8 *endPtr;     /* End of loop */
   int rc;         /* The return code */
   int hdr;        /* Beginning of the header.  0 most pages.  100 page 1 */
 
@@ -55200,13 +57237,8 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
     *pRC = rc;
     return;
   }
-  endPtr = &pPage->aCellIdx[2*pPage->nCell - 2];
-  assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 );  /* ptr is always 2-byte aligned */
-  while( ptr<endPtr ){
-    *(u16*)ptr = *(u16*)&ptr[2];
-    ptr += 2;
-  }
   pPage->nCell--;
+  memmove(ptr, ptr+2, 2*(pPage->nCell - idx));
   put2byte(&data[hdr+3], pPage->nCell);
   pPage->nFree += 2;
 }
@@ -55243,15 +57275,13 @@ static void insertCell(
   int ins;          /* Index in data[] where new cell pointer is inserted */
   int cellOffset;   /* Address of first cell pointer in data[] */
   u8 *data;         /* The content of the whole page */
-  u8 *ptr;          /* Used for moving information around in data[] */
-  u8 *endPtr;       /* End of the loop */
-
   int nSkip = (iChild ? 4 : 0);
 
   if( *pRC ) return;
 
   assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
-  assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921 );
+  assert( MX_CELL(pPage->pBt)<=10921 );
+  assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB );
   assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) );
   assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) );
   assert( sqlite3_mutex_held(pPage->pBt->mutex) );
@@ -55296,13 +57326,7 @@ static void insertCell(
     if( iChild ){
       put4byte(&data[idx], iChild);
     }
-    ptr = &data[end];
-    endPtr = &data[ins];
-    assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 );  /* ptr is always 2-byte aligned */
-    while( ptr>endPtr ){
-      *(u16*)ptr = *(u16*)&ptr[-2];
-      ptr -= 2;
-    }
+    memmove(&data[ins+2], &data[ins], end-ins);
     put2byte(&data[ins], idx);
     put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
 #ifndef SQLITE_OMIT_AUTOVACUUM
@@ -56492,7 +58516,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
   }
 
   assert( cursorHoldsMutex(pCur) );
-  assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE
+  assert( (pCur->curFlags & BTCF_WriteFlag)!=0 && pBt->inTransaction==TRANS_WRITE
               && (pBt->btsFlags & BTS_READ_ONLY)==0 );
   assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
 
@@ -56517,11 +58541,17 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
   rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
   if( rc ) return rc;
 
-  /* If this is an insert into a table b-tree, invalidate any incrblob 
-  ** cursors open on the row being replaced (assuming this is a replace
-  ** operation - if it is not, the following is a no-op).  */
   if( pCur->pKeyInfo==0 ){
+    /* If this is an insert into a table b-tree, invalidate any incrblob 
+    ** cursors open on the row being replaced */
     invalidateIncrblobCursors(p, nKey, 0);
+
+    /* If the cursor is currently on the last row and we are appending a
+    ** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto()
+    ** call */
+    if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0 && pCur->info.nKey==nKey-1 ){
+      loc = -1;
+    }
   }
 
   if( !loc ){
@@ -56572,7 +58602,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
 
   /* If no error has occurred and pPage has an overflow cell, call balance() 
   ** to redistribute the cells within the tree. Since balance() may move
-  ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
+  ** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey
   ** variables.
   **
   ** Previous versions of SQLite called moveToRoot() to move the cursor
@@ -56591,8 +58621,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
   ** row without seeking the cursor. This can be a big performance boost.
   */
   pCur->info.nSize = 0;
-  pCur->validNKey = 0;
   if( rc==SQLITE_OK && pPage->nOverflow ){
+    pCur->curFlags &= ~(BTCF_ValidNKey);
     rc = balance(pCur);
 
     /* Must make sure nOverflow is reset to zero even if the balance()
@@ -56624,7 +58654,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
   assert( cursorHoldsMutex(pCur) );
   assert( pBt->inTransaction==TRANS_WRITE );
   assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
-  assert( pCur->wrFlag );
+  assert( pCur->curFlags & BTCF_WriteFlag );
   assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
   assert( !hasReadConflicts(p, pCur->pgnoRoot) );
 
@@ -56647,7 +58677,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
   ** sub-tree headed by the child page of the cell being deleted. This makes
   ** balancing the tree following the delete operation easier.  */
   if( !pPage->leaf ){
-    int notUsed;
+    int notUsed = 0;
     rc = sqlite3BtreePrevious(pCur, &notUsed);
     if( rc ) return rc;
   }
@@ -56809,7 +58839,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
       }
 
       /* Move the page currently at pgnoRoot to pgnoMove. */
-      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
+      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
       if( rc!=SQLITE_OK ){
         return rc;
       }
@@ -56830,7 +58860,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
       if( rc!=SQLITE_OK ){
         return rc;
       }
-      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
+      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
       if( rc!=SQLITE_OK ){
         return rc;
       }
@@ -56900,6 +58930,7 @@ static int clearDatabasePage(
   int rc;
   unsigned char *pCell;
   int i;
+  int hdr;
 
   assert( sqlite3_mutex_held(pBt->mutex) );
   if( pgno>btreePagecount(pBt) ){
@@ -56908,6 +58939,7 @@ static int clearDatabasePage(
 
   rc = getAndInitPage(pBt, pgno, &pPage, 0);
   if( rc ) return rc;
+  hdr = pPage->hdrOffset;
   for(i=0; i<pPage->nCell; i++){
     pCell = findCell(pPage, i);
     if( !pPage->leaf ){
@@ -56918,7 +58950,7 @@ static int clearDatabasePage(
     if( rc ) goto cleardatabasepage_out;
   }
   if( !pPage->leaf ){
-    rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), 1, pnChange);
+    rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
     if( rc ) goto cleardatabasepage_out;
   }else if( pnChange ){
     assert( pPage->intKey );
@@ -56927,7 +58959,7 @@ static int clearDatabasePage(
   if( freePageFlag ){
     freePage(pPage, &rc);
   }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
-    zeroPage(pPage, pPage->aData[0] | PTF_LEAF);
+    zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
   }
 
 cleardatabasepage_out:
@@ -56968,6 +59000,15 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
 }
 
 /*
+** Delete all information from the single table that pCur is open on.
+**
+** This routine only work for pCur on an ephemeral table.
+*/
+SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){
+  return sqlite3BtreeClearTable(pCur->pBtree, pCur->pgnoRoot, 0);
+}
+
+/*
 ** Erase all information in a table and add the root of the table to
 ** the freelist.  Except, the root of the principle table (the one on
 ** page 1) is never added to the freelist.
@@ -57008,7 +59049,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
     return SQLITE_LOCKED_SHAREDCACHE;
   }
 
-  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0, 0);
+  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
   if( rc ) return rc;
   rc = sqlite3BtreeClearTable(p, iTable, 0);
   if( rc ){
@@ -57043,7 +59084,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
         */
         MemPage *pMove;
         releasePage(pPage);
-        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
+        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
         if( rc!=SQLITE_OK ){
           return rc;
         }
@@ -57053,7 +59094,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
           return rc;
         }
         pMove = 0;
-        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
+        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
         freePage(pMove, &rc);
         releasePage(pMove);
         if( rc!=SQLITE_OK ){
@@ -57264,11 +59305,11 @@ static void checkAppendMsg(
     sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
   }
   if( zMsg1 ){
-    sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1);
+    sqlite3StrAccumAppendAll(&pCheck->errMsg, zMsg1);
   }
   sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
   va_end(ap);
-  if( pCheck->errMsg.mallocFailed ){
+  if( pCheck->errMsg.accError==STRACCUM_NOMEM ){
     pCheck->mallocFailed = 1;
   }
 }
@@ -57465,7 +59506,7 @@ static int checkTreePage(
   usableSize = pBt->usableSize;
   if( iPage==0 ) return 0;
   if( checkRef(pCheck, iPage, zParentContext) ) return 0;
-  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0, 0))!=0 ){
+  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
     checkAppendMsg(pCheck, zContext,
        "unable to get the page. error code=%d", rc);
     return 0;
@@ -57926,7 +59967,7 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void
   int rc;
   assert( cursorHoldsMutex(pCsr) );
   assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
-  assert( pCsr->isIncrblobHandle );
+  assert( pCsr->curFlags & BTCF_Incrblob );
 
   rc = restoreCursorPosition(pCsr);
   if( rc!=SQLITE_OK ){
@@ -57955,7 +59996,7 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void
   **   (d) there are no conflicting read-locks, and
   **   (e) the cursor points at a valid row of an intKey table.
   */
-  if( !pCsr->wrFlag ){
+  if( (pCsr->curFlags & BTCF_WriteFlag)==0 ){
     return SQLITE_READONLY;
   }
   assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0
@@ -57968,20 +60009,10 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void
 }
 
 /* 
-** Set a flag on this cursor to cache the locations of pages from the 
-** overflow list for the current row. This is used by cursors opened
-** for incremental blob IO only.
-**
-** This function sets a flag only. The actual page location cache
-** (stored in BtCursor.aOverflow[]) is allocated and used by function
-** accessPayload() (the worker function for sqlite3BtreeData() and
-** sqlite3BtreePutData()).
+** Mark this cursor as an incremental blob cursor.
 */
-SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *pCur){
-  assert( cursorHoldsMutex(pCur) );
-  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
-  invalidateOverflowCache(pCur);
-  pCur->isIncrblobHandle = 1;
+SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
+  pCur->curFlags |= BTCF_Incrblob;
 }
 #endif
 
@@ -58030,6 +60061,13 @@ SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
   pCsr->hints = mask;
 }
 
+/*
+** Return true if the given Btree is read-only.
+*/
+SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *p){
+  return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
+}
+
 /************** End of btree.c ***********************************************/
 /************** Begin file backup.c ******************************************/
 /*
@@ -58047,12 +60085,6 @@ SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
 ** API functions and the related features.
 */
 
-/* Macro to find the minimum of two numeric values.
-*/
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
 /*
 ** Structure allocated for each backup operation.
 */
@@ -58134,6 +60166,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
         rc = SQLITE_ERROR;
       }
       sqlite3DbFree(pErrorDb, pParse->zErrMsg);
+      sqlite3ParserReset(pParse);
       sqlite3StackFree(pErrorDb, pParse);
     }
     if( rc ){
@@ -58430,7 +60463,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
       if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
         DbPage *pSrcPg;                             /* Source page object */
         rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg,
-                                 PAGER_ACQUIRE_READONLY);
+                                 PAGER_GET_READONLY);
         if( rc==SQLITE_OK ){
           rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
           sqlite3PagerUnref(pSrcPg);
@@ -58563,7 +60596,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
 
           /* Sync the database file to disk. */
           if( rc==SQLITE_OK ){
-            rc = sqlite3PagerSync(pDestPager);
+            rc = sqlite3PagerSync(pDestPager, 0);
           }
         }else{
           sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
@@ -58638,10 +60671,10 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
 
   /* Set the error code of the destination database handle. */
   rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
-  sqlite3Error(p->pDestDb, rc, 0);
-
-  /* Exit the mutexes and free the backup context structure. */
   if( p->pDestDb ){
+    sqlite3Error(p->pDestDb, rc, 0);
+
+    /* Exit the mutexes and free the backup context structure. */
     sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
   }
   sqlite3BtreeLeave(p->pSrc);
@@ -58804,6 +60837,42 @@ copy_finished:
 ** name sqlite_value
 */
 
+#ifdef SQLITE_DEBUG
+/*
+** Check invariants on a Mem object.
+**
+** This routine is intended for use inside of assert() statements, like
+** this:    assert( sqlite3VdbeCheckMemInvariants(pMem) );
+*/
+SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
+  /* The MEM_Dyn bit is set if and only if Mem.xDel is a non-NULL destructor
+  ** function for Mem.z 
+  */
+  assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
+  assert( (p->flags & MEM_Dyn)!=0 || p->xDel==0 );
+
+  /* If p holds a string or blob, the Mem.z must point to exactly
+  ** one of the following:
+  **
+  **   (1) Memory in Mem.zMalloc and managed by the Mem object
+  **   (2) Memory to be freed using Mem.xDel
+  **   (3) An ephermal string or blob
+  **   (4) A static string or blob
+  */
+  if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){
+    assert( 
+      ((p->z==p->zMalloc)? 1 : 0) +
+      ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
+      ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
+      ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1
+    );
+  }
+
+  return 1;
+}
+#endif
+
+
 /*
 ** If pMem is an object with a valid string representation, this routine
 ** ensures the internal encoding for the string representation is
@@ -58845,57 +60914,51 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
 
 /*
 ** Make sure pMem->z points to a writable allocation of at least 
-** n bytes.
-**
-** If the third argument passed to this function is true, then memory
-** cell pMem must contain a string or blob. In this case the content is
-** preserved. Otherwise, if the third parameter to this function is false,
-** any current string or blob value may be discarded.
-**
-** This function sets the MEM_Dyn flag and clears any xDel callback.
-** It also clears MEM_Ephem and MEM_Static. If the preserve flag is 
-** not set, Mem.n is zeroed.
-*/
-SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
-  assert( 1 >=
-    ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
-    (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + 
-    ((pMem->flags&MEM_Ephem) ? 1 : 0) + 
-    ((pMem->flags&MEM_Static) ? 1 : 0)
-  );
+** min(n,32) bytes.
+**
+** If the bPreserve argument is true, then copy of the content of
+** pMem->z into the new allocation.  pMem must be either a string or
+** blob if bPreserve is true.  If bPreserve is false, any prior content
+** in pMem->z is discarded.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
+  assert( sqlite3VdbeCheckMemInvariants(pMem) );
   assert( (pMem->flags&MEM_RowSet)==0 );
 
-  /* If the preserve flag is set to true, then the memory cell must already
+  /* If the bPreserve flag is set to true, then the memory cell must already
   ** contain a valid string or blob value.  */
-  assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
+  assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
+  testcase( bPreserve && pMem->z==0 );
 
-  if( n<32 ) n = 32;
-  if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
-    if( preserve && pMem->z==pMem->zMalloc ){
+  if( pMem->zMalloc==0 || sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
+    if( n<32 ) n = 32;
+    if( bPreserve && pMem->z==pMem->zMalloc ){
       pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
-      preserve = 0;
+      bPreserve = 0;
     }else{
       sqlite3DbFree(pMem->db, pMem->zMalloc);
       pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
     }
+    if( pMem->zMalloc==0 ){
+      VdbeMemRelease(pMem);
+      pMem->z = 0;
+      pMem->flags = MEM_Null;  
+      return SQLITE_NOMEM;
+    }
   }
 
-  if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){
+  if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){
     memcpy(pMem->zMalloc, pMem->z, pMem->n);
   }
-  if( pMem->flags&MEM_Dyn && pMem->xDel ){
-    assert( pMem->xDel!=SQLITE_DYNAMIC );
+  if( (pMem->flags&MEM_Dyn)!=0 ){
+    assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
     pMem->xDel((void *)(pMem->z));
   }
 
   pMem->z = pMem->zMalloc;
-  if( pMem->z==0 ){
-    pMem->flags = MEM_Null;
-  }else{
-    pMem->flags &= ~(MEM_Ephem|MEM_Static);
-  }
+  pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static);
   pMem->xDel = 0;
-  return (pMem->z ? SQLITE_OK : SQLITE_NOMEM);
+  return SQLITE_OK;
 }
 
 /*
@@ -59062,9 +61125,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
     sqlite3VdbeMemFinalize(p, p->u.pDef);
     assert( (p->flags & MEM_Agg)==0 );
     sqlite3VdbeMemRelease(p);
-  }else if( p->flags&MEM_Dyn && p->xDel ){
+  }else if( p->flags&MEM_Dyn ){
     assert( (p->flags&MEM_RowSet)==0 );
-    assert( p->xDel!=SQLITE_DYNAMIC );
+    assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
     p->xDel((void *)p->z);
     p->xDel = 0;
   }else if( p->flags&MEM_RowSet ){
@@ -59077,27 +61140,23 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
 /*
 ** Release any memory held by the Mem. This may leave the Mem in an
 ** inconsistent state, for example with (Mem.z==0) and
-** (Mem.type==SQLITE_TEXT).
+** (Mem.flags==MEM_Str).
 */
 SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
+  assert( sqlite3VdbeCheckMemInvariants(p) );
   VdbeMemRelease(p);
-  sqlite3DbFree(p->db, p->zMalloc);
+  if( p->zMalloc ){
+    sqlite3DbFree(p->db, p->zMalloc);
+    p->zMalloc = 0;
+  }
   p->z = 0;
-  p->zMalloc = 0;
-  p->xDel = 0;
+  assert( p->xDel==0 );  /* Zeroed by VdbeMemRelease() above */
 }
 
 /*
 ** Convert a 64-bit IEEE double into a 64-bit signed integer.
-** If the double is too large, return 0x8000000000000000.
-**
-** Most systems appear to do this simply by assigning
-** variables and without the extra range tests.  But
-** there are reports that windows throws an expection
-** if the floating point value is out of range. (See ticket #2880.)
-** Because we do not completely understand the problem, we will
-** take the conservative approach and always do range tests
-** before attempting the conversion.
+** If the double is out of range of a 64-bit signed integer then
+** return the closest available 64-bit signed integer.
 */
 static i64 doubleToInt64(double r){
 #ifdef SQLITE_OMIT_FLOATING_POINT
@@ -59114,14 +61173,10 @@ static i64 doubleToInt64(double r){
   static const i64 maxInt = LARGEST_INT64;
   static const i64 minInt = SMALLEST_INT64;
 
-  if( r<(double)minInt ){
-    return minInt;
-  }else if( r>(double)maxInt ){
-    /* minInt is correct here - not maxInt.  It turns out that assigning
-    ** a very large positive number to an integer results in a very large
-    ** negative integer.  This makes no sense, but it is what x86 hardware
-    ** does so for compatibility we will do the same in software. */
+  if( r<=(double)minInt ){
     return minInt;
+  }else if( r>=(double)maxInt ){
+    return maxInt;
   }else{
     return (i64)r;
   }
@@ -59203,17 +61258,11 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){
   **
   ** The second and third terms in the following conditional enforces
   ** the second condition under the assumption that addition overflow causes
-  ** values to wrap around.  On x86 hardware, the third term is always
-  ** true and could be omitted.  But we leave it in because other
-  ** architectures might behave differently.
+  ** values to wrap around.
   */
   if( pMem->r==(double)pMem->u.i
    && pMem->u.i>SMALLEST_INT64
-#if defined(__i486__) || defined(__x86_64__)
-   && ALWAYS(pMem->u.i<LARGEST_INT64)
-#else
    && pMem->u.i<LARGEST_INT64
-#endif
   ){
     pMem->flags |= MEM_Int;
   }
@@ -59283,7 +61332,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){
     sqlite3RowSetClear(pMem->u.pRowSet);
   }
   MemSetTypeFlag(pMem, MEM_Null);
-  pMem->type = SQLITE_NULL;
+}
+SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){
+  sqlite3VdbeMemSetNull((Mem*)p); 
 }
 
 /*
@@ -59293,7 +61344,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){
 SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
   sqlite3VdbeMemRelease(pMem);
   pMem->flags = MEM_Blob|MEM_Zero;
-  pMem->type = SQLITE_BLOB;
   pMem->n = 0;
   if( n<0 ) n = 0;
   pMem->u.nZero = n;
@@ -59316,7 +61366,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
   sqlite3VdbeMemRelease(pMem);
   pMem->u.i = val;
   pMem->flags = MEM_Int;
-  pMem->type = SQLITE_INTEGER;
 }
 
 #ifndef SQLITE_OMIT_FLOATING_POINT
@@ -59331,7 +61380,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
     sqlite3VdbeMemRelease(pMem);
     pMem->r = val;
     pMem->flags = MEM_Real;
-    pMem->type = SQLITE_FLOAT;
   }
 }
 #endif
@@ -59387,7 +61435,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
   Mem *pX;
   for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){
     if( pX->pScopyFrom==pMem ){
-      pX->flags |= MEM_Invalid;
+      pX->flags |= MEM_Undefined;
       pX->pScopyFrom = 0;
     }
   }
@@ -59398,7 +61446,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
 /*
 ** Size of struct Mem not including the Mem.zMalloc member.
 */
-#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))
+#define MEMCELLSIZE offsetof(Mem,zMalloc)
 
 /*
 ** Make an shallow copy of pFrom into pTo.  Prior contents of
@@ -59429,6 +61477,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
   VdbeMemRelease(pTo);
   memcpy(pTo, pFrom, MEMCELLSIZE);
   pTo->flags &= ~MEM_Dyn;
+  pTo->xDel = 0;
 
   if( pTo->flags&(MEM_Str|MEM_Blob) ){
     if( 0==(pFrom->flags&MEM_Static) ){
@@ -59539,7 +61588,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
   pMem->n = nByte;
   pMem->flags = flags;
   pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
-  pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT);
 
 #ifndef SQLITE_OMIT_UTF16
   if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
@@ -59555,124 +61603,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
 }
 
 /*
-** Compare the values contained by the two memory cells, returning
-** negative, zero or positive if pMem1 is less than, equal to, or greater
-** than pMem2. Sorting order is NULL's first, followed by numbers (integers
-** and reals) sorted numerically, followed by text ordered by the collating
-** sequence pColl and finally blob's ordered by memcmp().
-**
-** Two NULL values are considered equal by this function.
-*/
-SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
-  int rc;
-  int f1, f2;
-  int combined_flags;
-
-  f1 = pMem1->flags;
-  f2 = pMem2->flags;
-  combined_flags = f1|f2;
-  assert( (combined_flags & MEM_RowSet)==0 );
- 
-  /* If one value is NULL, it is less than the other. If both values
-  ** are NULL, return 0.
-  */
-  if( combined_flags&MEM_Null ){
-    return (f2&MEM_Null) - (f1&MEM_Null);
-  }
-
-  /* If one value is a number and the other is not, the number is less.
-  ** If both are numbers, compare as reals if one is a real, or as integers
-  ** if both values are integers.
-  */
-  if( combined_flags&(MEM_Int|MEM_Real) ){
-    if( !(f1&(MEM_Int|MEM_Real)) ){
-      return 1;
-    }
-    if( !(f2&(MEM_Int|MEM_Real)) ){
-      return -1;
-    }
-    if( (f1 & f2 & MEM_Int)==0 ){
-      double r1, r2;
-      if( (f1&MEM_Real)==0 ){
-        r1 = (double)pMem1->u.i;
-      }else{
-        r1 = pMem1->r;
-      }
-      if( (f2&MEM_Real)==0 ){
-        r2 = (double)pMem2->u.i;
-      }else{
-        r2 = pMem2->r;
-      }
-      if( r1<r2 ) return -1;
-      if( r1>r2 ) return 1;
-      return 0;
-    }else{
-      assert( f1&MEM_Int );
-      assert( f2&MEM_Int );
-      if( pMem1->u.i < pMem2->u.i ) return -1;
-      if( pMem1->u.i > pMem2->u.i ) return 1;
-      return 0;
-    }
-  }
-
-  /* If one value is a string and the other is a blob, the string is less.
-  ** If both are strings, compare using the collating functions.
-  */
-  if( combined_flags&MEM_Str ){
-    if( (f1 & MEM_Str)==0 ){
-      return 1;
-    }
-    if( (f2 & MEM_Str)==0 ){
-      return -1;
-    }
-
-    assert( pMem1->enc==pMem2->enc );
-    assert( pMem1->enc==SQLITE_UTF8 || 
-            pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
-
-    /* The collation sequence must be defined at this point, even if
-    ** the user deletes the collation sequence after the vdbe program is
-    ** compiled (this was not always the case).
-    */
-    assert( !pColl || pColl->xCmp );
-
-    if( pColl ){
-      if( pMem1->enc==pColl->enc ){
-        /* The strings are already in the correct encoding.  Call the
-        ** comparison function directly */
-        return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
-      }else{
-        const void *v1, *v2;
-        int n1, n2;
-        Mem c1;
-        Mem c2;
-        memset(&c1, 0, sizeof(c1));
-        memset(&c2, 0, sizeof(c2));
-        sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
-        sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
-        v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
-        n1 = v1==0 ? 0 : c1.n;
-        v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
-        n2 = v2==0 ? 0 : c2.n;
-        rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
-        sqlite3VdbeMemRelease(&c1);
-        sqlite3VdbeMemRelease(&c2);
-        return rc;
-      }
-    }
-    /* If a NULL pointer was passed as the collate function, fall through
-    ** to the blob case and use memcmp().  */
-  }
- 
-  /* Both values must be blobs.  Compare using memcmp().  */
-  rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
-  if( rc==0 ){
-    rc = pMem1->n - pMem2->n;
-  }
-  return rc;
-}
-
-/*
 ** Move data out of a btree key or data field and into a Mem structure.
 ** The data or key is taken from the entry that pCur is currently pointing
 ** to.  offset and amt determine what portion of the data or key to retrieve.
@@ -59687,13 +61617,13 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
 */
 SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
   BtCursor *pCur,   /* Cursor pointing at record to retrieve. */
-  int offset,       /* Offset from the start of data to return bytes from. */
-  int amt,          /* Number of bytes to return. */
+  u32 offset,       /* Offset from the start of data to return bytes from. */
+  u32 amt,          /* Number of bytes to return. */
   int key,          /* If true, retrieve from the btree key, not data. */
   Mem *pMem         /* OUT: Return data in this Mem structure. */
 ){
   char *zData;        /* Data from the btree layer */
-  int available = 0;  /* Number of bytes available on the local btree page */
+  u32 available = 0;  /* Number of bytes available on the local btree page */
   int rc = SQLITE_OK; /* Return code */
 
   assert( sqlite3BtreeCursorIsValid(pCur) );
@@ -59708,26 +61638,26 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
   }
   assert( zData!=0 );
 
-  if( offset+amt<=available && (pMem->flags&MEM_Dyn)==0 ){
+  if( offset+amt<=available ){
     sqlite3VdbeMemRelease(pMem);
     pMem->z = &zData[offset];
     pMem->flags = MEM_Blob|MEM_Ephem;
+    pMem->n = (int)amt;
   }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
-    pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
-    pMem->enc = 0;
-    pMem->type = SQLITE_BLOB;
     if( key ){
       rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
     }else{
       rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
     }
-    pMem->z[amt] = 0;
-    pMem->z[amt+1] = 0;
-    if( rc!=SQLITE_OK ){
+    if( rc==SQLITE_OK ){
+      pMem->z[amt] = 0;
+      pMem->z[amt+1] = 0;
+      pMem->flags = MEM_Blob|MEM_Term;
+      pMem->n = (int)amt;
+    }else{
       sqlite3VdbeMemRelease(pMem);
     }
   }
-  pMem->n = amt;
 
   return rc;
 }
@@ -59785,50 +61715,105 @@ SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){
   Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
   if( p ){
     p->flags = MEM_Null;
-    p->type = SQLITE_NULL;
     p->db = db;
   }
   return p;
 }
 
 /*
-** Create a new sqlite3_value object, containing the value of pExpr.
+** Context object passed by sqlite3Stat4ProbeSetValue() through to 
+** valueNew(). See comments above valueNew() for details.
+*/
+struct ValueNewStat4Ctx {
+  Parse *pParse;
+  Index *pIdx;
+  UnpackedRecord **ppRec;
+  int iVal;
+};
+
+/*
+** Allocate and return a pointer to a new sqlite3_value object. If
+** the second argument to this function is NULL, the object is allocated
+** by calling sqlite3ValueNew().
 **
-** This only works for very simple expressions that consist of one constant
-** token (i.e. "5", "5.1", "'a string'"). If the expression can
-** be converted directly into a value, then the value is allocated and
-** a pointer written to *ppVal. The caller is responsible for deallocating
-** the value by passing it to sqlite3ValueFree() later on. If the expression
-** cannot be converted to a value, then *ppVal is set to NULL.
+** Otherwise, if the second argument is non-zero, then this function is 
+** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not
+** already been allocated, allocate the UnpackedRecord structure that 
+** that function will return to its caller here. Then return a pointer 
+** an sqlite3_value within the UnpackedRecord.a[] array.
 */
-SQLITE_PRIVATE int sqlite3ValueFromExpr(
-  sqlite3 *db,              /* The database connection */
-  Expr *pExpr,              /* The expression to evaluate */
-  u8 enc,                   /* Encoding to use */
-  u8 affinity,              /* Affinity to use */
-  sqlite3_value **ppVal     /* Write the new value here */
+static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  if( p ){
+    UnpackedRecord *pRec = p->ppRec[0];
+
+    if( pRec==0 ){
+      Index *pIdx = p->pIdx;      /* Index being probed */
+      int nByte;                  /* Bytes of space to allocate */
+      int i;                      /* Counter variable */
+      int nCol = pIdx->nColumn;   /* Number of index columns including rowid */
+  
+      nByte = sizeof(Mem) * nCol + ROUND8(sizeof(UnpackedRecord));
+      pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte);
+      if( pRec ){
+        pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx);
+        if( pRec->pKeyInfo ){
+          assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
+          assert( pRec->pKeyInfo->enc==ENC(db) );
+          pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
+          for(i=0; i<nCol; i++){
+            pRec->aMem[i].flags = MEM_Null;
+            pRec->aMem[i].db = db;
+          }
+        }else{
+          sqlite3DbFree(db, pRec);
+          pRec = 0;
+        }
+      }
+      if( pRec==0 ) return 0;
+      p->ppRec[0] = pRec;
+    }
+  
+    pRec->nField = p->iVal+1;
+    return &pRec->aMem[p->iVal];
+  }
+#else
+  UNUSED_PARAMETER(p);
+#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
+  return sqlite3ValueNew(db);
+}
+
+/*
+** Extract a value from the supplied expression in the manner described
+** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object
+** using valueNew().
+**
+** If pCtx is NULL and an error occurs after the sqlite3_value object
+** has been allocated, it is freed before returning. Or, if pCtx is not
+** NULL, it is assumed that the caller will free any allocated object
+** in all cases.
+*/
+static int valueFromExpr(
+  sqlite3 *db,                    /* The database connection */
+  Expr *pExpr,                    /* The expression to evaluate */
+  u8 enc,                         /* Encoding to use */
+  u8 affinity,                    /* Affinity to use */
+  sqlite3_value **ppVal,          /* Write the new value here */
+  struct ValueNewStat4Ctx *pCtx   /* Second argument for valueNew() */
 ){
   int op;
   char *zVal = 0;
   sqlite3_value *pVal = 0;
   int negInt = 1;
   const char *zNeg = "";
+  int rc = SQLITE_OK;
 
   if( !pExpr ){
     *ppVal = 0;
     return SQLITE_OK;
   }
   op = pExpr->op;
-
-  /* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT3.
-  ** The ifdef here is to enable us to achieve 100% branch test coverage even
-  ** when SQLITE_ENABLE_STAT3 is omitted.
-  */
-#ifdef SQLITE_ENABLE_STAT3
-  if( op==TK_REGISTER ) op = pExpr->op2;
-#else
   if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
-#endif
 
   /* Handle negative integers in a single step.  This is needed in the
   ** case when the value is -9223372036854775808.
@@ -59842,7 +61827,7 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
   }
 
   if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
-    pVal = sqlite3ValueNew(db);
+    pVal = valueNew(db, pCtx);
     if( pVal==0 ) goto no_mem;
     if( ExprHasProperty(pExpr, EP_IntValue) ){
       sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
@@ -59850,7 +61835,6 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
       zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
       if( zVal==0 ) goto no_mem;
       sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
-      if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT;
     }
     if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
       sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
@@ -59859,16 +61843,18 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
     }
     if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
     if( enc!=SQLITE_UTF8 ){
-      sqlite3VdbeChangeEncoding(pVal, enc);
+      rc = sqlite3VdbeChangeEncoding(pVal, enc);
     }
   }else if( op==TK_UMINUS ) {
     /* This branch happens for multiple negative signs.  Ex: -(-5) */
-    if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
+    if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) 
+     && pVal!=0
+    ){
       sqlite3VdbeMemNumerify(pVal);
       if( pVal->u.i==SMALLEST_INT64 ){
-        pVal->flags &= MEM_Int;
+        pVal->flags &= ~MEM_Int;
         pVal->flags |= MEM_Real;
-        pVal->r = (double)LARGEST_INT64;
+        pVal->r = (double)SMALLEST_INT64;
       }else{
         pVal->u.i = -pVal->u.i;
       }
@@ -59876,7 +61862,7 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
       sqlite3ValueApplyAffinity(pVal, affinity, enc);
     }
   }else if( op==TK_NULL ){
-    pVal = sqlite3ValueNew(db);
+    pVal = valueNew(db, pCtx);
     if( pVal==0 ) goto no_mem;
   }
 #ifndef SQLITE_OMIT_BLOB_LITERAL
@@ -59884,7 +61870,7 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
     int nVal;
     assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
     assert( pExpr->u.zToken[1]=='\'' );
-    pVal = sqlite3ValueNew(db);
+    pVal = valueNew(db, pCtx);
     if( !pVal ) goto no_mem;
     zVal = &pExpr->u.zToken[2];
     nVal = sqlite3Strlen30(zVal)-1;
@@ -59894,21 +61880,301 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
   }
 #endif
 
-  if( pVal ){
-    sqlite3VdbeMemStoreType(pVal);
-  }
   *ppVal = pVal;
-  return SQLITE_OK;
+  return rc;
 
 no_mem:
   db->mallocFailed = 1;
   sqlite3DbFree(db, zVal);
-  sqlite3ValueFree(pVal);
-  *ppVal = 0;
+  assert( *ppVal==0 );
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  if( pCtx==0 ) sqlite3ValueFree(pVal);
+#else
+  assert( pCtx==0 ); sqlite3ValueFree(pVal);
+#endif
   return SQLITE_NOMEM;
 }
 
 /*
+** Create a new sqlite3_value object, containing the value of pExpr.
+**
+** This only works for very simple expressions that consist of one constant
+** token (i.e. "5", "5.1", "'a string'"). If the expression can
+** be converted directly into a value, then the value is allocated and
+** a pointer written to *ppVal. The caller is responsible for deallocating
+** the value by passing it to sqlite3ValueFree() later on. If the expression
+** cannot be converted to a value, then *ppVal is set to NULL.
+*/
+SQLITE_PRIVATE int sqlite3ValueFromExpr(
+  sqlite3 *db,              /* The database connection */
+  Expr *pExpr,              /* The expression to evaluate */
+  u8 enc,                   /* Encoding to use */
+  u8 affinity,              /* Affinity to use */
+  sqlite3_value **ppVal     /* Write the new value here */
+){
+  return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0);
+}
+
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+/*
+** The implementation of the sqlite_record() function. This function accepts
+** a single argument of any type. The return value is a formatted database 
+** record (a blob) containing the argument value.
+**
+** This is used to convert the value stored in the 'sample' column of the
+** sqlite_stat3 table to the record format SQLite uses internally.
+*/
+static void recordFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const int file_format = 1;
+  int iSerial;                    /* Serial type */
+  int nSerial;                    /* Bytes of space for iSerial as varint */
+  int nVal;                       /* Bytes of space required for argv[0] */
+  int nRet;
+  sqlite3 *db;
+  u8 *aRet;
+
+  UNUSED_PARAMETER( argc );
+  iSerial = sqlite3VdbeSerialType(argv[0], file_format);
+  nSerial = sqlite3VarintLen(iSerial);
+  nVal = sqlite3VdbeSerialTypeLen(iSerial);
+  db = sqlite3_context_db_handle(context);
+
+  nRet = 1 + nSerial + nVal;
+  aRet = sqlite3DbMallocRaw(db, nRet);
+  if( aRet==0 ){
+    sqlite3_result_error_nomem(context);
+  }else{
+    aRet[0] = nSerial+1;
+    sqlite3PutVarint(&aRet[1], iSerial);
+    sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
+    sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
+    sqlite3DbFree(db, aRet);
+  }
+}
+
+/*
+** Register built-in functions used to help read ANALYZE data.
+*/
+SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void){
+  static SQLITE_WSD FuncDef aAnalyzeTableFuncs[] = {
+    FUNCTION(sqlite_record,   1, 0, 0, recordFunc),
+  };
+  int i;
+  FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+  FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAnalyzeTableFuncs);
+  for(i=0; i<ArraySize(aAnalyzeTableFuncs); i++){
+    sqlite3FuncDefInsert(pHash, &aFunc[i]);
+  }
+}
+
+/*
+** Attempt to extract a value from pExpr and use it to construct *ppVal.
+**
+** If pAlloc is not NULL, then an UnpackedRecord object is created for
+** pAlloc if one does not exist and the new value is added to the
+** UnpackedRecord object.
+**
+** A value is extracted in the following cases:
+**
+**  * (pExpr==0). In this case the value is assumed to be an SQL NULL,
+**
+**  * The expression is a bound variable, and this is a reprepare, or
+**
+**  * The expression is a literal value.
+**
+** On success, *ppVal is made to point to the extracted value.  The caller
+** is responsible for ensuring that the value is eventually freed.
+*/
+static int stat4ValueFromExpr(
+  Parse *pParse,                  /* Parse context */
+  Expr *pExpr,                    /* The expression to extract a value from */
+  u8 affinity,                    /* Affinity to use */
+  struct ValueNewStat4Ctx *pAlloc,/* How to allocate space.  Or NULL */
+  sqlite3_value **ppVal           /* OUT: New value object (or NULL) */
+){
+  int rc = SQLITE_OK;
+  sqlite3_value *pVal = 0;
+  sqlite3 *db = pParse->db;
+
+  /* Skip over any TK_COLLATE nodes */
+  pExpr = sqlite3ExprSkipCollate(pExpr);
+
+  if( !pExpr ){
+    pVal = valueNew(db, pAlloc);
+    if( pVal ){
+      sqlite3VdbeMemSetNull((Mem*)pVal);
+    }
+  }else if( pExpr->op==TK_VARIABLE
+        || NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
+  ){
+    Vdbe *v;
+    int iBindVar = pExpr->iColumn;
+    sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar);
+    if( (v = pParse->pReprepare)!=0 ){
+      pVal = valueNew(db, pAlloc);
+      if( pVal ){
+        rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
+        if( rc==SQLITE_OK ){
+          sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
+        }
+        pVal->db = pParse->db;
+      }
+    }
+  }else{
+    rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, pAlloc);
+  }
+
+  assert( pVal==0 || pVal->db==db );
+  *ppVal = pVal;
+  return rc;
+}
+
+/*
+** This function is used to allocate and populate UnpackedRecord 
+** structures intended to be compared against sample index keys stored 
+** in the sqlite_stat4 table.
+**
+** A single call to this function attempts to populates field iVal (leftmost 
+** is 0 etc.) of the unpacked record with a value extracted from expression
+** pExpr. Extraction of values is possible if:
+**
+**  * (pExpr==0). In this case the value is assumed to be an SQL NULL,
+**
+**  * The expression is a bound variable, and this is a reprepare, or
+**
+**  * The sqlite3ValueFromExpr() function is able to extract a value 
+**    from the expression (i.e. the expression is a literal value).
+**
+** If a value can be extracted, the affinity passed as the 5th argument
+** is applied to it before it is copied into the UnpackedRecord. Output
+** parameter *pbOk is set to true if a value is extracted, or false 
+** otherwise.
+**
+** When this function is called, *ppRec must either point to an object
+** allocated by an earlier call to this function, or must be NULL. If it
+** is NULL and a value can be successfully extracted, a new UnpackedRecord
+** is allocated (and *ppRec set to point to it) before returning.
+**
+** Unless an error is encountered, SQLITE_OK is returned. It is not an
+** error if a value cannot be extracted from pExpr. If an error does
+** occur, an SQLite error code is returned.
+*/
+SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(
+  Parse *pParse,                  /* Parse context */
+  Index *pIdx,                    /* Index being probed */
+  UnpackedRecord **ppRec,         /* IN/OUT: Probe record */
+  Expr *pExpr,                    /* The expression to extract a value from */
+  u8 affinity,                    /* Affinity to use */
+  int iVal,                       /* Array element to populate */
+  int *pbOk                       /* OUT: True if value was extracted */
+){
+  int rc;
+  sqlite3_value *pVal = 0;
+  struct ValueNewStat4Ctx alloc;
+
+  alloc.pParse = pParse;
+  alloc.pIdx = pIdx;
+  alloc.ppRec = ppRec;
+  alloc.iVal = iVal;
+
+  rc = stat4ValueFromExpr(pParse, pExpr, affinity, &alloc, &pVal);
+  assert( pVal==0 || pVal->db==pParse->db );
+  *pbOk = (pVal!=0);
+  return rc;
+}
+
+/*
+** Attempt to extract a value from expression pExpr using the methods
+** as described for sqlite3Stat4ProbeSetValue() above. 
+**
+** If successful, set *ppVal to point to a new value object and return 
+** SQLITE_OK. If no value can be extracted, but no other error occurs
+** (e.g. OOM), return SQLITE_OK and set *ppVal to NULL. Or, if an error
+** does occur, return an SQLite error code. The final value of *ppVal
+** is undefined in this case.
+*/
+SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(
+  Parse *pParse,                  /* Parse context */
+  Expr *pExpr,                    /* The expression to extract a value from */
+  u8 affinity,                    /* Affinity to use */
+  sqlite3_value **ppVal           /* OUT: New value object (or NULL) */
+){
+  return stat4ValueFromExpr(pParse, pExpr, affinity, 0, ppVal);
+}
+
+/*
+** Extract the iCol-th column from the nRec-byte record in pRec.  Write
+** the column value into *ppVal.  If *ppVal is initially NULL then a new
+** sqlite3_value object is allocated.
+**
+** If *ppVal is initially NULL then the caller is responsible for 
+** ensuring that the value written into *ppVal is eventually freed.
+*/
+SQLITE_PRIVATE int sqlite3Stat4Column(
+  sqlite3 *db,                    /* Database handle */
+  const void *pRec,               /* Pointer to buffer containing record */
+  int nRec,                       /* Size of buffer pRec in bytes */
+  int iCol,                       /* Column to extract */
+  sqlite3_value **ppVal           /* OUT: Extracted value */
+){
+  u32 t;                          /* a column type code */
+  int nHdr;                       /* Size of the header in the record */
+  int iHdr;                       /* Next unread header byte */
+  int iField;                     /* Next unread data byte */
+  int szField;                    /* Size of the current data field */
+  int i;                          /* Column index */
+  u8 *a = (u8*)pRec;              /* Typecast byte array */
+  Mem *pMem = *ppVal;             /* Write result into this Mem object */
+
+  assert( iCol>0 );
+  iHdr = getVarint32(a, nHdr);
+  if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
+  iField = nHdr;
+  for(i=0; i<=iCol; i++){
+    iHdr += getVarint32(&a[iHdr], t);
+    testcase( iHdr==nHdr );
+    testcase( iHdr==nHdr+1 );
+    if( iHdr>nHdr ) return SQLITE_CORRUPT_BKPT;
+    szField = sqlite3VdbeSerialTypeLen(t);
+    iField += szField;
+  }
+  testcase( iField==nRec );
+  testcase( iField==nRec+1 );
+  if( iField>nRec ) return SQLITE_CORRUPT_BKPT;
+  if( pMem==0 ){
+    pMem = *ppVal = sqlite3ValueNew(db);
+    if( pMem==0 ) return SQLITE_NOMEM;
+  }
+  sqlite3VdbeSerialGet(&a[iField-szField], t, pMem);
+  pMem->enc = ENC(db);
+  return SQLITE_OK;
+}
+
+/*
+** Unless it is NULL, the argument must be an UnpackedRecord object returned
+** by an earlier call to sqlite3Stat4ProbeSetValue(). This call deletes
+** the object.
+*/
+SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
+  if( pRec ){
+    int i;
+    int nCol = pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField;
+    Mem *aMem = pRec->aMem;
+    sqlite3 *db = aMem[0].db;
+    for(i=0; i<nCol; i++){
+      sqlite3DbFree(db, aMem[i].zMalloc);
+    }
+    sqlite3KeyInfoUnref(pRec->pKeyInfo);
+    sqlite3DbFree(db, pRec);
+  }
+}
+#endif /* ifdef SQLITE_ENABLE_STAT4 */
+
+/*
 ** Change the string value of an sqlite3_value object
 */
 SQLITE_PRIVATE void sqlite3ValueSetStr(
@@ -59968,7 +62234,8 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
 /*
 ** Create a new virtual database engine.
 */
-SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
+SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
+  sqlite3 *db = pParse->db;
   Vdbe *p;
   p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
   if( p==0 ) return 0;
@@ -59980,6 +62247,10 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
   p->pPrev = 0;
   db->pVdbe = p;
   p->magic = VDBE_MAGIC_INIT;
+  p->pParse = pParse;
+  assert( pParse->aLabel==0 );
+  assert( pParse->nLabel==0 );
+  assert( pParse->nOpAlloc==0 );
   return p;
 }
 
@@ -60026,35 +62297,55 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
   pB->isPrepareV2 = pA->isPrepareV2;
 }
 
-#ifdef SQLITE_DEBUG
 /*
-** Turn tracing on or off
-*/
-SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe *p, FILE *trace){
-  p->trace = trace;
-}
-#endif
-
-/*
-** Resize the Vdbe.aOp array so that it is at least one op larger than 
-** it was.
+** Resize the Vdbe.aOp array so that it is at least nOp elements larger 
+** than its current size. nOp is guaranteed to be less than or equal
+** to 1024/sizeof(Op).
 **
 ** If an out-of-memory error occurs while resizing the array, return
-** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain 
+** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain 
 ** unchanged (this is so that any opcodes already allocated can be 
 ** correctly deallocated along with the rest of the Vdbe).
 */
-static int growOpArray(Vdbe *p){
+static int growOpArray(Vdbe *v, int nOp){
   VdbeOp *pNew;
+  Parse *p = v->pParse;
+
+  /* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force
+  ** more frequent reallocs and hence provide more opportunities for 
+  ** simulated OOM faults.  SQLITE_TEST_REALLOC_STRESS is generally used
+  ** during testing only.  With SQLITE_TEST_REALLOC_STRESS grow the op array
+  ** by the minimum* amount required until the size reaches 512.  Normal
+  ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
+  ** size of the op array or add 1KB of space, whichever is smaller. */
+#ifdef SQLITE_TEST_REALLOC_STRESS
+  int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
+#else
   int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
-  pNew = sqlite3DbRealloc(p->db, p->aOp, nNew*sizeof(Op));
+  UNUSED_PARAMETER(nOp);
+#endif
+
+  assert( nOp<=(1024/sizeof(Op)) );
+  assert( nNew>=(p->nOpAlloc+nOp) );
+  pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
   if( pNew ){
     p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
-    p->aOp = pNew;
+    v->aOp = pNew;
   }
   return (pNew ? SQLITE_OK : SQLITE_NOMEM);
 }
 
+#ifdef SQLITE_DEBUG
+/* This routine is just a convenient place to set a breakpoint that will
+** fire after each opcode is inserted and displayed using
+** "PRAGMA vdbe_addoptrace=on".
+*/
+static void test_addop_breakpoint(void){
+  static int n = 0;
+  n++;
+}
+#endif
+
 /*
 ** Add a new instruction to the list of instructions current in the
 ** VDBE.  Return the address of the new instruction.
@@ -60078,8 +62369,8 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
   i = p->nOp;
   assert( p->magic==VDBE_MAGIC_INIT );
   assert( op>0 && op<0xff );
-  if( p->nOpAlloc<=i ){
-    if( growOpArray(p) ){
+  if( p->pParse->nOpAlloc<=i ){
+    if( growOpArray(p, 1) ){
       return 1;
     }
   }
@@ -60092,16 +62383,31 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
   pOp->p3 = p3;
   pOp->p4.p = 0;
   pOp->p4type = P4_NOTUSED;
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
   pOp->zComment = 0;
+#endif
+#ifdef SQLITE_DEBUG
   if( p->db->flags & SQLITE_VdbeAddopTrace ){
+    int jj, kk;
+    Parse *pParse = p->pParse;
+    for(jj=kk=0; jj<SQLITE_N_COLCACHE; jj++){
+      struct yColCache *x = pParse->aColCache + jj;
+      if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue;
+      printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
+      kk++;
+    }
+    if( kk ) printf("\n");
     sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+    test_addop_breakpoint();
   }
 #endif
 #ifdef VDBE_PROFILE
   pOp->cycles = 0;
   pOp->cnt = 0;
 #endif
+#ifdef SQLITE_VDBE_COVERAGE
+  pOp->iSrcLine = 0;
+#endif
   return i;
 }
 SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){
@@ -60177,9 +62483,10 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
 **
 ** Zero is returned if a malloc() fails.
 */
-SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){
+SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){
+  Parse *p = v->pParse;
   int i = p->nLabel++;
-  assert( p->magic==VDBE_MAGIC_INIT );
+  assert( v->magic==VDBE_MAGIC_INIT );
   if( (i & (i-1))==0 ){
     p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, 
                                        (i*2+1)*sizeof(p->aLabel[0]));
@@ -60195,13 +62502,15 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){
 ** be inserted.  The parameter "x" must have been obtained from
 ** a prior call to sqlite3VdbeMakeLabel().
 */
-SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *p, int x){
+SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
+  Parse *p = v->pParse;
   int j = -1-x;
-  assert( p->magic==VDBE_MAGIC_INIT );
-  assert( j>=0 && j<p->nLabel );
-  if( p->aLabel ){
-    p->aLabel[j] = p->nOp;
+  assert( v->magic==VDBE_MAGIC_INIT );
+  assert( j<p->nLabel );
+  if( ALWAYS(j>=0) && p->aLabel ){
+    p->aLabel[j] = v->nOp;
   }
+  p->iFixedOp = v->nOp - 1;
 }
 
 /*
@@ -60349,43 +62658,79 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
   int i;
   int nMaxArgs = *pMaxFuncArgs;
   Op *pOp;
-  int *aLabel = p->aLabel;
+  Parse *pParse = p->pParse;
+  int *aLabel = pParse->aLabel;
   p->readOnly = 1;
+  p->bIsReader = 0;
   for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
     u8 opcode = pOp->opcode;
 
-    pOp->opflags = sqlite3OpcodeProperty[opcode];
-    if( opcode==OP_Function || opcode==OP_AggStep ){
-      if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
-    }else if( (opcode==OP_Transaction && pOp->p2!=0) || opcode==OP_Vacuum ){
-      p->readOnly = 0;
+    /* NOTE: Be sure to update mkopcodeh.awk when adding or removing
+    ** cases from this switch! */
+    switch( opcode ){
+      case OP_Function:
+      case OP_AggStep: {
+        if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
+        break;
+      }
+      case OP_Transaction: {
+        if( pOp->p2!=0 ) p->readOnly = 0;
+        /* fall thru */
+      }
+      case OP_AutoCommit:
+      case OP_Savepoint: {
+        p->bIsReader = 1;
+        break;
+      }
+#ifndef SQLITE_OMIT_WAL
+      case OP_Checkpoint:
+#endif
+      case OP_Vacuum:
+      case OP_JournalMode: {
+        p->readOnly = 0;
+        p->bIsReader = 1;
+        break;
+      }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-    }else if( opcode==OP_VUpdate ){
-      if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
-    }else if( opcode==OP_VFilter ){
-      int n;
-      assert( p->nOp - i >= 3 );
-      assert( pOp[-1].opcode==OP_Integer );
-      n = pOp[-1].p1;
-      if( n>nMaxArgs ) nMaxArgs = n;
+      case OP_VUpdate: {
+        if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
+        break;
+      }
+      case OP_VFilter: {
+        int n;
+        assert( p->nOp - i >= 3 );
+        assert( pOp[-1].opcode==OP_Integer );
+        n = pOp[-1].p1;
+        if( n>nMaxArgs ) nMaxArgs = n;
+        break;
+      }
 #endif
-    }else if( opcode==OP_Next || opcode==OP_SorterNext ){
-      pOp->p4.xAdvance = sqlite3BtreeNext;
-      pOp->p4type = P4_ADVANCE;
-    }else if( opcode==OP_Prev ){
-      pOp->p4.xAdvance = sqlite3BtreePrevious;
-      pOp->p4type = P4_ADVANCE;
+      case OP_Next:
+      case OP_NextIfOpen:
+      case OP_SorterNext: {
+        pOp->p4.xAdvance = sqlite3BtreeNext;
+        pOp->p4type = P4_ADVANCE;
+        break;
+      }
+      case OP_Prev:
+      case OP_PrevIfOpen: {
+        pOp->p4.xAdvance = sqlite3BtreePrevious;
+        pOp->p4type = P4_ADVANCE;
+        break;
+      }
     }
 
+    pOp->opflags = sqlite3OpcodeProperty[opcode];
     if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
-      assert( -1-pOp->p2<p->nLabel );
+      assert( -1-pOp->p2<pParse->nLabel );
       pOp->p2 = aLabel[-1-pOp->p2];
     }
   }
-  sqlite3DbFree(p->db, p->aLabel);
-  p->aLabel = 0;
-
+  sqlite3DbFree(p->db, pParse->aLabel);
+  pParse->aLabel = 0;
+  pParse->nLabel = 0;
   *pMaxFuncArgs = nMaxArgs;
+  assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
 }
 
 /*
@@ -60412,7 +62757,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg)
   assert( aOp && !p->db->mallocFailed );
 
   /* Check that sqlite3VdbeUsesBtree() was not called on this VM */
-  assert( p->btreeMask==0 );
+  assert( DbMaskAllZero(p->btreeMask) );
 
   resolveP2Values(p, pnMaxArg);
   *pnOp = p->nOp;
@@ -60424,10 +62769,10 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg)
 ** Add a whole list of operations to the operation stack.  Return the
 ** address of the first operation added.
 */
-SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
+SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
   int addr;
   assert( p->magic==VDBE_MAGIC_INIT );
-  if( p->nOp + nOp > p->nOpAlloc && growOpArray(p) ){
+  if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
     return 0;
   }
   addr = p->nOp;
@@ -60439,7 +62784,8 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp)
       VdbeOp *pOut = &p->aOp[i+addr];
       pOut->opcode = pIn->opcode;
       pOut->p1 = pIn->p1;
-      if( p2<0 && (sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP)!=0 ){
+      if( p2<0 ){
+        assert( sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP );
         pOut->p2 = addr + ADDR(p2);
       }else{
         pOut->p2 = p2;
@@ -60448,8 +62794,15 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp)
       pOut->p4type = P4_NOTUSED;
       pOut->p4.p = 0;
       pOut->p5 = 0;
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
       pOut->zComment = 0;
+#endif
+#ifdef SQLITE_VDBE_COVERAGE
+      pOut->iSrcLine = iLineno+i;
+#else
+      (void)iLineno;
+#endif
+#ifdef SQLITE_DEBUG
       if( p->db->flags & SQLITE_VdbeAddopTrace ){
         sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
       }
@@ -60511,8 +62864,8 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 val){
 ** the address of the next instruction to be coded.
 */
 SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
-  assert( addr>=0 || p->db->mallocFailed );
-  if( addr>=0 ) sqlite3VdbeChangeP2(p, addr, p->nOp);
+  sqlite3VdbeChangeP2(p, addr, p->nOp);
+  p->pParse->iFixedOp = p->nOp - 1;
 }
 
 
@@ -60521,7 +62874,7 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
 ** the FuncDef is not ephermal, then do nothing.
 */
 static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
-  if( ALWAYS(pDef) && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){
+  if( ALWAYS(pDef) && (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){
     sqlite3DbFree(db, pDef);
   }
 }
@@ -60538,21 +62891,16 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
       case P4_REAL:
       case P4_INT64:
       case P4_DYNAMIC:
-      case P4_KEYINFO:
-      case P4_INTARRAY:
-      case P4_KEYINFO_HANDOFF: {
+      case P4_INTARRAY: {
         sqlite3DbFree(db, p4);
         break;
       }
-      case P4_MPRINTF: {
-        if( db->pnBytesFreed==0 ) sqlite3_free(p4);
+      case P4_KEYINFO: {
+        if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
         break;
       }
-      case P4_VDBEFUNC: {
-        VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
-        freeEphemeralFunction(db, pVdbeFunc->pFunc);
-        if( db->pnBytesFreed==0 ) sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
-        sqlite3DbFree(db, pVdbeFunc);
+      case P4_MPRINTF: {
+        if( db->pnBytesFreed==0 ) sqlite3_free(p4);
         break;
       }
       case P4_FUNCDEF: {
@@ -60587,7 +62935,7 @@ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
     Op *pOp;
     for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
       freeP4(db, pOp->p4type, pOp->p4.p);
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
       sqlite3DbFree(db, pOp->zComment);
 #endif     
     }
@@ -60609,12 +62957,25 @@ SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
 ** Change the opcode at addr into OP_Noop
 */
 SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
-  if( p->aOp ){
+  if( addr<p->nOp ){
     VdbeOp *pOp = &p->aOp[addr];
     sqlite3 *db = p->db;
     freeP4(db, pOp->p4type, pOp->p4.p);
     memset(pOp, 0, sizeof(pOp[0]));
     pOp->opcode = OP_Noop;
+    if( addr==p->nOp-1 ) p->nOp--;
+  }
+}
+
+/*
+** Remove the last opcode inserted
+*/
+SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
+  if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
+    sqlite3VdbeChangeToNoop(p, p->nOp-1);
+    return 1;
+  }else{
+    return 0;
   }
 }
 
@@ -60628,14 +62989,6 @@ SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
 ** the string is made into memory obtained from sqlite3_malloc().
 ** A value of n==0 means copy bytes of zP4 up to and including the
 ** first null byte.  If n>0 then copy n+1 bytes of zP4.
-**
-** If n==P4_KEYINFO it means that zP4 is a pointer to a KeyInfo structure.
-** A copy is made of the KeyInfo structure into memory obtained from
-** sqlite3_malloc, to be freed when the Vdbe is finalized.
-** n==P4_KEYINFO_HANDOFF indicates that zP4 points to a KeyInfo structure
-** stored in memory that the caller has obtained from sqlite3_malloc. The 
-** caller should not free the allocation, it will be freed when the Vdbe is
-** finalized.
 ** 
 ** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points
 ** to a string or structure that is guaranteed to exist for the lifetime of
@@ -60650,7 +63003,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
   db = p->db;
   assert( p->magic==VDBE_MAGIC_INIT );
   if( p->aOp==0 || db->mallocFailed ){
-    if ( n!=P4_KEYINFO && n!=P4_VTAB ) {
+    if( n!=P4_VTAB ){
       freeP4(db, n, (void*)*(char**)&zP4);
     }
     return;
@@ -60661,7 +63014,9 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
     addr = p->nOp - 1;
   }
   pOp = &p->aOp[addr];
-  assert( pOp->p4type==P4_NOTUSED || pOp->p4type==P4_INT32 );
+  assert( pOp->p4type==P4_NOTUSED
+       || pOp->p4type==P4_INT32
+       || pOp->p4type==P4_KEYINFO );
   freeP4(db, pOp->p4type, pOp->p4.p);
   pOp->p4.p = 0;
   if( n==P4_INT32 ){
@@ -60673,26 +63028,6 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
     pOp->p4.p = 0;
     pOp->p4type = P4_NOTUSED;
   }else if( n==P4_KEYINFO ){
-    KeyInfo *pKeyInfo;
-    int nField, nByte;
-
-    nField = ((KeyInfo*)zP4)->nField;
-    nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField;
-    pKeyInfo = sqlite3DbMallocRaw(0, nByte);
-    pOp->p4.pKeyInfo = pKeyInfo;
-    if( pKeyInfo ){
-      u8 *aSortOrder;
-      memcpy((char*)pKeyInfo, zP4, nByte - nField);
-      aSortOrder = pKeyInfo->aSortOrder;
-      assert( aSortOrder!=0 );
-      pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
-      memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
-      pOp->p4type = P4_KEYINFO;
-    }else{
-      p->db->mallocFailed = 1;
-      pOp->p4type = P4_NOTUSED;
-    }
-  }else if( n==P4_KEYINFO_HANDOFF ){
     pOp->p4.p = (void*)zP4;
     pOp->p4type = P4_KEYINFO;
   }else if( n==P4_VTAB ){
@@ -60710,7 +63045,19 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
   }
 }
 
-#ifndef NDEBUG
+/*
+** Set the P4 on the most recently added opcode to the KeyInfo for the
+** index given.
+*/
+SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
+  Vdbe *v = pParse->pVdbe;
+  assert( v!=0 );
+  assert( pIdx!=0 );
+  sqlite3VdbeChangeP4(v, -1, (char*)sqlite3KeyInfoOfIndex(pParse, pIdx),
+                      P4_KEYINFO);
+}
+
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
 /*
 ** Change the comment on the most recently coded instruction.  Or
 ** insert a No-op and add the comment to that new instruction.  This
@@ -60745,6 +63092,15 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
 }
 #endif  /* NDEBUG */
 
+#ifdef SQLITE_VDBE_COVERAGE
+/*
+** Set the value if the iSrcLine field for the previously coded instruction.
+*/
+SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){
+  sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine;
+}
+#endif /* SQLITE_VDBE_COVERAGE */
+
 /*
 ** Return the opcode for a given address.  If the address is -1, then
 ** return the most recently inserted opcode.
@@ -60757,14 +63113,6 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
 ** this routine is a valid pointer.  But because the dummy.opcode is 0,
 ** dummy will never be written to.  This is verified by code inspection and
 ** by running with Valgrind.
-**
-** About the #ifdef SQLITE_OMIT_TRACE:  Normally, this routine is never called
-** unless p->nOp>0.  This is because in the absense of SQLITE_OMIT_TRACE,
-** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as
-** a new VDBE is created.  So we are free to set addr to p->nOp-1 without
-** having to double-check to make sure that the result is non-negative. But
-** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to
-** check the value of p->nOp-1 before continuing.
 */
 SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
   /* C89 specifies that the constant "dummy" will be initialized to all
@@ -60772,9 +63120,6 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
   static VdbeOp dummy;  /* Ignore the MSVC warning about no initializer */
   assert( p->magic==VDBE_MAGIC_INIT );
   if( addr<0 ){
-#ifdef SQLITE_OMIT_TRACE
-    if( p->nOp==0 ) return (VdbeOp*)&dummy;
-#endif
     addr = p->nOp - 1;
   }
   assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
@@ -60785,6 +63130,97 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
   }
 }
 
+#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
+/*
+** Return an integer value for one of the parameters to the opcode pOp
+** determined by character c.
+*/
+static int translateP(char c, const Op *pOp){
+  if( c=='1' ) return pOp->p1;
+  if( c=='2' ) return pOp->p2;
+  if( c=='3' ) return pOp->p3;
+  if( c=='4' ) return pOp->p4.i;
+  return pOp->p5;
+}
+
+/*
+** Compute a string for the "comment" field of a VDBE opcode listing.
+**
+** The Synopsis: field in comments in the vdbe.c source file gets converted
+** to an extra string that is appended to the sqlite3OpcodeName().  In the
+** absence of other comments, this synopsis becomes the comment on the opcode.
+** Some translation occurs:
+**
+**       "PX"      ->  "r[X]"
+**       "PX at PY"   ->  "r[X..X+Y-1]"  or "r[x]" if y is 0 or 1
+**       "PX at PY+1" ->  "r[X..X+Y]"    or "r[x]" if y is 0
+**       "PY..PY"  ->  "r[X..Y]"      or "r[x]" if y<=x
+*/
+static int displayComment(
+  const Op *pOp,     /* The opcode to be commented */
+  const char *zP4,   /* Previously obtained value for P4 */
+  char *zTemp,       /* Write result here */
+  int nTemp          /* Space available in zTemp[] */
+){
+  const char *zOpName;
+  const char *zSynopsis;
+  int nOpName;
+  int ii, jj;
+  zOpName = sqlite3OpcodeName(pOp->opcode);
+  nOpName = sqlite3Strlen30(zOpName);
+  if( zOpName[nOpName+1] ){
+    int seenCom = 0;
+    char c;
+    zSynopsis = zOpName += nOpName + 1;
+    for(ii=jj=0; jj<nTemp-1 && (c = zSynopsis[ii])!=0; ii++){
+      if( c=='P' ){
+        c = zSynopsis[++ii];
+        if( c=='4' ){
+          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zP4);
+        }else if( c=='X' ){
+          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", pOp->zComment);
+          seenCom = 1;
+        }else{
+          int v1 = translateP(c, pOp);
+          int v2;
+          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1);
+          if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
+            ii += 3;
+            jj += sqlite3Strlen30(zTemp+jj);
+            v2 = translateP(zSynopsis[ii], pOp);
+            if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){
+              ii += 2;
+              v2++;
+            }
+            if( v2>1 ){
+              sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
+            }
+          }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
+            ii += 4;
+          }
+        }
+        jj += sqlite3Strlen30(zTemp+jj);
+      }else{
+        zTemp[jj++] = c;
+      }
+    }
+    if( !seenCom && jj<nTemp-5 && pOp->zComment ){
+      sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment);
+      jj += sqlite3Strlen30(zTemp+jj);
+    }
+    if( jj<nTemp ) zTemp[jj] = 0;
+  }else if( pOp->zComment ){
+    sqlite3_snprintf(nTemp, zTemp, "%s", pOp->zComment);
+    jj = sqlite3Strlen30(zTemp);
+  }else{
+    zTemp[0] = 0;
+    jj = 0;
+  }
+  return jj;
+}
+#endif /* SQLITE_DEBUG */
+
+
 #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
      || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
 /*
@@ -60795,17 +63231,20 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
   char *zP4 = zTemp;
   assert( nTemp>=20 );
   switch( pOp->p4type ){
-    case P4_KEYINFO_STATIC:
     case P4_KEYINFO: {
       int i, j;
       KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
       assert( pKeyInfo->aSortOrder!=0 );
-      sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
+      sqlite3_snprintf(nTemp, zTemp, "k(%d", pKeyInfo->nField);
       i = sqlite3Strlen30(zTemp);
       for(j=0; j<pKeyInfo->nField; j++){
         CollSeq *pColl = pKeyInfo->aColl[j];
         const char *zColl = pColl ? pColl->zName : "nil";
         int n = sqlite3Strlen30(zColl);
+        if( n==6 && memcmp(zColl,"BINARY",6)==0 ){
+          zColl = "B";
+          n = 1;
+        }
         if( i+n>nTemp-6 ){
           memcpy(&zTemp[i],",...",4);
           break;
@@ -60824,7 +63263,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
     }
     case P4_COLLSEQ: {
       CollSeq *pColl = pOp->p4.pColl;
-      sqlite3_snprintf(nTemp, zTemp, "collseq(%.20s)", pColl->zName);
+      sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName);
       break;
     }
     case P4_FUNCDEF: {
@@ -60903,9 +63342,9 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
 SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
   assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
   assert( i<(int)sizeof(p->btreeMask)*8 );
-  p->btreeMask |= ((yDbMask)1)<<i;
+  DbMaskSet(p->btreeMask, i);
   if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
-    p->lockMask |= ((yDbMask)1)<<i;
+    DbMaskSet(p->lockMask, i);
   }
 }
 
@@ -60933,16 +63372,15 @@ SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
 */
 SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){
   int i;
-  yDbMask mask;
   sqlite3 *db;
   Db *aDb;
   int nDb;
-  if( p->lockMask==0 ) return;  /* The common case */
+  if( DbMaskAllZero(p->lockMask) ) return;  /* The common case */
   db = p->db;
   aDb = db->aDb;
   nDb = db->nDb;
-  for(i=0, mask=1; i<nDb; i++, mask += mask){
-    if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
+  for(i=0; i<nDb; i++){
+    if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
       sqlite3BtreeEnter(aDb[i].pBt);
     }
   }
@@ -60955,16 +63393,15 @@ SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){
 */
 SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){
   int i;
-  yDbMask mask;
   sqlite3 *db;
   Db *aDb;
   int nDb;
-  if( p->lockMask==0 ) return;  /* The common case */
+  if( DbMaskAllZero(p->lockMask) ) return;  /* The common case */
   db = p->db;
   aDb = db->aDb;
   nDb = db->nDb;
-  for(i=0, mask=1; i<nDb; i++, mask += mask){
-    if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
+  for(i=0; i<nDb; i++){
+    if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
       sqlite3BtreeLeave(aDb[i].pBt);
     }
   }
@@ -60978,16 +63415,21 @@ SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){
 SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
   char *zP4;
   char zPtr[50];
-  static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";
+  char zCom[100];
+  static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
   if( pOut==0 ) pOut = stdout;
   zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
-  fprintf(pOut, zFormat1, pc, 
-      sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
-#ifdef SQLITE_DEBUG
-      pOp->zComment ? pOp->zComment : ""
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+  displayComment(pOp, zP4, zCom, sizeof(zCom));
 #else
-      ""
+  zCom[0] = 0;
 #endif
+  /* NB:  The sqlite3OpcodeName() function is implemented by code created
+  ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
+  ** information from the vdbe.c source text */
+  fprintf(pOut, zFormat1, pc, 
+      sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
+      zCom
   );
   fflush(pOut);
 }
@@ -61009,6 +63451,7 @@ static void releaseMemArray(Mem *p, int N){
     }
     for(pEnd=&p[N]; p<pEnd; p++){
       assert( (&p[1])==pEnd || p[0].db==p[1].db );
+      assert( sqlite3VdbeCheckMemInvariants(p) );
 
       /* This block is really an inlined version of sqlite3VdbeMemRelease()
       ** that takes advantage of the fact that the memory cell value is 
@@ -61022,6 +63465,10 @@ static void releaseMemArray(Mem *p, int N){
       ** with no indexes using a single prepared INSERT statement, bind() 
       ** and reset(). Inserts are grouped into a transaction.
       */
+      testcase( p->flags & MEM_Agg );
+      testcase( p->flags & MEM_Dyn );
+      testcase( p->flags & MEM_Frame );
+      testcase( p->flags & MEM_RowSet );
       if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
         sqlite3VdbeMemRelease(p);
       }else if( p->zMalloc ){
@@ -61029,7 +63476,7 @@ static void releaseMemArray(Mem *p, int N){
         p->zMalloc = 0;
       }
 
-      p->flags = MEM_Invalid;
+      p->flags = MEM_Undefined;
     }
     db->mallocFailed = malloc_failed;
   }
@@ -61133,7 +63580,7 @@ SQLITE_PRIVATE int sqlite3VdbeList(
     rc = SQLITE_ERROR;
     sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc));
   }else{
-    char *z;
+    char *zP4;
     Op *pOp;
     if( i<p->nOp ){
       /* The output line number is small enough that we are still in the
@@ -61151,15 +63598,13 @@ SQLITE_PRIVATE int sqlite3VdbeList(
     }
     if( p->explain==1 ){
       pMem->flags = MEM_Int;
-      pMem->type = SQLITE_INTEGER;
       pMem->u.i = i;                                /* Program counter */
       pMem++;
   
       pMem->flags = MEM_Static|MEM_Str|MEM_Term;
-      pMem->z = (char*)sqlite3OpcodeName(pOp->opcode);  /* Opcode */
+      pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
       assert( pMem->z!=0 );
       pMem->n = sqlite3Strlen30(pMem->z);
-      pMem->type = SQLITE_TEXT;
       pMem->enc = SQLITE_UTF8;
       pMem++;
 
@@ -61185,33 +63630,29 @@ SQLITE_PRIVATE int sqlite3VdbeList(
 
     pMem->flags = MEM_Int;
     pMem->u.i = pOp->p1;                          /* P1 */
-    pMem->type = SQLITE_INTEGER;
     pMem++;
 
     pMem->flags = MEM_Int;
     pMem->u.i = pOp->p2;                          /* P2 */
-    pMem->type = SQLITE_INTEGER;
     pMem++;
 
     pMem->flags = MEM_Int;
     pMem->u.i = pOp->p3;                          /* P3 */
-    pMem->type = SQLITE_INTEGER;
     pMem++;
 
     if( sqlite3VdbeMemGrow(pMem, 32, 0) ){            /* P4 */
       assert( p->db->mallocFailed );
       return SQLITE_ERROR;
     }
-    pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
-    z = displayP4(pOp, pMem->z, 32);
-    if( z!=pMem->z ){
-      sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, 0);
+    pMem->flags = MEM_Str|MEM_Term;
+    zP4 = displayP4(pOp, pMem->z, 32);
+    if( zP4!=pMem->z ){
+      sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
     }else{
       assert( pMem->z!=0 );
       pMem->n = sqlite3Strlen30(pMem->z);
       pMem->enc = SQLITE_UTF8;
     }
-    pMem->type = SQLITE_TEXT;
     pMem++;
 
     if( p->explain==1 ){
@@ -61219,26 +63660,23 @@ SQLITE_PRIVATE int sqlite3VdbeList(
         assert( p->db->mallocFailed );
         return SQLITE_ERROR;
       }
-      pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
+      pMem->flags = MEM_Str|MEM_Term;
       pMem->n = 2;
       sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5);   /* P5 */
-      pMem->type = SQLITE_TEXT;
       pMem->enc = SQLITE_UTF8;
       pMem++;
   
-#ifdef SQLITE_DEBUG
-      if( pOp->zComment ){
-        pMem->flags = MEM_Str|MEM_Term;
-        pMem->z = pOp->zComment;
-        pMem->n = sqlite3Strlen30(pMem->z);
-        pMem->enc = SQLITE_UTF8;
-        pMem->type = SQLITE_TEXT;
-      }else
-#endif
-      {
-        pMem->flags = MEM_Null;                       /* Comment */
-        pMem->type = SQLITE_NULL;
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+      if( sqlite3VdbeMemGrow(pMem, 500, 0) ){
+        assert( p->db->mallocFailed );
+        return SQLITE_ERROR;
       }
+      pMem->flags = MEM_Str|MEM_Term;
+      pMem->n = displayComment(pOp, zP4, pMem->z, 500);
+      pMem->enc = SQLITE_UTF8;
+#else
+      pMem->flags = MEM_Null;                       /* Comment */
+#endif
     }
 
     p->nResColumn = 8 - 4*(p->explain-1);
@@ -61255,15 +63693,17 @@ SQLITE_PRIVATE int sqlite3VdbeList(
 ** Print the SQL that was used to generate a VDBE program.
 */
 SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){
-  int nOp = p->nOp;
-  VdbeOp *pOp;
-  if( nOp<1 ) return;
-  pOp = &p->aOp[0];
-  if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
-    const char *z = pOp->p4.z;
-    while( sqlite3Isspace(*z) ) z++;
-    printf("SQL: [%s]\n", z);
+  const char *z = 0;
+  if( p->zSql ){
+    z = p->zSql;
+  }else if( p->nOp>=1 ){
+    const VdbeOp *pOp = &p->aOp[0];
+    if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){
+      z = pOp->p4.z;
+      while( sqlite3Isspace(*z) ) z++;
+    }
   }
+  if( z ) printf("SQL: [%s]\n", z);
 }
 #endif
 
@@ -61277,7 +63717,7 @@ SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){
   if( sqlite3IoTrace==0 ) return;
   if( nOp<1 ) return;
   pOp = &p->aOp[0];
-  if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
+  if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){
     int i, j;
     char z[1000];
     sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z);
@@ -61414,6 +63854,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
   assert( p->nOp>0 );
   assert( pParse!=0 );
   assert( p->magic==VDBE_MAGIC_INIT );
+  assert( pParse==p->pParse );
   db = p->db;
   assert( db->mallocFailed==0 );
   nVar = pParse->nVar;
@@ -61437,8 +63878,8 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
   /* Allocate space for memory registers, SQL variables, VDBE cursors and 
   ** an array to marshal SQL function arguments in.
   */
-  zCsr = (u8*)&p->aOp[p->nOp];       /* Memory avaliable for allocation */
-  zEnd = (u8*)&p->aOp[p->nOpAlloc];  /* First byte past end of zCsr[] */
+  zCsr = (u8*)&p->aOp[p->nOp];            /* Memory avaliable for allocation */
+  zEnd = (u8*)&p->aOp[pParse->nOpAlloc];  /* First byte past end of zCsr[] */
 
   resolveP2Values(p, &nArg);
   p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
@@ -61494,7 +63935,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
     p->aMem--;                      /* aMem[] goes from 1..nMem */
     p->nMem = nMem;                 /*       not from 0..nMem-1 */
     for(n=1; n<=nMem; n++){
-      p->aMem[n].flags = MEM_Invalid;
+      p->aMem[n].flags = MEM_Undefined;
       p->aMem[n].db = db;
     }
   }
@@ -61521,7 +63962,7 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   if( pCx->pVtabCursor ){
     sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
-    const sqlite3_module *pModule = pCx->pModule;
+    const sqlite3_module *pModule = pVtabCursor->pVtab->pModule;
     p->inVtabMethod = 1;
     pModule->xClose(pVtabCursor);
     p->inVtabMethod = 0;
@@ -61584,6 +64025,10 @@ static void closeAllCursors(Vdbe *p){
     p->pDelFrame = pDel->pParent;
     sqlite3VdbeFrameDelete(pDel);
   }
+
+  /* Delete any auxdata allocations made by the VM */
+  sqlite3VdbeDeleteAuxData(p, -1, 0);
+  assert( p->pAuxData==0 );
 }
 
 /*
@@ -61602,7 +64047,7 @@ static void Cleanup(Vdbe *p){
   int i;
   if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
   if( p->aMem ){
-    for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid );
+    for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
   }
 #endif
 
@@ -61692,7 +64137,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
   ** required, as an xSync() callback may add an attached database
   ** to the transaction.
   */
-  rc = sqlite3VtabSync(db, &p->zErrMsg);
+  rc = sqlite3VtabSync(db, p);
 
   /* This loop determines (a) if the commit hook should be invoked and
   ** (b) how many database files have open write transactions, not 
@@ -61911,7 +64356,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
 }
 
 /* 
-** This routine checks that the sqlite3.activeVdbeCnt count variable
+** This routine checks that the sqlite3.nVdbeActive count variable
 ** matches the number of vdbe's in the list sqlite3.pVdbe that are
 ** currently active. An assertion fails if the two counts do not match.
 ** This is an internal self-check only - it is not an essential processing
@@ -61924,16 +64369,19 @@ static void checkActiveVdbeCnt(sqlite3 *db){
   Vdbe *p;
   int cnt = 0;
   int nWrite = 0;
+  int nRead = 0;
   p = db->pVdbe;
   while( p ){
-    if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
+    if( sqlite3_stmt_busy((sqlite3_stmt*)p) ){
       cnt++;
       if( p->readOnly==0 ) nWrite++;
+      if( p->bIsReader ) nRead++;
     }
     p = p->pNext;
   }
-  assert( cnt==db->activeVdbeCnt );
-  assert( nWrite==db->writeVdbeCnt );
+  assert( cnt==db->nVdbeActive );
+  assert( nWrite==db->nVdbeWrite );
+  assert( nRead==db->nVdbeRead );
 }
 #else
 #define checkActiveVdbeCnt(x)
@@ -61944,7 +64392,7 @@ static void checkActiveVdbeCnt(sqlite3 *db){
 ** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
 ** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
 ** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the 
-** statement transaction is commtted.
+** statement transaction is committed.
 **
 ** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned. 
 ** Otherwise SQLITE_OK.
@@ -61998,6 +64446,7 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
     ** the statement transaction was opened.  */
     if( eOp==SAVEPOINT_ROLLBACK ){
       db->nDeferredCons = p->nStmtDefCons;
+      db->nDeferredImmCons = p->nStmtDefImmCons;
     }
   }
   return rc;
@@ -62016,10 +64465,12 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
 #ifndef SQLITE_OMIT_FOREIGN_KEY
 SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
   sqlite3 *db = p->db;
-  if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
+  if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) 
+   || (!deferred && p->nFkConstraint>0) 
+  ){
     p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
     p->errorAction = OE_Abort;
-    sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
+    sqlite3SetString(&p->zErrMsg, db, "FOREIGN KEY constraint failed");
     return SQLITE_ERROR;
   }
   return SQLITE_OK;
@@ -62069,8 +64520,9 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
   }
   checkActiveVdbeCnt(db);
 
-  /* No commit or rollback needed if the program never started */
-  if( p->pc>=0 ){
+  /* No commit or rollback needed if the program never started or if the
+  ** SQL statement does not read or write a database file.  */
+  if( p->pc>=0 && p->bIsReader ){
     int mrc;   /* Primary error code from p->rc */
     int eStatementOp = 0;
     int isSpecialError;            /* Set to true if a 'special' error */
@@ -62080,7 +64532,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
 
     /* Check for one of the special errors */
     mrc = p->rc & 0xff;
-    assert( p->rc!=SQLITE_IOERR_BLOCKED );  /* This error no longer exists */
     isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
                      || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
     if( isSpecialError ){
@@ -62123,7 +64574,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
     */
     if( !sqlite3VtabInSync(db) 
      && db->autoCommit 
-     && db->writeVdbeCnt==(p->readOnly==0) 
+     && db->nVdbeWrite==(p->readOnly==0) 
     ){
       if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
         rc = sqlite3VdbeCheckFk(p, 1);
@@ -62148,6 +64599,8 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
           sqlite3RollbackAll(db, SQLITE_OK);
         }else{
           db->nDeferredCons = 0;
+          db->nDeferredImmCons = 0;
+          db->flags &= ~SQLITE_DeferFKs;
           sqlite3CommitInternalChanges(db);
         }
       }else{
@@ -62204,11 +64657,12 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
 
   /* We have successfully halted and closed the VM.  Record this fact. */
   if( p->pc>=0 ){
-    db->activeVdbeCnt--;
-    if( !p->readOnly ){
-      db->writeVdbeCnt--;
-    }
-    assert( db->activeVdbeCnt>=db->writeVdbeCnt );
+    db->nVdbeActive--;
+    if( !p->readOnly ) db->nVdbeWrite--;
+    if( p->bIsReader ) db->nVdbeRead--;
+    assert( db->nVdbeActive>=db->nVdbeRead );
+    assert( db->nVdbeRead>=db->nVdbeWrite );
+    assert( db->nVdbeWrite>=0 );
   }
   p->magic = VDBE_MAGIC_HALT;
   checkActiveVdbeCnt(db);
@@ -62224,7 +64678,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
     sqlite3ConnectionUnlocked(db);
   }
 
-  assert( db->activeVdbeCnt>0 || db->autoCommit==0 || db->nStatement==0 );
+  assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 );
   return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK);
 }
 
@@ -62251,6 +64705,7 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
   if( p->zErrMsg ){
     u8 mallocFailed = db->mallocFailed;
     sqlite3BeginBenignMalloc();
+    if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db);
     sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
     sqlite3EndBenignMalloc();
     db->mallocFailed = mallocFailed;
@@ -62319,8 +64774,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
     ** to sqlite3_step(). For consistency (since sqlite3_step() was
     ** called), set the database error in this case as well.
     */
-    sqlite3Error(db, p->rc, 0);
-    sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
+    sqlite3Error(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
     sqlite3DbFree(db, p->zErrMsg);
     p->zErrMsg = 0;
   }
@@ -62341,18 +64795,31 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
         fprintf(out, "%02x", p->aOp[i].opcode);
       }
       fprintf(out, "\n");
+      if( p->zSql ){
+        char c, pc = 0;
+        fprintf(out, "-- ");
+        for(i=0; (c = p->zSql[i])!=0; i++){
+          if( pc=='\n' ) fprintf(out, "-- ");
+          putc(c, out);
+          pc = c;
+        }
+        if( pc!='\n' ) fprintf(out, "\n");
+      }
       for(i=0; i<p->nOp; i++){
-        fprintf(out, "%6d %10lld %8lld ",
+        char zHdr[100];
+        sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ",
            p->aOp[i].cnt,
            p->aOp[i].cycles,
            p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
         );
+        fprintf(out, "%s", zHdr);
         sqlite3VdbePrintOp(out, i, &p->aOp[i]);
       }
       fclose(out);
     }
   }
 #endif
+  p->iCurrentTime = 0;
   p->magic = VDBE_MAGIC_INIT;
   return p->rc & db->errMask;
 }
@@ -62372,20 +64839,36 @@ SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
 }
 
 /*
-** Call the destructor for each auxdata entry in pVdbeFunc for which
-** the corresponding bit in mask is clear.  Auxdata entries beyond 31
-** are always destroyed.  To destroy all auxdata entries, call this
-** routine with mask==0.
+** If parameter iOp is less than zero, then invoke the destructor for
+** all auxiliary data pointers currently cached by the VM passed as
+** the first argument.
+**
+** Or, if iOp is greater than or equal to zero, then the destructor is
+** only invoked for those auxiliary data pointers created by the user 
+** function invoked by the OP_Function opcode at instruction iOp of 
+** VM pVdbe, and only then if:
+**
+**    * the associated function parameter is the 32nd or later (counting
+**      from left to right), or
+**
+**    * the corresponding bit in argument mask is clear (where the first
+**      function parameter corrsponds to bit 0 etc.).
 */
-SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
-  int i;
-  for(i=0; i<pVdbeFunc->nAux; i++){
-    struct AuxData *pAux = &pVdbeFunc->apAux[i];
-    if( (i>31 || !(mask&(((u32)1)<<i))) && pAux->pAux ){
+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
+  AuxData **pp = &pVdbe->pAuxData;
+  while( *pp ){
+    AuxData *pAux = *pp;
+    if( (iOp<0)
+     || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
+    ){
+      testcase( pAux->iArg==31 );
       if( pAux->xDelete ){
         pAux->xDelete(pAux->pAux);
       }
-      pAux->pAux = 0;
+      *pp = pAux->pNext;
+      sqlite3DbFree(pVdbe->db, pAux);
+    }else{
+      pp= &pAux->pNext;
     }
   }
 }
@@ -62411,7 +64894,6 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
   }
   for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
   vdbeFreeOpArray(db, p->aOp, p->nOp);
-  sqlite3DbFree(db, p->aLabel);
   sqlite3DbFree(db, p->aColName);
   sqlite3DbFree(db, p->zSql);
   sqlite3DbFree(db, p->pFree);
@@ -62475,13 +64957,13 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
 #endif
     p->deferredMoveto = 0;
     p->cacheStatus = CACHE_STALE;
-  }else if( ALWAYS(p->pCursor) ){
+  }else if( p->pCursor ){
     int hasMoved;
     int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved);
     if( rc ) return rc;
     if( hasMoved ){
       p->cacheStatus = CACHE_STALE;
-      p->nullRow = 1;
+      if( hasMoved==2 ) p->nullRow = 1;
     }
   }
   return SQLITE_OK;
@@ -62534,7 +65016,7 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
 */
 SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
   int flags = pMem->flags;
-  int n;
+  u32 n;
 
   if( flags&MEM_Null ){
     return 0;
@@ -62564,11 +65046,11 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
     return 7;
   }
   assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
-  n = pMem->n;
+  assert( pMem->n>=0 );
+  n = (u32)pMem->n;
   if( flags & MEM_Zero ){
     n += pMem->u.nZero;
   }
-  assert( n>=0 );
   return ((n*2) + 12 + ((flags&MEM_Str)!=0));
 }
 
@@ -62642,21 +65124,15 @@ static u64 floatSwap(u64 in){
 ** buf. It is assumed that the caller has allocated sufficient space.
 ** Return the number of bytes written.
 **
-** nBuf is the amount of space left in buf[].  nBuf must always be
-** large enough to hold the entire field.  Except, if the field is
-** a blob with a zero-filled tail, then buf[] might be just the right
-** size to hold everything except for the zero-filled tail.  If buf[]
-** is only big enough to hold the non-zero prefix, then only write that
-** prefix into buf[].  But if buf[] is large enough to hold both the
-** prefix and the tail then write the prefix and set the tail to all
-** zeros.
+** nBuf is the amount of space left in buf[].  The caller is responsible
+** for allocating enough space to buf[] to hold the entire field, exclusive
+** of the pMem->u.nZero bytes for a MEM_Zero value.
 **
 ** Return the number of bytes actually written into buf[].  The number
 ** of bytes in the zero-filled tail is included in the return value only
 ** if those bytes were zeroed in buf[].
 */ 
-SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){
-  u32 serial_type = sqlite3VdbeSerialType(pMem, file_format);
+SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
   u32 len;
 
   /* Integer and Real */
@@ -62671,7 +65147,6 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_f
       v = pMem->u.i;
     }
     len = i = sqlite3VdbeSerialTypeLen(serial_type);
-    assert( len<=(u32)nBuf );
     while( i-- ){
       buf[i] = (u8)(v&0xFF);
       v >>= 8;
@@ -62683,17 +65158,8 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_f
   if( serial_type>=12 ){
     assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
              == (int)sqlite3VdbeSerialTypeLen(serial_type) );
-    assert( pMem->n<=nBuf );
     len = pMem->n;
     memcpy(buf, pMem->z, len);
-    if( pMem->flags & MEM_Zero ){
-      len += pMem->u.nZero;
-      assert( nBuf>=0 );
-      if( len > (u32)nBuf ){
-        len = (u32)nBuf;
-      }
-      memset(&buf[pMem->n], 0, len-pMem->n);
-    }
     return len;
   }
 
@@ -62701,6 +65167,14 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_f
   return 0;
 }
 
+/* Input "x" is a sequence of unsigned characters that represent a
+** big-endian integer.  Return the equivalent native integer
+*/
+#define ONE_BYTE_INT(x)    ((i8)(x)[0])
+#define TWO_BYTE_INT(x)    (256*(i8)((x)[0])|(x)[1])
+#define THREE_BYTE_INT(x)  (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
+#define FOUR_BYTE_UINT(x)  (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
+
 /*
 ** Deserialize the data blob pointed to by buf as serial type serial_type
 ** and store the result in pMem.  Return the number of bytes read.
@@ -62710,6 +65184,8 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
   u32 serial_type,              /* Serial type to deserialize */
   Mem *pMem                     /* Memory cell to write value into */
 ){
+  u64 x;
+  u32 y;
   switch( serial_type ){
     case 10:   /* Reserved for future use */
     case 11:   /* Reserved for future use */
@@ -62718,37 +65194,38 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
       break;
     }
     case 1: { /* 1-byte signed integer */
-      pMem->u.i = (signed char)buf[0];
+      pMem->u.i = ONE_BYTE_INT(buf);
       pMem->flags = MEM_Int;
+      testcase( pMem->u.i<0 );
       return 1;
     }
     case 2: { /* 2-byte signed integer */
-      pMem->u.i = (((signed char)buf[0])<<8) | buf[1];
+      pMem->u.i = TWO_BYTE_INT(buf);
       pMem->flags = MEM_Int;
+      testcase( pMem->u.i<0 );
       return 2;
     }
     case 3: { /* 3-byte signed integer */
-      pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
+      pMem->u.i = THREE_BYTE_INT(buf);
       pMem->flags = MEM_Int;
+      testcase( pMem->u.i<0 );
       return 3;
     }
     case 4: { /* 4-byte signed integer */
-      pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
+      y = FOUR_BYTE_UINT(buf);
+      pMem->u.i = (i64)*(int*)&y;
       pMem->flags = MEM_Int;
+      testcase( pMem->u.i<0 );
       return 4;
     }
     case 5: { /* 6-byte signed integer */
-      u64 x = (((signed char)buf[0])<<8) | buf[1];
-      u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
-      x = (x<<32) | y;
-      pMem->u.i = *(i64*)&x;
+      pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
       pMem->flags = MEM_Int;
+      testcase( pMem->u.i<0 );
       return 6;
     }
     case 6:   /* 8-byte signed integer */
     case 7: { /* IEEE floating point */
-      u64 x;
-      u32 y;
 #if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
       /* Verify that integers and floating point values use the same
       ** byte order.  Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
@@ -62761,13 +65238,13 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
       swapMixedEndianFloat(t2);
       assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
 #endif
-
-      x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
-      y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
+      x = FOUR_BYTE_UINT(buf);
+      y = FOUR_BYTE_UINT(buf+4);
       x = (x<<32) | y;
       if( serial_type==6 ){
         pMem->u.i = *(i64*)&x;
         pMem->flags = MEM_Int;
+        testcase( pMem->u.i<0 );
       }else{
         assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
         swapMixedEndianFloat(x);
@@ -62783,15 +65260,12 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
       return 0;
     }
     default: {
+      static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem };
       u32 len = (serial_type-12)/2;
       pMem->z = (char *)buf;
       pMem->n = len;
       pMem->xDel = 0;
-      if( serial_type&0x01 ){
-        pMem->flags = MEM_Str | MEM_Ephem;
-      }else{
-        pMem->flags = MEM_Blob | MEM_Ephem;
-      }
+      pMem->flags = aFlag[serial_type&1];
       return len;
     }
   }
@@ -62862,7 +65336,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
   u32 szHdr;
   Mem *pMem = p->aMem;
 
-  p->flags = 0;
+  p->default_rc = 0;
   assert( EIGHT_BYTE_ALIGNMENT(pMem) );
   idx = getVarint32(aKey, szHdr);
   d = szHdr;
@@ -62883,32 +65357,23 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
   p->nField = u;
 }
 
+#if SQLITE_DEBUG
 /*
-** 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 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.
-** 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.
+** This function compares two index or table record keys in the same way
+** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
+** this function deserializes and compares values using the
+** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used
+** in assert() statements to ensure that the optimized code in
+** sqlite3VdbeRecordCompare() returns results with these two primitives.
 */
-SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
+static int vdbeRecordCompareDebug(
   int nKey1, const void *pKey1, /* Left key */
-  UnpackedRecord *pPKey2        /* Right key */
+  const UnpackedRecord *pPKey2  /* Right key */
 ){
-  int d1;            /* Offset into aKey[] of next data element */
+  u32 d1;            /* Offset into aKey[] of next data element */
   u32 idx1;          /* Offset into aKey[] of next header element */
   u32 szHdr1;        /* Number of bytes in header */
   int i = 0;
-  int nField;
   int rc = 0;
   const unsigned char *aKey1 = (const unsigned char *)pKey1;
   KeyInfo *pKeyInfo;
@@ -62931,14 +65396,27 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
   
   idx1 = getVarint32(aKey1, szHdr1);
   d1 = szHdr1;
-  nField = pKeyInfo->nField;
+  assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB );
   assert( pKeyInfo->aSortOrder!=0 );
-  while( idx1<szHdr1 && i<pPKey2->nField ){
+  assert( pKeyInfo->nField>0 );
+  assert( idx1<=szHdr1 || CORRUPT_DB );
+  do{
     u32 serial_type1;
 
     /* Read the serial types for the next element in each key. */
     idx1 += getVarint32( aKey1+idx1, serial_type1 );
-    if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
+
+    /* Verify that there is enough key space remaining to avoid
+    ** a buffer overread.  The "d1+serial_type1+2" subexpression will
+    ** always be greater than or equal to the amount of required key space.
+    ** Use that approximation to avoid the more expensive call to
+    ** sqlite3VdbeSerialTypeLen() in the common case.
+    */
+    if( d1+serial_type1+2>(u32)nKey1
+     && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1 
+    ){
+      break;
+    }
 
     /* Extract the values to be compared.
     */
@@ -62946,32 +65424,16 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
 
     /* Do the comparison
     */
-    rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i],
-                           i<nField ? pKeyInfo->aColl[i] : 0);
+    rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]);
     if( rc!=0 ){
       assert( mem1.zMalloc==0 );  /* See comment below */
-
-      /* Invert the result if we are using DESC sort order. */
-      if( i<nField && pKeyInfo->aSortOrder[i] ){
-        rc = -rc;
+      if( pKeyInfo->aSortOrder[i] ){
+        rc = -rc;  /* Invert the result for DESC sort order. */
       }
-    
-      /* If the PREFIX_SEARCH flag is set and all fields except the final
-      ** rowid field were equal, then clear the PREFIX_SEARCH flag and set 
-      ** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1).
-      ** This is used by the OP_IsUnique opcode.
-      */
-      if( (pPKey2->flags & UNPACKED_PREFIX_SEARCH) && i==(pPKey2->nField-1) ){
-        assert( idx1==szHdr1 && rc );
-        assert( mem1.flags & MEM_Int );
-        pPKey2->flags &= ~UNPACKED_PREFIX_SEARCH;
-        pPKey2->rowid = mem1.u.i;
-      }
-    
       return rc;
     }
     i++;
-  }
+  }while( idx1<szHdr1 && i<pPKey2->nField );
 
   /* No memory allocation is ever used on mem1.  Prove this using
   ** the following assert().  If the assert() fails, it indicates a
@@ -62980,24 +65442,594 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
   assert( mem1.zMalloc==0 );
 
   /* 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.
-  */
-  assert( rc==0 );
-  if( pPKey2->flags & UNPACKED_INCRKEY ){
-    rc = -1;
-  }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
-    /* Leave rc==0 */
-  }else if( idx1<szHdr1 ){
-    rc = 1;
+  ** all the fields up to that point were equal. Return the the default_rc
+  ** value.  */
+  return pPKey2->default_rc;
+}
+#endif
+
+/*
+** Both *pMem1 and *pMem2 contain string values. Compare the two values
+** using the collation sequence pColl. As usual, return a negative , zero
+** or positive value if *pMem1 is less than, equal to or greater than 
+** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
+*/
+static int vdbeCompareMemString(
+  const Mem *pMem1,
+  const Mem *pMem2,
+  const CollSeq *pColl
+){
+  if( pMem1->enc==pColl->enc ){
+    /* The strings are already in the correct encoding.  Call the
+     ** comparison function directly */
+    return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
+  }else{
+    int rc;
+    const void *v1, *v2;
+    int n1, n2;
+    Mem c1;
+    Mem c2;
+    memset(&c1, 0, sizeof(c1));
+    memset(&c2, 0, sizeof(c2));
+    sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
+    sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
+    v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
+    n1 = v1==0 ? 0 : c1.n;
+    v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
+    n2 = v2==0 ? 0 : c2.n;
+    rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
+    sqlite3VdbeMemRelease(&c1);
+    sqlite3VdbeMemRelease(&c2);
+    return rc;
   }
-  return rc;
 }
+
+/*
+** Compare the values contained by the two memory cells, returning
+** negative, zero or positive if pMem1 is less than, equal to, or greater
+** than pMem2. Sorting order is NULL's first, followed by numbers (integers
+** and reals) sorted numerically, followed by text ordered by the collating
+** sequence pColl and finally blob's ordered by memcmp().
+**
+** Two NULL values are considered equal by this function.
+*/
+SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
+  int rc;
+  int f1, f2;
+  int combined_flags;
+
+  f1 = pMem1->flags;
+  f2 = pMem2->flags;
+  combined_flags = f1|f2;
+  assert( (combined_flags & MEM_RowSet)==0 );
  
+  /* If one value is NULL, it is less than the other. If both values
+  ** are NULL, return 0.
+  */
+  if( combined_flags&MEM_Null ){
+    return (f2&MEM_Null) - (f1&MEM_Null);
+  }
+
+  /* If one value is a number and the other is not, the number is less.
+  ** If both are numbers, compare as reals if one is a real, or as integers
+  ** if both values are integers.
+  */
+  if( combined_flags&(MEM_Int|MEM_Real) ){
+    double r1, r2;
+    if( (f1 & f2 & MEM_Int)!=0 ){
+      if( pMem1->u.i < pMem2->u.i ) return -1;
+      if( pMem1->u.i > pMem2->u.i ) return 1;
+      return 0;
+    }
+    if( (f1&MEM_Real)!=0 ){
+      r1 = pMem1->r;
+    }else if( (f1&MEM_Int)!=0 ){
+      r1 = (double)pMem1->u.i;
+    }else{
+      return 1;
+    }
+    if( (f2&MEM_Real)!=0 ){
+      r2 = pMem2->r;
+    }else if( (f2&MEM_Int)!=0 ){
+      r2 = (double)pMem2->u.i;
+    }else{
+      return -1;
+    }
+    if( r1<r2 ) return -1;
+    if( r1>r2 ) return 1;
+    return 0;
+  }
+
+  /* If one value is a string and the other is a blob, the string is less.
+  ** If both are strings, compare using the collating functions.
+  */
+  if( combined_flags&MEM_Str ){
+    if( (f1 & MEM_Str)==0 ){
+      return 1;
+    }
+    if( (f2 & MEM_Str)==0 ){
+      return -1;
+    }
+
+    assert( pMem1->enc==pMem2->enc );
+    assert( pMem1->enc==SQLITE_UTF8 || 
+            pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
+
+    /* The collation sequence must be defined at this point, even if
+    ** the user deletes the collation sequence after the vdbe program is
+    ** compiled (this was not always the case).
+    */
+    assert( !pColl || pColl->xCmp );
+
+    if( pColl ){
+      return vdbeCompareMemString(pMem1, pMem2, pColl);
+    }
+    /* If a NULL pointer was passed as the collate function, fall through
+    ** to the blob case and use memcmp().  */
+  }
+ 
+  /* Both values must be blobs.  Compare using memcmp().  */
+  rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
+  if( rc==0 ){
+    rc = pMem1->n - pMem2->n;
+  }
+  return rc;
+}
+
+
+/*
+** The first argument passed to this function is a serial-type that
+** corresponds to an integer - all values between 1 and 9 inclusive 
+** except 7. The second points to a buffer containing an integer value
+** serialized according to serial_type. This function deserializes
+** and returns the value.
+*/
+static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
+  u32 y;
+  assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
+  switch( serial_type ){
+    case 0:
+    case 1:
+      testcase( aKey[0]&0x80 );
+      return ONE_BYTE_INT(aKey);
+    case 2:
+      testcase( aKey[0]&0x80 );
+      return TWO_BYTE_INT(aKey);
+    case 3:
+      testcase( aKey[0]&0x80 );
+      return THREE_BYTE_INT(aKey);
+    case 4: {
+      testcase( aKey[0]&0x80 );
+      y = FOUR_BYTE_UINT(aKey);
+      return (i64)*(int*)&y;
+    }
+    case 5: {
+      testcase( aKey[0]&0x80 );
+      return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
+    }
+    case 6: {
+      u64 x = FOUR_BYTE_UINT(aKey);
+      testcase( aKey[0]&0x80 );
+      x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
+      return (i64)*(i64*)&x;
+    }
+  }
+
+  return (serial_type - 8);
+}
+
+/*
+** 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 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.
+**
+** If argument bSkip is non-zero, it is assumed that the caller has already
+** determined that the first fields of the keys are equal.
+**
+** Key1 and Key2 do not have to contain the same number of fields. If all 
+** fields that appear in both keys are equal, then pPKey2->default_rc is 
+** returned.
+**
+** If database corruption is discovered, set pPKey2->isCorrupt to non-zero
+** and return 0.
+*/
+SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
+  int nKey1, const void *pKey1,   /* Left key */
+  UnpackedRecord *pPKey2,         /* Right key */
+  int bSkip                       /* If true, skip the first field */
+){
+  u32 d1;                         /* Offset into aKey[] of next data element */
+  int i;                          /* Index of next field to compare */
+  u32 szHdr1;                     /* Size of record header in bytes */
+  u32 idx1;                       /* Offset of first type in header */
+  int rc = 0;                     /* Return value */
+  Mem *pRhs = pPKey2->aMem;       /* Next field of pPKey2 to compare */
+  KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
+  const unsigned char *aKey1 = (const unsigned char *)pKey1;
+  Mem mem1;
+
+  /* If bSkip is true, then the caller has already determined that the first
+  ** two elements in the keys are equal. Fix the various stack variables so
+  ** that this routine begins comparing at the second field. */
+  if( bSkip ){
+    u32 s1;
+    idx1 = 1 + getVarint32(&aKey1[1], s1);
+    szHdr1 = aKey1[0];
+    d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
+    i = 1;
+    pRhs++;
+  }else{
+    idx1 = getVarint32(aKey1, szHdr1);
+    d1 = szHdr1;
+    if( d1>(unsigned)nKey1 ){ 
+      pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
+      return 0;  /* Corruption */
+    }
+    i = 0;
+  }
+
+  VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
+  assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField 
+       || CORRUPT_DB );
+  assert( pPKey2->pKeyInfo->aSortOrder!=0 );
+  assert( pPKey2->pKeyInfo->nField>0 );
+  assert( idx1<=szHdr1 || CORRUPT_DB );
+  do{
+    u32 serial_type;
+
+    /* RHS is an integer */
+    if( pRhs->flags & MEM_Int ){
+      serial_type = aKey1[idx1];
+      testcase( serial_type==12 );
+      if( serial_type>=12 ){
+        rc = +1;
+      }else if( serial_type==0 ){
+        rc = -1;
+      }else if( serial_type==7 ){
+        double rhs = (double)pRhs->u.i;
+        sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
+        if( mem1.r<rhs ){
+          rc = -1;
+        }else if( mem1.r>rhs ){
+          rc = +1;
+        }
+      }else{
+        i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
+        i64 rhs = pRhs->u.i;
+        if( lhs<rhs ){
+          rc = -1;
+        }else if( lhs>rhs ){
+          rc = +1;
+        }
+      }
+    }
+
+    /* RHS is real */
+    else if( pRhs->flags & MEM_Real ){
+      serial_type = aKey1[idx1];
+      if( serial_type>=12 ){
+        rc = +1;
+      }else if( serial_type==0 ){
+        rc = -1;
+      }else{
+        double rhs = pRhs->r;
+        double lhs;
+        sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
+        if( serial_type==7 ){
+          lhs = mem1.r;
+        }else{
+          lhs = (double)mem1.u.i;
+        }
+        if( lhs<rhs ){
+          rc = -1;
+        }else if( lhs>rhs ){
+          rc = +1;
+        }
+      }
+    }
+
+    /* RHS is a string */
+    else if( pRhs->flags & MEM_Str ){
+      getVarint32(&aKey1[idx1], serial_type);
+      testcase( serial_type==12 );
+      if( serial_type<12 ){
+        rc = -1;
+      }else if( !(serial_type & 0x01) ){
+        rc = +1;
+      }else{
+        mem1.n = (serial_type - 12) / 2;
+        testcase( (d1+mem1.n)==(unsigned)nKey1 );
+        testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
+        if( (d1+mem1.n) > (unsigned)nKey1 ){
+          pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
+          return 0;                /* Corruption */
+        }else if( pKeyInfo->aColl[i] ){
+          mem1.enc = pKeyInfo->enc;
+          mem1.db = pKeyInfo->db;
+          mem1.flags = MEM_Str;
+          mem1.z = (char*)&aKey1[d1];
+          rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]);
+        }else{
+          int nCmp = MIN(mem1.n, pRhs->n);
+          rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
+          if( rc==0 ) rc = mem1.n - pRhs->n; 
+        }
+      }
+    }
+
+    /* RHS is a blob */
+    else if( pRhs->flags & MEM_Blob ){
+      getVarint32(&aKey1[idx1], serial_type);
+      testcase( serial_type==12 );
+      if( serial_type<12 || (serial_type & 0x01) ){
+        rc = -1;
+      }else{
+        int nStr = (serial_type - 12) / 2;
+        testcase( (d1+nStr)==(unsigned)nKey1 );
+        testcase( (d1+nStr+1)==(unsigned)nKey1 );
+        if( (d1+nStr) > (unsigned)nKey1 ){
+          pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
+          return 0;                /* Corruption */
+        }else{
+          int nCmp = MIN(nStr, pRhs->n);
+          rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
+          if( rc==0 ) rc = nStr - pRhs->n;
+        }
+      }
+    }
+
+    /* RHS is null */
+    else{
+      serial_type = aKey1[idx1];
+      rc = (serial_type!=0);
+    }
+
+    if( rc!=0 ){
+      if( pKeyInfo->aSortOrder[i] ){
+        rc = -rc;
+      }
+      assert( CORRUPT_DB
+          || (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
+          || (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
+          || pKeyInfo->db->mallocFailed
+      );
+      assert( mem1.zMalloc==0 );  /* See comment below */
+      return rc;
+    }
+
+    i++;
+    pRhs++;
+    d1 += sqlite3VdbeSerialTypeLen(serial_type);
+    idx1 += sqlite3VarintLen(serial_type);
+  }while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
+
+  /* No memory allocation is ever used on mem1.  Prove this using
+  ** the following assert().  If the assert() fails, it indicates a
+  ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).  */
+  assert( mem1.zMalloc==0 );
+
+  /* rc==0 here means that one or both of the keys ran out of fields and
+  ** all the fields up to that point were equal. Return the the default_rc
+  ** value.  */
+  assert( CORRUPT_DB 
+       || pPKey2->default_rc==vdbeRecordCompareDebug(nKey1, pKey1, pPKey2) 
+       || pKeyInfo->db->mallocFailed
+  );
+  return pPKey2->default_rc;
+}
+
+/*
+** This function is an optimized version of sqlite3VdbeRecordCompare() 
+** that (a) the first field of pPKey2 is an integer, and (b) the 
+** size-of-header varint at the start of (pKey1/nKey1) fits in a single
+** byte (i.e. is less than 128).
+**
+** To avoid concerns about buffer overreads, this routine is only used
+** on schemas where the maximum valid header size is 63 bytes or less.
+*/
+static int vdbeRecordCompareInt(
+  int nKey1, const void *pKey1, /* Left key */
+  UnpackedRecord *pPKey2,       /* Right key */
+  int bSkip                     /* Ignored */
+){
+  const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
+  int serial_type = ((const u8*)pKey1)[1];
+  int res;
+  u32 y;
+  u64 x;
+  i64 v = pPKey2->aMem[0].u.i;
+  i64 lhs;
+  UNUSED_PARAMETER(bSkip);
+
+  assert( bSkip==0 );
+  assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB );
+  switch( serial_type ){
+    case 1: { /* 1-byte signed integer */
+      lhs = ONE_BYTE_INT(aKey);
+      testcase( lhs<0 );
+      break;
+    }
+    case 2: { /* 2-byte signed integer */
+      lhs = TWO_BYTE_INT(aKey);
+      testcase( lhs<0 );
+      break;
+    }
+    case 3: { /* 3-byte signed integer */
+      lhs = THREE_BYTE_INT(aKey);
+      testcase( lhs<0 );
+      break;
+    }
+    case 4: { /* 4-byte signed integer */
+      y = FOUR_BYTE_UINT(aKey);
+      lhs = (i64)*(int*)&y;
+      testcase( lhs<0 );
+      break;
+    }
+    case 5: { /* 6-byte signed integer */
+      lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
+      testcase( lhs<0 );
+      break;
+    }
+    case 6: { /* 8-byte signed integer */
+      x = FOUR_BYTE_UINT(aKey);
+      x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
+      lhs = *(i64*)&x;
+      testcase( lhs<0 );
+      break;
+    }
+    case 8: 
+      lhs = 0;
+      break;
+    case 9:
+      lhs = 1;
+      break;
+
+    /* This case could be removed without changing the results of running
+    ** this code. Including it causes gcc to generate a faster switch 
+    ** statement (since the range of switch targets now starts at zero and
+    ** is contiguous) but does not cause any duplicate code to be generated
+    ** (as gcc is clever enough to combine the two like cases). Other 
+    ** compilers might be similar.  */ 
+    case 0: case 7:
+      return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
+
+    default:
+      return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
+  }
+
+  if( v>lhs ){
+    res = pPKey2->r1;
+  }else if( v<lhs ){
+    res = pPKey2->r2;
+  }else if( pPKey2->nField>1 ){
+    /* The first fields of the two keys are equal. Compare the trailing 
+    ** fields.  */
+    res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
+  }else{
+    /* The first fields of the two keys are equal and there are no trailing
+    ** fields. Return pPKey2->default_rc in this case. */
+    res = pPKey2->default_rc;
+  }
+
+  assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
+       || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
+       || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
+       || CORRUPT_DB
+  );
+  return res;
+}
+
+/*
+** This function is an optimized version of sqlite3VdbeRecordCompare() 
+** that (a) the first field of pPKey2 is a string, that (b) the first field
+** uses the collation sequence BINARY and (c) that the size-of-header varint 
+** at the start of (pKey1/nKey1) fits in a single byte.
+*/
+static int vdbeRecordCompareString(
+  int nKey1, const void *pKey1, /* Left key */
+  UnpackedRecord *pPKey2,       /* Right key */
+  int bSkip
+){
+  const u8 *aKey1 = (const u8*)pKey1;
+  int serial_type;
+  int res;
+  UNUSED_PARAMETER(bSkip);
+
+  assert( bSkip==0 );
+  getVarint32(&aKey1[1], serial_type);
+
+  if( serial_type<12 ){
+    res = pPKey2->r1;      /* (pKey1/nKey1) is a number or a null */
+  }else if( !(serial_type & 0x01) ){ 
+    res = pPKey2->r2;      /* (pKey1/nKey1) is a blob */
+  }else{
+    int nCmp;
+    int nStr;
+    int szHdr = aKey1[0];
+
+    nStr = (serial_type-12) / 2;
+    if( (szHdr + nStr) > nKey1 ){
+      pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
+      return 0;    /* Corruption */
+    }
+    nCmp = MIN( pPKey2->aMem[0].n, nStr );
+    res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
+
+    if( res==0 ){
+      res = nStr - pPKey2->aMem[0].n;
+      if( res==0 ){
+        if( pPKey2->nField>1 ){
+          res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
+        }else{
+          res = pPKey2->default_rc;
+        }
+      }else if( res>0 ){
+        res = pPKey2->r2;
+      }else{
+        res = pPKey2->r1;
+      }
+    }else if( res>0 ){
+      res = pPKey2->r2;
+    }else{
+      res = pPKey2->r1;
+    }
+  }
+
+  assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
+       || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
+       || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
+       || CORRUPT_DB
+       || pPKey2->pKeyInfo->db->mallocFailed
+  );
+  return res;
+}
+
+/*
+** Return a pointer to an sqlite3VdbeRecordCompare() compatible function
+** suitable for comparing serialized records to the unpacked record passed
+** as the only argument.
+*/
+SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
+  /* varintRecordCompareInt() and varintRecordCompareString() both assume
+  ** that the size-of-header varint that occurs at the start of each record
+  ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt()
+  ** also assumes that it is safe to overread a buffer by at least the 
+  ** maximum possible legal header size plus 8 bytes. Because there is
+  ** guaranteed to be at least 74 (but not 136) bytes of padding following each
+  ** buffer passed to varintRecordCompareInt() this makes it convenient to
+  ** limit the size of the header to 64 bytes in cases where the first field
+  ** is an integer.
+  **
+  ** The easiest way to enforce this limit is to consider only records with
+  ** 13 fields or less. If the first field is an integer, the maximum legal
+  ** header size is (12*5 + 1 + 1) bytes.  */
+  if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){
+    int flags = p->aMem[0].flags;
+    if( p->pKeyInfo->aSortOrder[0] ){
+      p->r1 = 1;
+      p->r2 = -1;
+    }else{
+      p->r1 = -1;
+      p->r2 = 1;
+    }
+    if( (flags & MEM_Int) ){
+      return vdbeRecordCompareInt;
+    }
+    testcase( flags & MEM_Real );
+    testcase( flags & MEM_Null );
+    testcase( flags & MEM_Blob );
+    if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){
+      assert( flags & MEM_Str );
+      return vdbeRecordCompareString;
+    }
+  }
+
+  return sqlite3VdbeRecordCompare;
+}
 
 /*
 ** pCur points at an index entry created using the OP_MakeRecord opcode.
@@ -63029,7 +66061,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
 
   /* Read in the complete content of the index entry */
   memset(&m, 0, sizeof(m));
-  rc = sqlite3VdbeMemFromBtree(pCur, 0, (int)nCellKey, 1, &m);
+  rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
   if( rc ){
     return rc;
   }
@@ -63088,9 +66120,9 @@ idx_rowid_corruption:
 ** of the keys prior to the final rowid, not the entire key.
 */
 SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
-  VdbeCursor *pC,             /* The cursor to compare against */
-  UnpackedRecord *pUnpacked,  /* Unpacked version of key to compare against */
-  int *res                    /* Write the comparison result here */
+  VdbeCursor *pC,                  /* The cursor to compare against */
+  UnpackedRecord *pUnpacked,       /* Unpacked version of key */
+  int *res                         /* Write the comparison result here */
 ){
   i64 nCellKey = 0;
   int rc;
@@ -63100,19 +66132,18 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
   assert( sqlite3BtreeCursorIsValid(pCur) );
   VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
   assert( rc==SQLITE_OK );    /* pCur is always valid so KeySize cannot fail */
-  /* nCellKey will always be between 0 and 0xffffffff because of the say
+  /* nCellKey will always be between 0 and 0xffffffff because of the way
   ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
   if( nCellKey<=0 || nCellKey>0x7fffffff ){
     *res = 0;
     return SQLITE_CORRUPT_BKPT;
   }
   memset(&m, 0, sizeof(m));
-  rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m);
+  rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (u32)nCellKey, 1, &m);
   if( rc ){
     return rc;
   }
-  assert( pUnpacked->flags & UNPACKED_PREFIX_MATCH );
-  *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
+  *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0);
   sqlite3VdbeMemRelease(&m);
   return SQLITE_OK;
 }
@@ -63167,7 +66198,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){
 **
 ** The returned value must be freed by the caller using sqlite3ValueFree().
 */
-SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe *v, int iVar, u8 aff){
+SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
   assert( iVar>0 );
   if( v ){
     Mem *pMem = &v->aVar[iVar-1];
@@ -63176,7 +66207,6 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe *v, int iVar, u8 aff){
       if( pRet ){
         sqlite3VdbeMemCopy((Mem *)pRet, pMem);
         sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
-        sqlite3VdbeMemStoreType((Mem *)pRet);
       }
       return pRet;
     }
@@ -63198,6 +66228,21 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
   }
 }
 
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
+** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
+** in memory obtained from sqlite3DbMalloc).
+*/
+SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
+  sqlite3 *db = p->db;
+  sqlite3DbFree(db, p->zErrMsg);
+  p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
+  sqlite3_free(pVtab->zErrMsg);
+  pVtab->zErrMsg = 0;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
 /************** End of vdbeaux.c *********************************************/
 /************** Begin file vdbeapi.c *****************************************/
 /*
@@ -63335,7 +66380,6 @@ SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){
   Mem *p = (Mem*)pVal;
   if( p->flags & (MEM_Blob|MEM_Str) ){
     sqlite3VdbeMemExpandBlob(p);
-    p->flags &= ~MEM_Str;
     p->flags |= MEM_Blob;
     return p->n ? p->z : 0;
   }else{
@@ -63372,7 +66416,41 @@ SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){
 }
 #endif /* SQLITE_OMIT_UTF16 */
 SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
-  return pVal->type;
+  static const u8 aType[] = {
+     SQLITE_BLOB,     /* 0x00 */
+     SQLITE_NULL,     /* 0x01 */
+     SQLITE_TEXT,     /* 0x02 */
+     SQLITE_NULL,     /* 0x03 */
+     SQLITE_INTEGER,  /* 0x04 */
+     SQLITE_NULL,     /* 0x05 */
+     SQLITE_INTEGER,  /* 0x06 */
+     SQLITE_NULL,     /* 0x07 */
+     SQLITE_FLOAT,    /* 0x08 */
+     SQLITE_NULL,     /* 0x09 */
+     SQLITE_FLOAT,    /* 0x0a */
+     SQLITE_NULL,     /* 0x0b */
+     SQLITE_INTEGER,  /* 0x0c */
+     SQLITE_NULL,     /* 0x0d */
+     SQLITE_INTEGER,  /* 0x0e */
+     SQLITE_NULL,     /* 0x0f */
+     SQLITE_BLOB,     /* 0x10 */
+     SQLITE_NULL,     /* 0x11 */
+     SQLITE_TEXT,     /* 0x12 */
+     SQLITE_NULL,     /* 0x13 */
+     SQLITE_INTEGER,  /* 0x14 */
+     SQLITE_NULL,     /* 0x15 */
+     SQLITE_INTEGER,  /* 0x16 */
+     SQLITE_NULL,     /* 0x17 */
+     SQLITE_FLOAT,    /* 0x18 */
+     SQLITE_NULL,     /* 0x19 */
+     SQLITE_FLOAT,    /* 0x1a */
+     SQLITE_NULL,     /* 0x1b */
+     SQLITE_INTEGER,  /* 0x1c */
+     SQLITE_NULL,     /* 0x1d */
+     SQLITE_INTEGER,  /* 0x1e */
+     SQLITE_NULL,     /* 0x1f */
+  };
+  return aType[pVal->flags&MEM_AffMask];
 }
 
 /**************************** sqlite3_result_  *******************************
@@ -63411,12 +66489,14 @@ SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
 SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
   assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   pCtx->isError = SQLITE_ERROR;
+  pCtx->fErrorOrAux = 1;
   sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
 }
 #ifndef SQLITE_OMIT_UTF16
 SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
   assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   pCtx->isError = SQLITE_ERROR;
+  pCtx->fErrorOrAux = 1;
   sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
 }
 #endif
@@ -63480,6 +66560,7 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
 }
 SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
   pCtx->isError = errCode;
+  pCtx->fErrorOrAux = 1;
   if( pCtx->s.flags & MEM_Null ){
     sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1, 
                          SQLITE_UTF8, SQLITE_STATIC);
@@ -63490,6 +66571,7 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
 SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
   assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   pCtx->isError = SQLITE_TOOBIG;
+  pCtx->fErrorOrAux = 1;
   sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1, 
                        SQLITE_UTF8, SQLITE_STATIC);
 }
@@ -63499,6 +66581,7 @@ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
   assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   sqlite3VdbeMemSetNull(&pCtx->s);
   pCtx->isError = SQLITE_NOMEM;
+  pCtx->fErrorOrAux = 1;
   pCtx->s.db->mallocFailed = 1;
 }
 
@@ -63582,11 +66665,13 @@ static int sqlite3Step(Vdbe *p){
     ** reset the interrupt flag.  This prevents a call to sqlite3_interrupt
     ** from interrupting a statement that has not yet started.
     */
-    if( db->activeVdbeCnt==0 ){
+    if( db->nVdbeActive==0 ){
       db->u1.isInterrupted = 0;
     }
 
-    assert( db->writeVdbeCnt>0 || db->autoCommit==0 || db->nDeferredCons==0 );
+    assert( db->nVdbeWrite>0 || db->autoCommit==0 
+        || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
+    );
 
 #ifndef SQLITE_OMIT_TRACE
     if( db->xProfile && !db->init.busy ){
@@ -63594,8 +66679,9 @@ static int sqlite3Step(Vdbe *p){
     }
 #endif
 
-    db->activeVdbeCnt++;
-    if( p->readOnly==0 ) db->writeVdbeCnt++;
+    db->nVdbeActive++;
+    if( p->readOnly==0 ) db->nVdbeWrite++;
+    if( p->bIsReader ) db->nVdbeRead++;
     p->pc = 0;
   }
 #ifndef SQLITE_OMIT_EXPLAIN
@@ -63604,9 +66690,9 @@ static int sqlite3Step(Vdbe *p){
   }else
 #endif /* SQLITE_OMIT_EXPLAIN */
   {
-    db->vdbeExecCnt++;
+    db->nVdbeExec++;
     rc = sqlite3VdbeExec(p);
-    db->vdbeExecCnt--;
+    db->nVdbeExec--;
   }
 
 #ifndef SQLITE_OMIT_TRACE
@@ -63678,7 +66764,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
     v->doingRerun = 1;
     assert( v->expired==0 );
   }
-  if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
+  if( rc2!=SQLITE_OK ){
     /* This case occurs after failing to recompile an sql statement. 
     ** The error message from the SQL compiler has already been loaded 
     ** into the database handle. This block copies the error message 
@@ -63688,6 +66774,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
     ** sqlite3_errmsg() and sqlite3_errcode().
     */
     const char *zErr = (const char *)sqlite3_value_text(db->pErr); 
+    assert( zErr!=0 || db->mallocFailed );
     sqlite3DbFree(db, v->zErrMsg);
     if( !db->mallocFailed ){
       v->zErrMsg = sqlite3DbStrDup(db, zErr);
@@ -63702,6 +66789,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
   return rc;
 }
 
+
 /*
 ** Extract the user data from a sqlite3_context structure and return a
 ** pointer to it.
@@ -63727,6 +66815,19 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
 }
 
 /*
+** Return the current time for a statement
+*/
+SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
+  Vdbe *v = p->pVdbe;
+  int rc;
+  if( v->iCurrentTime==0 ){
+    rc = sqlite3OsCurrentTimeInt64(p->s.db->pVfs, &v->iCurrentTime);
+    if( rc ) v->iCurrentTime = 0;
+  }
+  return v->iCurrentTime;
+}
+
+/*
 ** The following is the implementation of an SQL function that always
 ** fails with an error message stating that the function is used in the
 ** wrong context.  The sqlite3_overload_function() API might construct
@@ -63781,14 +66882,14 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
 ** the user-function defined by pCtx.
 */
 SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
-  VdbeFunc *pVdbeFunc;
+  AuxData *pAuxData;
 
   assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
-  pVdbeFunc = pCtx->pVdbeFunc;
-  if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
-    return 0;
+  for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
+    if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
   }
-  return pVdbeFunc->apAux[iArg].pAux;
+
+  return (pAuxData ? pAuxData->pAux : 0);
 }
 
 /*
@@ -63802,29 +66903,30 @@ SQLITE_API void sqlite3_set_auxdata(
   void *pAux, 
   void (*xDelete)(void*)
 ){
-  struct AuxData *pAuxData;
-  VdbeFunc *pVdbeFunc;
-  if( iArg<0 ) goto failed;
+  AuxData *pAuxData;
+  Vdbe *pVdbe = pCtx->pVdbe;
 
   assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
-  pVdbeFunc = pCtx->pVdbeFunc;
-  if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
-    int nAux = (pVdbeFunc ? pVdbeFunc->nAux : 0);
-    int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
-    pVdbeFunc = sqlite3DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc);
-    if( !pVdbeFunc ){
-      goto failed;
-    }
-    pCtx->pVdbeFunc = pVdbeFunc;
-    memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux));
-    pVdbeFunc->nAux = iArg+1;
-    pVdbeFunc->pFunc = pCtx->pFunc;
-  }
+  if( iArg<0 ) goto failed;
 
-  pAuxData = &pVdbeFunc->apAux[iArg];
-  if( pAuxData->pAux && pAuxData->xDelete ){
+  for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
+    if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
+  }
+  if( pAuxData==0 ){
+    pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
+    if( !pAuxData ) goto failed;
+    pAuxData->iOp = pCtx->iOp;
+    pAuxData->iArg = iArg;
+    pAuxData->pNext = pVdbe->pAuxData;
+    pVdbe->pAuxData = pAuxData;
+    if( pCtx->fErrorOrAux==0 ){
+      pCtx->isError = 0;
+      pCtx->fErrorOrAux = 1;
+    }
+  }else if( pAuxData->xDelete ){
     pAuxData->xDelete(pAuxData->pAux);
   }
+
   pAuxData->pAux = pAux;
   pAuxData->xDelete = xDelete;
   return;
@@ -63869,6 +66971,30 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){
   return pVm->nResColumn;
 }
 
+/*
+** Return a pointer to static memory containing an SQL NULL value.
+*/
+static const Mem *columnNullValue(void){
+  /* Even though the Mem structure contains an element
+  ** of type i64, on certain architectures (x86) with certain compiler
+  ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
+  ** instead of an 8-byte one. This all works fine, except that when
+  ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
+  ** that a Mem structure is located on an 8-byte boundary. To prevent
+  ** these assert()s from failing, when building with SQLITE_DEBUG defined
+  ** using gcc, we force nullMem to be 8-byte aligned using the magical
+  ** __attribute__((aligned(8))) macro.  */
+  static const Mem nullMem 
+#if defined(SQLITE_DEBUG) && defined(__GNUC__)
+    __attribute__((aligned(8))) 
+#endif
+    = {0, "", (double)0, {0}, 0, MEM_Null, 0,
+#ifdef SQLITE_DEBUG
+       0, 0,  /* pScopyFrom, pFiller */
+#endif
+       0, 0 };
+  return &nullMem;
+}
 
 /*
 ** Check to see if column iCol of the given statement is valid.  If
@@ -63885,32 +67011,11 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
     sqlite3_mutex_enter(pVm->db->mutex);
     pOut = &pVm->pResultSet[i];
   }else{
-    /* If the value passed as the second argument is out of range, return
-    ** a pointer to the following static Mem object which contains the
-    ** value SQL NULL. Even though the Mem structure contains an element
-    ** of type i64, on certain architectures (x86) with certain compiler
-    ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
-    ** instead of an 8-byte one. This all works fine, except that when
-    ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
-    ** that a Mem structure is located on an 8-byte boundary. To prevent
-    ** these assert()s from failing, when building with SQLITE_DEBUG defined
-    ** using gcc, we force nullMem to be 8-byte aligned using the magical
-    ** __attribute__((aligned(8))) macro.  */
-    static const Mem nullMem 
-#if defined(SQLITE_DEBUG) && defined(__GNUC__)
-      __attribute__((aligned(8))) 
-#endif
-      = {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0,
-#ifdef SQLITE_DEBUG
-         0, 0,  /* pScopyFrom, pFiller */
-#endif
-         0, 0 };
-
     if( pVm && ALWAYS(pVm->db) ){
       sqlite3_mutex_enter(pVm->db->mutex);
       sqlite3Error(pVm->db, SQLITE_RANGE, 0);
     }
-    pOut = (Mem*)&nullMem;
+    pOut = (Mem*)columnNullValue();
   }
   return pOut;
 }
@@ -64013,13 +67118,6 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
   return iType;
 }
 
-/* The following function is experimental and subject to change or
-** removal */
-/*int sqlite3_column_numeric_type(sqlite3_stmt *pStmt, int i){
-**  return sqlite3_value_numeric_type( columnMem(pStmt,i) );
-**}
-*/
-
 /*
 ** Convert the N-th element of pStmt->pColName[] into a string using
 ** xFunc() then return that string.  If N is out of range, return 0.
@@ -64314,7 +67412,7 @@ SQLITE_API int sqlite3_bind_text16(
 #endif /* SQLITE_OMIT_UTF16 */
 SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
   int rc;
-  switch( pValue->type ){
+  switch( sqlite3_value_type((sqlite3_value*)pValue) ){
     case SQLITE_INTEGER: {
       rc = sqlite3_bind_int64(pStmt, i, pValue->u.i);
       break;
@@ -64470,7 +67568,7 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
 */
 SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
   Vdbe *v = (Vdbe*)pStmt;
-  return v!=0 && v->pc>0 && v->magic==VDBE_MAGIC_RUN;
+  return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN;
 }
 
 /*
@@ -64496,9 +67594,9 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
 */
 SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
   Vdbe *pVdbe = (Vdbe*)pStmt;
-  int v = pVdbe->aCounter[op-1];
-  if( resetFlag ) pVdbe->aCounter[op-1] = 0;
-  return v;
+  u32 v = pVdbe->aCounter[op];
+  if( resetFlag ) pVdbe->aCounter[op] = 0;
+  return (int)v;
 }
 
 /************** End of vdbeapi.c *********************************************/
@@ -64550,9 +67648,9 @@ static int findNextHostParameter(const char *zSql, int *pnToken){
 
 /*
 ** This function returns a pointer to a nul-terminated string in memory
-** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
+** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the
 ** string contains a copy of zRawSql but with host parameters expanded to 
-** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, 
+** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1, 
 ** then the returned string holds a copy of zRawSql with "-- " prepended
 ** to each line of text.
 **
@@ -64590,11 +67688,12 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
   sqlite3StrAccumInit(&out, zBase, sizeof(zBase), 
                       db->aLimit[SQLITE_LIMIT_LENGTH]);
   out.db = db;
-  if( db->vdbeExecCnt>1 ){
+  if( db->nVdbeExec>1 ){
     while( *zRawSql ){
       const char *zStart = zRawSql;
       while( *(zRawSql++)!='\n' && *zRawSql );
       sqlite3StrAccumAppend(&out, "-- ", 3);
+      assert( (zRawSql - zStart) > 0 );
       sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
     }
   }else{
@@ -64627,9 +67726,9 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
       if( pVar->flags & MEM_Null ){
         sqlite3StrAccumAppend(&out, "NULL", 4);
       }else if( pVar->flags & MEM_Int ){
-        sqlite3XPrintf(&out, "%lld", pVar->u.i);
+        sqlite3XPrintf(&out, 0, "%lld", pVar->u.i);
       }else if( pVar->flags & MEM_Real ){
-        sqlite3XPrintf(&out, "%!.15g", pVar->r);
+        sqlite3XPrintf(&out, 0, "%!.15g", pVar->r);
       }else if( pVar->flags & MEM_Str ){
         int nOut;  /* Number of bytes of the string text to include in output */
 #ifndef SQLITE_OMIT_UTF16
@@ -64650,15 +67749,17 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
           while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
         }
 #endif    
-        sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z);
+        sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z);
 #ifdef SQLITE_TRACE_SIZE_LIMIT
-        if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
+        if( nOut<pVar->n ){
+          sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
+        }
 #endif
 #ifndef SQLITE_OMIT_UTF16
         if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);
 #endif
       }else if( pVar->flags & MEM_Zero ){
-        sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
+        sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero);
       }else{
         int nOut;  /* Number of bytes of the blob to include in output */
         assert( pVar->flags & MEM_Blob );
@@ -64668,11 +67769,13 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
         if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT;
 #endif
         for(i=0; i<nOut; i++){
-          sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
+          sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff);
         }
         sqlite3StrAccumAppend(&out, "'", 1);
 #ifdef SQLITE_TRACE_SIZE_LIMIT
-        if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
+        if( nOut<pVar->n ){
+          sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
+        }
 #endif
       }
     }
@@ -64731,7 +67834,7 @@ SQLITE_PRIVATE void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){
       sqlite3AppendSpace(&p->str, p->aIndent[n-1]);
     }   
     va_start(ap, zFormat);
-    sqlite3VXPrintf(&p->str, 1, zFormat, ap);
+    sqlite3VXPrintf(&p->str, SQLITE_PRINTF_INTERNAL, zFormat, ap);
     va_end(ap);
   }
 }
@@ -64810,33 +67913,8 @@ SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe *pVdbe){
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** The code in this file implements execution method of the 
-** Virtual Database Engine (VDBE).  A separate file ("vdbeaux.c")
-** handles housekeeping details such as creating and deleting
-** VDBE instances.  This file is solely interested in executing
-** the VDBE program.
-**
-** In the external interface, an "sqlite3_stmt*" is an opaque pointer
-** to a VDBE.
-**
-** The SQL parser generates a program which is then executed by
-** the VDBE to do the work of the SQL statement.  VDBE programs are 
-** similar in form to assembly language.  The program consists of
-** a linear sequence of operations.  Each operation has an opcode 
-** and 5 operands.  Operands P1, P2, and P3 are integers.  Operand P4 
-** is a null-terminated string.  Operand P5 is an unsigned character.
-** Few opcodes use all 5 operands.
-**
-** Computation results are stored on a set of registers numbered beginning
-** with 1 and going up to Vdbe.nMem.  Each register can store
-** either an integer, a null-terminated string, a floating point
-** number, or the SQL "NULL" value.  An implicit conversion from one
-** type to the other occurs as necessary.
-** 
-** Most of the code in this file is taken up by the sqlite3VdbeExec()
-** function which does the work of interpreting a VDBE program.
-** But other routines are also provided to help in building up
-** a program instruction by instruction.
+** The code in this file implements the function that runs the
+** bytecode of a prepared statement.
 **
 ** Various scripts scan this source file in order to generate HTML
 ** documentation, headers files, or other derived files.  The formatting
@@ -64848,7 +67926,11 @@ SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe *pVdbe){
 /*
 ** Invoke this macro on memory cells just prior to changing the
 ** value of the cell.  This macro verifies that shallow copies are
-** not misused.
+** not misused.  A shallow copy of a string or blob just copies a
+** pointer to the string or blob, not the content.  If the original
+** is changed while the copy is still in use, the string or blob might
+** be changed out from under the copy.  This macro verifies that nothing
+** like that ever happens.
 */
 #ifdef SQLITE_DEBUG
 # define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M)
@@ -64907,7 +67989,7 @@ static void updateMaxBlobsize(Mem *p){
 #endif
 
 /*
-** The next global variable is incremented each type the OP_Found opcode
+** The next global variable is incremented each time the OP_Found opcode
 ** is executed. This is used to test whether or not the foreign key
 ** operation implemented using OP_FkIsZero is working. This variable
 ** has no function other than to help verify the correct operation of the
@@ -64928,6 +68010,40 @@ SQLITE_API int sqlite3_found_count = 0;
 #endif
 
 /*
+** Invoke the VDBE coverage callback, if that callback is defined.  This
+** feature is used for test suite validation only and does not appear an
+** production builds.
+**
+** M is an integer, 2 or 3, that indices how many different ways the
+** branch can go.  It is usually 2.  "I" is the direction the branch
+** goes.  0 means falls through.  1 means branch is taken.  2 means the
+** second alternative branch is taken.
+**
+** iSrcLine is the source code line (from the __LINE__ macro) that
+** generated the VDBE instruction.  This instrumentation assumes that all
+** source code is in a single file (the amalgamation).  Special values 1
+** and 2 for the iSrcLine parameter mean that this particular branch is
+** always taken or never taken, respectively.
+*/
+#if !defined(SQLITE_VDBE_COVERAGE)
+# define VdbeBranchTaken(I,M)
+#else
+# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
+  static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){
+    if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){
+      M = iSrcLine;
+      /* Assert the truth of VdbeCoverageAlwaysTaken() and 
+      ** VdbeCoverageNeverTaken() */
+      assert( (M & I)==I );
+    }else{
+      if( sqlite3GlobalConfig.xVdbeBranch==0 ) return;  /*NO_TEST*/
+      sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
+                                      iSrcLine,I,M);
+    }
+  }
+#endif
+
+/*
 ** Convert the given register into a string if it isn't one
 ** already. Return non-zero if a malloc() fails.
 */
@@ -64944,38 +68060,14 @@ SQLITE_API int sqlite3_found_count = 0;
 **
 ** This routine converts an ephemeral string into a dynamically allocated
 ** string that the register itself controls.  In other words, it
-** converts an MEM_Ephem string into an MEM_Dyn string.
+** converts an MEM_Ephem string into a string with P.z==P.zMalloc.
 */
 #define Deephemeralize(P) \
    if( ((P)->flags&MEM_Ephem)!=0 \
        && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
 
 /* Return true if the cursor was opened using the OP_OpenSorter opcode. */
-# define isSorter(x) ((x)->pSorter!=0)
-
-/*
-** Argument pMem points at a register that will be passed to a
-** user-defined function or returned to the user as the result of a query.
-** This routine sets the pMem->type variable used by the sqlite3_value_*() 
-** routines.
-*/
-SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem){
-  int flags = pMem->flags;
-  if( flags & MEM_Null ){
-    pMem->type = SQLITE_NULL;
-  }
-  else if( flags & MEM_Int ){
-    pMem->type = SQLITE_INTEGER;
-  }
-  else if( flags & MEM_Real ){
-    pMem->type = SQLITE_FLOAT;
-  }
-  else if( flags & MEM_Str ){
-    pMem->type = SQLITE_TEXT;
-  }else{
-    pMem->type = SQLITE_BLOB;
-  }
-}
+#define isSorter(x) ((x)->pSorter!=0)
 
 /*
 ** Allocate VdbeCursor number iCur.  Return a pointer to it.  Return NULL
@@ -65011,9 +68103,8 @@ static VdbeCursor *allocateCursor(
   int nByte;
   VdbeCursor *pCx = 0;
   nByte = 
-      ROUND8(sizeof(VdbeCursor)) + 
-      (isBtreeCursor?sqlite3BtreeCursorSize():0) + 
-      2*nField*sizeof(u32);
+      ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + 
+      (isBtreeCursor?sqlite3BtreeCursorSize():0);
 
   assert( iCur<p->nCursor );
   if( p->apCsr[iCur] ){
@@ -65025,12 +68116,9 @@ static VdbeCursor *allocateCursor(
     memset(pCx, 0, sizeof(VdbeCursor));
     pCx->iDb = iDb;
     pCx->nField = nField;
-    if( nField ){
-      pCx->aType = (u32 *)&pMem->z[ROUND8(sizeof(VdbeCursor))];
-    }
     if( isBtreeCursor ){
       pCx->pCursor = (BtCursor*)
-          &pMem->z[ROUND8(sizeof(VdbeCursor))+2*nField*sizeof(u32)];
+          &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
       sqlite3BtreeCursorZero(pCx->pCursor);
     }
   }
@@ -65044,21 +68132,21 @@ static VdbeCursor *allocateCursor(
 ** look like a number, leave it alone.
 */
 static void applyNumericAffinity(Mem *pRec){
-  if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
-    double rValue;
-    i64 iValue;
-    u8 enc = pRec->enc;
-    if( (pRec->flags&MEM_Str)==0 ) return;
-    if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
-    if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
-      pRec->u.i = iValue;
-      pRec->flags |= MEM_Int;
-    }else{
-      pRec->r = rValue;
-      pRec->flags |= MEM_Real;
-    }
+  double rValue;
+  i64 iValue;
+  u8 enc = pRec->enc;
+  if( (pRec->flags&MEM_Str)==0 ) return;
+  if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
+  if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
+    pRec->u.i = iValue;
+    pRec->flags |= MEM_Int;
+  }else{
+    pRec->r = rValue;
+    pRec->flags |= MEM_Real;
   }
 }
+#define ApplyNumericAffinity(X)  \
+   if(((X)->flags&(MEM_Real|MEM_Int))==0){applyNumericAffinity(X);}
 
 /*
 ** Processing is determine by the affinity parameter:
@@ -65095,7 +68183,7 @@ static void applyAffinity(
   }else if( affinity!=SQLITE_AFF_NONE ){
     assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
              || affinity==SQLITE_AFF_NUMERIC );
-    applyNumericAffinity(pRec);
+    ApplyNumericAffinity(pRec);
     if( pRec->flags & MEM_Real ){
       sqlite3VdbeIntegerAffinity(pRec);
     }
@@ -65109,12 +68197,13 @@ static void applyAffinity(
 ** loss of information and return the revised type of the argument.
 */
 SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){
-  Mem *pMem = (Mem*)pVal;
-  if( pMem->type==SQLITE_TEXT ){
+  int eType = sqlite3_value_type(pVal);
+  if( eType==SQLITE_TEXT ){
+    Mem *pMem = (Mem*)pVal;
     applyNumericAffinity(pMem);
-    sqlite3VdbeMemStoreType(pMem);
+    eType = sqlite3_value_type(pVal);
   }
-  return pMem->type;
+  return eType;
 }
 
 /*
@@ -65129,6 +68218,29 @@ SQLITE_PRIVATE void sqlite3ValueApplyAffinity(
   applyAffinity((Mem *)pVal, affinity, enc);
 }
 
+/*
+** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or
+** none.  
+**
+** Unlike applyNumericAffinity(), this routine does not modify pMem->flags.
+** But it does set pMem->r and pMem->u.i appropriately.
+*/
+static u16 numericType(Mem *pMem){
+  if( pMem->flags & (MEM_Int|MEM_Real) ){
+    return pMem->flags & (MEM_Int|MEM_Real);
+  }
+  if( pMem->flags & (MEM_Str|MEM_Blob) ){
+    if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){
+      return 0;
+    }
+    if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){
+      return MEM_Int;
+    }
+    return MEM_Real;
+  }
+  return 0;
+}
+
 #ifdef SQLITE_DEBUG
 /*
 ** Write a nice string representation of the contents of cell pMem
@@ -65216,37 +68328,36 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
 /*
 ** Print the value of a register for tracing purposes:
 */
-static void memTracePrint(FILE *out, Mem *p){
-  if( p->flags & MEM_Invalid ){
-    fprintf(out, " undefined");
+static void memTracePrint(Mem *p){
+  if( p->flags & MEM_Undefined ){
+    printf(" undefined");
   }else if( p->flags & MEM_Null ){
-    fprintf(out, " NULL");
+    printf(" NULL");
   }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
-    fprintf(out, " si:%lld", p->u.i);
+    printf(" si:%lld", p->u.i);
   }else if( p->flags & MEM_Int ){
-    fprintf(out, " i:%lld", p->u.i);
+    printf(" i:%lld", p->u.i);
 #ifndef SQLITE_OMIT_FLOATING_POINT
   }else if( p->flags & MEM_Real ){
-    fprintf(out, " r:%g", p->r);
+    printf(" r:%g", p->r);
 #endif
   }else if( p->flags & MEM_RowSet ){
-    fprintf(out, " (rowset)");
+    printf(" (rowset)");
   }else{
     char zBuf[200];
     sqlite3VdbeMemPrettyPrint(p, zBuf);
-    fprintf(out, " ");
-    fprintf(out, "%s", zBuf);
+    printf(" %s", zBuf);
   }
 }
-static void registerTrace(FILE *out, int iReg, Mem *p){
-  fprintf(out, "REG[%d] = ", iReg);
-  memTracePrint(out, p);
-  fprintf(out, "\n");
+static void registerTrace(int iReg, Mem *p){
+  printf("REG[%d] = ", iReg);
+  memTracePrint(p);
+  printf("\n");
 }
 #endif
 
 #ifdef SQLITE_DEBUG
-#  define REGISTER_TRACE(R,M) if(p->trace)registerTrace(p->trace,R,M)
+#  define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
 #else
 #  define REGISTER_TRACE(R,M)
 #endif
@@ -65351,20 +68462,6 @@ SQLITE_PRIVATE   sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
 
 #endif
 
-/*
-** The CHECK_FOR_INTERRUPT macro defined here looks to see if the
-** sqlite3_interrupt() routine has been called.  If it has been, then
-** processing of the VDBE program is interrupted.
-**
-** This macro added to every instruction that does a jump in order to
-** implement a loop.  This test used to be on every single instruction,
-** but that meant we more testing than we needed.  By only testing the
-** flag on jump instructions, we get a (small) speed improvement.
-*/
-#define CHECK_FOR_INTERRUPT \
-   if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
-
-
 #ifndef NDEBUG
 /*
 ** This function is only called from within an assert() expression. It
@@ -65385,50 +68482,10 @@ static int checkSavepointCount(sqlite3 *db){
 }
 #endif
 
-/*
-** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
-** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
-** in memory obtained from sqlite3DbMalloc).
-*/
-static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){
-  sqlite3 *db = p->db;
-  sqlite3DbFree(db, p->zErrMsg);
-  p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
-  sqlite3_free(pVtab->zErrMsg);
-  pVtab->zErrMsg = 0;
-}
-
 
 /*
-** Execute as much of a VDBE program as we can then return.
-**
-** sqlite3VdbeMakeReady() must be called before this routine in order to
-** close the program with a final OP_Halt and to set up the callbacks
-** and the error message pointer.
-**
-** Whenever a row or result data is available, this routine will either
-** invoke the result callback (if there is one) or return with
-** SQLITE_ROW.
-**
-** If an attempt is made to open a locked database, then this routine
-** will either invoke the busy callback (if there is one) or it will
-** return SQLITE_BUSY.
-**
-** If an error occurs, an error message is written to memory obtained
-** from sqlite3_malloc() and p->zErrMsg is made to point to that memory.
-** The error code is stored in p->rc and this routine returns SQLITE_ERROR.
-**
-** If the callback ever returns non-zero, then the program exits
-** immediately.  There will be no error message but the p->rc field is
-** set to SQLITE_ABORT and this routine will return SQLITE_ERROR.
-**
-** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this
-** routine to return SQLITE_ERROR.
-**
-** Other fatal errors return SQLITE_ERROR.
-**
-** After this routine has finished, sqlite3VdbeFinalize() should be
-** used to clean up the mess that was left behind.
+** Execute as much of a VDBE program as we can.
+** This is the core of sqlite3_step().  
 */
 SQLITE_PRIVATE int sqlite3VdbeExec(
   Vdbe *p                    /* The VDBE */
@@ -65440,452 +68497,22 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
   sqlite3 *db = p->db;       /* The database */
   u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
   u8 encoding = ENC(db);     /* The database encoding */
+  int iCompare = 0;          /* Result of last OP_Compare operation */
+  unsigned nVmStep = 0;      /* Number of virtual machine steps */
 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
-  int checkProgress;         /* True if progress callbacks are enabled */
-  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
+  unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */
 #endif
   Mem *aMem = p->aMem;       /* Copy of p->aMem */
   Mem *pIn1 = 0;             /* 1st input operand */
   Mem *pIn2 = 0;             /* 2nd input operand */
   Mem *pIn3 = 0;             /* 3rd input operand */
   Mem *pOut = 0;             /* Output operand */
-  int iCompare = 0;          /* Result of last OP_Compare operation */
   int *aPermute = 0;         /* Permutation of columns for OP_Compare */
   i64 lastRowid = db->lastRowid;  /* Saved value of the last insert ROWID */
 #ifdef VDBE_PROFILE
   u64 start;                 /* CPU clock count at start of opcode */
-  int origPc;                /* Program counter at start of opcode */
-#endif
-  /********************************************************************
-  ** Automatically generated code
-  **
-  ** The following union is automatically generated by the
-  ** vdbe-compress.tcl script.  The purpose of this union is to
-  ** reduce the amount of stack space required by this function.
-  ** See comments in the vdbe-compress.tcl script for details.
-  */
-  union vdbeExecUnion {
-    struct OP_Yield_stack_vars {
-      int pcDest;
-    } aa;
-    struct OP_Null_stack_vars {
-      int cnt;
-      u16 nullFlag;
-    } ab;
-    struct OP_Variable_stack_vars {
-      Mem *pVar;       /* Value being transferred */
-    } ac;
-    struct OP_Move_stack_vars {
-      char *zMalloc;   /* Holding variable for allocated memory */
-      int n;           /* Number of registers left to copy */
-      int p1;          /* Register to copy from */
-      int p2;          /* Register to copy to */
-    } ad;
-    struct OP_Copy_stack_vars {
-      int n;
-    } ae;
-    struct OP_ResultRow_stack_vars {
-      Mem *pMem;
-      int i;
-    } af;
-    struct OP_Concat_stack_vars {
-      i64 nByte;
-    } ag;
-    struct OP_Remainder_stack_vars {
-      char bIntint;   /* Started out as two integer operands */
-      int flags;      /* Combined MEM_* flags from both inputs */
-      i64 iA;         /* Integer value of left operand */
-      i64 iB;         /* Integer value of right operand */
-      double rA;      /* Real value of left operand */
-      double rB;      /* Real value of right operand */
-    } ah;
-    struct OP_Function_stack_vars {
-      int i;
-      Mem *pArg;
-      sqlite3_context ctx;
-      sqlite3_value **apVal;
-      int n;
-    } ai;
-    struct OP_ShiftRight_stack_vars {
-      i64 iA;
-      u64 uA;
-      i64 iB;
-      u8 op;
-    } aj;
-    struct OP_Ge_stack_vars {
-      int res;            /* Result of the comparison of pIn1 against pIn3 */
-      char affinity;      /* Affinity to use for comparison */
-      u16 flags1;         /* Copy of initial value of pIn1->flags */
-      u16 flags3;         /* Copy of initial value of pIn3->flags */
-    } ak;
-    struct OP_Compare_stack_vars {
-      int n;
-      int i;
-      int p1;
-      int p2;
-      const KeyInfo *pKeyInfo;
-      int idx;
-      CollSeq *pColl;    /* Collating sequence to use on this term */
-      int bRev;          /* True for DESCENDING sort order */
-    } al;
-    struct OP_Or_stack_vars {
-      int v1;    /* Left operand:  0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-      int v2;    /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-    } am;
-    struct OP_IfNot_stack_vars {
-      int c;
-    } an;
-    struct OP_Column_stack_vars {
-      u32 payloadSize;   /* Number of bytes in the record */
-      i64 payloadSize64; /* Number of bytes in the record */
-      int p1;            /* P1 value of the opcode */
-      int p2;            /* column number to retrieve */
-      VdbeCursor *pC;    /* The VDBE cursor */
-      char *zRec;        /* Pointer to complete record-data */
-      BtCursor *pCrsr;   /* The BTree cursor */
-      u32 *aType;        /* aType[i] holds the numeric type of the i-th column */
-      u32 *aOffset;      /* aOffset[i] is offset to start of data for i-th column */
-      int nField;        /* number of fields in the record */
-      int len;           /* The length of the serialized data for the column */
-      int i;             /* Loop counter */
-      char *zData;       /* Part of the record being decoded */
-      Mem *pDest;        /* Where to write the extracted value */
-      Mem sMem;          /* For storing the record being decoded */
-      u8 *zIdx;          /* Index into header */
-      u8 *zEndHdr;       /* Pointer to first byte after the header */
-      u32 offset;        /* Offset into the data */
-      u32 szField;       /* Number of bytes in the content of a field */
-      int szHdr;         /* Size of the header size field at start of record */
-      int avail;         /* Number of bytes of available data */
-      u32 t;             /* A type code from the record header */
-      Mem *pReg;         /* PseudoTable input register */
-    } ao;
-    struct OP_Affinity_stack_vars {
-      const char *zAffinity;   /* The affinity to be applied */
-      char cAff;               /* A single character of affinity */
-    } ap;
-    struct OP_MakeRecord_stack_vars {
-      u8 *zNewRecord;        /* A buffer to hold the data for the new record */
-      Mem *pRec;             /* The new record */
-      u64 nData;             /* Number of bytes of data space */
-      int nHdr;              /* Number of bytes of header space */
-      i64 nByte;             /* Data space required for this record */
-      int nZero;             /* Number of zero bytes at the end of the record */
-      int nVarint;           /* Number of bytes in a varint */
-      u32 serial_type;       /* Type field */
-      Mem *pData0;           /* First field to be combined into the record */
-      Mem *pLast;            /* Last field of the record */
-      int nField;            /* Number of fields in the record */
-      char *zAffinity;       /* The affinity string for the record */
-      int file_format;       /* File format to use for encoding */
-      int i;                 /* Space used in zNewRecord[] */
-      int len;               /* Length of a field */
-    } aq;
-    struct OP_Count_stack_vars {
-      i64 nEntry;
-      BtCursor *pCrsr;
-    } ar;
-    struct OP_Savepoint_stack_vars {
-      int p1;                         /* Value of P1 operand */
-      char *zName;                    /* Name of savepoint */
-      int nName;
-      Savepoint *pNew;
-      Savepoint *pSavepoint;
-      Savepoint *pTmp;
-      int iSavepoint;
-      int ii;
-    } as;
-    struct OP_AutoCommit_stack_vars {
-      int desiredAutoCommit;
-      int iRollback;
-      int turnOnAC;
-    } at;
-    struct OP_Transaction_stack_vars {
-      Btree *pBt;
-    } au;
-    struct OP_ReadCookie_stack_vars {
-      int iMeta;
-      int iDb;
-      int iCookie;
-    } av;
-    struct OP_SetCookie_stack_vars {
-      Db *pDb;
-    } aw;
-    struct OP_VerifyCookie_stack_vars {
-      int iMeta;
-      int iGen;
-      Btree *pBt;
-    } ax;
-    struct OP_OpenWrite_stack_vars {
-      int nField;
-      KeyInfo *pKeyInfo;
-      int p2;
-      int iDb;
-      int wrFlag;
-      Btree *pX;
-      VdbeCursor *pCur;
-      Db *pDb;
-    } ay;
-    struct OP_OpenEphemeral_stack_vars {
-      VdbeCursor *pCx;
-    } az;
-    struct OP_SorterOpen_stack_vars {
-      VdbeCursor *pCx;
-    } ba;
-    struct OP_OpenPseudo_stack_vars {
-      VdbeCursor *pCx;
-    } bb;
-    struct OP_SeekGt_stack_vars {
-      int res;
-      int oc;
-      VdbeCursor *pC;
-      UnpackedRecord r;
-      int nField;
-      i64 iKey;      /* The rowid we are to seek to */
-    } bc;
-    struct OP_Seek_stack_vars {
-      VdbeCursor *pC;
-    } bd;
-    struct OP_Found_stack_vars {
-      int alreadyExists;
-      VdbeCursor *pC;
-      int res;
-      char *pFree;
-      UnpackedRecord *pIdxKey;
-      UnpackedRecord r;
-      char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-    } be;
-    struct OP_IsUnique_stack_vars {
-      u16 ii;
-      VdbeCursor *pCx;
-      BtCursor *pCrsr;
-      u16 nField;
-      Mem *aMx;
-      UnpackedRecord r;                  /* B-Tree index search key */
-      i64 R;                             /* Rowid stored in register P3 */
-    } bf;
-    struct OP_NotExists_stack_vars {
-      VdbeCursor *pC;
-      BtCursor *pCrsr;
-      int res;
-      u64 iKey;
-    } bg;
-    struct OP_NewRowid_stack_vars {
-      i64 v;                 /* The new rowid */
-      VdbeCursor *pC;        /* Cursor of table to get the new rowid */
-      int res;               /* Result of an sqlite3BtreeLast() */
-      int cnt;               /* Counter to limit the number of searches */
-      Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
-      VdbeFrame *pFrame;     /* Root frame of VDBE */
-    } bh;
-    struct OP_InsertInt_stack_vars {
-      Mem *pData;       /* MEM cell holding data for the record to be inserted */
-      Mem *pKey;        /* MEM cell holding key  for the record */
-      i64 iKey;         /* The integer ROWID or key for the record to be inserted */
-      VdbeCursor *pC;   /* Cursor to table into which insert is written */
-      int nZero;        /* Number of zero-bytes to append */
-      int seekResult;   /* Result of prior seek or 0 if no USESEEKRESULT flag */
-      const char *zDb;  /* database name - used by the update hook */
-      const char *zTbl; /* Table name - used by the opdate hook */
-      int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
-    } bi;
-    struct OP_Delete_stack_vars {
-      i64 iKey;
-      VdbeCursor *pC;
-    } bj;
-    struct OP_SorterCompare_stack_vars {
-      VdbeCursor *pC;
-      int res;
-    } bk;
-    struct OP_SorterData_stack_vars {
-      VdbeCursor *pC;
-    } bl;
-    struct OP_RowData_stack_vars {
-      VdbeCursor *pC;
-      BtCursor *pCrsr;
-      u32 n;
-      i64 n64;
-    } bm;
-    struct OP_Rowid_stack_vars {
-      VdbeCursor *pC;
-      i64 v;
-      sqlite3_vtab *pVtab;
-      const sqlite3_module *pModule;
-    } bn;
-    struct OP_NullRow_stack_vars {
-      VdbeCursor *pC;
-    } bo;
-    struct OP_Last_stack_vars {
-      VdbeCursor *pC;
-      BtCursor *pCrsr;
-      int res;
-    } bp;
-    struct OP_Rewind_stack_vars {
-      VdbeCursor *pC;
-      BtCursor *pCrsr;
-      int res;
-    } bq;
-    struct OP_Next_stack_vars {
-      VdbeCursor *pC;
-      int res;
-    } br;
-    struct OP_IdxInsert_stack_vars {
-      VdbeCursor *pC;
-      BtCursor *pCrsr;
-      int nKey;
-      const char *zKey;
-    } bs;
-    struct OP_IdxDelete_stack_vars {
-      VdbeCursor *pC;
-      BtCursor *pCrsr;
-      int res;
-      UnpackedRecord r;
-    } bt;
-    struct OP_IdxRowid_stack_vars {
-      BtCursor *pCrsr;
-      VdbeCursor *pC;
-      i64 rowid;
-    } bu;
-    struct OP_IdxGE_stack_vars {
-      VdbeCursor *pC;
-      int res;
-      UnpackedRecord r;
-    } bv;
-    struct OP_Destroy_stack_vars {
-      int iMoved;
-      int iCnt;
-      Vdbe *pVdbe;
-      int iDb;
-    } bw;
-    struct OP_Clear_stack_vars {
-      int nChange;
-    } bx;
-    struct OP_CreateTable_stack_vars {
-      int pgno;
-      int flags;
-      Db *pDb;
-    } by;
-    struct OP_ParseSchema_stack_vars {
-      int iDb;
-      const char *zMaster;
-      char *zSql;
-      InitData initData;
-    } bz;
-    struct OP_IntegrityCk_stack_vars {
-      int nRoot;      /* Number of tables to check.  (Number of root pages.) */
-      int *aRoot;     /* Array of rootpage numbers for tables to be checked */
-      int j;          /* Loop counter */
-      int nErr;       /* Number of errors reported */
-      char *z;        /* Text of the error report */
-      Mem *pnErr;     /* Register keeping track of errors remaining */
-    } ca;
-    struct OP_RowSetRead_stack_vars {
-      i64 val;
-    } cb;
-    struct OP_RowSetTest_stack_vars {
-      int iSet;
-      int exists;
-    } cc;
-    struct OP_Program_stack_vars {
-      int nMem;               /* Number of memory registers for sub-program */
-      int nByte;              /* Bytes of runtime space required for sub-program */
-      Mem *pRt;               /* Register to allocate runtime space */
-      Mem *pMem;              /* Used to iterate through memory cells */
-      Mem *pEnd;              /* Last memory cell in new array */
-      VdbeFrame *pFrame;      /* New vdbe frame to execute in */
-      SubProgram *pProgram;   /* Sub-program to execute */
-      void *t;                /* Token identifying trigger */
-    } cd;
-    struct OP_Param_stack_vars {
-      VdbeFrame *pFrame;
-      Mem *pIn;
-    } ce;
-    struct OP_MemMax_stack_vars {
-      Mem *pIn1;
-      VdbeFrame *pFrame;
-    } cf;
-    struct OP_AggStep_stack_vars {
-      int n;
-      int i;
-      Mem *pMem;
-      Mem *pRec;
-      sqlite3_context ctx;
-      sqlite3_value **apVal;
-    } cg;
-    struct OP_AggFinal_stack_vars {
-      Mem *pMem;
-    } ch;
-    struct OP_Checkpoint_stack_vars {
-      int i;                          /* Loop counter */
-      int aRes[3];                    /* Results */
-      Mem *pMem;                      /* Write results here */
-    } ci;
-    struct OP_JournalMode_stack_vars {
-      Btree *pBt;                     /* Btree to change journal mode of */
-      Pager *pPager;                  /* Pager associated with pBt */
-      int eNew;                       /* New journal mode */
-      int eOld;                       /* The old journal mode */
-#ifndef SQLITE_OMIT_WAL
-      const char *zFilename;          /* Name of database file for pPager */
 #endif
-    } cj;
-    struct OP_IncrVacuum_stack_vars {
-      Btree *pBt;
-    } ck;
-    struct OP_VBegin_stack_vars {
-      VTable *pVTab;
-    } cl;
-    struct OP_VOpen_stack_vars {
-      VdbeCursor *pCur;
-      sqlite3_vtab_cursor *pVtabCursor;
-      sqlite3_vtab *pVtab;
-      sqlite3_module *pModule;
-    } cm;
-    struct OP_VFilter_stack_vars {
-      int nArg;
-      int iQuery;
-      const sqlite3_module *pModule;
-      Mem *pQuery;
-      Mem *pArgc;
-      sqlite3_vtab_cursor *pVtabCursor;
-      sqlite3_vtab *pVtab;
-      VdbeCursor *pCur;
-      int res;
-      int i;
-      Mem **apArg;
-    } cn;
-    struct OP_VColumn_stack_vars {
-      sqlite3_vtab *pVtab;
-      const sqlite3_module *pModule;
-      Mem *pDest;
-      sqlite3_context sContext;
-    } co;
-    struct OP_VNext_stack_vars {
-      sqlite3_vtab *pVtab;
-      const sqlite3_module *pModule;
-      int res;
-      VdbeCursor *pCur;
-    } cp;
-    struct OP_VRename_stack_vars {
-      sqlite3_vtab *pVtab;
-      Mem *pName;
-    } cq;
-    struct OP_VUpdate_stack_vars {
-      sqlite3_vtab *pVtab;
-      sqlite3_module *pModule;
-      int nArg;
-      int i;
-      sqlite_int64 rowid;
-      Mem **apArg;
-      Mem *pX;
-    } cr;
-    struct OP_Trace_stack_vars {
-      char *zTrace;
-      char *z;
-    } cs;
-  } u;
-  /* End automatically generated code
-  ********************************************************************/
+  /*** INSERT STACK UNION HERE ***/
 
   assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
   sqlite3VdbeEnter(p);
@@ -65895,24 +68522,49 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
     goto no_mem;
   }
   assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
+  assert( p->bIsReader || p->readOnly!=0 );
   p->rc = SQLITE_OK;
+  p->iCurrentTime = 0;
   assert( p->explain==0 );
   p->pResultSet = 0;
   db->busyHandler.nBusy = 0;
-  CHECK_FOR_INTERRUPT;
+  if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
   sqlite3VdbeIOTraceSql(p);
 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
-  checkProgress = db->xProgress!=0;
+  if( db->xProgress ){
+    assert( 0 < db->nProgressOps );
+    nProgressLimit = (unsigned)p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
+    if( nProgressLimit==0 ){
+      nProgressLimit = db->nProgressOps;
+    }else{
+      nProgressLimit %= (unsigned)db->nProgressOps;
+    }
+  }
 #endif
 #ifdef SQLITE_DEBUG
   sqlite3BeginBenignMalloc();
-  if( p->pc==0  && (p->db->flags & SQLITE_VdbeListing)!=0 ){
+  if( p->pc==0
+   && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0
+  ){
     int i;
-    printf("VDBE Program Listing:\n");
+    int once = 1;
     sqlite3VdbePrintSql(p);
-    for(i=0; i<p->nOp; i++){
-      sqlite3VdbePrintOp(stdout, i, &aOp[i]);
+    if( p->db->flags & SQLITE_VdbeListing ){
+      printf("VDBE Program Listing:\n");
+      for(i=0; i<p->nOp; i++){
+        sqlite3VdbePrintOp(stdout, i, &aOp[i]);
+      }
+    }
+    if( p->db->flags & SQLITE_VdbeEQP ){
+      for(i=0; i<p->nOp; i++){
+        if( aOp[i].opcode==OP_Explain ){
+          if( once ) printf("VDBE Query Plan:\n");
+          printf("%s\n", aOp[i].p4.z);
+          once = 0;
+        }
+      }
     }
+    if( p->db->flags & SQLITE_VdbeTrace )  printf("VDBE Trace:\n");
   }
   sqlite3EndBenignMalloc();
 #endif
@@ -65920,20 +68572,16 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
     assert( pc>=0 && pc<p->nOp );
     if( db->mallocFailed ) goto no_mem;
 #ifdef VDBE_PROFILE
-    origPc = pc;
     start = sqlite3Hwtime();
 #endif
+    nVmStep++;
     pOp = &aOp[pc];
 
     /* Only allow tracing if SQLITE_DEBUG is defined.
     */
 #ifdef SQLITE_DEBUG
-    if( p->trace ){
-      if( pc==0 ){
-        printf("VDBE Execution Trace:\n");
-        sqlite3VdbePrintSql(p);
-      }
-      sqlite3VdbePrintOp(p->trace, pc, pOp);
+    if( db->flags & SQLITE_VdbeTrace ){
+      sqlite3VdbePrintOp(stdout, pc, pOp);
     }
 #endif
       
@@ -65950,27 +68598,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
     }
 #endif
 
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
-    /* Call the progress callback if it is configured and the required number
-    ** of VDBE ops have been executed (either since this invocation of
-    ** sqlite3VdbeExec() or since last time the progress callback was called).
-    ** If the progress callback returns non-zero, exit the virtual machine with
-    ** a return code SQLITE_ABORT.
-    */
-    if( checkProgress ){
-      if( db->nProgressOps==nProgressOps ){
-        int prc;
-        prc = db->xProgress(db->pProgressArg);
-        if( prc!=0 ){
-          rc = SQLITE_INTERRUPT;
-          goto vdbe_error_halt;
-        }
-        nProgressOps = 0;
-      }
-      nProgressOps++;
-    }
-#endif
-
     /* On any opcode with the "out2-prerelease" tag, free any
     ** external allocations out of mem[p2] and set mem[p2] to be
     ** an undefined integer.  Opcodes will either fill in the integer
@@ -65979,7 +68606,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
     assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
     if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
       assert( pOp->p2>0 );
-      assert( pOp->p2<=p->nMem );
+      assert( pOp->p2<=(p->nMem-p->nCursor) );
       pOut = &aMem[pOp->p2];
       memAboutToChange(p, pOut);
       VdbeMemRelease(pOut);
@@ -65990,30 +68617,33 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
 #ifdef SQLITE_DEBUG
     if( (pOp->opflags & OPFLG_IN1)!=0 ){
       assert( pOp->p1>0 );
-      assert( pOp->p1<=p->nMem );
+      assert( pOp->p1<=(p->nMem-p->nCursor) );
       assert( memIsValid(&aMem[pOp->p1]) );
+      assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) );
       REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
     }
     if( (pOp->opflags & OPFLG_IN2)!=0 ){
       assert( pOp->p2>0 );
-      assert( pOp->p2<=p->nMem );
+      assert( pOp->p2<=(p->nMem-p->nCursor) );
       assert( memIsValid(&aMem[pOp->p2]) );
+      assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) );
       REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
     }
     if( (pOp->opflags & OPFLG_IN3)!=0 ){
       assert( pOp->p3>0 );
-      assert( pOp->p3<=p->nMem );
+      assert( pOp->p3<=(p->nMem-p->nCursor) );
       assert( memIsValid(&aMem[pOp->p3]) );
+      assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) );
       REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
     }
     if( (pOp->opflags & OPFLG_OUT2)!=0 ){
       assert( pOp->p2>0 );
-      assert( pOp->p2<=p->nMem );
+      assert( pOp->p2<=(p->nMem-p->nCursor) );
       memAboutToChange(p, &aMem[pOp->p2]);
     }
     if( (pOp->opflags & OPFLG_OUT3)!=0 ){
       assert( pOp->p3>0 );
-      assert( pOp->p3<=p->nMem );
+      assert( pOp->p3<=(p->nMem-p->nCursor) );
       memAboutToChange(p, &aMem[pOp->p3]);
     }
 #endif
@@ -66061,10 +68691,44 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
 ** The next instruction executed will be 
 ** the one at index P2 from the beginning of
 ** the program.
+**
+** The P1 parameter is not actually used by this opcode.  However, it
+** is sometimes set to 1 instead of 0 as a hint to the command-line shell
+** that this Goto is the bottom of a loop and that the lines from P2 down
+** to the current line should be indented for EXPLAIN output.
 */
 case OP_Goto: {             /* jump */
-  CHECK_FOR_INTERRUPT;
   pc = pOp->p2 - 1;
+
+  /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
+  ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon
+  ** completion.  Check to see if sqlite3_interrupt() has been called
+  ** or if the progress callback needs to be invoked. 
+  **
+  ** This code uses unstructured "goto" statements and does not look clean.
+  ** But that is not due to sloppy coding habits. The code is written this
+  ** way for performance, to avoid having to run the interrupt and progress
+  ** checks on every opcode.  This helps sqlite3_step() to run about 1.5%
+  ** faster according to "valgrind --tool=cachegrind" */
+check_for_interrupt:
+  if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+  /* Call the progress callback if it is configured and the required number
+  ** of VDBE ops have been executed (either since this invocation of
+  ** sqlite3VdbeExec() or since last time the progress callback was called).
+  ** If the progress callback returns non-zero, exit the virtual machine with
+  ** a return code SQLITE_ABORT.
+  */
+  if( db->xProgress!=0 && nVmStep>=nProgressLimit ){
+    assert( db->nProgressOps!=0 );
+    nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
+    if( db->xProgress(db->pProgressArg) ){
+      rc = SQLITE_INTERRUPT;
+      goto vdbe_error_halt;
+    }
+  }
+#endif
+  
   break;
 }
 
@@ -66074,9 +68738,9 @@ case OP_Goto: {             /* jump */
 ** and then jump to address P2.
 */
 case OP_Gosub: {            /* jump */
-  assert( pOp->p1>0 && pOp->p1<=p->nMem );
+  assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
   pIn1 = &aMem[pOp->p1];
-  assert( (pIn1->flags & MEM_Dyn)==0 );
+  assert( VdbeMemDynamic(pIn1)==0 );
   memAboutToChange(p, pIn1);
   pIn1->flags = MEM_Int;
   pIn1->u.i = pc;
@@ -66087,38 +68751,93 @@ case OP_Gosub: {            /* jump */
 
 /* Opcode:  Return P1 * * * *
 **
-** Jump to the next instruction after the address in register P1.
+** Jump to the next instruction after the address in register P1.  After
+** the jump, register P1 becomes undefined.
 */
 case OP_Return: {           /* in1 */
   pIn1 = &aMem[pOp->p1];
-  assert( pIn1->flags & MEM_Int );
+  assert( pIn1->flags==MEM_Int );
   pc = (int)pIn1->u.i;
+  pIn1->flags = MEM_Undefined;
+  break;
+}
+
+/* Opcode: InitCoroutine P1 P2 P3 * *
+**
+** Set up register P1 so that it will Yield to the coroutine
+** located at address P3.
+**
+** If P2!=0 then the coroutine implementation immediately follows
+** this opcode.  So jump over the coroutine implementation to
+** address P2.
+**
+** See also: EndCoroutine
+*/
+case OP_InitCoroutine: {     /* jump */
+  assert( pOp->p1>0 &&  pOp->p1<=(p->nMem-p->nCursor) );
+  assert( pOp->p2>=0 && pOp->p2<p->nOp );
+  assert( pOp->p3>=0 && pOp->p3<p->nOp );
+  pOut = &aMem[pOp->p1];
+  assert( !VdbeMemDynamic(pOut) );
+  pOut->u.i = pOp->p3 - 1;
+  pOut->flags = MEM_Int;
+  if( pOp->p2 ) pc = pOp->p2 - 1;
+  break;
+}
+
+/* Opcode:  EndCoroutine P1 * * * *
+**
+** The instruction at the address in register P1 is a Yield.
+** Jump to the P2 parameter of that Yield.
+** After the jump, register P1 becomes undefined.
+**
+** See also: InitCoroutine
+*/
+case OP_EndCoroutine: {           /* in1 */
+  VdbeOp *pCaller;
+  pIn1 = &aMem[pOp->p1];
+  assert( pIn1->flags==MEM_Int );
+  assert( pIn1->u.i>=0 && pIn1->u.i<p->nOp );
+  pCaller = &aOp[pIn1->u.i];
+  assert( pCaller->opcode==OP_Yield );
+  assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
+  pc = pCaller->p2 - 1;
+  pIn1->flags = MEM_Undefined;
   break;
 }
 
-/* Opcode:  Yield P1 * * * *
+/* Opcode:  Yield P1 P2 * * *
+**
+** Swap the program counter with the value in register P1.  This
+** has the effect of yielding to a coroutine.
 **
-** Swap the program counter with the value in register P1.
+** If the coroutine that is launched by this instruction ends with
+** Yield or Return then continue to the next instruction.  But if
+** the coroutine launched by this instruction ends with
+** EndCoroutine, then jump to P2 rather than continuing with the
+** next instruction.
+**
+** See also: InitCoroutine
 */
-case OP_Yield: {            /* in1 */
-#if 0  /* local variables moved into u.aa */
+case OP_Yield: {            /* in1, jump */
   int pcDest;
-#endif /* local variables moved into u.aa */
   pIn1 = &aMem[pOp->p1];
-  assert( (pIn1->flags & MEM_Dyn)==0 );
+  assert( VdbeMemDynamic(pIn1)==0 );
   pIn1->flags = MEM_Int;
-  u.aa.pcDest = (int)pIn1->u.i;
+  pcDest = (int)pIn1->u.i;
   pIn1->u.i = pc;
   REGISTER_TRACE(pOp->p1, pIn1);
-  pc = u.aa.pcDest;
+  pc = pcDest;
   break;
 }
 
-/* Opcode:  HaltIfNull  P1 P2 P3 P4 *
+/* Opcode:  HaltIfNull  P1 P2 P3 P4 P5
+** Synopsis:  if r[P3]=null halt
 **
 ** Check the value in register P3.  If it is NULL then Halt using
 ** parameter P1, P2, and P4 as if this were a Halt instruction.  If the
 ** value in register P3 is not NULL, then this routine is a no-op.
+** The P5 parameter should be 1.
 */
 case OP_HaltIfNull: {      /* in3 */
   pIn3 = &aMem[pOp->p3];
@@ -66126,7 +68845,7 @@ case OP_HaltIfNull: {      /* in3 */
   /* Fall through into OP_Halt */
 }
 
-/* Opcode:  Halt P1 P2 * P4 *
+/* Opcode:  Halt P1 P2 * P4 P5
 **
 ** Exit immediately.  All open cursors, etc are closed
 ** automatically.
@@ -66141,11 +68860,25 @@ case OP_HaltIfNull: {      /* in3 */
 **
 ** If P4 is not null then it is an error message string.
 **
+** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
+**
+**    0:  (no change)
+**    1:  NOT NULL contraint failed: P4
+**    2:  UNIQUE constraint failed: P4
+**    3:  CHECK constraint failed: P4
+**    4:  FOREIGN KEY constraint failed: P4
+**
+** If P5 is not zero and P4 is NULL, then everything after the ":" is
+** omitted.
+**
 ** There is an implied "Halt 0 0 0" instruction inserted at the very end of
 ** every program.  So a jump past the last instruction of the program
 ** is the same as executing Halt.
 */
 case OP_Halt: {
+  const char *zType;
+  const char *zLogFmt;
+
   if( pOp->p1==SQLITE_OK && p->pFrame ){
     /* Halt the sub-program. Return control to the parent frame. */
     VdbeFrame *pFrame = p->pFrame;
@@ -66166,18 +68899,33 @@ case OP_Halt: {
     aMem = p->aMem;
     break;
   }
-
   p->rc = pOp->p1;
   p->errorAction = (u8)pOp->p2;
   p->pc = pc;
-  if( pOp->p4.z ){
-    assert( p->rc!=SQLITE_OK );
-    sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
-    testcase( sqlite3GlobalConfig.xLog!=0 );
-    sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z);
-  }else if( p->rc ){
-    testcase( sqlite3GlobalConfig.xLog!=0 );
-    sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql);
+  if( p->rc ){
+    if( pOp->p5 ){
+      static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
+                                             "FOREIGN KEY" };
+      assert( pOp->p5>=1 && pOp->p5<=4 );
+      testcase( pOp->p5==1 );
+      testcase( pOp->p5==2 );
+      testcase( pOp->p5==3 );
+      testcase( pOp->p5==4 );
+      zType = azType[pOp->p5-1];
+    }else{
+      zType = 0;
+    }
+    assert( zType!=0 || pOp->p4.z!=0 );
+    zLogFmt = "abort at %d in [%s]: %s";
+    if( zType && pOp->p4.z ){
+      sqlite3SetString(&p->zErrMsg, db, "%s constraint failed: %s", 
+                       zType, pOp->p4.z);
+    }else if( pOp->p4.z ){
+      sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
+    }else{
+      sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", zType);
+    }
+    sqlite3_log(pOp->p1, zLogFmt, pc, p->zSql, p->zErrMsg);
   }
   rc = sqlite3VdbeHalt(p);
   assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@@ -66185,13 +68933,14 @@ case OP_Halt: {
     p->rc = rc = SQLITE_BUSY;
   }else{
     assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
-    assert( rc==SQLITE_OK || db->nDeferredCons>0 );
+    assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
     rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
   }
   goto vdbe_return;
 }
 
 /* Opcode: Integer P1 P2 * * *
+** Synopsis: r[P2]=P1
 **
 ** The 32-bit integer value P1 is written into register P2.
 */
@@ -66201,6 +68950,7 @@ case OP_Integer: {         /* out2-prerelease */
 }
 
 /* Opcode: Int64 * P2 * P4 *
+** Synopsis: r[P2]=P4
 **
 ** P4 is a pointer to a 64-bit integer value.
 ** Write that value into register P2.
@@ -66213,6 +68963,7 @@ case OP_Int64: {           /* out2-prerelease */
 
 #ifndef SQLITE_OMIT_FLOATING_POINT
 /* Opcode: Real * P2 * P4 *
+** Synopsis: r[P2]=P4
 **
 ** P4 is a pointer to a 64-bit floating point value.
 ** Write that value into register P2.
@@ -66226,9 +68977,12 @@ case OP_Real: {            /* same as TK_FLOAT, out2-prerelease */
 #endif
 
 /* Opcode: String8 * P2 * P4 *
+** Synopsis: r[P2]='P4'
 **
 ** P4 points to a nul terminated UTF-8 string. This opcode is transformed 
-** into an OP_String before it is executed for the first time.
+** into a String before it is executed for the first time.  During
+** this transformation, the length of string P4 is computed and stored
+** as the P1 parameter.
 */
 case OP_String8: {         /* same as TK_STRING, out2-prerelease */
   assert( pOp->p4.z!=0 );
@@ -66241,10 +68995,9 @@ case OP_String8: {         /* same as TK_STRING, out2-prerelease */
     if( rc==SQLITE_TOOBIG ) goto too_big;
     if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
     assert( pOut->zMalloc==pOut->z );
-    assert( pOut->flags & MEM_Dyn );
+    assert( VdbeMemDynamic(pOut)==0 );
     pOut->zMalloc = 0;
     pOut->flags |= MEM_Static;
-    pOut->flags &= ~MEM_Dyn;
     if( pOp->p4type==P4_DYNAMIC ){
       sqlite3DbFree(db, pOp->p4.z);
     }
@@ -66260,6 +69013,7 @@ case OP_String8: {         /* same as TK_STRING, out2-prerelease */
 }
   
 /* Opcode: String P1 P2 * P4 *
+** Synopsis: r[P2]='P4' (len=P1)
 **
 ** The string value P4 of length P1 (bytes) is stored in register P2.
 */
@@ -66274,6 +69028,7 @@ case OP_String: {          /* out2-prerelease */
 }
 
 /* Opcode: Null P1 P2 P3 * *
+** Synopsis:  r[P2..P3]=NULL
 **
 ** Write a NULL into registers P2.  If P3 greater than P2, then also write
 ** NULL into register P3 and every register in between P2 and P3.  If P3
@@ -66285,25 +69040,38 @@ case OP_String: {          /* out2-prerelease */
 ** OP_Ne or OP_Eq.
 */
 case OP_Null: {           /* out2-prerelease */
-#if 0  /* local variables moved into u.ab */
   int cnt;
   u16 nullFlag;
-#endif /* local variables moved into u.ab */
-  u.ab.cnt = pOp->p3-pOp->p2;
-  assert( pOp->p3<=p->nMem );
-  pOut->flags = u.ab.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
-  while( u.ab.cnt>0 ){
+  cnt = pOp->p3-pOp->p2;
+  assert( pOp->p3<=(p->nMem-p->nCursor) );
+  pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
+  while( cnt>0 ){
     pOut++;
     memAboutToChange(p, pOut);
     VdbeMemRelease(pOut);
-    pOut->flags = u.ab.nullFlag;
-    u.ab.cnt--;
+    pOut->flags = nullFlag;
+    cnt--;
   }
   break;
 }
 
+/* Opcode: SoftNull P1 * * * *
+** Synopsis:  r[P1]=NULL
+**
+** Set register P1 to have the value NULL as seen by the OP_MakeRecord
+** instruction, but do not free any string or blob memory associated with
+** the register, so that if the value was a string or blob that was
+** previously copied using OP_SCopy, the copies will continue to be valid.
+*/
+case OP_SoftNull: {
+  assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
+  pOut = &aMem[pOp->p1];
+  pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined;
+  break;
+}
 
-/* Opcode: Blob P1 P2 * P4
+/* Opcode: Blob P1 P2 * P4 *
+** Synopsis: r[P2]=P4 (len=P1)
 **
 ** P4 points to a blob of data P1 bytes long.  Store this
 ** blob in register P2.
@@ -66317,73 +69085,75 @@ case OP_Blob: {                /* out2-prerelease */
 }
 
 /* Opcode: Variable P1 P2 * P4 *
+** Synopsis: r[P2]=parameter(P1,P4)
 **
 ** Transfer the values of bound parameter P1 into register P2
 **
-** If the parameter is named, then its name appears in P4 and P3==1.
+** If the parameter is named, then its name appears in P4.
 ** The P4 value is used by sqlite3_bind_parameter_name().
 */
 case OP_Variable: {            /* out2-prerelease */
-#if 0  /* local variables moved into u.ac */
   Mem *pVar;       /* Value being transferred */
-#endif /* local variables moved into u.ac */
 
   assert( pOp->p1>0 && pOp->p1<=p->nVar );
   assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
-  u.ac.pVar = &p->aVar[pOp->p1 - 1];
-  if( sqlite3VdbeMemTooBig(u.ac.pVar) ){
+  pVar = &p->aVar[pOp->p1 - 1];
+  if( sqlite3VdbeMemTooBig(pVar) ){
     goto too_big;
   }
-  sqlite3VdbeMemShallowCopy(pOut, u.ac.pVar, MEM_Static);
+  sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
   UPDATE_MAX_BLOBSIZE(pOut);
   break;
 }
 
 /* Opcode: Move P1 P2 P3 * *
+** Synopsis:  r[P2 at P3]=r[P1 at P3]
 **
-** Move the values in register P1..P1+P3 over into
-** registers P2..P2+P3.  Registers P1..P1+P3 are
+** Move the P3 values in register P1..P1+P3-1 over into
+** registers P2..P2+P3-1.  Registers P1..P1+P3-1 are
 ** left holding a NULL.  It is an error for register ranges
-** P1..P1+P3 and P2..P2+P3 to overlap.
+** P1..P1+P3-1 and P2..P2+P3-1 to overlap.  It is an error
+** for P3 to be less than 1.
 */
 case OP_Move: {
-#if 0  /* local variables moved into u.ad */
   char *zMalloc;   /* Holding variable for allocated memory */
   int n;           /* Number of registers left to copy */
   int p1;          /* Register to copy from */
   int p2;          /* Register to copy to */
-#endif /* local variables moved into u.ad */
-
-  u.ad.n = pOp->p3 + 1;
-  u.ad.p1 = pOp->p1;
-  u.ad.p2 = pOp->p2;
-  assert( u.ad.n>0 && u.ad.p1>0 && u.ad.p2>0 );
-  assert( u.ad.p1+u.ad.n<=u.ad.p2 || u.ad.p2+u.ad.n<=u.ad.p1 );
-
-  pIn1 = &aMem[u.ad.p1];
-  pOut = &aMem[u.ad.p2];
-  while( u.ad.n-- ){
-    assert( pOut<=&aMem[p->nMem] );
-    assert( pIn1<=&aMem[p->nMem] );
+
+  n = pOp->p3;
+  p1 = pOp->p1;
+  p2 = pOp->p2;
+  assert( n>0 && p1>0 && p2>0 );
+  assert( p1+n<=p2 || p2+n<=p1 );
+
+  pIn1 = &aMem[p1];
+  pOut = &aMem[p2];
+  do{
+    assert( pOut<=&aMem[(p->nMem-p->nCursor)] );
+    assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
     assert( memIsValid(pIn1) );
     memAboutToChange(p, pOut);
-    u.ad.zMalloc = pOut->zMalloc;
-    pOut->zMalloc = 0;
-    sqlite3VdbeMemMove(pOut, pIn1);
+    VdbeMemRelease(pOut);
+    zMalloc = pOut->zMalloc;
+    memcpy(pOut, pIn1, sizeof(Mem));
 #ifdef SQLITE_DEBUG
-    if( pOut->pScopyFrom>=&aMem[u.ad.p1] && pOut->pScopyFrom<&aMem[u.ad.p1+pOp->p3] ){
-      pOut->pScopyFrom += u.ad.p1 - pOp->p2;
+    if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
+      pOut->pScopyFrom += p1 - pOp->p2;
     }
 #endif
-    pIn1->zMalloc = u.ad.zMalloc;
-    REGISTER_TRACE(u.ad.p2++, pOut);
+    pIn1->flags = MEM_Undefined;
+    pIn1->xDel = 0;
+    pIn1->zMalloc = zMalloc;
+    REGISTER_TRACE(p2++, pOut);
     pIn1++;
     pOut++;
-  }
+  }while( --n );
   break;
 }
 
 /* Opcode: Copy P1 P2 P3 * *
+** Synopsis: r[P2 at P3+1]=r[P1 at P3+1]
 **
 ** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
 **
@@ -66391,11 +69161,9 @@ case OP_Move: {
 ** is made of any string or blob constant.  See also OP_SCopy.
 */
 case OP_Copy: {
-#if 0  /* local variables moved into u.ae */
   int n;
-#endif /* local variables moved into u.ae */
 
-  u.ae.n = pOp->p3;
+  n = pOp->p3;
   pIn1 = &aMem[pOp->p1];
   pOut = &aMem[pOp->p2];
   assert( pOut!=pIn1 );
@@ -66405,8 +69173,8 @@ case OP_Copy: {
 #ifdef SQLITE_DEBUG
     pOut->pScopyFrom = 0;
 #endif
-    REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut);
-    if( (u.ae.n--)==0 ) break;
+    REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut);
+    if( (n--)==0 ) break;
     pOut++;
     pIn1++;
   }
@@ -66414,6 +69182,7 @@ case OP_Copy: {
 }
 
 /* Opcode: SCopy P1 P2 * * *
+** Synopsis: r[P2]=r[P1]
 **
 ** Make a shallow copy of register P1 into register P2.
 **
@@ -66425,7 +69194,7 @@ case OP_Copy: {
 ** during the lifetime of the copy.  Use OP_Copy to make a complete
 ** copy.
 */
-case OP_SCopy: {            /* in1, out2 */
+case OP_SCopy: {            /* out2 */
   pIn1 = &aMem[pOp->p1];
   pOut = &aMem[pOp->p2];
   assert( pOut!=pIn1 );
@@ -66433,26 +69202,36 @@ case OP_SCopy: {            /* in1, out2 */
 #ifdef SQLITE_DEBUG
   if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1;
 #endif
-  REGISTER_TRACE(pOp->p2, pOut);
   break;
 }
 
 /* Opcode: ResultRow P1 P2 * * *
+** Synopsis:  output=r[P1 at P2]
 **
 ** The registers P1 through P1+P2-1 contain a single row of
 ** results. This opcode causes the sqlite3_step() call to terminate
 ** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
-** structure to provide access to the top P1 values as the result
-** row.
+** structure to provide access to the r(P1)..r(P1+P2-1) values as
+** the result row.
 */
 case OP_ResultRow: {
-#if 0  /* local variables moved into u.af */
   Mem *pMem;
   int i;
-#endif /* local variables moved into u.af */
   assert( p->nResColumn==pOp->p2 );
   assert( pOp->p1>0 );
-  assert( pOp->p1+pOp->p2<=p->nMem+1 );
+  assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 );
+
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+  /* Run the progress counter just before returning.
+  */
+  if( db->xProgress!=0
+   && nVmStep>=nProgressLimit
+   && db->xProgress(db->pProgressArg)!=0
+  ){
+    rc = SQLITE_INTERRUPT;
+    goto vdbe_error_halt;
+  }
+#endif
 
   /* If this statement has violated immediate foreign key constraints, do
   ** not return the number of rows modified. And do not RELEASE the statement
@@ -66463,8 +69242,8 @@ case OP_ResultRow: {
     break;
   }
 
-  /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then
-  ** DML statements invoke this opcode to return the number of rows
+  /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then 
+  ** DML statements invoke this opcode to return the number of rows 
   ** modified to the user. This is the only way that a VM that
   ** opens a statement transaction may invoke this opcode.
   **
@@ -66491,15 +69270,14 @@ case OP_ResultRow: {
   ** and have an assigned type.  The results are de-ephemeralized as
   ** a side effect.
   */
-  u.af.pMem = p->pResultSet = &aMem[pOp->p1];
-  for(u.af.i=0; u.af.i<pOp->p2; u.af.i++){
-    assert( memIsValid(&u.af.pMem[u.af.i]) );
-    Deephemeralize(&u.af.pMem[u.af.i]);
-    assert( (u.af.pMem[u.af.i].flags & MEM_Ephem)==0
-            || (u.af.pMem[u.af.i].flags & (MEM_Str|MEM_Blob))==0 );
-    sqlite3VdbeMemNulTerminate(&u.af.pMem[u.af.i]);
-    sqlite3VdbeMemStoreType(&u.af.pMem[u.af.i]);
-    REGISTER_TRACE(pOp->p1+u.af.i, &u.af.pMem[u.af.i]);
+  pMem = p->pResultSet = &aMem[pOp->p1];
+  for(i=0; i<pOp->p2; i++){
+    assert( memIsValid(&pMem[i]) );
+    Deephemeralize(&pMem[i]);
+    assert( (pMem[i].flags & MEM_Ephem)==0
+            || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
+    sqlite3VdbeMemNulTerminate(&pMem[i]);
+    REGISTER_TRACE(pOp->p1+i, &pMem[i]);
   }
   if( db->mallocFailed ) goto no_mem;
 
@@ -66511,6 +69289,7 @@ case OP_ResultRow: {
 }
 
 /* Opcode: Concat P1 P2 P3 * *
+** Synopsis: r[P3]=r[P2]+r[P1]
 **
 ** Add the text in register P1 onto the end of the text in
 ** register P2 and store the result in register P3.
@@ -66523,9 +69302,7 @@ case OP_ResultRow: {
 ** to avoid a memcpy().
 */
 case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
-#if 0  /* local variables moved into u.ag */
   i64 nByte;
-#endif /* local variables moved into u.ag */
 
   pIn1 = &aMem[pOp->p1];
   pIn2 = &aMem[pOp->p2];
@@ -66538,34 +69315,36 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
   if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
   Stringify(pIn1, encoding);
   Stringify(pIn2, encoding);
-  u.ag.nByte = pIn1->n + pIn2->n;
-  if( u.ag.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+  nByte = pIn1->n + pIn2->n;
+  if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
     goto too_big;
   }
-  MemSetTypeFlag(pOut, MEM_Str);
-  if( sqlite3VdbeMemGrow(pOut, (int)u.ag.nByte+2, pOut==pIn2) ){
+  if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
     goto no_mem;
   }
+  MemSetTypeFlag(pOut, MEM_Str);
   if( pOut!=pIn2 ){
     memcpy(pOut->z, pIn2->z, pIn2->n);
   }
   memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
-  pOut->z[u.ag.nByte] = 0;
-  pOut->z[u.ag.nByte+1] = 0;
+  pOut->z[nByte]=0;
+  pOut->z[nByte+1] = 0;
   pOut->flags |= MEM_Term;
-  pOut->n = (int)u.ag.nByte;
+  pOut->n = (int)nByte;
   pOut->enc = encoding;
   UPDATE_MAX_BLOBSIZE(pOut);
   break;
 }
 
 /* Opcode: Add P1 P2 P3 * *
+** Synopsis:  r[P3]=r[P1]+r[P2]
 **
 ** Add the value in register P1 to the value in register P2
 ** and store the result in register P3.
 ** If either input is NULL, the result is NULL.
 */
 /* Opcode: Multiply P1 P2 P3 * *
+** Synopsis:  r[P3]=r[P1]*r[P2]
 **
 **
 ** Multiply the value in register P1 by the value in register P2
@@ -66573,12 +69352,14 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
 ** If either input is NULL, the result is NULL.
 */
 /* Opcode: Subtract P1 P2 P3 * *
+** Synopsis:  r[P3]=r[P2]-r[P1]
 **
 ** Subtract the value in register P1 from the value in register P2
 ** and store the result in register P3.
 ** If either input is NULL, the result is NULL.
 */
 /* Opcode: Divide P1 P2 P3 * *
+** Synopsis:  r[P3]=r[P2]/r[P1]
 **
 ** Divide the value in register P1 by the value in register P2
 ** and store the result in register P3 (P3=P2/P1). If the value in 
@@ -66586,10 +69367,11 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
 ** NULL, the result is NULL.
 */
 /* Opcode: Remainder P1 P2 P3 * *
+** Synopsis:  r[P3]=r[P2]%r[P1]
 **
-** Compute the remainder after integer division of the value in
-** register P1 by the value in register P2 and store the result in P3. 
-** If the value in register P2 is zero the result is NULL.
+** Compute the remainder after integer register P2 is divided by 
+** register P1 and store the result in register P3. 
+** If the value in register P1 is zero the result is NULL.
 ** If either operand is NULL, the result is NULL.
 */
 case OP_Add:                   /* same as TK_PLUS, in1, in2, out3 */
@@ -66597,79 +69379,79 @@ case OP_Subtract:              /* same as TK_MINUS, in1, in2, out3 */
 case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
 case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
 case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
-#if 0  /* local variables moved into u.ah */
   char bIntint;   /* Started out as two integer operands */
-  int flags;      /* Combined MEM_* flags from both inputs */
+  u16 flags;      /* Combined MEM_* flags from both inputs */
+  u16 type1;      /* Numeric type of left operand */
+  u16 type2;      /* Numeric type of right operand */
   i64 iA;         /* Integer value of left operand */
   i64 iB;         /* Integer value of right operand */
   double rA;      /* Real value of left operand */
   double rB;      /* Real value of right operand */
-#endif /* local variables moved into u.ah */
 
   pIn1 = &aMem[pOp->p1];
-  applyNumericAffinity(pIn1);
+  type1 = numericType(pIn1);
   pIn2 = &aMem[pOp->p2];
-  applyNumericAffinity(pIn2);
+  type2 = numericType(pIn2);
   pOut = &aMem[pOp->p3];
-  u.ah.flags = pIn1->flags | pIn2->flags;
-  if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
-  if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
-    u.ah.iA = pIn1->u.i;
-    u.ah.iB = pIn2->u.i;
-    u.ah.bIntint = 1;
+  flags = pIn1->flags | pIn2->flags;
+  if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
+  if( (type1 & type2 & MEM_Int)!=0 ){
+    iA = pIn1->u.i;
+    iB = pIn2->u.i;
+    bIntint = 1;
     switch( pOp->opcode ){
-      case OP_Add:       if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
-      case OP_Subtract:  if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
-      case OP_Multiply:  if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math;  break;
+      case OP_Add:       if( sqlite3AddInt64(&iB,iA) ) goto fp_math;  break;
+      case OP_Subtract:  if( sqlite3SubInt64(&iB,iA) ) goto fp_math;  break;
+      case OP_Multiply:  if( sqlite3MulInt64(&iB,iA) ) goto fp_math;  break;
       case OP_Divide: {
-        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
-        if( u.ah.iA==-1 && u.ah.iB==SMALLEST_INT64 ) goto fp_math;
-        u.ah.iB /= u.ah.iA;
+        if( iA==0 ) goto arithmetic_result_is_null;
+        if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math;
+        iB /= iA;
         break;
       }
       default: {
-        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
-        if( u.ah.iA==-1 ) u.ah.iA = 1;
-        u.ah.iB %= u.ah.iA;
+        if( iA==0 ) goto arithmetic_result_is_null;
+        if( iA==-1 ) iA = 1;
+        iB %= iA;
         break;
       }
     }
-    pOut->u.i = u.ah.iB;
+    pOut->u.i = iB;
     MemSetTypeFlag(pOut, MEM_Int);
   }else{
-    u.ah.bIntint = 0;
+    bIntint = 0;
 fp_math:
-    u.ah.rA = sqlite3VdbeRealValue(pIn1);
-    u.ah.rB = sqlite3VdbeRealValue(pIn2);
+    rA = sqlite3VdbeRealValue(pIn1);
+    rB = sqlite3VdbeRealValue(pIn2);
     switch( pOp->opcode ){
-      case OP_Add:         u.ah.rB += u.ah.rA;       break;
-      case OP_Subtract:    u.ah.rB -= u.ah.rA;       break;
-      case OP_Multiply:    u.ah.rB *= u.ah.rA;       break;
+      case OP_Add:         rB += rA;       break;
+      case OP_Subtract:    rB -= rA;       break;
+      case OP_Multiply:    rB *= rA;       break;
       case OP_Divide: {
         /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
-        if( u.ah.rA==(double)0 ) goto arithmetic_result_is_null;
-        u.ah.rB /= u.ah.rA;
+        if( rA==(double)0 ) goto arithmetic_result_is_null;
+        rB /= rA;
         break;
       }
       default: {
-        u.ah.iA = (i64)u.ah.rA;
-        u.ah.iB = (i64)u.ah.rB;
-        if( u.ah.iA==0 ) goto arithmetic_result_is_null;
-        if( u.ah.iA==-1 ) u.ah.iA = 1;
-        u.ah.rB = (double)(u.ah.iB % u.ah.iA);
+        iA = (i64)rA;
+        iB = (i64)rB;
+        if( iA==0 ) goto arithmetic_result_is_null;
+        if( iA==-1 ) iA = 1;
+        rB = (double)(iB % iA);
         break;
       }
     }
 #ifdef SQLITE_OMIT_FLOATING_POINT
-    pOut->u.i = u.ah.rB;
+    pOut->u.i = rB;
     MemSetTypeFlag(pOut, MEM_Int);
 #else
-    if( sqlite3IsNaN(u.ah.rB) ){
+    if( sqlite3IsNaN(rB) ){
       goto arithmetic_result_is_null;
     }
-    pOut->r = u.ah.rB;
+    pOut->r = rB;
     MemSetTypeFlag(pOut, MEM_Real);
-    if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){
+    if( ((type1|type2)&MEM_Real)==0 && !bIntint ){
       sqlite3VdbeIntegerAffinity(pOut);
     }
 #endif
@@ -66705,6 +69487,7 @@ case OP_CollSeq: {
 }
 
 /* Opcode: Function P1 P2 P3 P4 P5
+** Synopsis: r[P3]=func(r[P2 at P5])
 **
 ** Invoke a user function (P4 is a pointer to a Function structure that
 ** defines the function) with P5 arguments taken from register P2 and
@@ -66721,92 +69504,78 @@ case OP_CollSeq: {
 ** See also: AggStep and AggFinal
 */
 case OP_Function: {
-#if 0  /* local variables moved into u.ai */
   int i;
   Mem *pArg;
   sqlite3_context ctx;
   sqlite3_value **apVal;
   int n;
-#endif /* local variables moved into u.ai */
 
-  u.ai.n = pOp->p5;
-  u.ai.apVal = p->apArg;
-  assert( u.ai.apVal || u.ai.n==0 );
-  assert( pOp->p3>0 && pOp->p3<=p->nMem );
+  n = pOp->p5;
+  apVal = p->apArg;
+  assert( apVal || n==0 );
+  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
   pOut = &aMem[pOp->p3];
   memAboutToChange(p, pOut);
 
-  assert( u.ai.n==0 || (pOp->p2>0 && pOp->p2+u.ai.n<=p->nMem+1) );
-  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ai.n );
-  u.ai.pArg = &aMem[pOp->p2];
-  for(u.ai.i=0; u.ai.i<u.ai.n; u.ai.i++, u.ai.pArg++){
-    assert( memIsValid(u.ai.pArg) );
-    u.ai.apVal[u.ai.i] = u.ai.pArg;
-    Deephemeralize(u.ai.pArg);
-    sqlite3VdbeMemStoreType(u.ai.pArg);
-    REGISTER_TRACE(pOp->p2+u.ai.i, u.ai.pArg);
-  }
-
-  assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
-  if( pOp->p4type==P4_FUNCDEF ){
-    u.ai.ctx.pFunc = pOp->p4.pFunc;
-    u.ai.ctx.pVdbeFunc = 0;
-  }else{
-    u.ai.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
-    u.ai.ctx.pFunc = u.ai.ctx.pVdbeFunc->pFunc;
+  assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
+  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
+  pArg = &aMem[pOp->p2];
+  for(i=0; i<n; i++, pArg++){
+    assert( memIsValid(pArg) );
+    apVal[i] = pArg;
+    Deephemeralize(pArg);
+    REGISTER_TRACE(pOp->p2+i, pArg);
   }
 
-  u.ai.ctx.s.flags = MEM_Null;
-  u.ai.ctx.s.db = db;
-  u.ai.ctx.s.xDel = 0;
-  u.ai.ctx.s.zMalloc = 0;
+  assert( pOp->p4type==P4_FUNCDEF );
+  ctx.pFunc = pOp->p4.pFunc;
+  ctx.iOp = pc;
+  ctx.pVdbe = p;
 
   /* The output cell may already have a buffer allocated. Move
-  ** the pointer to u.ai.ctx.s so in case the user-function can use
+  ** the pointer to ctx.s so in case the user-function can use
   ** the already allocated buffer instead of allocating a new one.
   */
-  sqlite3VdbeMemMove(&u.ai.ctx.s, pOut);
-  MemSetTypeFlag(&u.ai.ctx.s, MEM_Null);
+  memcpy(&ctx.s, pOut, sizeof(Mem));
+  pOut->flags = MEM_Null;
+  pOut->xDel = 0;
+  pOut->zMalloc = 0;
+  MemSetTypeFlag(&ctx.s, MEM_Null);
 
-  u.ai.ctx.isError = 0;
-  if( u.ai.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+  ctx.fErrorOrAux = 0;
+  if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
     assert( pOp>aOp );
     assert( pOp[-1].p4type==P4_COLLSEQ );
     assert( pOp[-1].opcode==OP_CollSeq );
-    u.ai.ctx.pColl = pOp[-1].p4.pColl;
+    ctx.pColl = pOp[-1].p4.pColl;
   }
   db->lastRowid = lastRowid;
-  (*u.ai.ctx.pFunc->xFunc)(&u.ai.ctx, u.ai.n, u.ai.apVal); /* IMP: R-24505-23230 */
+  (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
   lastRowid = db->lastRowid;
 
-  /* If any auxiliary data functions have been called by this user function,
-  ** immediately call the destructor for any non-static values.
-  */
-  if( u.ai.ctx.pVdbeFunc ){
-    sqlite3VdbeDeleteAuxData(u.ai.ctx.pVdbeFunc, pOp->p1);
-    pOp->p4.pVdbeFunc = u.ai.ctx.pVdbeFunc;
-    pOp->p4type = P4_VDBEFUNC;
-  }
-
   if( db->mallocFailed ){
     /* Even though a malloc() has failed, the implementation of the
     ** user function may have called an sqlite3_result_XXX() function
     ** to return a value. The following call releases any resources
     ** associated with such a value.
     */
-    sqlite3VdbeMemRelease(&u.ai.ctx.s);
+    sqlite3VdbeMemRelease(&ctx.s);
     goto no_mem;
   }
 
   /* If the function returned an error, throw an exception */
-  if( u.ai.ctx.isError ){
-    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s));
-    rc = u.ai.ctx.isError;
+  if( ctx.fErrorOrAux ){
+    if( ctx.isError ){
+      sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s));
+      rc = ctx.isError;
+    }
+    sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
   }
 
   /* Copy the result of the function into register P3 */
-  sqlite3VdbeChangeEncoding(&u.ai.ctx.s, encoding);
-  sqlite3VdbeMemMove(pOut, &u.ai.ctx.s);
+  sqlite3VdbeChangeEncoding(&ctx.s, encoding);
+  assert( pOut->flags==MEM_Null );
+  memcpy(pOut, &ctx.s, sizeof(Mem));
   if( sqlite3VdbeMemTooBig(pOut) ){
     goto too_big;
   }
@@ -66825,18 +69594,21 @@ case OP_Function: {
 }
 
 /* Opcode: BitAnd P1 P2 P3 * *
+** Synopsis:  r[P3]=r[P1]&r[P2]
 **
 ** Take the bit-wise AND of the values in register P1 and P2 and
 ** store the result in register P3.
 ** If either input is NULL, the result is NULL.
 */
 /* Opcode: BitOr P1 P2 P3 * *
+** Synopsis:  r[P3]=r[P1]|r[P2]
 **
 ** Take the bit-wise OR of the values in register P1 and P2 and
 ** store the result in register P3.
 ** If either input is NULL, the result is NULL.
 */
 /* Opcode: ShiftLeft P1 P2 P3 * *
+** Synopsis:  r[P3]=r[P2]<<r[P1]
 **
 ** Shift the integer value in register P2 to the left by the
 ** number of bits specified by the integer in register P1.
@@ -66844,6 +69616,7 @@ case OP_Function: {
 ** If either input is NULL, the result is NULL.
 */
 /* Opcode: ShiftRight P1 P2 P3 * *
+** Synopsis:  r[P3]=r[P2]>>r[P1]
 **
 ** Shift the integer value in register P2 to the right by the
 ** number of bits specified by the integer in register P1.
@@ -66854,12 +69627,10 @@ case OP_BitAnd:                 /* same as TK_BITAND, in1, in2, out3 */
 case OP_BitOr:                  /* same as TK_BITOR, in1, in2, out3 */
 case OP_ShiftLeft:              /* same as TK_LSHIFT, in1, in2, out3 */
 case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
-#if 0  /* local variables moved into u.aj */
   i64 iA;
   u64 uA;
   i64 iB;
   u8 op;
-#endif /* local variables moved into u.aj */
 
   pIn1 = &aMem[pOp->p1];
   pIn2 = &aMem[pOp->p2];
@@ -66868,43 +69639,44 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
     sqlite3VdbeMemSetNull(pOut);
     break;
   }
-  u.aj.iA = sqlite3VdbeIntValue(pIn2);
-  u.aj.iB = sqlite3VdbeIntValue(pIn1);
-  u.aj.op = pOp->opcode;
-  if( u.aj.op==OP_BitAnd ){
-    u.aj.iA &= u.aj.iB;
-  }else if( u.aj.op==OP_BitOr ){
-    u.aj.iA |= u.aj.iB;
-  }else if( u.aj.iB!=0 ){
-    assert( u.aj.op==OP_ShiftRight || u.aj.op==OP_ShiftLeft );
+  iA = sqlite3VdbeIntValue(pIn2);
+  iB = sqlite3VdbeIntValue(pIn1);
+  op = pOp->opcode;
+  if( op==OP_BitAnd ){
+    iA &= iB;
+  }else if( op==OP_BitOr ){
+    iA |= iB;
+  }else if( iB!=0 ){
+    assert( op==OP_ShiftRight || op==OP_ShiftLeft );
 
     /* If shifting by a negative amount, shift in the other direction */
-    if( u.aj.iB<0 ){
+    if( iB<0 ){
       assert( OP_ShiftRight==OP_ShiftLeft+1 );
-      u.aj.op = 2*OP_ShiftLeft + 1 - u.aj.op;
-      u.aj.iB = u.aj.iB>(-64) ? -u.aj.iB : 64;
+      op = 2*OP_ShiftLeft + 1 - op;
+      iB = iB>(-64) ? -iB : 64;
     }
 
-    if( u.aj.iB>=64 ){
-      u.aj.iA = (u.aj.iA>=0 || u.aj.op==OP_ShiftLeft) ? 0 : -1;
+    if( iB>=64 ){
+      iA = (iA>=0 || op==OP_ShiftLeft) ? 0 : -1;
     }else{
-      memcpy(&u.aj.uA, &u.aj.iA, sizeof(u.aj.uA));
-      if( u.aj.op==OP_ShiftLeft ){
-        u.aj.uA <<= u.aj.iB;
+      memcpy(&uA, &iA, sizeof(uA));
+      if( op==OP_ShiftLeft ){
+        uA <<= iB;
       }else{
-        u.aj.uA >>= u.aj.iB;
+        uA >>= iB;
         /* Sign-extend on a right shift of a negative number */
-        if( u.aj.iA<0 ) u.aj.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.aj.iB);
+        if( iA<0 ) uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-iB);
       }
-      memcpy(&u.aj.iA, &u.aj.uA, sizeof(u.aj.iA));
+      memcpy(&iA, &uA, sizeof(iA));
     }
   }
-  pOut->u.i = u.aj.iA;
+  pOut->u.i = iA;
   MemSetTypeFlag(pOut, MEM_Int);
   break;
 }
 
 /* Opcode: AddImm  P1 P2 * * *
+** Synopsis:  r[P1]=r[P1]+P2
 ** 
 ** Add the constant P2 to the value in register P1.
 ** The result is always an integer.
@@ -66928,17 +69700,20 @@ case OP_AddImm: {            /* in1 */
 */
 case OP_MustBeInt: {            /* jump, in1 */
   pIn1 = &aMem[pOp->p1];
-  applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
   if( (pIn1->flags & MEM_Int)==0 ){
-    if( pOp->p2==0 ){
-      rc = SQLITE_MISMATCH;
-      goto abort_due_to_error;
-    }else{
-      pc = pOp->p2 - 1;
+    applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
+    VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2);
+    if( (pIn1->flags & MEM_Int)==0 ){
+      if( pOp->p2==0 ){
+        rc = SQLITE_MISMATCH;
+        goto abort_due_to_error;
+      }else{
+        pc = pOp->p2 - 1;
+        break;
+      }
     }
-  }else{
-    MemSetTypeFlag(pIn1, MEM_Int);
   }
+  MemSetTypeFlag(pIn1, MEM_Int);
   break;
 }
 
@@ -66966,7 +69741,7 @@ case OP_RealAffinity: {                  /* in1 */
 **
 ** Force the value in register P1 to be text.
 ** If the value is numeric, convert it to a string using the
-** equivalent of printf().  Blob values are unchanged and
+** equivalent of sprintf().  Blob values are unchanged and
 ** are afterwards simply interpreted as text.
 **
 ** A NULL value is not changed by this routine.  It remains NULL.
@@ -67063,6 +69838,7 @@ case OP_ToReal: {                  /* same as TK_TO_REAL, in1 */
 #endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */
 
 /* Opcode: Lt P1 P2 P3 P4 P5
+** Synopsis: if r[P1]<r[P3] goto P2
 **
 ** Compare the values in register P1 and P3.  If reg(P3)<reg(P1) then
 ** jump to address P2.  
@@ -67097,6 +69873,7 @@ case OP_ToReal: {                  /* same as TK_TO_REAL, in1 */
 ** bit set.
 */
 /* Opcode: Ne P1 P2 P3 P4 P5
+** Synopsis: if r[P1]!=r[P3] goto P2
 **
 ** This works just like the Lt opcode except that the jump is taken if
 ** the operands in registers P1 and P3 are not equal.  See the Lt opcode for
@@ -67109,6 +69886,7 @@ case OP_ToReal: {                  /* same as TK_TO_REAL, in1 */
 ** the SQLITE_NULLEQ flag were omitted from P5.
 */
 /* Opcode: Eq P1 P2 P3 P4 P5
+** Synopsis: if r[P1]==r[P3] goto P2
 **
 ** This works just like the Lt opcode except that the jump is taken if
 ** the operands in registers P1 and P3 are equal.
@@ -67121,18 +69899,21 @@ case OP_ToReal: {                  /* same as TK_TO_REAL, in1 */
 ** the SQLITE_NULLEQ flag were omitted from P5.
 */
 /* Opcode: Le P1 P2 P3 P4 P5
+** Synopsis: if r[P1]<=r[P3] goto P2
 **
 ** This works just like the Lt opcode except that the jump is taken if
 ** the content of register P3 is less than or equal to the content of
 ** register P1.  See the Lt opcode for additional information.
 */
 /* Opcode: Gt P1 P2 P3 P4 P5
+** Synopsis: if r[P1]>r[P3] goto P2
 **
 ** This works just like the Lt opcode except that the jump is taken if
 ** the content of register P3 is greater than the content of
 ** register P1.  See the Lt opcode for additional information.
 */
 /* Opcode: Ge P1 P2 P3 P4 P5
+** Synopsis: if r[P1]>=r[P3] goto P2
 **
 ** This works just like the Lt opcode except that the jump is taken if
 ** the content of register P3 is greater than or equal to the content of
@@ -67144,18 +69925,16 @@ case OP_Lt:               /* same as TK_LT, jump, in1, in3 */
 case OP_Le:               /* same as TK_LE, jump, in1, in3 */
 case OP_Gt:               /* same as TK_GT, jump, in1, in3 */
 case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
-#if 0  /* local variables moved into u.ak */
   int res;            /* Result of the comparison of pIn1 against pIn3 */
   char affinity;      /* Affinity to use for comparison */
   u16 flags1;         /* Copy of initial value of pIn1->flags */
   u16 flags3;         /* Copy of initial value of pIn3->flags */
-#endif /* local variables moved into u.ak */
 
   pIn1 = &aMem[pOp->p1];
   pIn3 = &aMem[pOp->p3];
-  u.ak.flags1 = pIn1->flags;
-  u.ak.flags3 = pIn3->flags;
-  if( (u.ak.flags1 | u.ak.flags3)&MEM_Null ){
+  flags1 = pIn1->flags;
+  flags3 = pIn3->flags;
+  if( (flags1 | flags3)&MEM_Null ){
     /* One or both operands are NULL */
     if( pOp->p5 & SQLITE_NULLEQ ){
       /* If SQLITE_NULLEQ is set (which will only happen if the operator is
@@ -67163,14 +69942,15 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
       ** or not both operands are null.
       */
       assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
-      assert( (u.ak.flags1 & MEM_Cleared)==0 );
-      if( (u.ak.flags1&MEM_Null)!=0
-       && (u.ak.flags3&MEM_Null)!=0
-       && (u.ak.flags3&MEM_Cleared)==0
+      assert( (flags1 & MEM_Cleared)==0 );
+      assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
+      if( (flags1&MEM_Null)!=0
+       && (flags3&MEM_Null)!=0
+       && (flags3&MEM_Cleared)==0
       ){
-        u.ak.res = 0;  /* Results are equal */
+        res = 0;  /* Results are equal */
       }else{
-        u.ak.res = 1;  /* Results are not equal */
+        res = 1;  /* Results are not equal */
       }
     }else{
       /* SQLITE_NULLEQ is clear and at least one operand is NULL,
@@ -67181,47 +69961,52 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
         pOut = &aMem[pOp->p2];
         MemSetTypeFlag(pOut, MEM_Null);
         REGISTER_TRACE(pOp->p2, pOut);
-      }else if( pOp->p5 & SQLITE_JUMPIFNULL ){
-        pc = pOp->p2-1;
+      }else{
+        VdbeBranchTaken(2,3);
+        if( pOp->p5 & SQLITE_JUMPIFNULL ){
+          pc = pOp->p2-1;
+        }
       }
       break;
     }
   }else{
     /* Neither operand is NULL.  Do a comparison. */
-    u.ak.affinity = pOp->p5 & SQLITE_AFF_MASK;
-    if( u.ak.affinity ){
-      applyAffinity(pIn1, u.ak.affinity, encoding);
-      applyAffinity(pIn3, u.ak.affinity, encoding);
+    affinity = pOp->p5 & SQLITE_AFF_MASK;
+    if( affinity ){
+      applyAffinity(pIn1, affinity, encoding);
+      applyAffinity(pIn3, affinity, encoding);
       if( db->mallocFailed ) goto no_mem;
     }
 
     assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
     ExpandBlob(pIn1);
     ExpandBlob(pIn3);
-    u.ak.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
+    res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
   }
   switch( pOp->opcode ){
-    case OP_Eq:    u.ak.res = u.ak.res==0;     break;
-    case OP_Ne:    u.ak.res = u.ak.res!=0;     break;
-    case OP_Lt:    u.ak.res = u.ak.res<0;      break;
-    case OP_Le:    u.ak.res = u.ak.res<=0;     break;
-    case OP_Gt:    u.ak.res = u.ak.res>0;      break;
-    default:       u.ak.res = u.ak.res>=0;     break;
+    case OP_Eq:    res = res==0;     break;
+    case OP_Ne:    res = res!=0;     break;
+    case OP_Lt:    res = res<0;      break;
+    case OP_Le:    res = res<=0;     break;
+    case OP_Gt:    res = res>0;      break;
+    default:       res = res>=0;     break;
   }
 
   if( pOp->p5 & SQLITE_STOREP2 ){
     pOut = &aMem[pOp->p2];
     memAboutToChange(p, pOut);
     MemSetTypeFlag(pOut, MEM_Int);
-    pOut->u.i = u.ak.res;
+    pOut->u.i = res;
     REGISTER_TRACE(pOp->p2, pOut);
-  }else if( u.ak.res ){
-    pc = pOp->p2-1;
+  }else{
+    VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+    if( res ){
+      pc = pOp->p2-1;
+    }
   }
-
   /* Undo any changes made by applyAffinity() to the input registers. */
-  pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.ak.flags1&MEM_TypeMask);
-  pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.ak.flags3&MEM_TypeMask);
+  pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask);
+  pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask);
   break;
 }
 
@@ -67242,6 +70027,7 @@ case OP_Permutation: {
 }
 
 /* Opcode: Compare P1 P2 P3 P4 P5
+** Synopsis: r[P1 at P3] <-> r[P2 at P3]
 **
 ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
 ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B").  Save the result of
@@ -67261,7 +70047,6 @@ case OP_Permutation: {
 ** and strings are less than blobs.
 */
 case OP_Compare: {
-#if 0  /* local variables moved into u.al */
   int n;
   int i;
   int p1;
@@ -67270,38 +70055,37 @@ case OP_Compare: {
   int idx;
   CollSeq *pColl;    /* Collating sequence to use on this term */
   int bRev;          /* True for DESCENDING sort order */
-#endif /* local variables moved into u.al */
 
   if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
-  u.al.n = pOp->p3;
-  u.al.pKeyInfo = pOp->p4.pKeyInfo;
-  assert( u.al.n>0 );
-  assert( u.al.pKeyInfo!=0 );
-  u.al.p1 = pOp->p1;
-  u.al.p2 = pOp->p2;
+  n = pOp->p3;
+  pKeyInfo = pOp->p4.pKeyInfo;
+  assert( n>0 );
+  assert( pKeyInfo!=0 );
+  p1 = pOp->p1;
+  p2 = pOp->p2;
 #if SQLITE_DEBUG
   if( aPermute ){
     int k, mx = 0;
-    for(k=0; k<u.al.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
-    assert( u.al.p1>0 && u.al.p1+mx<=p->nMem+1 );
-    assert( u.al.p2>0 && u.al.p2+mx<=p->nMem+1 );
+    for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
+    assert( p1>0 && p1+mx<=(p->nMem-p->nCursor)+1 );
+    assert( p2>0 && p2+mx<=(p->nMem-p->nCursor)+1 );
   }else{
-    assert( u.al.p1>0 && u.al.p1+u.al.n<=p->nMem+1 );
-    assert( u.al.p2>0 && u.al.p2+u.al.n<=p->nMem+1 );
+    assert( p1>0 && p1+n<=(p->nMem-p->nCursor)+1 );
+    assert( p2>0 && p2+n<=(p->nMem-p->nCursor)+1 );
   }
 #endif /* SQLITE_DEBUG */
-  for(u.al.i=0; u.al.i<u.al.n; u.al.i++){
-    u.al.idx = aPermute ? aPermute[u.al.i] : u.al.i;
-    assert( memIsValid(&aMem[u.al.p1+u.al.idx]) );
-    assert( memIsValid(&aMem[u.al.p2+u.al.idx]) );
-    REGISTER_TRACE(u.al.p1+u.al.idx, &aMem[u.al.p1+u.al.idx]);
-    REGISTER_TRACE(u.al.p2+u.al.idx, &aMem[u.al.p2+u.al.idx]);
-    assert( u.al.i<u.al.pKeyInfo->nField );
-    u.al.pColl = u.al.pKeyInfo->aColl[u.al.i];
-    u.al.bRev = u.al.pKeyInfo->aSortOrder[u.al.i];
-    iCompare = sqlite3MemCompare(&aMem[u.al.p1+u.al.idx], &aMem[u.al.p2+u.al.idx], u.al.pColl);
+  for(i=0; i<n; i++){
+    idx = aPermute ? aPermute[i] : i;
+    assert( memIsValid(&aMem[p1+idx]) );
+    assert( memIsValid(&aMem[p2+idx]) );
+    REGISTER_TRACE(p1+idx, &aMem[p1+idx]);
+    REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
+    assert( i<pKeyInfo->nField );
+    pColl = pKeyInfo->aColl[i];
+    bRev = pKeyInfo->aSortOrder[i];
+    iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
     if( iCompare ){
-      if( u.al.bRev ) iCompare = -iCompare;
+      if( bRev ) iCompare = -iCompare;
       break;
     }
   }
@@ -67317,16 +70101,17 @@ case OP_Compare: {
 */
 case OP_Jump: {             /* jump */
   if( iCompare<0 ){
-    pc = pOp->p1 - 1;
+    pc = pOp->p1 - 1;  VdbeBranchTaken(0,3);
   }else if( iCompare==0 ){
-    pc = pOp->p2 - 1;
+    pc = pOp->p2 - 1;  VdbeBranchTaken(1,3);
   }else{
-    pc = pOp->p3 - 1;
+    pc = pOp->p3 - 1;  VdbeBranchTaken(2,3);
   }
   break;
 }
 
 /* Opcode: And P1 P2 P3 * *
+** Synopsis: r[P3]=(r[P1] && r[P2])
 **
 ** Take the logical AND of the values in registers P1 and P2 and
 ** write the result into register P3.
@@ -67336,6 +70121,7 @@ case OP_Jump: {             /* jump */
 ** a NULL output.
 */
 /* Opcode: Or P1 P2 P3 * *
+** Synopsis: r[P3]=(r[P1] || r[P2])
 **
 ** Take the logical OR of the values in register P1 and P2 and
 ** store the answer in register P3.
@@ -67346,41 +70132,40 @@ case OP_Jump: {             /* jump */
 */
 case OP_And:              /* same as TK_AND, in1, in2, out3 */
 case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
-#if 0  /* local variables moved into u.am */
   int v1;    /* Left operand:  0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
   int v2;    /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-#endif /* local variables moved into u.am */
 
   pIn1 = &aMem[pOp->p1];
   if( pIn1->flags & MEM_Null ){
-    u.am.v1 = 2;
+    v1 = 2;
   }else{
-    u.am.v1 = sqlite3VdbeIntValue(pIn1)!=0;
+    v1 = sqlite3VdbeIntValue(pIn1)!=0;
   }
   pIn2 = &aMem[pOp->p2];
   if( pIn2->flags & MEM_Null ){
-    u.am.v2 = 2;
+    v2 = 2;
   }else{
-    u.am.v2 = sqlite3VdbeIntValue(pIn2)!=0;
+    v2 = sqlite3VdbeIntValue(pIn2)!=0;
   }
   if( pOp->opcode==OP_And ){
     static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
-    u.am.v1 = and_logic[u.am.v1*3+u.am.v2];
+    v1 = and_logic[v1*3+v2];
   }else{
     static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
-    u.am.v1 = or_logic[u.am.v1*3+u.am.v2];
+    v1 = or_logic[v1*3+v2];
   }
   pOut = &aMem[pOp->p3];
-  if( u.am.v1==2 ){
+  if( v1==2 ){
     MemSetTypeFlag(pOut, MEM_Null);
   }else{
-    pOut->u.i = u.am.v1;
+    pOut->u.i = v1;
     MemSetTypeFlag(pOut, MEM_Int);
   }
   break;
 }
 
 /* Opcode: Not P1 P2 * * *
+** Synopsis: r[P2]= !r[P1]
 **
 ** Interpret the value in register P1 as a boolean value.  Store the
 ** boolean complement in register P2.  If the value in register P1 is 
@@ -67398,6 +70183,7 @@ case OP_Not: {                /* same as TK_NOT, in1, out2 */
 }
 
 /* Opcode: BitNot P1 P2 * * *
+** Synopsis: r[P1]= ~r[P1]
 **
 ** Interpret the content of register P1 as an integer.  Store the
 ** ones-complement of the P1 value into register P2.  If P1 holds
@@ -67416,11 +70202,18 @@ case OP_BitNot: {             /* same as TK_BITNOT, in1, out2 */
 
 /* Opcode: Once P1 P2 * * *
 **
-** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
-** set the flag and fall through to the next instruction.
+** Check the "once" flag number P1. If it is set, jump to instruction P2. 
+** Otherwise, set the flag and fall through to the next instruction.
+** In other words, this opcode causes all following opcodes up through P2
+** (but not including P2) to run just once and to be skipped on subsequent
+** times through the loop.
+**
+** All "once" flags are initially cleared whenever a prepared statement
+** first begins to run.
 */
 case OP_Once: {             /* jump */
   assert( pOp->p1<p->nOnceFlag );
+  VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2);
   if( p->aOnceFlag[pOp->p1] ){
     pc = pOp->p2-1;
   }else{
@@ -67433,42 +70226,43 @@ case OP_Once: {             /* jump */
 **
 ** Jump to P2 if the value in register P1 is true.  The value
 ** is considered true if it is numeric and non-zero.  If the value
-** in P1 is NULL then take the jump if P3 is non-zero.
+** in P1 is NULL then take the jump if and only if P3 is non-zero.
 */
 /* Opcode: IfNot P1 P2 P3 * *
 **
 ** Jump to P2 if the value in register P1 is False.  The value
 ** is considered false if it has a numeric value of zero.  If the value
-** in P1 is NULL then take the jump if P3 is zero.
+** in P1 is NULL then take the jump if and only if P3 is non-zero.
 */
 case OP_If:                 /* jump, in1 */
 case OP_IfNot: {            /* jump, in1 */
-#if 0  /* local variables moved into u.an */
   int c;
-#endif /* local variables moved into u.an */
   pIn1 = &aMem[pOp->p1];
   if( pIn1->flags & MEM_Null ){
-    u.an.c = pOp->p3;
+    c = pOp->p3;
   }else{
 #ifdef SQLITE_OMIT_FLOATING_POINT
-    u.an.c = sqlite3VdbeIntValue(pIn1)!=0;
+    c = sqlite3VdbeIntValue(pIn1)!=0;
 #else
-    u.an.c = sqlite3VdbeRealValue(pIn1)!=0.0;
+    c = sqlite3VdbeRealValue(pIn1)!=0.0;
 #endif
-    if( pOp->opcode==OP_IfNot ) u.an.c = !u.an.c;
+    if( pOp->opcode==OP_IfNot ) c = !c;
   }
-  if( u.an.c ){
+  VdbeBranchTaken(c!=0, 2);
+  if( c ){
     pc = pOp->p2-1;
   }
   break;
 }
 
 /* Opcode: IsNull P1 P2 * * *
+** Synopsis:  if r[P1]==NULL goto P2
 **
 ** Jump to P2 if the value in register P1 is NULL.
 */
 case OP_IsNull: {            /* same as TK_ISNULL, jump, in1 */
   pIn1 = &aMem[pOp->p1];
+  VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
   if( (pIn1->flags & MEM_Null)!=0 ){
     pc = pOp->p2 - 1;
   }
@@ -67476,11 +70270,13 @@ case OP_IsNull: {            /* same as TK_ISNULL, jump, in1 */
 }
 
 /* Opcode: NotNull P1 P2 * * *
+** Synopsis: if r[P1]!=NULL goto P2
 **
 ** Jump to P2 if the value in register P1 is not NULL.  
 */
 case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */
   pIn1 = &aMem[pOp->p1];
+  VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2);
   if( (pIn1->flags & MEM_Null)==0 ){
     pc = pOp->p2 - 1;
   }
@@ -67488,6 +70284,7 @@ case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */
 }
 
 /* Opcode: Column P1 P2 P3 P4 P5
+** Synopsis:  r[P3]=PX
 **
 ** Interpret the data that cursor P1 points to as a structure built using
 ** the MakeRecord instruction.  (See the MakeRecord opcode for additional
@@ -67512,155 +70309,98 @@ case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */
 ** skipped for length() and all content loading can be skipped for typeof().
 */
 case OP_Column: {
-#if 0  /* local variables moved into u.ao */
-  u32 payloadSize;   /* Number of bytes in the record */
   i64 payloadSize64; /* Number of bytes in the record */
-  int p1;            /* P1 value of the opcode */
   int p2;            /* column number to retrieve */
   VdbeCursor *pC;    /* The VDBE cursor */
-  char *zRec;        /* Pointer to complete record-data */
   BtCursor *pCrsr;   /* The BTree cursor */
   u32 *aType;        /* aType[i] holds the numeric type of the i-th column */
   u32 *aOffset;      /* aOffset[i] is offset to start of data for i-th column */
-  int nField;        /* number of fields in the record */
   int len;           /* The length of the serialized data for the column */
   int i;             /* Loop counter */
-  char *zData;       /* Part of the record being decoded */
   Mem *pDest;        /* Where to write the extracted value */
   Mem sMem;          /* For storing the record being decoded */
-  u8 *zIdx;          /* Index into header */
-  u8 *zEndHdr;       /* Pointer to first byte after the header */
+  const u8 *zData;   /* Part of the record being decoded */
+  const u8 *zHdr;    /* Next unparsed byte of the header */
+  const u8 *zEndHdr; /* Pointer to first byte after the header */
   u32 offset;        /* Offset into the data */
   u32 szField;       /* Number of bytes in the content of a field */
-  int szHdr;         /* Size of the header size field at start of record */
-  int avail;         /* Number of bytes of available data */
+  u32 avail;         /* Number of bytes of available data */
   u32 t;             /* A type code from the record header */
   Mem *pReg;         /* PseudoTable input register */
-#endif /* local variables moved into u.ao */
-
-
-  u.ao.p1 = pOp->p1;
-  u.ao.p2 = pOp->p2;
-  u.ao.pC = 0;
-  memset(&u.ao.sMem, 0, sizeof(u.ao.sMem));
-  assert( u.ao.p1<p->nCursor );
-  assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.ao.pDest = &aMem[pOp->p3];
-  memAboutToChange(p, u.ao.pDest);
-  u.ao.zRec = 0;
 
-  /* This block sets the variable u.ao.payloadSize to be the total number of
-  ** bytes in the record.
-  **
-  ** u.ao.zRec is set to be the complete text of the record if it is available.
-  ** The complete record text is always available for pseudo-tables
-  ** If the record is stored in a cursor, the complete record text
-  ** might be available in the  u.ao.pC->aRow cache.  Or it might not be.
-  ** If the data is unavailable,  u.ao.zRec is set to NULL.
-  **
-  ** We also compute the number of columns in the record.  For cursors,
-  ** the number of columns is stored in the VdbeCursor.nField element.
-  */
-  u.ao.pC = p->apCsr[u.ao.p1];
-  assert( u.ao.pC!=0 );
+  p2 = pOp->p2;
+  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
+  pDest = &aMem[pOp->p3];
+  memAboutToChange(p, pDest);
+  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  assert( p2<pC->nField );
+  aType = pC->aType;
+  aOffset = aType + pC->nField;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  assert( u.ao.pC->pVtabCursor==0 );
-#endif
-  u.ao.pCrsr = u.ao.pC->pCursor;
-  if( u.ao.pCrsr!=0 ){
-    /* The record is stored in a B-Tree */
-    rc = sqlite3VdbeCursorMoveto(u.ao.pC);
-    if( rc ) goto abort_due_to_error;
-    if( u.ao.pC->nullRow ){
-      u.ao.payloadSize = 0;
-    }else if( u.ao.pC->cacheStatus==p->cacheCtr ){
-      u.ao.payloadSize = u.ao.pC->payloadSize;
-      u.ao.zRec = (char*)u.ao.pC->aRow;
-    }else if( u.ao.pC->isIndex ){
-      assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
-      VVA_ONLY(rc =) sqlite3BtreeKeySize(u.ao.pCrsr, &u.ao.payloadSize64);
-      assert( rc==SQLITE_OK );   /* True because of CursorMoveto() call above */
-      /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
-      ** payload size, so it is impossible for u.ao.payloadSize64 to be
-      ** larger than 32 bits. */
-      assert( (u.ao.payloadSize64 & SQLITE_MAX_U32)==(u64)u.ao.payloadSize64 );
-      u.ao.payloadSize = (u32)u.ao.payloadSize64;
-    }else{
-      assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
-      VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ao.pCrsr, &u.ao.payloadSize);
-      assert( rc==SQLITE_OK );   /* DataSize() cannot fail */
-    }
-  }else if( ALWAYS(u.ao.pC->pseudoTableReg>0) ){
-    u.ao.pReg = &aMem[u.ao.pC->pseudoTableReg];
-    if( u.ao.pC->multiPseudo ){
-      sqlite3VdbeMemShallowCopy(u.ao.pDest, u.ao.pReg+u.ao.p2, MEM_Ephem);
-      Deephemeralize(u.ao.pDest);
-      goto op_column_out;
-    }
-    assert( u.ao.pReg->flags & MEM_Blob );
-    assert( memIsValid(u.ao.pReg) );
-    u.ao.payloadSize = u.ao.pReg->n;
-    u.ao.zRec = u.ao.pReg->z;
-    u.ao.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
-    assert( u.ao.payloadSize==0 || u.ao.zRec!=0 );
-  }else{
-    /* Consider the row to be NULL */
-    u.ao.payloadSize = 0;
-  }
-
-  /* If u.ao.payloadSize is 0, then just store a NULL.  This can happen because of
-  ** nullRow or because of a corrupt database. */
-  if( u.ao.payloadSize==0 ){
-    MemSetTypeFlag(u.ao.pDest, MEM_Null);
-    goto op_column_out;
-  }
-  assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
-  if( u.ao.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
-    goto too_big;
-  }
-
-  u.ao.nField = u.ao.pC->nField;
-  assert( u.ao.p2<u.ao.nField );
-
-  /* Read and parse the table header.  Store the results of the parse
-  ** into the record header cache fields of the cursor.
-  */
-  u.ao.aType = u.ao.pC->aType;
-  if( u.ao.pC->cacheStatus==p->cacheCtr ){
-    u.ao.aOffset = u.ao.pC->aOffset;
-  }else{
-    assert(u.ao.aType);
-    u.ao.avail = 0;
-    u.ao.pC->aOffset = u.ao.aOffset = &u.ao.aType[u.ao.nField];
-    u.ao.pC->payloadSize = u.ao.payloadSize;
-    u.ao.pC->cacheStatus = p->cacheCtr;
-
-    /* Figure out how many bytes are in the header */
-    if( u.ao.zRec ){
-      u.ao.zData = u.ao.zRec;
-    }else{
-      if( u.ao.pC->isIndex ){
-        u.ao.zData = (char*)sqlite3BtreeKeyFetch(u.ao.pCrsr, &u.ao.avail);
+  assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */
+#endif
+  pCrsr = pC->pCursor;
+  assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */
+  assert( pCrsr!=0 || pC->nullRow );          /* pC->nullRow on PseudoTables */
+
+  /* If the cursor cache is stale, bring it up-to-date */
+  rc = sqlite3VdbeCursorMoveto(pC);
+  if( rc ) goto abort_due_to_error;
+  if( pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){
+    if( pC->nullRow ){
+      if( pCrsr==0 ){
+        assert( pC->pseudoTableReg>0 );
+        pReg = &aMem[pC->pseudoTableReg];
+        assert( pReg->flags & MEM_Blob );
+        assert( memIsValid(pReg) );
+        pC->payloadSize = pC->szRow = avail = pReg->n;
+        pC->aRow = (u8*)pReg->z;
       }else{
-        u.ao.zData = (char*)sqlite3BtreeDataFetch(u.ao.pCrsr, &u.ao.avail);
+        MemSetTypeFlag(pDest, MEM_Null);
+        goto op_column_out;
       }
-      /* If KeyFetch()/DataFetch() managed to get the entire payload,
-      ** save the payload in the u.ao.pC->aRow cache.  That will save us from
-      ** having to make additional calls to fetch the content portion of
-      ** the record.
-      */
-      assert( u.ao.avail>=0 );
-      if( u.ao.payloadSize <= (u32)u.ao.avail ){
-        u.ao.zRec = u.ao.zData;
-        u.ao.pC->aRow = (u8*)u.ao.zData;
+    }else{
+      assert( pCrsr );
+      if( pC->isTable==0 ){
+        assert( sqlite3BtreeCursorIsValid(pCrsr) );
+        VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64);
+        assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
+        /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
+        ** payload size, so it is impossible for payloadSize64 to be
+        ** larger than 32 bits. */
+        assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 );
+        pC->aRow = sqlite3BtreeKeyFetch(pCrsr, &avail);
+        pC->payloadSize = (u32)payloadSize64;
+      }else{
+        assert( sqlite3BtreeCursorIsValid(pCrsr) );
+        VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &pC->payloadSize);
+        assert( rc==SQLITE_OK );   /* DataSize() cannot fail */
+        pC->aRow = sqlite3BtreeDataFetch(pCrsr, &avail);
+      }
+      assert( avail<=65536 );  /* Maximum page size is 64KiB */
+      if( pC->payloadSize <= (u32)avail ){
+        pC->szRow = pC->payloadSize;
       }else{
-        u.ao.pC->aRow = 0;
+        pC->szRow = avail;
       }
+      if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+        goto too_big;
+      }
+    }
+    pC->cacheStatus = p->cacheCtr;
+    pC->iHdrOffset = getVarint32(pC->aRow, offset);
+    pC->nHdrParsed = 0;
+    aOffset[0] = offset;
+    if( avail<offset ){
+      /* pC->aRow does not have to hold the entire row, but it does at least
+      ** need to cover the header of the record.  If pC->aRow does not contain
+      ** the complete header, then set it to zero, forcing the header to be
+      ** dynamically allocated. */
+      pC->aRow = 0;
+      pC->szRow = 0;
     }
-    /* The following assert is true in all cases except when
-    ** the database file has been corrupted externally.
-    **    assert( u.ao.zRec!=0 || u.ao.avail>=u.ao.payloadSize || u.ao.avail>=9 ); */
-    u.ao.szHdr = getVarint32((u8*)u.ao.zData, u.ao.offset);
 
     /* Make sure a corrupt database has not given us an oversize header.
     ** Do this now to avoid an oversize memory allocation.
@@ -67671,161 +70411,156 @@ case OP_Column: {
     ** 3-byte type for each of the maximum of 32768 columns plus three
     ** extra bytes for the header length itself.  32768*3 + 3 = 98307.
     */
-    if( u.ao.offset > 98307 ){
+    if( offset > 98307 || offset > pC->payloadSize ){
       rc = SQLITE_CORRUPT_BKPT;
-      goto op_column_out;
+      goto op_column_error;
     }
+  }
 
-    /* Compute in u.ao.len the number of bytes of data we need to read in order
-    ** to get u.ao.nField type values.  u.ao.offset is an upper bound on this.  But
-    ** u.ao.nField might be significantly less than the true number of columns
-    ** in the table, and in that case, 5*u.ao.nField+3 might be smaller than u.ao.offset.
-    ** We want to minimize u.ao.len in order to limit the size of the memory
-    ** allocation, especially if a corrupt database file has caused u.ao.offset
-    ** to be oversized. Offset is limited to 98307 above.  But 98307 might
-    ** still exceed Robson memory allocation limits on some configurations.
-    ** On systems that cannot tolerate large memory allocations, u.ao.nField*5+3
-    ** will likely be much smaller since u.ao.nField will likely be less than
-    ** 20 or so.  This insures that Robson memory allocation limits are
-    ** not exceeded even for corrupt database files.
-    */
-    u.ao.len = u.ao.nField*5 + 3;
-    if( u.ao.len > (int)u.ao.offset ) u.ao.len = (int)u.ao.offset;
-
-    /* The KeyFetch() or DataFetch() above are fast and will get the entire
-    ** record header in most cases.  But they will fail to get the complete
-    ** record header if the record header does not fit on a single page
-    ** in the B-Tree.  When that happens, use sqlite3VdbeMemFromBtree() to
-    ** acquire the complete header text.
+  /* Make sure at least the first p2+1 entries of the header have been
+  ** parsed and valid information is in aOffset[] and aType[].
+  */
+  if( pC->nHdrParsed<=p2 ){
+    /* If there is more header available for parsing in the record, try
+    ** to extract additional fields up through the p2+1-th field 
     */
-    if( !u.ao.zRec && u.ao.avail<u.ao.len ){
-      u.ao.sMem.flags = 0;
-      u.ao.sMem.db = 0;
-      rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, 0, u.ao.len, u.ao.pC->isIndex, &u.ao.sMem);
-      if( rc!=SQLITE_OK ){
-        goto op_column_out;
+    if( pC->iHdrOffset<aOffset[0] ){
+      /* Make sure zData points to enough of the record to cover the header. */
+      if( pC->aRow==0 ){
+        memset(&sMem, 0, sizeof(sMem));
+        rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], 
+                                     !pC->isTable, &sMem);
+        if( rc!=SQLITE_OK ){
+          goto op_column_error;
+        }
+        zData = (u8*)sMem.z;
+      }else{
+        zData = pC->aRow;
       }
-      u.ao.zData = u.ao.sMem.z;
-    }
-    u.ao.zEndHdr = (u8 *)&u.ao.zData[u.ao.len];
-    u.ao.zIdx = (u8 *)&u.ao.zData[u.ao.szHdr];
-
-    /* Scan the header and use it to fill in the u.ao.aType[] and u.ao.aOffset[]
-    ** arrays.  u.ao.aType[u.ao.i] will contain the type integer for the u.ao.i-th
-    ** column and u.ao.aOffset[u.ao.i] will contain the u.ao.offset from the beginning
-    ** of the record to the start of the data for the u.ao.i-th column
-    */
-    for(u.ao.i=0; u.ao.i<u.ao.nField; u.ao.i++){
-      if( u.ao.zIdx<u.ao.zEndHdr ){
-        u.ao.aOffset[u.ao.i] = u.ao.offset;
-        if( u.ao.zIdx[0]<0x80 ){
-          u.ao.t = u.ao.zIdx[0];
-          u.ao.zIdx++;
+  
+      /* Fill in aType[i] and aOffset[i] values through the p2-th field. */
+      i = pC->nHdrParsed;
+      offset = aOffset[i];
+      zHdr = zData + pC->iHdrOffset;
+      zEndHdr = zData + aOffset[0];
+      assert( i<=p2 && zHdr<zEndHdr );
+      do{
+        if( zHdr[0]<0x80 ){
+          t = zHdr[0];
+          zHdr++;
         }else{
-          u.ao.zIdx += sqlite3GetVarint32(u.ao.zIdx, &u.ao.t);
+          zHdr += sqlite3GetVarint32(zHdr, &t);
         }
-        u.ao.aType[u.ao.i] = u.ao.t;
-        u.ao.szField = sqlite3VdbeSerialTypeLen(u.ao.t);
-        u.ao.offset += u.ao.szField;
-        if( u.ao.offset<u.ao.szField ){  /* True if u.ao.offset overflows */
-          u.ao.zIdx = &u.ao.zEndHdr[1];  /* Forces SQLITE_CORRUPT return below */
+        aType[i] = t;
+        szField = sqlite3VdbeSerialTypeLen(t);
+        offset += szField;
+        if( offset<szField ){  /* True if offset overflows */
+          zHdr = &zEndHdr[1];  /* Forces SQLITE_CORRUPT return below */
           break;
         }
-      }else{
-        /* If u.ao.i is less that u.ao.nField, then there are fewer fields in this
-        ** record than SetNumColumns indicated there are columns in the
-        ** table. Set the u.ao.offset for any extra columns not present in
-        ** the record to 0. This tells code below to store the default value
-        ** for the column instead of deserializing a value from the record.
-        */
-        u.ao.aOffset[u.ao.i] = 0;
+        i++;
+        aOffset[i] = offset;
+      }while( i<=p2 && zHdr<zEndHdr );
+      pC->nHdrParsed = i;
+      pC->iHdrOffset = (u32)(zHdr - zData);
+      if( pC->aRow==0 ){
+        sqlite3VdbeMemRelease(&sMem);
+        sMem.flags = MEM_Null;
+      }
+  
+      /* If we have read more header data than was contained in the header,
+      ** or if the end of the last field appears to be past the end of the
+      ** record, or if the end of the last field appears to be before the end
+      ** of the record (when all fields present), then we must be dealing 
+      ** with a corrupt database.
+      */
+      if( (zHdr > zEndHdr)
+       || (offset > pC->payloadSize)
+       || (zHdr==zEndHdr && offset!=pC->payloadSize)
+      ){
+        rc = SQLITE_CORRUPT_BKPT;
+        goto op_column_error;
       }
     }
-    sqlite3VdbeMemRelease(&u.ao.sMem);
-    u.ao.sMem.flags = MEM_Null;
 
-    /* If we have read more header data than was contained in the header,
-    ** or if the end of the last field appears to be past the end of the
-    ** record, or if the end of the last field appears to be before the end
-    ** of the record (when all fields present), then we must be dealing
-    ** with a corrupt database.
+    /* If after trying to extra new entries from the header, nHdrParsed is
+    ** still not up to p2, that means that the record has fewer than p2
+    ** columns.  So the result will be either the default value or a NULL.
     */
-    if( (u.ao.zIdx > u.ao.zEndHdr) || (u.ao.offset > u.ao.payloadSize)
-         || (u.ao.zIdx==u.ao.zEndHdr && u.ao.offset!=u.ao.payloadSize) ){
-      rc = SQLITE_CORRUPT_BKPT;
+    if( pC->nHdrParsed<=p2 ){
+      if( pOp->p4type==P4_MEM ){
+        sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
+      }else{
+        MemSetTypeFlag(pDest, MEM_Null);
+      }
       goto op_column_out;
     }
   }
 
-  /* Get the column information. If u.ao.aOffset[u.ao.p2] is non-zero, then
-  ** deserialize the value from the record. If u.ao.aOffset[u.ao.p2] is zero,
-  ** then there are not enough fields in the record to satisfy the
-  ** request.  In this case, set the value NULL or to P4 if P4 is
-  ** a pointer to a Mem object.
+  /* Extract the content for the p2+1-th column.  Control can only
+  ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are
+  ** all valid.
   */
-  if( u.ao.aOffset[u.ao.p2] ){
-    assert( rc==SQLITE_OK );
-    if( u.ao.zRec ){
-      /* This is the common case where the whole row fits on a single page */
-      VdbeMemRelease(u.ao.pDest);
-      sqlite3VdbeSerialGet((u8 *)&u.ao.zRec[u.ao.aOffset[u.ao.p2]], u.ao.aType[u.ao.p2], u.ao.pDest);
+  assert( p2<pC->nHdrParsed );
+  assert( rc==SQLITE_OK );
+  assert( sqlite3VdbeCheckMemInvariants(pDest) );
+  if( pC->szRow>=aOffset[p2+1] ){
+    /* This is the common case where the desired content fits on the original
+    ** page - where the content is not on an overflow page */
+    VdbeMemRelease(pDest);
+    sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest);
+  }else{
+    /* This branch happens only when content is on overflow pages */
+    t = aType[p2];
+    if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
+          && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
+     || (len = sqlite3VdbeSerialTypeLen(t))==0
+    ){
+      /* Content is irrelevant for the typeof() function and for
+      ** the length(X) function if X is a blob.  So we might as well use
+      ** bogus content rather than reading content from disk.  NULL works
+      ** for text and blob and whatever is in the payloadSize64 variable
+      ** will work for everything else.  Content is also irrelevant if
+      ** the content length is 0. */
+      zData = t<=13 ? (u8*)&payloadSize64 : 0;
+      sMem.zMalloc = 0;
     }else{
-      /* This branch happens only when the row overflows onto multiple pages */
-      u.ao.t = u.ao.aType[u.ao.p2];
-      if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
-       && ((u.ao.t>=12 && (u.ao.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
-      ){
-        /* Content is irrelevant for the typeof() function and for
-        ** the length(X) function if X is a blob.  So we might as well use
-        ** bogus content rather than reading content from disk.  NULL works
-        ** for text and blob and whatever is in the u.ao.payloadSize64 variable
-        ** will work for everything else. */
-        u.ao.zData = u.ao.t<12 ? (char*)&u.ao.payloadSize64 : 0;
-      }else{
-        u.ao.len = sqlite3VdbeSerialTypeLen(u.ao.t);
-        sqlite3VdbeMemMove(&u.ao.sMem, u.ao.pDest);
-        rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, u.ao.aOffset[u.ao.p2], u.ao.len,  u.ao.pC->isIndex,
-                                     &u.ao.sMem);
-        if( rc!=SQLITE_OK ){
-          goto op_column_out;
-        }
-        u.ao.zData = u.ao.sMem.z;
+      memset(&sMem, 0, sizeof(sMem));
+      sqlite3VdbeMemMove(&sMem, pDest);
+      rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable,
+                                   &sMem);
+      if( rc!=SQLITE_OK ){
+        goto op_column_error;
       }
-      sqlite3VdbeSerialGet((u8*)u.ao.zData, u.ao.t, u.ao.pDest);
+      zData = (u8*)sMem.z;
     }
-    u.ao.pDest->enc = encoding;
-  }else{
-    if( pOp->p4type==P4_MEM ){
-      sqlite3VdbeMemShallowCopy(u.ao.pDest, pOp->p4.pMem, MEM_Static);
-    }else{
-      MemSetTypeFlag(u.ao.pDest, MEM_Null);
+    sqlite3VdbeSerialGet(zData, t, pDest);
+    /* If we dynamically allocated space to hold the data (in the
+    ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
+    ** dynamically allocated space over to the pDest structure.
+    ** This prevents a memory copy. */
+    if( sMem.zMalloc ){
+      assert( sMem.z==sMem.zMalloc );
+      assert( VdbeMemDynamic(pDest)==0 );
+      assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z );
+      pDest->flags &= ~(MEM_Ephem|MEM_Static);
+      pDest->flags |= MEM_Term;
+      pDest->z = sMem.z;
+      pDest->zMalloc = sMem.zMalloc;
     }
   }
-
-  /* If we dynamically allocated space to hold the data (in the
-  ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
-  ** dynamically allocated space over to the u.ao.pDest structure.
-  ** This prevents a memory copy.
-  */
-  if( u.ao.sMem.zMalloc ){
-    assert( u.ao.sMem.z==u.ao.sMem.zMalloc );
-    assert( !(u.ao.pDest->flags & MEM_Dyn) );
-    assert( !(u.ao.pDest->flags & (MEM_Blob|MEM_Str)) || u.ao.pDest->z==u.ao.sMem.z );
-    u.ao.pDest->flags &= ~(MEM_Ephem|MEM_Static);
-    u.ao.pDest->flags |= MEM_Term;
-    u.ao.pDest->z = u.ao.sMem.z;
-    u.ao.pDest->zMalloc = u.ao.sMem.zMalloc;
-  }
-
-  rc = sqlite3VdbeMemMakeWriteable(u.ao.pDest);
+  pDest->enc = encoding;
 
 op_column_out:
-  UPDATE_MAX_BLOBSIZE(u.ao.pDest);
-  REGISTER_TRACE(pOp->p3, u.ao.pDest);
+  Deephemeralize(pDest);
+op_column_error:
+  UPDATE_MAX_BLOBSIZE(pDest);
+  REGISTER_TRACE(pOp->p3, pDest);
   break;
 }
 
 /* Opcode: Affinity P1 P2 * P4 *
+** Synopsis: affinity(r[P1 at P2])
 **
 ** Apply affinities to a range of P2 registers starting with P1.
 **
@@ -67834,26 +70569,24 @@ op_column_out:
 ** memory cell in the range.
 */
 case OP_Affinity: {
-#if 0  /* local variables moved into u.ap */
   const char *zAffinity;   /* The affinity to be applied */
   char cAff;               /* A single character of affinity */
-#endif /* local variables moved into u.ap */
 
-  u.ap.zAffinity = pOp->p4.z;
-  assert( u.ap.zAffinity!=0 );
-  assert( u.ap.zAffinity[pOp->p2]==0 );
+  zAffinity = pOp->p4.z;
+  assert( zAffinity!=0 );
+  assert( zAffinity[pOp->p2]==0 );
   pIn1 = &aMem[pOp->p1];
-  while( (u.ap.cAff = *(u.ap.zAffinity++))!=0 ){
-    assert( pIn1 <= &p->aMem[p->nMem] );
+  while( (cAff = *(zAffinity++))!=0 ){
+    assert( pIn1 <= &p->aMem[(p->nMem-p->nCursor)] );
     assert( memIsValid(pIn1) );
-    ExpandBlob(pIn1);
-    applyAffinity(pIn1, u.ap.cAff, encoding);
+    applyAffinity(pIn1, cAff, encoding);
     pIn1++;
   }
   break;
 }
 
 /* Opcode: MakeRecord P1 P2 P3 P4 *
+** Synopsis: r[P3]=mkrec(r[P1 at P2])
 **
 ** Convert P2 registers beginning with P1 into the [record format]
 ** use as a data record in a database table or as a key
@@ -67869,7 +70602,6 @@ case OP_Affinity: {
 ** If P4 is NULL then all index fields have the affinity NONE.
 */
 case OP_MakeRecord: {
-#if 0  /* local variables moved into u.aq */
   u8 *zNewRecord;        /* A buffer to hold the data for the new record */
   Mem *pRec;             /* The new record */
   u64 nData;             /* Number of bytes of data space */
@@ -67883,102 +70615,120 @@ case OP_MakeRecord: {
   int nField;            /* Number of fields in the record */
   char *zAffinity;       /* The affinity string for the record */
   int file_format;       /* File format to use for encoding */
-  int i;                 /* Space used in zNewRecord[] */
+  int i;                 /* Space used in zNewRecord[] header */
+  int j;                 /* Space used in zNewRecord[] content */
   int len;               /* Length of a field */
-#endif /* local variables moved into u.aq */
 
   /* Assuming the record contains N fields, the record format looks
   ** like this:
   **
   ** ------------------------------------------------------------------------
-  ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 |
+  ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | 
   ** ------------------------------------------------------------------------
   **
   ** Data(0) is taken from register P1.  Data(1) comes from register P1+1
   ** and so froth.
   **
-  ** Each type field is a varint representing the serial type of the
+  ** Each type field is a varint representing the serial type of the 
   ** corresponding data element (see sqlite3VdbeSerialType()). The
   ** hdr-size field is also a varint which is the offset from the beginning
   ** of the record to data0.
   */
-  u.aq.nData = 0;         /* Number of bytes of data space */
-  u.aq.nHdr = 0;          /* Number of bytes of header space */
-  u.aq.nZero = 0;         /* Number of zero bytes at the end of the record */
-  u.aq.nField = pOp->p1;
-  u.aq.zAffinity = pOp->p4.z;
-  assert( u.aq.nField>0 && pOp->p2>0 && pOp->p2+u.aq.nField<=p->nMem+1 );
-  u.aq.pData0 = &aMem[u.aq.nField];
-  u.aq.nField = pOp->p2;
-  u.aq.pLast = &u.aq.pData0[u.aq.nField-1];
-  u.aq.file_format = p->minWriteFileFormat;
+  nData = 0;         /* Number of bytes of data space */
+  nHdr = 0;          /* Number of bytes of header space */
+  nZero = 0;         /* Number of zero bytes at the end of the record */
+  nField = pOp->p1;
+  zAffinity = pOp->p4.z;
+  assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem-p->nCursor)+1 );
+  pData0 = &aMem[nField];
+  nField = pOp->p2;
+  pLast = &pData0[nField-1];
+  file_format = p->minWriteFileFormat;
 
   /* Identify the output register */
   assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
   pOut = &aMem[pOp->p3];
   memAboutToChange(p, pOut);
 
+  /* Apply the requested affinity to all inputs
+  */
+  assert( pData0<=pLast );
+  if( zAffinity ){
+    pRec = pData0;
+    do{
+      applyAffinity(pRec++, *(zAffinity++), encoding);
+      assert( zAffinity[0]==0 || pRec<=pLast );
+    }while( zAffinity[0] );
+  }
+
   /* Loop through the elements that will make up the record to figure
   ** out how much space is required for the new record.
   */
-  for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
-    assert( memIsValid(u.aq.pRec) );
-    if( u.aq.zAffinity ){
-      applyAffinity(u.aq.pRec, u.aq.zAffinity[u.aq.pRec-u.aq.pData0], encoding);
-    }
-    if( u.aq.pRec->flags&MEM_Zero && u.aq.pRec->n>0 ){
-      sqlite3VdbeMemExpandBlob(u.aq.pRec);
-    }
-    u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
-    u.aq.len = sqlite3VdbeSerialTypeLen(u.aq.serial_type);
-    u.aq.nData += u.aq.len;
-    u.aq.nHdr += sqlite3VarintLen(u.aq.serial_type);
-    if( u.aq.pRec->flags & MEM_Zero ){
-      /* Only pure zero-filled BLOBs can be input to this Opcode.
-      ** We do not allow blobs with a prefix and a zero-filled tail. */
-      u.aq.nZero += u.aq.pRec->u.nZero;
-    }else if( u.aq.len ){
-      u.aq.nZero = 0;
+  pRec = pLast;
+  do{
+    assert( memIsValid(pRec) );
+    serial_type = sqlite3VdbeSerialType(pRec, file_format);
+    len = sqlite3VdbeSerialTypeLen(serial_type);
+    if( pRec->flags & MEM_Zero ){
+      if( nData ){
+        sqlite3VdbeMemExpandBlob(pRec);
+      }else{
+        nZero += pRec->u.nZero;
+        len -= pRec->u.nZero;
+      }
     }
-  }
+    nData += len;
+    testcase( serial_type==127 );
+    testcase( serial_type==128 );
+    nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
+  }while( (--pRec)>=pData0 );
 
   /* Add the initial header varint and total the size */
-  u.aq.nHdr += u.aq.nVarint = sqlite3VarintLen(u.aq.nHdr);
-  if( u.aq.nVarint<sqlite3VarintLen(u.aq.nHdr) ){
-    u.aq.nHdr++;
-  }
-  u.aq.nByte = u.aq.nHdr+u.aq.nData-u.aq.nZero;
-  if( u.aq.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+  testcase( nHdr==126 );
+  testcase( nHdr==127 );
+  if( nHdr<=126 ){
+    /* The common case */
+    nHdr += 1;
+  }else{
+    /* Rare case of a really large header */
+    nVarint = sqlite3VarintLen(nHdr);
+    nHdr += nVarint;
+    if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
+  }
+  nByte = nHdr+nData;
+  if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
     goto too_big;
   }
 
-  /* Make sure the output register has a buffer large enough to store
+  /* Make sure the output register has a buffer large enough to store 
   ** the new record. The output register (pOp->p3) is not allowed to
   ** be one of the input registers (because the following call to
   ** sqlite3VdbeMemGrow() could clobber the value before it is used).
   */
-  if( sqlite3VdbeMemGrow(pOut, (int)u.aq.nByte, 0) ){
+  if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){
     goto no_mem;
   }
-  u.aq.zNewRecord = (u8 *)pOut->z;
+  zNewRecord = (u8 *)pOut->z;
 
   /* Write the record */
-  u.aq.i = putVarint32(u.aq.zNewRecord, u.aq.nHdr);
-  for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
-    u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
-    u.aq.i += putVarint32(&u.aq.zNewRecord[u.aq.i], u.aq.serial_type);      /* serial type */
-  }
-  for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){  /* serial data */
-    u.aq.i += sqlite3VdbeSerialPut(&u.aq.zNewRecord[u.aq.i], (int)(u.aq.nByte-u.aq.i), u.aq.pRec,u.aq.file_format);
-  }
-  assert( u.aq.i==u.aq.nByte );
-
-  assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  pOut->n = (int)u.aq.nByte;
-  pOut->flags = MEM_Blob | MEM_Dyn;
+  i = putVarint32(zNewRecord, nHdr);
+  j = nHdr;
+  assert( pData0<=pLast );
+  pRec = pData0;
+  do{
+    serial_type = sqlite3VdbeSerialType(pRec, file_format);
+    i += putVarint32(&zNewRecord[i], serial_type);            /* serial type */
+    j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */
+  }while( (++pRec)<=pLast );
+  assert( i==nHdr );
+  assert( j==nByte );
+
+  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
+  pOut->n = (int)nByte;
+  pOut->flags = MEM_Blob;
   pOut->xDel = 0;
-  if( u.aq.nZero ){
-    pOut->u.nZero = u.aq.nZero;
+  if( nZero ){
+    pOut->u.nZero = nZero;
     pOut->flags |= MEM_Zero;
   }
   pOut->enc = SQLITE_UTF8;  /* In case the blob is ever converted to text */
@@ -67988,24 +70738,21 @@ case OP_MakeRecord: {
 }
 
 /* Opcode: Count P1 P2 * * *
+** Synopsis: r[P2]=count()
 **
 ** Store the number of entries (an integer value) in the table or index 
 ** opened by cursor P1 in register P2
 */
 #ifndef SQLITE_OMIT_BTREECOUNT
 case OP_Count: {         /* out2-prerelease */
-#if 0  /* local variables moved into u.ar */
   i64 nEntry;
   BtCursor *pCrsr;
-#endif /* local variables moved into u.ar */
 
-  u.ar.pCrsr = p->apCsr[pOp->p1]->pCursor;
-  if( ALWAYS(u.ar.pCrsr) ){
-    rc = sqlite3BtreeCount(u.ar.pCrsr, &u.ar.nEntry);
-  }else{
-    u.ar.nEntry = 0;
-  }
-  pOut->u.i = u.ar.nEntry;
+  pCrsr = p->apCsr[pOp->p1]->pCursor;
+  assert( pCrsr );
+  nEntry = 0;  /* Not needed.  Only used to silence a warning. */
+  rc = sqlite3BtreeCount(pCrsr, &nEntry);
+  pOut->u.i = nEntry;
   break;
 }
 #endif
@@ -68017,7 +70764,6 @@ case OP_Count: {         /* out2-prerelease */
 ** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
 */
 case OP_Savepoint: {
-#if 0  /* local variables moved into u.as */
   int p1;                         /* Value of P1 operand */
   char *zName;                    /* Name of savepoint */
   int nName;
@@ -68026,29 +70772,29 @@ case OP_Savepoint: {
   Savepoint *pTmp;
   int iSavepoint;
   int ii;
-#endif /* local variables moved into u.as */
 
-  u.as.p1 = pOp->p1;
-  u.as.zName = pOp->p4.z;
+  p1 = pOp->p1;
+  zName = pOp->p4.z;
 
-  /* Assert that the u.as.p1 parameter is valid. Also that if there is no open
-  ** transaction, then there cannot be any savepoints.
+  /* Assert that the p1 parameter is valid. Also that if there is no open
+  ** transaction, then there cannot be any savepoints. 
   */
   assert( db->pSavepoint==0 || db->autoCommit==0 );
-  assert( u.as.p1==SAVEPOINT_BEGIN||u.as.p1==SAVEPOINT_RELEASE||u.as.p1==SAVEPOINT_ROLLBACK );
+  assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK );
   assert( db->pSavepoint || db->isTransactionSavepoint==0 );
   assert( checkSavepointCount(db) );
+  assert( p->bIsReader );
 
-  if( u.as.p1==SAVEPOINT_BEGIN ){
-    if( db->writeVdbeCnt>0 ){
-      /* A new savepoint cannot be created if there are active write
+  if( p1==SAVEPOINT_BEGIN ){
+    if( db->nVdbeWrite>0 ){
+      /* A new savepoint cannot be created if there are active write 
       ** statements (i.e. open read/write incremental blob handles).
       */
       sqlite3SetString(&p->zErrMsg, db, "cannot open savepoint - "
         "SQL statements in progress");
       rc = SQLITE_BUSY;
     }else{
-      u.as.nName = sqlite3Strlen30(u.as.zName);
+      nName = sqlite3Strlen30(zName);
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
       /* This call is Ok even if this savepoint is actually a transaction
@@ -68062,11 +70808,11 @@ case OP_Savepoint: {
 #endif
 
       /* Create a new savepoint structure. */
-      u.as.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.as.nName+1);
-      if( u.as.pNew ){
-        u.as.pNew->zName = (char *)&u.as.pNew[1];
-        memcpy(u.as.pNew->zName, u.as.zName, u.as.nName+1);
-
+      pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1);
+      if( pNew ){
+        pNew->zName = (char *)&pNew[1];
+        memcpy(pNew->zName, zName, nName+1);
+    
         /* If there is no open transaction, then mark this as a special
         ** "transaction savepoint". */
         if( db->autoCommit ){
@@ -68075,44 +70821,45 @@ case OP_Savepoint: {
         }else{
           db->nSavepoint++;
         }
-
+    
         /* Link the new savepoint into the database handle's list. */
-        u.as.pNew->pNext = db->pSavepoint;
-        db->pSavepoint = u.as.pNew;
-        u.as.pNew->nDeferredCons = db->nDeferredCons;
+        pNew->pNext = db->pSavepoint;
+        db->pSavepoint = pNew;
+        pNew->nDeferredCons = db->nDeferredCons;
+        pNew->nDeferredImmCons = db->nDeferredImmCons;
       }
     }
   }else{
-    u.as.iSavepoint = 0;
+    iSavepoint = 0;
 
     /* Find the named savepoint. If there is no such savepoint, then an
     ** an error is returned to the user.  */
     for(
-      u.as.pSavepoint = db->pSavepoint;
-      u.as.pSavepoint && sqlite3StrICmp(u.as.pSavepoint->zName, u.as.zName);
-      u.as.pSavepoint = u.as.pSavepoint->pNext
+      pSavepoint = db->pSavepoint; 
+      pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName);
+      pSavepoint = pSavepoint->pNext
     ){
-      u.as.iSavepoint++;
+      iSavepoint++;
     }
-    if( !u.as.pSavepoint ){
-      sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.as.zName);
+    if( !pSavepoint ){
+      sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", zName);
       rc = SQLITE_ERROR;
-    }else if( db->writeVdbeCnt>0 && u.as.p1==SAVEPOINT_RELEASE ){
-      /* It is not possible to release (commit) a savepoint if there are
+    }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){
+      /* It is not possible to release (commit) a savepoint if there are 
       ** active write statements.
       */
-      sqlite3SetString(&p->zErrMsg, db,
+      sqlite3SetString(&p->zErrMsg, db, 
         "cannot release savepoint - SQL statements in progress"
       );
       rc = SQLITE_BUSY;
     }else{
 
       /* Determine whether or not this is a transaction savepoint. If so,
-      ** and this is a RELEASE command, then the current transaction
-      ** is committed.
+      ** and this is a RELEASE command, then the current transaction 
+      ** is committed. 
       */
-      int isTransaction = u.as.pSavepoint->pNext==0 && db->isTransactionSavepoint;
-      if( isTransaction && u.as.p1==SAVEPOINT_RELEASE ){
+      int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint;
+      if( isTransaction && p1==SAVEPOINT_RELEASE ){
         if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
           goto vdbe_return;
         }
@@ -68126,51 +70873,52 @@ case OP_Savepoint: {
         db->isTransactionSavepoint = 0;
         rc = p->rc;
       }else{
-        u.as.iSavepoint = db->nSavepoint - u.as.iSavepoint - 1;
-        if( u.as.p1==SAVEPOINT_ROLLBACK ){
-          for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
-            sqlite3BtreeTripAllCursors(db->aDb[u.as.ii].pBt, SQLITE_ABORT);
+        iSavepoint = db->nSavepoint - iSavepoint - 1;
+        if( p1==SAVEPOINT_ROLLBACK ){
+          for(ii=0; ii<db->nDb; ii++){
+            sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT);
           }
         }
-        for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
-          rc = sqlite3BtreeSavepoint(db->aDb[u.as.ii].pBt, u.as.p1, u.as.iSavepoint);
+        for(ii=0; ii<db->nDb; ii++){
+          rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint);
           if( rc!=SQLITE_OK ){
             goto abort_due_to_error;
           }
         }
-        if( u.as.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
+        if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
           sqlite3ExpirePreparedStatements(db);
           sqlite3ResetAllSchemasOfConnection(db);
           db->flags = (db->flags | SQLITE_InternChanges);
         }
       }
-
-      /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
+  
+      /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all 
       ** savepoints nested inside of the savepoint being operated on. */
-      while( db->pSavepoint!=u.as.pSavepoint ){
-        u.as.pTmp = db->pSavepoint;
-        db->pSavepoint = u.as.pTmp->pNext;
-        sqlite3DbFree(db, u.as.pTmp);
+      while( db->pSavepoint!=pSavepoint ){
+        pTmp = db->pSavepoint;
+        db->pSavepoint = pTmp->pNext;
+        sqlite3DbFree(db, pTmp);
         db->nSavepoint--;
       }
 
-      /* If it is a RELEASE, then destroy the savepoint being operated on
-      ** too. If it is a ROLLBACK TO, then set the number of deferred
+      /* If it is a RELEASE, then destroy the savepoint being operated on 
+      ** too. If it is a ROLLBACK TO, then set the number of deferred 
       ** constraint violations present in the database to the value stored
       ** when the savepoint was created.  */
-      if( u.as.p1==SAVEPOINT_RELEASE ){
-        assert( u.as.pSavepoint==db->pSavepoint );
-        db->pSavepoint = u.as.pSavepoint->pNext;
-        sqlite3DbFree(db, u.as.pSavepoint);
+      if( p1==SAVEPOINT_RELEASE ){
+        assert( pSavepoint==db->pSavepoint );
+        db->pSavepoint = pSavepoint->pNext;
+        sqlite3DbFree(db, pSavepoint);
         if( !isTransaction ){
           db->nSavepoint--;
         }
       }else{
-        db->nDeferredCons = u.as.pSavepoint->nDeferredCons;
+        db->nDeferredCons = pSavepoint->nDeferredCons;
+        db->nDeferredImmCons = pSavepoint->nDeferredImmCons;
       }
 
       if( !isTransaction ){
-        rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint);
+        rc = sqlite3VtabSavepoint(db, p1, iSavepoint);
         if( rc!=SQLITE_OK ) goto abort_due_to_error;
       }
     }
@@ -68189,49 +70937,48 @@ case OP_Savepoint: {
 ** This instruction causes the VM to halt.
 */
 case OP_AutoCommit: {
-#if 0  /* local variables moved into u.at */
   int desiredAutoCommit;
   int iRollback;
   int turnOnAC;
-#endif /* local variables moved into u.at */
 
-  u.at.desiredAutoCommit = pOp->p1;
-  u.at.iRollback = pOp->p2;
-  u.at.turnOnAC = u.at.desiredAutoCommit && !db->autoCommit;
-  assert( u.at.desiredAutoCommit==1 || u.at.desiredAutoCommit==0 );
-  assert( u.at.desiredAutoCommit==1 || u.at.iRollback==0 );
-  assert( db->activeVdbeCnt>0 );  /* At least this one VM is active */
+  desiredAutoCommit = pOp->p1;
+  iRollback = pOp->p2;
+  turnOnAC = desiredAutoCommit && !db->autoCommit;
+  assert( desiredAutoCommit==1 || desiredAutoCommit==0 );
+  assert( desiredAutoCommit==1 || iRollback==0 );
+  assert( db->nVdbeActive>0 );  /* At least this one VM is active */
+  assert( p->bIsReader );
 
 #if 0
-  if( u.at.turnOnAC && u.at.iRollback && db->activeVdbeCnt>1 ){
+  if( turnOnAC && iRollback && db->nVdbeActive>1 ){
     /* If this instruction implements a ROLLBACK and other VMs are
     ** still running, and a transaction is active, return an error indicating
-    ** that the other VMs must complete first.
+    ** that the other VMs must complete first. 
     */
     sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
         "SQL statements in progress");
     rc = SQLITE_BUSY;
   }else
 #endif
-  if( u.at.turnOnAC && !u.at.iRollback && db->writeVdbeCnt>0 ){
+  if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){
     /* If this instruction implements a COMMIT and other VMs are writing
-    ** return an error indicating that the other VMs must complete first.
+    ** return an error indicating that the other VMs must complete first. 
     */
     sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
         "SQL statements in progress");
     rc = SQLITE_BUSY;
-  }else if( u.at.desiredAutoCommit!=db->autoCommit ){
-    if( u.at.iRollback ){
-      assert( u.at.desiredAutoCommit==1 );
+  }else if( desiredAutoCommit!=db->autoCommit ){
+    if( iRollback ){
+      assert( desiredAutoCommit==1 );
       sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
       db->autoCommit = 1;
     }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
       goto vdbe_return;
     }else{
-      db->autoCommit = (u8)u.at.desiredAutoCommit;
+      db->autoCommit = (u8)desiredAutoCommit;
       if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
         p->pc = pc;
-        db->autoCommit = (u8)(1-u.at.desiredAutoCommit);
+        db->autoCommit = (u8)(1-desiredAutoCommit);
         p->rc = rc = SQLITE_BUSY;
         goto vdbe_return;
       }
@@ -68246,34 +70993,28 @@ case OP_AutoCommit: {
     goto vdbe_return;
   }else{
     sqlite3SetString(&p->zErrMsg, db,
-        (!u.at.desiredAutoCommit)?"cannot start a transaction within a transaction":(
-        (u.at.iRollback)?"cannot rollback - no transaction is active":
+        (!desiredAutoCommit)?"cannot start a transaction within a transaction":(
+        (iRollback)?"cannot rollback - no transaction is active":
                    "cannot commit - no transaction is active"));
-
+         
     rc = SQLITE_ERROR;
   }
   break;
 }
 
-/* Opcode: Transaction P1 P2 * * *
+/* Opcode: Transaction P1 P2 P3 P4 P5
 **
-** Begin a transaction.  The transaction ends when a Commit or Rollback
-** opcode is encountered.  Depending on the ON CONFLICT setting, the
-** transaction might also be rolled back if an error is encountered.
+** Begin a transaction on database P1 if a transaction is not already
+** active.
+** If P2 is non-zero, then a write-transaction is started, or if a 
+** read-transaction is already active, it is upgraded to a write-transaction.
+** If P2 is zero, then a read-transaction is started.
 **
 ** P1 is the index of the database file on which the transaction is
 ** started.  Index 0 is the main database file and index 1 is the
 ** file used for temporary tables.  Indices of 2 or more are used for
 ** attached databases.
 **
-** If P2 is non-zero, then a write-transaction is started.  A RESERVED lock is
-** obtained on the database file when a write-transaction is started.  No
-** other process can start another write transaction while this transaction is
-** underway.  Starting a write transaction also creates a rollback journal. A
-** write transaction must be started before any changes can be made to the
-** database.  If P2 is 2 or greater then an EXCLUSIVE lock is also obtained
-** on the file.
-**
 ** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
 ** true (this flag is set if the Vdbe may modify more than one row and may
 ** throw an ABORT exception), a statement transaction may also be opened.
@@ -68284,19 +71025,34 @@ case OP_AutoCommit: {
 ** entire transaction. If no error is encountered, the statement transaction
 ** will automatically commit when the VDBE halts.
 **
-** If P2 is zero, then a read-lock is obtained on the database file.
+** If P5!=0 then this opcode also checks the schema cookie against P3
+** and the schema generation counter against P4.
+** The cookie changes its value whenever the database schema changes.
+** This operation is used to detect when that the cookie has changed
+** and that the current process needs to reread the schema.  If the schema
+** cookie in P3 differs from the schema cookie in the database header or
+** if the schema generation counter in P4 differs from the current
+** generation counter, then an SQLITE_SCHEMA error is raised and execution
+** halts.  The sqlite3_step() wrapper function might then reprepare the
+** statement and rerun it from the beginning.
 */
 case OP_Transaction: {
-#if 0  /* local variables moved into u.au */
   Btree *pBt;
-#endif /* local variables moved into u.au */
+  int iMeta;
+  int iGen;
 
+  assert( p->bIsReader );
+  assert( p->readOnly==0 || pOp->p2==0 );
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
-  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.au.pBt = db->aDb[pOp->p1].pBt;
+  assert( DbMaskTest(p->btreeMask, pOp->p1) );
+  if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
+    rc = SQLITE_READONLY;
+    goto abort_due_to_error;
+  }
+  pBt = db->aDb[pOp->p1].pBt;
 
-  if( u.au.pBt ){
-    rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2);
+  if( pBt ){
+    rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
     if( rc==SQLITE_BUSY ){
       p->pc = pc;
       p->rc = rc = SQLITE_BUSY;
@@ -68306,26 +71062,56 @@ case OP_Transaction: {
       goto abort_due_to_error;
     }
 
-    if( pOp->p2 && p->usesStmtJournal
-     && (db->autoCommit==0 || db->activeVdbeCnt>1)
+    if( pOp->p2 && p->usesStmtJournal 
+     && (db->autoCommit==0 || db->nVdbeRead>1) 
     ){
-      assert( sqlite3BtreeIsInTrans(u.au.pBt) );
+      assert( sqlite3BtreeIsInTrans(pBt) );
       if( p->iStatement==0 ){
         assert( db->nStatement>=0 && db->nSavepoint>=0 );
-        db->nStatement++;
+        db->nStatement++; 
         p->iStatement = db->nSavepoint + db->nStatement;
       }
 
       rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
       if( rc==SQLITE_OK ){
-        rc = sqlite3BtreeBeginStmt(u.au.pBt, p->iStatement);
+        rc = sqlite3BtreeBeginStmt(pBt, p->iStatement);
       }
 
       /* Store the current value of the database handles deferred constraint
       ** counter. If the statement transaction needs to be rolled back,
       ** the value of this counter needs to be restored too.  */
       p->nStmtDefCons = db->nDeferredCons;
+      p->nStmtDefImmCons = db->nDeferredImmCons;
     }
+
+    /* Gather the schema version number for checking */
+    sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
+    iGen = db->aDb[pOp->p1].pSchema->iGeneration;
+  }else{
+    iGen = iMeta = 0;
+  }
+  assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
+  if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){
+    sqlite3DbFree(db, p->zErrMsg);
+    p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
+    /* If the schema-cookie from the database file matches the cookie 
+    ** stored with the in-memory representation of the schema, do
+    ** not reload the schema from the database file.
+    **
+    ** If virtual-tables are in use, this is not just an optimization.
+    ** Often, v-tables store their data in other SQLite tables, which
+    ** are queried from within xNext() and other v-table methods using
+    ** prepared queries. If such a query is out-of-date, we do not want to
+    ** discard the database schema, as the user code implementing the
+    ** v-table would have to be ready for the sqlite3_vtab structure itself
+    ** to be invalidated whenever sqlite3_step() is called from within 
+    ** a v-table method.
+    */
+    if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
+      sqlite3ResetOneSchema(db, pOp->p1);
+    }
+    p->expired = 1;
+    rc = SQLITE_SCHEMA;
   }
   break;
 }
@@ -68343,21 +71129,20 @@ case OP_Transaction: {
 ** executing this instruction.
 */
 case OP_ReadCookie: {               /* out2-prerelease */
-#if 0  /* local variables moved into u.av */
   int iMeta;
   int iDb;
   int iCookie;
-#endif /* local variables moved into u.av */
 
-  u.av.iDb = pOp->p1;
-  u.av.iCookie = pOp->p3;
+  assert( p->bIsReader );
+  iDb = pOp->p1;
+  iCookie = pOp->p3;
   assert( pOp->p3<SQLITE_N_BTREE_META );
-  assert( u.av.iDb>=0 && u.av.iDb<db->nDb );
-  assert( db->aDb[u.av.iDb].pBt!=0 );
-  assert( (p->btreeMask & (((yDbMask)1)<<u.av.iDb))!=0 );
+  assert( iDb>=0 && iDb<db->nDb );
+  assert( db->aDb[iDb].pBt!=0 );
+  assert( DbMaskTest(p->btreeMask, iDb) );
 
-  sqlite3BtreeGetMeta(db->aDb[u.av.iDb].pBt, u.av.iCookie, (u32 *)&u.av.iMeta);
-  pOut->u.i = u.av.iMeta;
+  sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
+  pOut->u.i = iMeta;
   break;
 }
 
@@ -68372,26 +71157,25 @@ case OP_ReadCookie: {               /* out2-prerelease */
 ** A transaction must be started before executing this opcode.
 */
 case OP_SetCookie: {       /* in3 */
-#if 0  /* local variables moved into u.aw */
   Db *pDb;
-#endif /* local variables moved into u.aw */
   assert( pOp->p2<SQLITE_N_BTREE_META );
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
-  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.aw.pDb = &db->aDb[pOp->p1];
-  assert( u.aw.pDb->pBt!=0 );
+  assert( DbMaskTest(p->btreeMask, pOp->p1) );
+  assert( p->readOnly==0 );
+  pDb = &db->aDb[pOp->p1];
+  assert( pDb->pBt!=0 );
   assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
   pIn3 = &aMem[pOp->p3];
   sqlite3VdbeMemIntegerify(pIn3);
   /* See note about index shifting on OP_ReadCookie */
-  rc = sqlite3BtreeUpdateMeta(u.aw.pDb->pBt, pOp->p2, (int)pIn3->u.i);
+  rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i);
   if( pOp->p2==BTREE_SCHEMA_VERSION ){
     /* When the schema cookie changes, record the new cookie internally */
-    u.aw.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
+    pDb->pSchema->schema_cookie = (int)pIn3->u.i;
     db->flags |= SQLITE_InternChanges;
   }else if( pOp->p2==BTREE_FILE_FORMAT ){
     /* Record changes in the file format */
-    u.aw.pDb->pSchema->file_format = (u8)pIn3->u.i;
+    pDb->pSchema->file_format = (u8)pIn3->u.i;
   }
   if( pOp->p1==1 ){
     /* Invalidate all prepared statements whenever the TEMP database
@@ -68402,68 +71186,8 @@ case OP_SetCookie: {       /* in3 */
   break;
 }
 
-/* Opcode: VerifyCookie P1 P2 P3 * *
-**
-** Check the value of global database parameter number 0 (the
-** schema version) and make sure it is equal to P2 and that the
-** generation counter on the local schema parse equals P3.
-**
-** P1 is the database number which is 0 for the main database file
-** and 1 for the file holding temporary tables and some higher number
-** for auxiliary databases.
-**
-** The cookie changes its value whenever the database schema changes.
-** This operation is used to detect when that the cookie has changed
-** and that the current process needs to reread the schema.
-**
-** Either a transaction needs to have been started or an OP_Open needs
-** to be executed (to establish a read lock) before this opcode is
-** invoked.
-*/
-case OP_VerifyCookie: {
-#if 0  /* local variables moved into u.ax */
-  int iMeta;
-  int iGen;
-  Btree *pBt;
-#endif /* local variables moved into u.ax */
-
-  assert( pOp->p1>=0 && pOp->p1<db->nDb );
-  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
-  u.ax.pBt = db->aDb[pOp->p1].pBt;
-  if( u.ax.pBt ){
-    sqlite3BtreeGetMeta(u.ax.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ax.iMeta);
-    u.ax.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
-  }else{
-    u.ax.iGen = u.ax.iMeta = 0;
-  }
-  if( u.ax.iMeta!=pOp->p2 || u.ax.iGen!=pOp->p3 ){
-    sqlite3DbFree(db, p->zErrMsg);
-    p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
-    /* If the schema-cookie from the database file matches the cookie
-    ** stored with the in-memory representation of the schema, do
-    ** not reload the schema from the database file.
-    **
-    ** If virtual-tables are in use, this is not just an optimization.
-    ** Often, v-tables store their data in other SQLite tables, which
-    ** are queried from within xNext() and other v-table methods using
-    ** prepared queries. If such a query is out-of-date, we do not want to
-    ** discard the database schema, as the user code implementing the
-    ** v-table would have to be ready for the sqlite3_vtab structure itself
-    ** to be invalidated whenever sqlite3_step() is called from within
-    ** a v-table method.
-    */
-    if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ax.iMeta ){
-      sqlite3ResetOneSchema(db, pOp->p1);
-    }
-
-    p->expired = 1;
-    rc = SQLITE_SCHEMA;
-  }
-  break;
-}
-
 /* Opcode: OpenRead P1 P2 P3 P4 P5
+** Synopsis: root=P2 iDb=P3
 **
 ** Open a read-only cursor for the database table whose root page is
 ** P2 in a database file.  The database file is determined by P3. 
@@ -68491,9 +71215,24 @@ case OP_VerifyCookie: {
 ** sequence of the index being opened. Otherwise, if P4 is an integer 
 ** value, it is set to the number of columns in the table.
 **
-** See also OpenWrite.
+** See also: OpenWrite, ReopenIdx
+*/
+/* Opcode: ReopenIdx P1 P2 P3 P4 P5
+** Synopsis: root=P2 iDb=P3
+**
+** The ReopenIdx opcode works exactly like ReadOpen except that it first
+** checks to see if the cursor on P1 is already open with a root page
+** number of P2 and if it is this opcode becomes a no-op.  In other words,
+** if the cursor is already open, do not reopen it.
+**
+** The ReopenIdx opcode may only be used with P5==0 and with P4 being
+** a P4_KEYINFO object.  Furthermore, the P3 value must be the same as
+** every other ReopenIdx or OpenRead for the same cursor number.
+**
+** See the OpenRead opcode documentation for additional information.
 */
 /* Opcode: OpenWrite P1 P2 P3 P4 P5
+** Synopsis: root=P2 iDb=P3
 **
 ** Open a read/write cursor named P1 on the table or index whose root
 ** page is P2.  Or if P5!=0 use the content of register P2 to find the
@@ -68512,9 +71251,21 @@ case OP_VerifyCookie: {
 **
 ** See also OpenRead.
 */
+case OP_ReopenIdx: {
+  VdbeCursor *pCur;
+
+  assert( pOp->p5==0 );
+  assert( pOp->p4type==P4_KEYINFO );
+  pCur = p->apCsr[pOp->p1];
+  if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
+    assert( pCur->iDb==pOp->p3 );      /* Guaranteed by the code generator */
+    break;
+  }
+  /* If the cursor is not currently open or is open on a different
+  ** index, then fall through into OP_OpenRead to force a reopen */
+}
 case OP_OpenRead:
 case OP_OpenWrite: {
-#if 0  /* local variables moved into u.ay */
   int nField;
   KeyInfo *pKeyInfo;
   int p2;
@@ -68523,82 +71274,88 @@ case OP_OpenWrite: {
   Btree *pX;
   VdbeCursor *pCur;
   Db *pDb;
-#endif /* local variables moved into u.ay */
 
   assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
   assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
+  assert( p->bIsReader );
+  assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
+          || p->readOnly==0 );
 
   if( p->expired ){
     rc = SQLITE_ABORT;
     break;
   }
 
-  u.ay.nField = 0;
-  u.ay.pKeyInfo = 0;
-  u.ay.p2 = pOp->p2;
-  u.ay.iDb = pOp->p3;
-  assert( u.ay.iDb>=0 && u.ay.iDb<db->nDb );
-  assert( (p->btreeMask & (((yDbMask)1)<<u.ay.iDb))!=0 );
-  u.ay.pDb = &db->aDb[u.ay.iDb];
-  u.ay.pX = u.ay.pDb->pBt;
-  assert( u.ay.pX!=0 );
+  nField = 0;
+  pKeyInfo = 0;
+  p2 = pOp->p2;
+  iDb = pOp->p3;
+  assert( iDb>=0 && iDb<db->nDb );
+  assert( DbMaskTest(p->btreeMask, iDb) );
+  pDb = &db->aDb[iDb];
+  pX = pDb->pBt;
+  assert( pX!=0 );
   if( pOp->opcode==OP_OpenWrite ){
-    u.ay.wrFlag = 1;
-    assert( sqlite3SchemaMutexHeld(db, u.ay.iDb, 0) );
-    if( u.ay.pDb->pSchema->file_format < p->minWriteFileFormat ){
-      p->minWriteFileFormat = u.ay.pDb->pSchema->file_format;
+    wrFlag = 1;
+    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+    if( pDb->pSchema->file_format < p->minWriteFileFormat ){
+      p->minWriteFileFormat = pDb->pSchema->file_format;
     }
   }else{
-    u.ay.wrFlag = 0;
+    wrFlag = 0;
   }
   if( pOp->p5 & OPFLAG_P2ISREG ){
-    assert( u.ay.p2>0 );
-    assert( u.ay.p2<=p->nMem );
-    pIn2 = &aMem[u.ay.p2];
+    assert( p2>0 );
+    assert( p2<=(p->nMem-p->nCursor) );
+    pIn2 = &aMem[p2];
     assert( memIsValid(pIn2) );
     assert( (pIn2->flags & MEM_Int)!=0 );
     sqlite3VdbeMemIntegerify(pIn2);
-    u.ay.p2 = (int)pIn2->u.i;
-    /* The u.ay.p2 value always comes from a prior OP_CreateTable opcode and
-    ** that opcode will always set the u.ay.p2 value to 2 or more or else fail.
+    p2 = (int)pIn2->u.i;
+    /* The p2 value always comes from a prior OP_CreateTable opcode and
+    ** that opcode will always set the p2 value to 2 or more or else fail.
     ** If there were a failure, the prepared statement would have halted
     ** before reaching this instruction. */
-    if( NEVER(u.ay.p2<2) ) {
+    if( NEVER(p2<2) ) {
       rc = SQLITE_CORRUPT_BKPT;
       goto abort_due_to_error;
     }
   }
   if( pOp->p4type==P4_KEYINFO ){
-    u.ay.pKeyInfo = pOp->p4.pKeyInfo;
-    u.ay.pKeyInfo->enc = ENC(p->db);
-    u.ay.nField = u.ay.pKeyInfo->nField+1;
+    pKeyInfo = pOp->p4.pKeyInfo;
+    assert( pKeyInfo->enc==ENC(db) );
+    assert( pKeyInfo->db==db );
+    nField = pKeyInfo->nField+pKeyInfo->nXField;
   }else if( pOp->p4type==P4_INT32 ){
-    u.ay.nField = pOp->p4.i;
+    nField = pOp->p4.i;
   }
   assert( pOp->p1>=0 );
-  u.ay.pCur = allocateCursor(p, pOp->p1, u.ay.nField, u.ay.iDb, 1);
-  if( u.ay.pCur==0 ) goto no_mem;
-  u.ay.pCur->nullRow = 1;
-  u.ay.pCur->isOrdered = 1;
-  rc = sqlite3BtreeCursor(u.ay.pX, u.ay.p2, u.ay.wrFlag, u.ay.pKeyInfo, u.ay.pCur->pCursor);
-  u.ay.pCur->pKeyInfo = u.ay.pKeyInfo;
+  assert( nField>=0 );
+  testcase( nField==0 );  /* Table with INTEGER PRIMARY KEY and nothing else */
+  pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
+  if( pCur==0 ) goto no_mem;
+  pCur->nullRow = 1;
+  pCur->isOrdered = 1;
+  pCur->pgnoRoot = p2;
+  rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
+  pCur->pKeyInfo = pKeyInfo;
   assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
-  sqlite3BtreeCursorHints(u.ay.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
+  sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
 
   /* Since it performs no memory allocation or IO, the only value that
   ** sqlite3BtreeCursor() may return is SQLITE_OK. */
   assert( rc==SQLITE_OK );
 
-  /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
+  /* Set the VdbeCursor.isTable variable. Previous versions of
   ** SQLite used to check if the root-page flags were sane at this point
   ** and report database corruption if they were not, but this check has
-  ** since moved into the btree layer.  */
-  u.ay.pCur->isTable = pOp->p4type!=P4_KEYINFO;
-  u.ay.pCur->isIndex = !u.ay.pCur->isTable;
+  ** since moved into the btree layer.  */  
+  pCur->isTable = pOp->p4type!=P4_KEYINFO;
   break;
 }
 
 /* Opcode: OpenEphemeral P1 P2 * P4 P5
+** Synopsis: nColumn=P2
 **
 ** Open a new cursor P1 to a transient table.
 ** The cursor is always opened read/write even if 
@@ -68610,18 +71367,13 @@ case OP_OpenWrite: {
 ** if P4 is not 0.  If P4 is not NULL, it points to a KeyInfo structure
 ** that defines the format of keys in the index.
 **
-** This opcode was once called OpenTemp.  But that created
-** confusion because the term "temp table", might refer either
-** to a TEMP table at the SQL level, or to a table opened by
-** this opcode.  Then this opcode was call OpenVirtual.  But
-** that created confusion with the whole virtual-table idea.
-**
 ** The P5 parameter can be a mask of the BTREE_* flags defined
 ** in btree.h.  These flags control aspects of the operation of
 ** the btree.  The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
 ** added automatically.
 */
 /* Opcode: OpenAutoindex P1 P2 * P4 *
+** Synopsis: nColumn=P2
 **
 ** This opcode works the same as OP_OpenEphemeral.  It has a
 ** different name to distinguish its use.  Tables created using
@@ -68630,24 +71382,25 @@ case OP_OpenWrite: {
 */
 case OP_OpenAutoindex: 
 case OP_OpenEphemeral: {
-#if 0  /* local variables moved into u.az */
   VdbeCursor *pCx;
-#endif /* local variables moved into u.az */
-  static const int vfsFlags =
+  KeyInfo *pKeyInfo;
+
+  static const int vfsFlags = 
       SQLITE_OPEN_READWRITE |
       SQLITE_OPEN_CREATE |
       SQLITE_OPEN_EXCLUSIVE |
       SQLITE_OPEN_DELETEONCLOSE |
       SQLITE_OPEN_TRANSIENT_DB;
-
   assert( pOp->p1>=0 );
-  u.az.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
-  if( u.az.pCx==0 ) goto no_mem;
-  u.az.pCx->nullRow = 1;
-  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.az.pCx->pBt,
+  assert( pOp->p2>=0 );
+  pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+  if( pCx==0 ) goto no_mem;
+  pCx->nullRow = 1;
+  pCx->isEphemeral = 1;
+  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, 
                         BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
   if( rc==SQLITE_OK ){
-    rc = sqlite3BtreeBeginTrans(u.az.pCx->pBt, 1);
+    rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
   }
   if( rc==SQLITE_OK ){
     /* If a transient index is required, create it by calling
@@ -68655,25 +71408,24 @@ case OP_OpenEphemeral: {
     ** opening it. If a transient table is required, just use the
     ** automatically created table with root-page 1 (an BLOB_INTKEY table).
     */
-    if( pOp->p4.pKeyInfo ){
+    if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
       int pgno;
       assert( pOp->p4type==P4_KEYINFO );
-      rc = sqlite3BtreeCreateTable(u.az.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
+      rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5); 
       if( rc==SQLITE_OK ){
         assert( pgno==MASTER_ROOT+1 );
-        rc = sqlite3BtreeCursor(u.az.pCx->pBt, pgno, 1,
-                                (KeyInfo*)pOp->p4.z, u.az.pCx->pCursor);
-        u.az.pCx->pKeyInfo = pOp->p4.pKeyInfo;
-        u.az.pCx->pKeyInfo->enc = ENC(p->db);
+        assert( pKeyInfo->db==db );
+        assert( pKeyInfo->enc==ENC(db) );
+        pCx->pKeyInfo = pKeyInfo;
+        rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor);
       }
-      u.az.pCx->isTable = 0;
+      pCx->isTable = 0;
     }else{
-      rc = sqlite3BtreeCursor(u.az.pCx->pBt, MASTER_ROOT, 1, 0, u.az.pCx->pCursor);
-      u.az.pCx->isTable = 1;
+      rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
+      pCx->isTable = 1;
     }
   }
-  u.az.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
-  u.az.pCx->isIndex = !u.az.pCx->isTable;
+  pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
   break;
 }
 
@@ -68684,26 +71436,26 @@ case OP_OpenEphemeral: {
 ** tables using an external merge-sort algorithm.
 */
 case OP_SorterOpen: {
-#if 0  /* local variables moved into u.ba */
   VdbeCursor *pCx;
-#endif /* local variables moved into u.ba */
-
-  u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
-  if( u.ba.pCx==0 ) goto no_mem;
-  u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo;
-  u.ba.pCx->pKeyInfo->enc = ENC(p->db);
-  u.ba.pCx->isSorter = 1;
-  rc = sqlite3VdbeSorterInit(db, u.ba.pCx);
+
+  assert( pOp->p1>=0 );
+  assert( pOp->p2>=0 );
+  pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+  if( pCx==0 ) goto no_mem;
+  pCx->pKeyInfo = pOp->p4.pKeyInfo;
+  assert( pCx->pKeyInfo->db==db );
+  assert( pCx->pKeyInfo->enc==ENC(db) );
+  rc = sqlite3VdbeSorterInit(db, pCx);
   break;
 }
 
-/* Opcode: OpenPseudo P1 P2 P3 * P5
+/* Opcode: OpenPseudo P1 P2 P3 * *
+** Synopsis: P3 columns in r[P2]
 **
 ** Open a new cursor that points to a fake table that contains a single
-** row of data.  The content of that one row in the content of memory
-** register P2 when P5==0.  In other words, cursor P1 becomes an alias for the 
-** MEM_Blob content contained in register P2.  When P5==1, then the
-** row is represented by P3 consecutive registers beginning with P2.
+** row of data.  The content of that one row is the content of memory
+** register P2.  In other words, cursor P1 becomes an alias for the 
+** MEM_Blob content contained in register P2.
 **
 ** A pseudo-table created by this opcode is used to hold a single
 ** row output from the sorter so that the row can be decomposed into
@@ -68714,18 +71466,16 @@ case OP_SorterOpen: {
 ** the pseudo-table.
 */
 case OP_OpenPseudo: {
-#if 0  /* local variables moved into u.bb */
   VdbeCursor *pCx;
-#endif /* local variables moved into u.bb */
 
   assert( pOp->p1>=0 );
-  u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
-  if( u.bb.pCx==0 ) goto no_mem;
-  u.bb.pCx->nullRow = 1;
-  u.bb.pCx->pseudoTableReg = pOp->p2;
-  u.bb.pCx->isTable = 1;
-  u.bb.pCx->isIndex = 0;
-  u.bb.pCx->multiPseudo = pOp->p5;
+  assert( pOp->p3>=0 );
+  pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
+  if( pCx==0 ) goto no_mem;
+  pCx->nullRow = 1;
+  pCx->pseudoTableReg = pOp->p2;
+  pCx->isTable = 1;
+  assert( pOp->p5==0 );
   break;
 }
 
@@ -68741,7 +71491,8 @@ case OP_Close: {
   break;
 }
 
-/* Opcode: SeekGe P1 P2 P3 P4 *
+/* Opcode: SeekGE P1 P2 P3 P4 *
+** Synopsis: key=r[P3 at P4]
 **
 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
 ** use the value in register P3 as the key.  If cursor P1 refers 
@@ -68752,9 +71503,14 @@ case OP_Close: {
 ** is greater than or equal to the key value. If there are no records 
 ** greater than or equal to the key and P2 is not zero, then jump to P2.
 **
-** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
+** This opcode leaves the cursor configured to move in forward order,
+** from the beginning toward the end.  In other words, the cursor is
+** configured to use Next, not Prev.
+**
+** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
 */
-/* Opcode: SeekGt P1 P2 P3 P4 *
+/* Opcode: SeekGT P1 P2 P3 P4 *
+** Synopsis: key=r[P3 at P4]
 **
 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
 ** use the value in register P3 as a key. If cursor P1 refers 
@@ -68765,9 +71521,14 @@ case OP_Close: {
 ** is greater than the key value. If there are no records greater than 
 ** the key and P2 is not zero, then jump to P2.
 **
-** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
+** This opcode leaves the cursor configured to move in forward order,
+** from the beginning toward the end.  In other words, the cursor is
+** configured to use Next, not Prev.
+**
+** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
 */
-/* Opcode: SeekLt P1 P2 P3 P4 * 
+/* Opcode: SeekLT P1 P2 P3 P4 * 
+** Synopsis: key=r[P3 at P4]
 **
 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
 ** use the value in register P3 as a key. If cursor P1 refers 
@@ -68778,9 +71539,14 @@ case OP_Close: {
 ** is less than the key value. If there are no records less than 
 ** the key and P2 is not zero, then jump to P2.
 **
-** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
+** This opcode leaves the cursor configured to move in reverse order,
+** from the end toward the beginning.  In other words, the cursor is
+** configured to use Prev, not Next.
+**
+** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
 */
-/* Opcode: SeekLe P1 P2 P3 P4 *
+/* Opcode: SeekLE P1 P2 P3 P4 *
+** Synopsis: key=r[P3 at P4]
 **
 ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
 ** use the value in register P3 as a key. If cursor P1 refers 
@@ -68791,163 +71557,157 @@ case OP_Close: {
 ** is less than or equal to the key value. If there are no records 
 ** less than or equal to the key and P2 is not zero, then jump to P2.
 **
-** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
+** This opcode leaves the cursor configured to move in reverse order,
+** from the end toward the beginning.  In other words, the cursor is
+** configured to use Prev, not Next.
+**
+** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
 */
-case OP_SeekLt:         /* jump, in3 */
-case OP_SeekLe:         /* jump, in3 */
-case OP_SeekGe:         /* jump, in3 */
-case OP_SeekGt: {       /* jump, in3 */
-#if 0  /* local variables moved into u.bc */
+case OP_SeekLT:         /* jump, in3 */
+case OP_SeekLE:         /* jump, in3 */
+case OP_SeekGE:         /* jump, in3 */
+case OP_SeekGT: {       /* jump, in3 */
   int res;
   int oc;
   VdbeCursor *pC;
   UnpackedRecord r;
   int nField;
   i64 iKey;      /* The rowid we are to seek to */
-#endif /* local variables moved into u.bc */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   assert( pOp->p2!=0 );
-  u.bc.pC = p->apCsr[pOp->p1];
-  assert( u.bc.pC!=0 );
-  assert( u.bc.pC->pseudoTableReg==0 );
-  assert( OP_SeekLe == OP_SeekLt+1 );
-  assert( OP_SeekGe == OP_SeekLt+2 );
-  assert( OP_SeekGt == OP_SeekLt+3 );
-  assert( u.bc.pC->isOrdered );
-  if( ALWAYS(u.bc.pC->pCursor!=0) ){
-    u.bc.oc = pOp->opcode;
-    u.bc.pC->nullRow = 0;
-    if( u.bc.pC->isTable ){
-      /* The input value in P3 might be of any type: integer, real, string,
-      ** blob, or NULL.  But it needs to be an integer before we can do
-      ** the seek, so covert it. */
-      pIn3 = &aMem[pOp->p3];
-      applyNumericAffinity(pIn3);
-      u.bc.iKey = sqlite3VdbeIntValue(pIn3);
-      u.bc.pC->rowidIsValid = 0;
-
-      /* If the P3 value could not be converted into an integer without
-      ** loss of information, then special processing is required... */
-      if( (pIn3->flags & MEM_Int)==0 ){
-        if( (pIn3->flags & MEM_Real)==0 ){
-          /* If the P3 value cannot be converted into any kind of a number,
-          ** then the seek is not possible, so jump to P2 */
-          pc = pOp->p2 - 1;
-          break;
-        }
-        /* If we reach this point, then the P3 value must be a floating
-        ** point number. */
-        assert( (pIn3->flags & MEM_Real)!=0 );
-
-        if( u.bc.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bc.iKey || pIn3->r>0) ){
-          /* The P3 value is too large in magnitude to be expressed as an
-          ** integer. */
-          u.bc.res = 1;
-          if( pIn3->r<0 ){
-            if( u.bc.oc>=OP_SeekGe ){  assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
-              rc = sqlite3BtreeFirst(u.bc.pC->pCursor, &u.bc.res);
-              if( rc!=SQLITE_OK ) goto abort_due_to_error;
-            }
-          }else{
-            if( u.bc.oc<=OP_SeekLe ){  assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
-              rc = sqlite3BtreeLast(u.bc.pC->pCursor, &u.bc.res);
-              if( rc!=SQLITE_OK ) goto abort_due_to_error;
-            }
-          }
-          if( u.bc.res ){
-            pc = pOp->p2 - 1;
-          }
-          break;
-        }else if( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekGe ){
-          /* Use the ceiling() function to convert real->int */
-          if( pIn3->r > (double)u.bc.iKey ) u.bc.iKey++;
-        }else{
-          /* Use the floor() function to convert real->int */
-          assert( u.bc.oc==OP_SeekLe || u.bc.oc==OP_SeekGt );
-          if( pIn3->r < (double)u.bc.iKey ) u.bc.iKey--;
-        }
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  assert( pC->pseudoTableReg==0 );
+  assert( OP_SeekLE == OP_SeekLT+1 );
+  assert( OP_SeekGE == OP_SeekLT+2 );
+  assert( OP_SeekGT == OP_SeekLT+3 );
+  assert( pC->isOrdered );
+  assert( pC->pCursor!=0 );
+  oc = pOp->opcode;
+  pC->nullRow = 0;
+#ifdef SQLITE_DEBUG
+  pC->seekOp = pOp->opcode;
+#endif
+  if( pC->isTable ){
+    /* The input value in P3 might be of any type: integer, real, string,
+    ** blob, or NULL.  But it needs to be an integer before we can do
+    ** the seek, so covert it. */
+    pIn3 = &aMem[pOp->p3];
+    ApplyNumericAffinity(pIn3);
+    iKey = sqlite3VdbeIntValue(pIn3);
+    pC->rowidIsValid = 0;
+
+    /* If the P3 value could not be converted into an integer without
+    ** loss of information, then special processing is required... */
+    if( (pIn3->flags & MEM_Int)==0 ){
+      if( (pIn3->flags & MEM_Real)==0 ){
+        /* If the P3 value cannot be converted into any kind of a number,
+        ** then the seek is not possible, so jump to P2 */
+        pc = pOp->p2 - 1;  VdbeBranchTaken(1,2);
+        break;
       }
-      rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, 0, (u64)u.bc.iKey, 0, &u.bc.res);
-      if( rc!=SQLITE_OK ){
-        goto abort_due_to_error;
+
+      /* If the approximation iKey is larger than the actual real search
+      ** term, substitute >= for > and < for <=. e.g. if the search term
+      ** is 4.9 and the integer approximation 5:
+      **
+      **        (x >  4.9)    ->     (x >= 5)
+      **        (x <= 4.9)    ->     (x <  5)
+      */
+      if( pIn3->r<(double)iKey ){
+        assert( OP_SeekGE==(OP_SeekGT-1) );
+        assert( OP_SeekLT==(OP_SeekLE-1) );
+        assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
+        if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--;
       }
-      if( u.bc.res==0 ){
-        u.bc.pC->rowidIsValid = 1;
-        u.bc.pC->lastRowid = u.bc.iKey;
+
+      /* If the approximation iKey is smaller than the actual real search
+      ** term, substitute <= for < and > for >=.  */
+      else if( pIn3->r>(double)iKey ){
+        assert( OP_SeekLE==(OP_SeekLT+1) );
+        assert( OP_SeekGT==(OP_SeekGE+1) );
+        assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
+        if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
       }
-    }else{
-      u.bc.nField = pOp->p4.i;
-      assert( pOp->p4type==P4_INT32 );
-      assert( u.bc.nField>0 );
-      u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
-      u.bc.r.nField = (u16)u.bc.nField;
-
-      /* The next line of code computes as follows, only faster:
-      **   if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekLe ){
-      **     u.bc.r.flags = UNPACKED_INCRKEY;
-      **   }else{
-      **     u.bc.r.flags = 0;
-      **   }
-      */
-      u.bc.r.flags = (u8)(UNPACKED_INCRKEY * (1 & (u.bc.oc - OP_SeekLt)));
-      assert( u.bc.oc!=OP_SeekGt || u.bc.r.flags==UNPACKED_INCRKEY );
-      assert( u.bc.oc!=OP_SeekLe || u.bc.r.flags==UNPACKED_INCRKEY );
-      assert( u.bc.oc!=OP_SeekGe || u.bc.r.flags==0 );
-      assert( u.bc.oc!=OP_SeekLt || u.bc.r.flags==0 );
+    } 
+    rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
+    if( rc!=SQLITE_OK ){
+      goto abort_due_to_error;
+    }
+    if( res==0 ){
+      pC->rowidIsValid = 1;
+      pC->lastRowid = iKey;
+    }
+  }else{
+    nField = pOp->p4.i;
+    assert( pOp->p4type==P4_INT32 );
+    assert( nField>0 );
+    r.pKeyInfo = pC->pKeyInfo;
+    r.nField = (u16)nField;
+
+    /* The next line of code computes as follows, only faster:
+    **   if( oc==OP_SeekGT || oc==OP_SeekLE ){
+    **     r.default_rc = -1;
+    **   }else{
+    **     r.default_rc = +1;
+    **   }
+    */
+    r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1);
+    assert( oc!=OP_SeekGT || r.default_rc==-1 );
+    assert( oc!=OP_SeekLE || r.default_rc==-1 );
+    assert( oc!=OP_SeekGE || r.default_rc==+1 );
+    assert( oc!=OP_SeekLT || r.default_rc==+1 );
 
-      u.bc.r.aMem = &aMem[pOp->p3];
+    r.aMem = &aMem[pOp->p3];
 #ifdef SQLITE_DEBUG
-      { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
+    { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
 #endif
-      ExpandBlob(u.bc.r.aMem);
-      rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, &u.bc.r, 0, 0, &u.bc.res);
-      if( rc!=SQLITE_OK ){
-        goto abort_due_to_error;
-      }
-      u.bc.pC->rowidIsValid = 0;
+    ExpandBlob(r.aMem);
+    rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
+    if( rc!=SQLITE_OK ){
+      goto abort_due_to_error;
     }
-    u.bc.pC->deferredMoveto = 0;
-    u.bc.pC->cacheStatus = CACHE_STALE;
+    pC->rowidIsValid = 0;
+  }
+  pC->deferredMoveto = 0;
+  pC->cacheStatus = CACHE_STALE;
 #ifdef SQLITE_TEST
-    sqlite3_search_count++;
+  sqlite3_search_count++;
 #endif
-    if( u.bc.oc>=OP_SeekGe ){  assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
-      if( u.bc.res<0 || (u.bc.res==0 && u.bc.oc==OP_SeekGt) ){
-        rc = sqlite3BtreeNext(u.bc.pC->pCursor, &u.bc.res);
-        if( rc!=SQLITE_OK ) goto abort_due_to_error;
-        u.bc.pC->rowidIsValid = 0;
-      }else{
-        u.bc.res = 0;
-      }
+  if( oc>=OP_SeekGE ){  assert( oc==OP_SeekGE || oc==OP_SeekGT );
+    if( res<0 || (res==0 && oc==OP_SeekGT) ){
+      res = 0;
+      rc = sqlite3BtreeNext(pC->pCursor, &res);
+      if( rc!=SQLITE_OK ) goto abort_due_to_error;
+      pC->rowidIsValid = 0;
     }else{
-      assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
-      if( u.bc.res>0 || (u.bc.res==0 && u.bc.oc==OP_SeekLt) ){
-        rc = sqlite3BtreePrevious(u.bc.pC->pCursor, &u.bc.res);
-        if( rc!=SQLITE_OK ) goto abort_due_to_error;
-        u.bc.pC->rowidIsValid = 0;
-      }else{
-        /* u.bc.res might be negative because the table is empty.  Check to
-        ** see if this is the case.
-        */
-        u.bc.res = sqlite3BtreeEof(u.bc.pC->pCursor);
-      }
-    }
-    assert( pOp->p2>0 );
-    if( u.bc.res ){
-      pc = pOp->p2 - 1;
+      res = 0;
     }
   }else{
-    /* This happens when attempting to open the sqlite3_master table
-    ** for read access returns SQLITE_EMPTY. In this case always
-    ** take the jump (since there are no records in the table).
-    */
+    assert( oc==OP_SeekLT || oc==OP_SeekLE );
+    if( res>0 || (res==0 && oc==OP_SeekLT) ){
+      res = 0;
+      rc = sqlite3BtreePrevious(pC->pCursor, &res);
+      if( rc!=SQLITE_OK ) goto abort_due_to_error;
+      pC->rowidIsValid = 0;
+    }else{
+      /* res might be negative because the table is empty.  Check to
+      ** see if this is the case.
+      */
+      res = sqlite3BtreeEof(pC->pCursor);
+    }
+  }
+  assert( pOp->p2>0 );
+  VdbeBranchTaken(res!=0,2);
+  if( res ){
     pc = pOp->p2 - 1;
   }
   break;
 }
 
 /* Opcode: Seek P1 P2 * * *
+** Synopsis:  intkey=r[P2]
 **
 ** P1 is an open table cursor and P2 is a rowid integer.  Arrange
 ** for P1 to move so that it points to the rowid given by P2.
@@ -68957,26 +71717,24 @@ case OP_SeekGt: {       /* jump, in3 */
 ** occur, no unnecessary I/O happens.
 */
 case OP_Seek: {    /* in2 */
-#if 0  /* local variables moved into u.bd */
   VdbeCursor *pC;
-#endif /* local variables moved into u.bd */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bd.pC = p->apCsr[pOp->p1];
-  assert( u.bd.pC!=0 );
-  if( ALWAYS(u.bd.pC->pCursor!=0) ){
-    assert( u.bd.pC->isTable );
-    u.bd.pC->nullRow = 0;
-    pIn2 = &aMem[pOp->p2];
-    u.bd.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
-    u.bd.pC->rowidIsValid = 0;
-    u.bd.pC->deferredMoveto = 1;
-  }
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  assert( pC->pCursor!=0 );
+  assert( pC->isTable );
+  pC->nullRow = 0;
+  pIn2 = &aMem[pOp->p2];
+  pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
+  pC->rowidIsValid = 0;
+  pC->deferredMoveto = 1;
   break;
 }
   
 
 /* Opcode: Found P1 P2 P3 P4 *
+** Synopsis: key=r[P3 at P4]
 **
 ** If P4==0 then register P3 holds a blob constructed by MakeRecord.  If
 ** P4>0 then register P3 is the first of P4 registers that form an unpacked
@@ -68985,8 +71743,15 @@ case OP_Seek: {    /* in2 */
 ** Cursor P1 is on an index btree.  If the record identified by P3 and P4
 ** is a prefix of any entry in P1 then a jump is made to P2 and
 ** P1 is left pointing at the matching entry.
+**
+** This operation leaves the cursor in a state where it can be
+** advanced in the forward direction.  The Next instruction will work,
+** but not the Prev instruction.
+**
+** See also: NotFound, NoConflict, NotExists. SeekGe
 */
 /* Opcode: NotFound P1 P2 P3 P4 *
+** Synopsis: key=r[P3 at P4]
 **
 ** If P4==0 then register P3 holds a blob constructed by MakeRecord.  If
 ** P4>0 then register P3 is the first of P4 registers that form an unpacked
@@ -68998,216 +71763,172 @@ case OP_Seek: {    /* in2 */
 ** falls through to the next instruction and P1 is left pointing at the
 ** matching entry.
 **
-** See also: Found, NotExists, IsUnique
+** This operation leaves the cursor in a state where it cannot be
+** advanced in either direction.  In other words, the Next and Prev
+** opcodes do not work after this operation.
+**
+** See also: Found, NotExists, NoConflict
 */
+/* Opcode: NoConflict P1 P2 P3 P4 *
+** Synopsis: key=r[P3 at P4]
+**
+** If P4==0 then register P3 holds a blob constructed by MakeRecord.  If
+** P4>0 then register P3 is the first of P4 registers that form an unpacked
+** record.
+** 
+** Cursor P1 is on an index btree.  If the record identified by P3 and P4
+** contains any NULL value, jump immediately to P2.  If all terms of the
+** record are not-NULL then a check is done to determine if any row in the
+** P1 index btree has a matching key prefix.  If there are no matches, jump
+** immediately to P2.  If there is a match, fall through and leave the P1
+** cursor pointing to the matching row.
+**
+** This opcode is similar to OP_NotFound with the exceptions that the
+** branch is always taken if any part of the search key input is NULL.
+**
+** This operation leaves the cursor in a state where it cannot be
+** advanced in either direction.  In other words, the Next and Prev
+** opcodes do not work after this operation.
+**
+** See also: NotFound, Found, NotExists
+*/
+case OP_NoConflict:     /* jump, in3 */
 case OP_NotFound:       /* jump, in3 */
 case OP_Found: {        /* jump, in3 */
-#if 0  /* local variables moved into u.be */
   int alreadyExists;
+  int ii;
   VdbeCursor *pC;
   int res;
   char *pFree;
   UnpackedRecord *pIdxKey;
   UnpackedRecord r;
-  char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-#endif /* local variables moved into u.be */
+  char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7];
 
 #ifdef SQLITE_TEST
-  sqlite3_found_count++;
+  if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
 #endif
 
-  u.be.alreadyExists = 0;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   assert( pOp->p4type==P4_INT32 );
-  u.be.pC = p->apCsr[pOp->p1];
-  assert( u.be.pC!=0 );
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+#ifdef SQLITE_DEBUG
+  pC->seekOp = pOp->opcode;
+#endif
   pIn3 = &aMem[pOp->p3];
-  if( ALWAYS(u.be.pC->pCursor!=0) ){
-
-    assert( u.be.pC->isTable==0 );
-    if( pOp->p4.i>0 ){
-      u.be.r.pKeyInfo = u.be.pC->pKeyInfo;
-      u.be.r.nField = (u16)pOp->p4.i;
-      u.be.r.aMem = pIn3;
+  assert( pC->pCursor!=0 );
+  assert( pC->isTable==0 );
+  pFree = 0;  /* Not needed.  Only used to suppress a compiler warning. */
+  if( pOp->p4.i>0 ){
+    r.pKeyInfo = pC->pKeyInfo;
+    r.nField = (u16)pOp->p4.i;
+    r.aMem = pIn3;
+    for(ii=0; ii<r.nField; ii++){
+      assert( memIsValid(&r.aMem[ii]) );
+      ExpandBlob(&r.aMem[ii]);
 #ifdef SQLITE_DEBUG
-      { int i; for(i=0; i<u.be.r.nField; i++) assert( memIsValid(&u.be.r.aMem[i]) ); }
+      if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
 #endif
-      u.be.r.flags = UNPACKED_PREFIX_MATCH;
-      u.be.pIdxKey = &u.be.r;
-    }else{
-      u.be.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
-          u.be.pC->pKeyInfo, u.be.aTempRec, sizeof(u.be.aTempRec), &u.be.pFree
-      );
-      if( u.be.pIdxKey==0 ) goto no_mem;
-      assert( pIn3->flags & MEM_Blob );
-      assert( (pIn3->flags & MEM_Zero)==0 );  /* zeroblobs already expanded */
-      sqlite3VdbeRecordUnpack(u.be.pC->pKeyInfo, pIn3->n, pIn3->z, u.be.pIdxKey);
-      u.be.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
     }
-    rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, u.be.pIdxKey, 0, 0, &u.be.res);
-    if( pOp->p4.i==0 ){
-      sqlite3DbFree(db, u.be.pFree);
-    }
-    if( rc!=SQLITE_OK ){
-      break;
+    pIdxKey = &r;
+  }else{
+    pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+        pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
+    ); 
+    if( pIdxKey==0 ) goto no_mem;
+    assert( pIn3->flags & MEM_Blob );
+    assert( (pIn3->flags & MEM_Zero)==0 );  /* zeroblobs already expanded */
+    sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
+  }
+  pIdxKey->default_rc = 0;
+  if( pOp->opcode==OP_NoConflict ){
+    /* For the OP_NoConflict opcode, take the jump if any of the
+    ** input fields are NULL, since any key with a NULL will not
+    ** conflict */
+    for(ii=0; ii<r.nField; ii++){
+      if( r.aMem[ii].flags & MEM_Null ){
+        pc = pOp->p2 - 1; VdbeBranchTaken(1,2);
+        break;
+      }
     }
-    u.be.alreadyExists = (u.be.res==0);
-    u.be.pC->deferredMoveto = 0;
-    u.be.pC->cacheStatus = CACHE_STALE;
   }
-  if( pOp->opcode==OP_Found ){
-    if( u.be.alreadyExists ) pc = pOp->p2 - 1;
-  }else{
-    if( !u.be.alreadyExists ) pc = pOp->p2 - 1;
+  rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
+  if( pOp->p4.i==0 ){
+    sqlite3DbFree(db, pFree);
   }
-  break;
-}
-
-/* Opcode: IsUnique P1 P2 P3 P4 *
-**
-** Cursor P1 is open on an index b-tree - that is to say, a btree which
-** no data and where the key are records generated by OP_MakeRecord with
-** the list field being the integer ROWID of the entry that the index
-** entry refers to.
-**
-** The P3 register contains an integer record number. Call this record 
-** number R. Register P4 is the first in a set of N contiguous registers
-** that make up an unpacked index key that can be used with cursor P1.
-** The value of N can be inferred from the cursor. N includes the rowid
-** value appended to the end of the index record. This rowid value may
-** or may not be the same as R.
-**
-** If any of the N registers beginning with register P4 contains a NULL
-** value, jump immediately to P2.
-**
-** Otherwise, this instruction checks if cursor P1 contains an entry
-** where the first (N-1) fields match but the rowid value at the end
-** of the index entry is not R. If there is no such entry, control jumps
-** to instruction P2. Otherwise, the rowid of the conflicting index
-** entry is copied to register P3 and control falls through to the next
-** instruction.
-**
-** See also: NotFound, NotExists, Found
-*/
-case OP_IsUnique: {        /* jump, in3 */
-#if 0  /* local variables moved into u.bf */
-  u16 ii;
-  VdbeCursor *pCx;
-  BtCursor *pCrsr;
-  u16 nField;
-  Mem *aMx;
-  UnpackedRecord r;                  /* B-Tree index search key */
-  i64 R;                             /* Rowid stored in register P3 */
-#endif /* local variables moved into u.bf */
-
-  pIn3 = &aMem[pOp->p3];
-  u.bf.aMx = &aMem[pOp->p4.i];
-  /* Assert that the values of parameters P1 and P4 are in range. */
-  assert( pOp->p4type==P4_INT32 );
-  assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
-  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
-  /* Find the index cursor. */
-  u.bf.pCx = p->apCsr[pOp->p1];
-  assert( u.bf.pCx->deferredMoveto==0 );
-  u.bf.pCx->seekResult = 0;
-  u.bf.pCx->cacheStatus = CACHE_STALE;
-  u.bf.pCrsr = u.bf.pCx->pCursor;
-
-  /* If any of the values are NULL, take the jump. */
-  u.bf.nField = u.bf.pCx->pKeyInfo->nField;
-  for(u.bf.ii=0; u.bf.ii<u.bf.nField; u.bf.ii++){
-    if( u.bf.aMx[u.bf.ii].flags & MEM_Null ){
-      pc = pOp->p2 - 1;
-      u.bf.pCrsr = 0;
-      break;
-    }
+  if( rc!=SQLITE_OK ){
+    break;
   }
-  assert( (u.bf.aMx[u.bf.nField].flags & MEM_Null)==0 );
-
-  if( u.bf.pCrsr!=0 ){
-    /* Populate the index search key. */
-    u.bf.r.pKeyInfo = u.bf.pCx->pKeyInfo;
-    u.bf.r.nField = u.bf.nField + 1;
-    u.bf.r.flags = UNPACKED_PREFIX_SEARCH;
-    u.bf.r.aMem = u.bf.aMx;
-#ifdef SQLITE_DEBUG
-    { int i; for(i=0; i<u.bf.r.nField; i++) assert( memIsValid(&u.bf.r.aMem[i]) ); }
-#endif
-
-    /* Extract the value of u.bf.R from register P3. */
-    sqlite3VdbeMemIntegerify(pIn3);
-    u.bf.R = pIn3->u.i;
-
-    /* Search the B-Tree index. If no conflicting record is found, jump
-    ** to P2. Otherwise, copy the rowid of the conflicting record to
-    ** register P3 and fall through to the next instruction.  */
-    rc = sqlite3BtreeMovetoUnpacked(u.bf.pCrsr, &u.bf.r, 0, 0, &u.bf.pCx->seekResult);
-    if( (u.bf.r.flags & UNPACKED_PREFIX_SEARCH) || u.bf.r.rowid==u.bf.R ){
-      pc = pOp->p2 - 1;
-    }else{
-      pIn3->u.i = u.bf.r.rowid;
-    }
+  pC->seekResult = res;
+  alreadyExists = (res==0);
+  pC->nullRow = 1-alreadyExists;
+  pC->deferredMoveto = 0;
+  pC->cacheStatus = CACHE_STALE;
+  if( pOp->opcode==OP_Found ){
+    VdbeBranchTaken(alreadyExists!=0,2);
+    if( alreadyExists ) pc = pOp->p2 - 1;
+  }else{
+    VdbeBranchTaken(alreadyExists==0,2);
+    if( !alreadyExists ) pc = pOp->p2 - 1;
   }
   break;
 }
 
 /* Opcode: NotExists P1 P2 P3 * *
+** Synopsis: intkey=r[P3]
 **
-** Use the content of register P3 as an integer key.  If a record 
-** with that key does not exist in table of P1, then jump to P2. 
-** If the record does exist, then fall through.  The cursor is left 
-** pointing to the record if it exists.
+** P1 is the index of a cursor open on an SQL table btree (with integer
+** keys).  P3 is an integer rowid.  If P1 does not contain a record with
+** rowid P3 then jump immediately to P2.  If P1 does contain a record
+** with rowid P3 then leave the cursor pointing at that record and fall
+** through to the next instruction.
 **
-** The difference between this operation and NotFound is that this
-** operation assumes the key is an integer and that P1 is a table whereas
-** NotFound assumes key is a blob constructed from MakeRecord and
-** P1 is an index.
+** The OP_NotFound opcode performs the same operation on index btrees
+** (with arbitrary multi-value keys).
 **
-** See also: Found, NotFound, IsUnique
+** This opcode leaves the cursor in a state where it cannot be advanced
+** in either direction.  In other words, the Next and Prev opcodes will
+** not work following this opcode.
+**
+** See also: Found, NotFound, NoConflict
 */
 case OP_NotExists: {        /* jump, in3 */
-#if 0  /* local variables moved into u.bg */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
   u64 iKey;
-#endif /* local variables moved into u.bg */
 
   pIn3 = &aMem[pOp->p3];
   assert( pIn3->flags & MEM_Int );
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bg.pC = p->apCsr[pOp->p1];
-  assert( u.bg.pC!=0 );
-  assert( u.bg.pC->isTable );
-  assert( u.bg.pC->pseudoTableReg==0 );
-  u.bg.pCrsr = u.bg.pC->pCursor;
-  if( ALWAYS(u.bg.pCrsr!=0) ){
-    u.bg.res = 0;
-    u.bg.iKey = pIn3->u.i;
-    rc = sqlite3BtreeMovetoUnpacked(u.bg.pCrsr, 0, u.bg.iKey, 0, &u.bg.res);
-    u.bg.pC->lastRowid = pIn3->u.i;
-    u.bg.pC->rowidIsValid = u.bg.res==0 ?1:0;
-    u.bg.pC->nullRow = 0;
-    u.bg.pC->cacheStatus = CACHE_STALE;
-    u.bg.pC->deferredMoveto = 0;
-    if( u.bg.res!=0 ){
-      pc = pOp->p2 - 1;
-      assert( u.bg.pC->rowidIsValid==0 );
-    }
-    u.bg.pC->seekResult = u.bg.res;
-  }else{
-    /* This happens when an attempt to open a read cursor on the
-    ** sqlite_master table returns SQLITE_EMPTY.
-    */
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+#ifdef SQLITE_DEBUG
+  pC->seekOp = 0;
+#endif
+  assert( pC->isTable );
+  assert( pC->pseudoTableReg==0 );
+  pCrsr = pC->pCursor;
+  assert( pCrsr!=0 );
+  res = 0;
+  iKey = pIn3->u.i;
+  rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
+  pC->lastRowid = pIn3->u.i;
+  pC->rowidIsValid = res==0 ?1:0;
+  pC->nullRow = 0;
+  pC->cacheStatus = CACHE_STALE;
+  pC->deferredMoveto = 0;
+  VdbeBranchTaken(res!=0,2);
+  if( res!=0 ){
     pc = pOp->p2 - 1;
-    assert( u.bg.pC->rowidIsValid==0 );
-    u.bg.pC->seekResult = 0;
+    assert( pC->rowidIsValid==0 );
   }
+  pC->seekResult = res;
   break;
 }
 
 /* Opcode: Sequence P1 P2 * * *
+** Synopsis: r[P2]=cursor[P1].ctr++
 **
 ** Find the next available sequence number for cursor P1.
 ** Write the sequence number into register P2.
@@ -69223,6 +71944,7 @@ case OP_Sequence: {           /* out2-prerelease */
 
 
 /* Opcode: NewRowid P1 P2 P3 * *
+** Synopsis: r[P2]=rowid
 **
 ** Get a new integer record number (a.k.a "rowid") used as the key to a table.
 ** The record number is not previously used as a key in the database
@@ -69237,21 +71959,19 @@ case OP_Sequence: {           /* out2-prerelease */
 ** AUTOINCREMENT feature.
 */
 case OP_NewRowid: {           /* out2-prerelease */
-#if 0  /* local variables moved into u.bh */
   i64 v;                 /* The new rowid */
   VdbeCursor *pC;        /* Cursor of table to get the new rowid */
   int res;               /* Result of an sqlite3BtreeLast() */
   int cnt;               /* Counter to limit the number of searches */
   Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
   VdbeFrame *pFrame;     /* Root frame of VDBE */
-#endif /* local variables moved into u.bh */
 
-  u.bh.v = 0;
-  u.bh.res = 0;
+  v = 0;
+  res = 0;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bh.pC = p->apCsr[pOp->p1];
-  assert( u.bh.pC!=0 );
-  if( NEVER(u.bh.pC->pCursor==0) ){
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  if( NEVER(pC->pCursor==0) ){
     /* The zero initialization above is all that is needed */
   }else{
     /* The next rowid or record number (different terms for the same
@@ -69267,7 +71987,7 @@ case OP_NewRowid: {           /* out2-prerelease */
     ** succeeded.  If the random rowid does exist, we select a new one
     ** and try again, up to 100 times.
     */
-    assert( u.bh.pC->isTable );
+    assert( pC->isTable );
 
 #ifdef SQLITE_32BIT_ROWID
 #   define MAX_ROWID 0x7fffffff
@@ -69279,61 +71999,56 @@ case OP_NewRowid: {           /* out2-prerelease */
 #   define MAX_ROWID  (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
 #endif
 
-    if( !u.bh.pC->useRandomRowid ){
-      u.bh.v = sqlite3BtreeGetCachedRowid(u.bh.pC->pCursor);
-      if( u.bh.v==0 ){
-        rc = sqlite3BtreeLast(u.bh.pC->pCursor, &u.bh.res);
-        if( rc!=SQLITE_OK ){
-          goto abort_due_to_error;
-        }
-        if( u.bh.res ){
-          u.bh.v = 1;   /* IMP: R-61914-48074 */
+    if( !pC->useRandomRowid ){
+      rc = sqlite3BtreeLast(pC->pCursor, &res);
+      if( rc!=SQLITE_OK ){
+        goto abort_due_to_error;
+      }
+      if( res ){
+        v = 1;   /* IMP: R-61914-48074 */
+      }else{
+        assert( sqlite3BtreeCursorIsValid(pC->pCursor) );
+        rc = sqlite3BtreeKeySize(pC->pCursor, &v);
+        assert( rc==SQLITE_OK );   /* Cannot fail following BtreeLast() */
+        if( v>=MAX_ROWID ){
+          pC->useRandomRowid = 1;
         }else{
-          assert( sqlite3BtreeCursorIsValid(u.bh.pC->pCursor) );
-          rc = sqlite3BtreeKeySize(u.bh.pC->pCursor, &u.bh.v);
-          assert( rc==SQLITE_OK );   /* Cannot fail following BtreeLast() */
-          if( u.bh.v>=MAX_ROWID ){
-            u.bh.pC->useRandomRowid = 1;
-          }else{
-            u.bh.v++;   /* IMP: R-29538-34987 */
-          }
+          v++;   /* IMP: R-29538-34987 */
         }
       }
+    }
 
 #ifndef SQLITE_OMIT_AUTOINCREMENT
-      if( pOp->p3 ){
+    if( pOp->p3 ){
+      /* Assert that P3 is a valid memory cell. */
+      assert( pOp->p3>0 );
+      if( p->pFrame ){
+        for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
         /* Assert that P3 is a valid memory cell. */
-        assert( pOp->p3>0 );
-        if( p->pFrame ){
-          for(u.bh.pFrame=p->pFrame; u.bh.pFrame->pParent; u.bh.pFrame=u.bh.pFrame->pParent);
-          /* Assert that P3 is a valid memory cell. */
-          assert( pOp->p3<=u.bh.pFrame->nMem );
-          u.bh.pMem = &u.bh.pFrame->aMem[pOp->p3];
-        }else{
-          /* Assert that P3 is a valid memory cell. */
-          assert( pOp->p3<=p->nMem );
-          u.bh.pMem = &aMem[pOp->p3];
-          memAboutToChange(p, u.bh.pMem);
-        }
-        assert( memIsValid(u.bh.pMem) );
-
-        REGISTER_TRACE(pOp->p3, u.bh.pMem);
-        sqlite3VdbeMemIntegerify(u.bh.pMem);
-        assert( (u.bh.pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
-        if( u.bh.pMem->u.i==MAX_ROWID || u.bh.pC->useRandomRowid ){
-          rc = SQLITE_FULL;   /* IMP: R-12275-61338 */
-          goto abort_due_to_error;
-        }
-        if( u.bh.v<u.bh.pMem->u.i+1 ){
-          u.bh.v = u.bh.pMem->u.i + 1;
-        }
-        u.bh.pMem->u.i = u.bh.v;
+        assert( pOp->p3<=pFrame->nMem );
+        pMem = &pFrame->aMem[pOp->p3];
+      }else{
+        /* Assert that P3 is a valid memory cell. */
+        assert( pOp->p3<=(p->nMem-p->nCursor) );
+        pMem = &aMem[pOp->p3];
+        memAboutToChange(p, pMem);
       }
-#endif
+      assert( memIsValid(pMem) );
 
-      sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, u.bh.v<MAX_ROWID ? u.bh.v+1 : 0);
+      REGISTER_TRACE(pOp->p3, pMem);
+      sqlite3VdbeMemIntegerify(pMem);
+      assert( (pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
+      if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
+        rc = SQLITE_FULL;   /* IMP: R-12275-61338 */
+        goto abort_due_to_error;
+      }
+      if( v<pMem->u.i+1 ){
+        v = pMem->u.i + 1;
+      }
+      pMem->u.i = v;
     }
-    if( u.bh.pC->useRandomRowid ){
+#endif
+    if( pC->useRandomRowid ){
       /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
       ** largest possible integer (9223372036854775807) then the database
       ** engine starts picking positive candidate ROWIDs at random until
@@ -69341,39 +72056,40 @@ case OP_NewRowid: {           /* out2-prerelease */
       assert( pOp->p3==0 );  /* We cannot be in random rowid mode if this is
                              ** an AUTOINCREMENT table. */
       /* on the first attempt, simply do one more than previous */
-      u.bh.v = lastRowid;
-      u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
-      u.bh.v++; /* ensure non-zero */
-      u.bh.cnt = 0;
-      while(   ((rc = sqlite3BtreeMovetoUnpacked(u.bh.pC->pCursor, 0, (u64)u.bh.v,
-                                                 0, &u.bh.res))==SQLITE_OK)
-            && (u.bh.res==0)
-            && (++u.bh.cnt<100)){
+      v = lastRowid;
+      v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+      v++; /* ensure non-zero */
+      cnt = 0;
+      while(   ((rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)v,
+                                                 0, &res))==SQLITE_OK)
+            && (res==0)
+            && (++cnt<100)){
         /* collision - try another random rowid */
-        sqlite3_randomness(sizeof(u.bh.v), &u.bh.v);
-        if( u.bh.cnt<5 ){
+        sqlite3_randomness(sizeof(v), &v);
+        if( cnt<5 ){
           /* try "small" random rowids for the initial attempts */
-          u.bh.v &= 0xffffff;
+          v &= 0xffffff;
         }else{
-          u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+          v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
         }
-        u.bh.v++; /* ensure non-zero */
+        v++; /* ensure non-zero */
       }
-      if( rc==SQLITE_OK && u.bh.res==0 ){
+      if( rc==SQLITE_OK && res==0 ){
         rc = SQLITE_FULL;   /* IMP: R-38219-53002 */
         goto abort_due_to_error;
       }
-      assert( u.bh.v>0 );  /* EV: R-40812-03570 */
+      assert( v>0 );  /* EV: R-40812-03570 */
     }
-    u.bh.pC->rowidIsValid = 0;
-    u.bh.pC->deferredMoveto = 0;
-    u.bh.pC->cacheStatus = CACHE_STALE;
+    pC->rowidIsValid = 0;
+    pC->deferredMoveto = 0;
+    pC->cacheStatus = CACHE_STALE;
   }
-  pOut->u.i = u.bh.v;
+  pOut->u.i = v;
   break;
 }
 
 /* Opcode: Insert P1 P2 P3 P4 P5
+** Synopsis: intkey=r[P3] data=r[P2]
 **
 ** Write an entry into the table of cursor P1.  A new entry is
 ** created if it doesn't already exist or the data for an existing
@@ -69413,13 +72129,13 @@ case OP_NewRowid: {           /* out2-prerelease */
 ** for indices is OP_IdxInsert.
 */
 /* Opcode: InsertInt P1 P2 P3 P4 P5
+** Synopsis:  intkey=P3 data=r[P2]
 **
 ** This works exactly like OP_Insert except that the key is the
 ** integer value P3, not the value of the integer stored in register P3.
 */
 case OP_Insert: 
 case OP_InsertInt: {
-#if 0  /* local variables moved into u.bi */
   Mem *pData;       /* MEM cell holding data for the record to be inserted */
   Mem *pKey;        /* MEM cell holding key  for the record */
   i64 iKey;         /* The integer ROWID or key for the record to be inserted */
@@ -69429,60 +72145,58 @@ case OP_InsertInt: {
   const char *zDb;  /* database name - used by the update hook */
   const char *zTbl; /* Table name - used by the opdate hook */
   int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
-#endif /* local variables moved into u.bi */
 
-  u.bi.pData = &aMem[pOp->p2];
+  pData = &aMem[pOp->p2];
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  assert( memIsValid(u.bi.pData) );
-  u.bi.pC = p->apCsr[pOp->p1];
-  assert( u.bi.pC!=0 );
-  assert( u.bi.pC->pCursor!=0 );
-  assert( u.bi.pC->pseudoTableReg==0 );
-  assert( u.bi.pC->isTable );
-  REGISTER_TRACE(pOp->p2, u.bi.pData);
+  assert( memIsValid(pData) );
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  assert( pC->pCursor!=0 );
+  assert( pC->pseudoTableReg==0 );
+  assert( pC->isTable );
+  REGISTER_TRACE(pOp->p2, pData);
 
   if( pOp->opcode==OP_Insert ){
-    u.bi.pKey = &aMem[pOp->p3];
-    assert( u.bi.pKey->flags & MEM_Int );
-    assert( memIsValid(u.bi.pKey) );
-    REGISTER_TRACE(pOp->p3, u.bi.pKey);
-    u.bi.iKey = u.bi.pKey->u.i;
+    pKey = &aMem[pOp->p3];
+    assert( pKey->flags & MEM_Int );
+    assert( memIsValid(pKey) );
+    REGISTER_TRACE(pOp->p3, pKey);
+    iKey = pKey->u.i;
   }else{
     assert( pOp->opcode==OP_InsertInt );
-    u.bi.iKey = pOp->p3;
+    iKey = pOp->p3;
   }
 
   if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
-  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bi.iKey;
-  if( u.bi.pData->flags & MEM_Null ){
-    u.bi.pData->z = 0;
-    u.bi.pData->n = 0;
+  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = iKey;
+  if( pData->flags & MEM_Null ){
+    pData->z = 0;
+    pData->n = 0;
   }else{
-    assert( u.bi.pData->flags & (MEM_Blob|MEM_Str) );
+    assert( pData->flags & (MEM_Blob|MEM_Str) );
   }
-  u.bi.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bi.pC->seekResult : 0);
-  if( u.bi.pData->flags & MEM_Zero ){
-    u.bi.nZero = u.bi.pData->u.nZero;
+  seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
+  if( pData->flags & MEM_Zero ){
+    nZero = pData->u.nZero;
   }else{
-    u.bi.nZero = 0;
+    nZero = 0;
   }
-  sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0);
-  rc = sqlite3BtreeInsert(u.bi.pC->pCursor, 0, u.bi.iKey,
-                          u.bi.pData->z, u.bi.pData->n, u.bi.nZero,
-                          pOp->p5 & OPFLAG_APPEND, u.bi.seekResult
+  rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
+                          pData->z, pData->n, nZero,
+                          (pOp->p5 & OPFLAG_APPEND)!=0, seekResult
   );
-  u.bi.pC->rowidIsValid = 0;
-  u.bi.pC->deferredMoveto = 0;
-  u.bi.pC->cacheStatus = CACHE_STALE;
+  pC->rowidIsValid = 0;
+  pC->deferredMoveto = 0;
+  pC->cacheStatus = CACHE_STALE;
 
   /* Invoke the update-hook if required. */
   if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
-    u.bi.zDb = db->aDb[u.bi.pC->iDb].zName;
-    u.bi.zTbl = pOp->p4.z;
-    u.bi.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
-    assert( u.bi.pC->isTable );
-    db->xUpdateCallback(db->pUpdateArg, u.bi.op, u.bi.zDb, u.bi.zTbl, u.bi.iKey);
-    assert( u.bi.pC->iDb>=0 );
+    zDb = db->aDb[pC->iDb].zName;
+    zTbl = pOp->p4.z;
+    op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
+    assert( pC->isTable );
+    db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey);
+    assert( pC->iDb>=0 );
   }
   break;
 }
@@ -69494,7 +72208,7 @@ case OP_InsertInt: {
 ** The cursor will be left pointing at either the next or the previous
 ** record in the table. If it is left pointing at the next record, then
 ** the next Next instruction will be a no-op.  Hence it is OK to delete
-** a record from within an Next loop.
+** a record from within a Next loop.
 **
 ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
 ** incremented (otherwise not).
@@ -69508,47 +72222,34 @@ case OP_InsertInt: {
 ** using OP_NotFound prior to invoking this opcode.
 */
 case OP_Delete: {
-#if 0  /* local variables moved into u.bj */
   i64 iKey;
   VdbeCursor *pC;
-#endif /* local variables moved into u.bj */
 
-  u.bj.iKey = 0;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bj.pC = p->apCsr[pOp->p1];
-  assert( u.bj.pC!=0 );
-  assert( u.bj.pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */
-
-  /* If the update-hook will be invoked, set u.bj.iKey to the rowid of the
-  ** row being deleted.
-  */
-  if( db->xUpdateCallback && pOp->p4.z ){
-    assert( u.bj.pC->isTable );
-    assert( u.bj.pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
-    u.bj.iKey = u.bj.pC->lastRowid;
-  }
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  assert( pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */
+  iKey = pC->lastRowid;      /* Only used for the update hook */
 
   /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
   ** OP_Column on the same table without any intervening operations that
-  ** might move or invalidate the cursor.  Hence cursor u.bj.pC is always pointing
+  ** might move or invalidate the cursor.  Hence cursor pC is always pointing
   ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
   ** below is always a no-op and cannot fail.  We will run it anyhow, though,
   ** to guard against future changes to the code generator.
   **/
-  assert( u.bj.pC->deferredMoveto==0 );
-  rc = sqlite3VdbeCursorMoveto(u.bj.pC);
+  assert( pC->deferredMoveto==0 );
+  rc = sqlite3VdbeCursorMoveto(pC);
   if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
 
-  sqlite3BtreeSetCachedRowid(u.bj.pC->pCursor, 0);
-  rc = sqlite3BtreeDelete(u.bj.pC->pCursor);
-  u.bj.pC->cacheStatus = CACHE_STALE;
+  rc = sqlite3BtreeDelete(pC->pCursor);
+  pC->cacheStatus = CACHE_STALE;
 
   /* Invoke the update-hook if required. */
-  if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
-    const char *zDb = db->aDb[u.bj.pC->iDb].zName;
-    const char *zTbl = pOp->p4.z;
-    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bj.iKey);
-    assert( u.bj.pC->iDb>=0 );
+  if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && pC->isTable ){
+    db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE,
+                        db->aDb[pC->iDb].zName, pOp->p4.z, iKey);
+    assert( pC->iDb>=0 );
   }
   if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
   break;
@@ -69566,46 +72267,57 @@ case OP_ResetCount: {
   break;
 }
 
-/* Opcode: SorterCompare P1 P2 P3
+/* Opcode: SorterCompare P1 P2 P3 P4
+** Synopsis:  if key(P1)!=trim(r[P3],P4) goto P2
+**
+** P1 is a sorter cursor. This instruction compares a prefix of the
+** record blob in register P3 against a prefix of the entry that 
+** the sorter cursor currently points to.  Only the first P4 fields
+** of r[P3] and the sorter record are compared.
 **
-** P1 is a sorter cursor. This instruction compares the record blob in 
-** register P3 with the entry that the sorter cursor currently points to.
-** If, excluding the rowid fields at the end, the two records are a match,
-** fall through to the next instruction. Otherwise, jump to instruction P2.
+** If either P3 or the sorter contains a NULL in one of their significant
+** fields (not counting the P4 fields at the end which are ignored) then
+** the comparison is assumed to be equal.
+**
+** Fall through to next instruction if the two records compare equal to
+** each other.  Jump to P2 if they are different.
 */
 case OP_SorterCompare: {
-#if 0  /* local variables moved into u.bk */
   VdbeCursor *pC;
   int res;
-#endif /* local variables moved into u.bk */
+  int nKeyCol;
 
-  u.bk.pC = p->apCsr[pOp->p1];
-  assert( isSorter(u.bk.pC) );
+  pC = p->apCsr[pOp->p1];
+  assert( isSorter(pC) );
+  assert( pOp->p4type==P4_INT32 );
   pIn3 = &aMem[pOp->p3];
-  rc = sqlite3VdbeSorterCompare(u.bk.pC, pIn3, &u.bk.res);
-  if( u.bk.res ){
+  nKeyCol = pOp->p4.i;
+  rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res);
+  VdbeBranchTaken(res!=0,2);
+  if( res ){
     pc = pOp->p2-1;
   }
   break;
 };
 
 /* Opcode: SorterData P1 P2 * * *
+** Synopsis: r[P2]=data
 **
 ** Write into register P2 the current sorter data for sorter cursor P1.
 */
 case OP_SorterData: {
-#if 0  /* local variables moved into u.bl */
   VdbeCursor *pC;
-#endif /* local variables moved into u.bl */
 
   pOut = &aMem[pOp->p2];
-  u.bl.pC = p->apCsr[pOp->p1];
-  assert( u.bl.pC->isSorter );
-  rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut);
+  pC = p->apCsr[pOp->p1];
+  assert( isSorter(pC) );
+  rc = sqlite3VdbeSorterRowkey(pC, pOut);
+  assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) );
   break;
 }
 
 /* Opcode: RowData P1 P2 * * *
+** Synopsis: r[P2]=data
 **
 ** Write into register P2 the complete row data for cursor P1.
 ** There is no interpretation of the data.  
@@ -69616,10 +72328,11 @@ case OP_SorterData: {
 ** of a real table, not a pseudo-table.
 */
 /* Opcode: RowKey P1 P2 * * *
+** Synopsis: r[P2]=key
 **
 ** Write into register P2 the complete row key for cursor P1.
 ** There is no interpretation of the data.  
-** The key is copied onto the P3 register exactly as 
+** The key is copied onto the P2 register exactly as 
 ** it is found in the database file.
 **
 ** If the P1 cursor must be pointing to a valid row (not a NULL row)
@@ -69627,69 +72340,69 @@ case OP_SorterData: {
 */
 case OP_RowKey:
 case OP_RowData: {
-#if 0  /* local variables moved into u.bm */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   u32 n;
   i64 n64;
-#endif /* local variables moved into u.bm */
 
   pOut = &aMem[pOp->p2];
   memAboutToChange(p, pOut);
 
   /* Note that RowKey and RowData are really exactly the same instruction */
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bm.pC = p->apCsr[pOp->p1];
-  assert( u.bm.pC->isSorter==0 );
-  assert( u.bm.pC->isTable || pOp->opcode!=OP_RowData );
-  assert( u.bm.pC->isIndex || pOp->opcode==OP_RowData );
-  assert( u.bm.pC!=0 );
-  assert( u.bm.pC->nullRow==0 );
-  assert( u.bm.pC->pseudoTableReg==0 );
-  assert( u.bm.pC->pCursor!=0 );
-  u.bm.pCrsr = u.bm.pC->pCursor;
-  assert( sqlite3BtreeCursorIsValid(u.bm.pCrsr) );
+  pC = p->apCsr[pOp->p1];
+  assert( isSorter(pC)==0 );
+  assert( pC->isTable || pOp->opcode!=OP_RowData );
+  assert( pC->isTable==0 || pOp->opcode==OP_RowData );
+  assert( pC!=0 );
+  assert( pC->nullRow==0 );
+  assert( pC->pseudoTableReg==0 );
+  assert( pC->pCursor!=0 );
+  pCrsr = pC->pCursor;
+  assert( sqlite3BtreeCursorIsValid(pCrsr) );
 
   /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
   ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
   ** the cursor.  Hence the following sqlite3VdbeCursorMoveto() call is always
   ** a no-op and can never fail.  But we leave it in place as a safety.
   */
-  assert( u.bm.pC->deferredMoveto==0 );
-  rc = sqlite3VdbeCursorMoveto(u.bm.pC);
+  assert( pC->deferredMoveto==0 );
+  rc = sqlite3VdbeCursorMoveto(pC);
   if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
 
-  if( u.bm.pC->isIndex ){
-    assert( !u.bm.pC->isTable );
-    VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bm.pCrsr, &u.bm.n64);
+  if( pC->isTable==0 ){
+    assert( !pC->isTable );
+    VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64);
     assert( rc==SQLITE_OK );    /* True because of CursorMoveto() call above */
-    if( u.bm.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+    if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
       goto too_big;
     }
-    u.bm.n = (u32)u.bm.n64;
+    n = (u32)n64;
   }else{
-    VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bm.pCrsr, &u.bm.n);
+    VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &n);
     assert( rc==SQLITE_OK );    /* DataSize() cannot fail */
-    if( u.bm.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+    if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
       goto too_big;
     }
   }
-  if( sqlite3VdbeMemGrow(pOut, u.bm.n, 0) ){
+  if( sqlite3VdbeMemGrow(pOut, n, 0) ){
     goto no_mem;
   }
-  pOut->n = u.bm.n;
+  pOut->n = n;
   MemSetTypeFlag(pOut, MEM_Blob);
-  if( u.bm.pC->isIndex ){
-    rc = sqlite3BtreeKey(u.bm.pCrsr, 0, u.bm.n, pOut->z);
+  if( pC->isTable==0 ){
+    rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
   }else{
-    rc = sqlite3BtreeData(u.bm.pCrsr, 0, u.bm.n, pOut->z);
+    rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
   }
   pOut->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
   UPDATE_MAX_BLOBSIZE(pOut);
+  REGISTER_TRACE(pOp->p2, pOut);
   break;
 }
 
 /* Opcode: Rowid P1 P2 * * *
+** Synopsis: r[P2]=rowid
 **
 ** Store in register P2 an integer which is the key of the table entry that
 ** P1 is currently point to.
@@ -69699,42 +72412,40 @@ case OP_RowData: {
 ** one opcode now works for both table types.
 */
 case OP_Rowid: {                 /* out2-prerelease */
-#if 0  /* local variables moved into u.bn */
   VdbeCursor *pC;
   i64 v;
   sqlite3_vtab *pVtab;
   const sqlite3_module *pModule;
-#endif /* local variables moved into u.bn */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bn.pC = p->apCsr[pOp->p1];
-  assert( u.bn.pC!=0 );
-  assert( u.bn.pC->pseudoTableReg==0 || u.bn.pC->nullRow );
-  if( u.bn.pC->nullRow ){
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  assert( pC->pseudoTableReg==0 || pC->nullRow );
+  if( pC->nullRow ){
     pOut->flags = MEM_Null;
     break;
-  }else if( u.bn.pC->deferredMoveto ){
-    u.bn.v = u.bn.pC->movetoTarget;
+  }else if( pC->deferredMoveto ){
+    v = pC->movetoTarget;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  }else if( u.bn.pC->pVtabCursor ){
-    u.bn.pVtab = u.bn.pC->pVtabCursor->pVtab;
-    u.bn.pModule = u.bn.pVtab->pModule;
-    assert( u.bn.pModule->xRowid );
-    rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v);
-    importVtabErrMsg(p, u.bn.pVtab);
+  }else if( pC->pVtabCursor ){
+    pVtab = pC->pVtabCursor->pVtab;
+    pModule = pVtab->pModule;
+    assert( pModule->xRowid );
+    rc = pModule->xRowid(pC->pVtabCursor, &v);
+    sqlite3VtabImportErrmsg(p, pVtab);
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
   }else{
-    assert( u.bn.pC->pCursor!=0 );
-    rc = sqlite3VdbeCursorMoveto(u.bn.pC);
+    assert( pC->pCursor!=0 );
+    rc = sqlite3VdbeCursorMoveto(pC);
     if( rc ) goto abort_due_to_error;
-    if( u.bn.pC->rowidIsValid ){
-      u.bn.v = u.bn.pC->lastRowid;
+    if( pC->rowidIsValid ){
+      v = pC->lastRowid;
     }else{
-      rc = sqlite3BtreeKeySize(u.bn.pC->pCursor, &u.bn.v);
+      rc = sqlite3BtreeKeySize(pC->pCursor, &v);
       assert( rc==SQLITE_OK );  /* Always so because of CursorMoveto() above */
     }
   }
-  pOut->u.i = u.bn.v;
+  pOut->u.i = v;
   break;
 }
 
@@ -69745,51 +72456,54 @@ case OP_Rowid: {                 /* out2-prerelease */
 ** write a NULL.
 */
 case OP_NullRow: {
-#if 0  /* local variables moved into u.bo */
   VdbeCursor *pC;
-#endif /* local variables moved into u.bo */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bo.pC = p->apCsr[pOp->p1];
-  assert( u.bo.pC!=0 );
-  u.bo.pC->nullRow = 1;
-  u.bo.pC->rowidIsValid = 0;
-  assert( u.bo.pC->pCursor || u.bo.pC->pVtabCursor );
-  if( u.bo.pC->pCursor ){
-    sqlite3BtreeClearCursor(u.bo.pC->pCursor);
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  pC->nullRow = 1;
+  pC->rowidIsValid = 0;
+  pC->cacheStatus = CACHE_STALE;
+  if( pC->pCursor ){
+    sqlite3BtreeClearCursor(pC->pCursor);
   }
   break;
 }
 
 /* Opcode: Last P1 P2 * * *
 **
-** The next use of the Rowid or Column or Next instruction for P1 
+** The next use of the Rowid or Column or Prev instruction for P1 
 ** will refer to the last entry in the database table or index.
 ** If the table or index is empty and P2>0, then jump immediately to P2.
 ** If P2 is 0 or if the table or index is not empty, fall through
 ** to the following instruction.
+**
+** This opcode leaves the cursor configured to move in reverse order,
+** from the end toward the beginning.  In other words, the cursor is
+** configured to use Prev, not Next.
 */
 case OP_Last: {        /* jump */
-#if 0  /* local variables moved into u.bp */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
-#endif /* local variables moved into u.bp */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bp.pC = p->apCsr[pOp->p1];
-  assert( u.bp.pC!=0 );
-  u.bp.pCrsr = u.bp.pC->pCursor;
-  u.bp.res = 0;
-  if( ALWAYS(u.bp.pCrsr!=0) ){
-    rc = sqlite3BtreeLast(u.bp.pCrsr, &u.bp.res);
-  }
-  u.bp.pC->nullRow = (u8)u.bp.res;
-  u.bp.pC->deferredMoveto = 0;
-  u.bp.pC->rowidIsValid = 0;
-  u.bp.pC->cacheStatus = CACHE_STALE;
-  if( pOp->p2>0 && u.bp.res ){
-    pc = pOp->p2 - 1;
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  pCrsr = pC->pCursor;
+  res = 0;
+  assert( pCrsr!=0 );
+  rc = sqlite3BtreeLast(pCrsr, &res);
+  pC->nullRow = (u8)res;
+  pC->deferredMoveto = 0;
+  pC->rowidIsValid = 0;
+  pC->cacheStatus = CACHE_STALE;
+#ifdef SQLITE_DEBUG
+  pC->seekOp = OP_Last;
+#endif
+  if( pOp->p2>0 ){
+    VdbeBranchTaken(res!=0,2);
+    if( res ) pc = pOp->p2 - 1;
   }
   break;
 }
@@ -69813,7 +72527,7 @@ case OP_Sort: {        /* jump */
   sqlite3_sort_count++;
   sqlite3_search_count--;
 #endif
-  p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
+  p->aCounter[SQLITE_STMTSTATUS_SORT]++;
   /* Fall through into OP_Rewind */
 }
 /* Opcode: Rewind P1 P2 * * *
@@ -69823,46 +72537,61 @@ case OP_Sort: {        /* jump */
 ** If the table or index is empty and P2>0, then jump immediately to P2.
 ** If P2 is 0 or if the table or index is not empty, fall through
 ** to the following instruction.
+**
+** This opcode leaves the cursor configured to move in forward order,
+** from the beginning toward the end.  In other words, the cursor is
+** configured to use Next, not Prev.
 */
 case OP_Rewind: {        /* jump */
-#if 0  /* local variables moved into u.bq */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
-#endif /* local variables moved into u.bq */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bq.pC = p->apCsr[pOp->p1];
-  assert( u.bq.pC!=0 );
-  assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterSort) );
-  u.bq.res = 1;
-  if( isSorter(u.bq.pC) ){
-    rc = sqlite3VdbeSorterRewind(db, u.bq.pC, &u.bq.res);
-  }else{
-    u.bq.pCrsr = u.bq.pC->pCursor;
-    assert( u.bq.pCrsr );
-    rc = sqlite3BtreeFirst(u.bq.pCrsr, &u.bq.res);
-    u.bq.pC->atFirst = u.bq.res==0 ?1:0;
-    u.bq.pC->deferredMoveto = 0;
-    u.bq.pC->cacheStatus = CACHE_STALE;
-    u.bq.pC->rowidIsValid = 0;
-  }
-  u.bq.pC->nullRow = (u8)u.bq.res;
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
+  res = 1;
+#ifdef SQLITE_DEBUG
+  pC->seekOp = OP_Rewind;
+#endif
+  if( isSorter(pC) ){
+    rc = sqlite3VdbeSorterRewind(db, pC, &res);
+  }else{
+    pCrsr = pC->pCursor;
+    assert( pCrsr );
+    rc = sqlite3BtreeFirst(pCrsr, &res);
+    pC->deferredMoveto = 0;
+    pC->cacheStatus = CACHE_STALE;
+    pC->rowidIsValid = 0;
+  }
+  pC->nullRow = (u8)res;
   assert( pOp->p2>0 && pOp->p2<p->nOp );
-  if( u.bq.res ){
+  VdbeBranchTaken(res!=0,2);
+  if( res ){
     pc = pOp->p2 - 1;
   }
   break;
 }
 
-/* Opcode: Next P1 P2 * P4 P5
+/* Opcode: Next P1 P2 P3 P4 P5
 **
 ** Advance cursor P1 so that it points to the next key/data pair in its
 ** table or index.  If there are no more key/value pairs then fall through
 ** to the following instruction.  But if the cursor advance was successful,
 ** jump immediately to P2.
 **
-** The P1 cursor must be for a real table, not a pseudo-table.
+** The Next opcode is only valid following an SeekGT, SeekGE, or
+** OP_Rewind opcode used to position the cursor.  Next is not allowed
+** to follow SeekLT, SeekLE, or OP_Last.
+**
+** The P1 cursor must be for a real table, not a pseudo-table.  P1 must have
+** been opened prior to this opcode or the program will segfault.
+**
+** The P3 value is a hint to the btree implementation. If P3==1, that
+** means P1 is an SQL index and that this instruction could have been
+** omitted if that index had been unique.  P3 is usually 0.  P3 is
+** always either 0 or 1.
 **
 ** P4 is always of type P4_ADVANCE. The function pointer points to
 ** sqlite3BtreeNext().
@@ -69870,16 +72599,32 @@ case OP_Rewind: {        /* jump */
 ** If P5 is positive and the jump is taken, then event counter
 ** number P5-1 in the prepared statement is incremented.
 **
-** See also: Prev
+** See also: Prev, NextIfOpen
+*/
+/* Opcode: NextIfOpen P1 P2 P3 P4 P5
+**
+** This opcode works just like Next except that if cursor P1 is not
+** open it behaves a no-op.
 */
-/* Opcode: Prev P1 P2 * * P5
+/* Opcode: Prev P1 P2 P3 P4 P5
 **
 ** Back up cursor P1 so that it points to the previous key/data pair in its
 ** table or index.  If there is no previous key/value pairs then fall through
 ** to the following instruction.  But if the cursor backup was successful,
 ** jump immediately to P2.
 **
-** The P1 cursor must be for a real table, not a pseudo-table.
+**
+** The Prev opcode is only valid following an SeekLT, SeekLE, or
+** OP_Last opcode used to position the cursor.  Prev is not allowed
+** to follow SeekGT, SeekGE, or OP_Rewind.
+**
+** The P1 cursor must be for a real table, not a pseudo-table.  If P1 is
+** not open then the behavior is undefined.
+**
+** The P3 value is a hint to the btree implementation. If P3==1, that
+** means P1 is an SQL index and that this instruction could have been
+** omitted if that index had been unique.  P3 is usually 0.  P3 is
+** always either 0 or 1.
 **
 ** P4 is always of type P4_ADVANCE. The function pointer points to
 ** sqlite3BtreePrevious().
@@ -69887,47 +72632,69 @@ case OP_Rewind: {        /* jump */
 ** If P5 is positive and the jump is taken, then event counter
 ** number P5-1 in the prepared statement is incremented.
 */
-case OP_SorterNext:    /* jump */
-case OP_Prev:          /* jump */
-case OP_Next: {        /* jump */
-#if 0  /* local variables moved into u.br */
+/* Opcode: PrevIfOpen P1 P2 P3 P4 P5
+**
+** This opcode works just like Prev except that if cursor P1 is not
+** open it behaves a no-op.
+*/
+case OP_SorterNext: {  /* jump */
   VdbeCursor *pC;
   int res;
-#endif /* local variables moved into u.br */
 
-  CHECK_FOR_INTERRUPT;
+  pC = p->apCsr[pOp->p1];
+  assert( isSorter(pC) );
+  res = 0;
+  rc = sqlite3VdbeSorterNext(db, pC, &res);
+  goto next_tail;
+case OP_PrevIfOpen:    /* jump */
+case OP_NextIfOpen:    /* jump */
+  if( p->apCsr[pOp->p1]==0 ) break;
+  /* Fall through */
+case OP_Prev:          /* jump */
+case OP_Next:          /* jump */
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  assert( pOp->p5<=ArraySize(p->aCounter) );
-  u.br.pC = p->apCsr[pOp->p1];
-  if( u.br.pC==0 ){
-    break;  /* See ticket #2273 */
-  }
-  assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterNext) );
-  if( isSorter(u.br.pC) ){
-    assert( pOp->opcode==OP_SorterNext );
-    rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res);
-  }else{
-    u.br.res = 1;
-    assert( u.br.pC->deferredMoveto==0 );
-    assert( u.br.pC->pCursor );
-    assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
-    assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
-    rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res);
-  }
-  u.br.pC->nullRow = (u8)u.br.res;
-  u.br.pC->cacheStatus = CACHE_STALE;
-  if( u.br.res==0 ){
+  assert( pOp->p5<ArraySize(p->aCounter) );
+  pC = p->apCsr[pOp->p1];
+  res = pOp->p3;
+  assert( pC!=0 );
+  assert( pC->deferredMoveto==0 );
+  assert( pC->pCursor );
+  assert( res==0 || (res==1 && pC->isTable==0) );
+  testcase( res==1 );
+  assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
+  assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
+  assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
+  assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
+
+  /* The Next opcode is only used after SeekGT, SeekGE, and Rewind.
+  ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
+  assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen
+       || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
+       || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found);
+  assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen
+       || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
+       || pC->seekOp==OP_Last );
+
+  rc = pOp->p4.xAdvance(pC->pCursor, &res);
+next_tail:
+  pC->cacheStatus = CACHE_STALE;
+  VdbeBranchTaken(res==0,2);
+  if( res==0 ){
+    pC->nullRow = 0;
     pc = pOp->p2 - 1;
-    if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
+    p->aCounter[pOp->p5]++;
 #ifdef SQLITE_TEST
     sqlite3_search_count++;
 #endif
+  }else{
+    pC->nullRow = 1;
   }
-  u.br.pC->rowidIsValid = 0;
-  break;
+  pC->rowidIsValid = 0;
+  goto check_for_interrupt;
 }
 
 /* Opcode: IdxInsert P1 P2 P3 * P5
+** Synopsis: key=r[P2]
 **
 ** Register P2 holds an SQL index key made using the
 ** MakeRecord instructions.  This opcode writes that key
@@ -69936,84 +72703,90 @@ case OP_Next: {        /* jump */
 ** P3 is a flag that provides a hint to the b-tree layer that this
 ** insert is likely to be an append.
 **
+** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is
+** incremented by this instruction.  If the OPFLAG_NCHANGE bit is clear,
+** then the change counter is unchanged.
+**
+** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have
+** just done a seek to the spot where the new entry is to be inserted.
+** This flag avoids doing an extra seek.
+**
 ** This instruction only works for indices.  The equivalent instruction
 ** for tables is OP_Insert.
 */
 case OP_SorterInsert:       /* in2 */
 case OP_IdxInsert: {        /* in2 */
-#if 0  /* local variables moved into u.bs */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int nKey;
   const char *zKey;
-#endif /* local variables moved into u.bs */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bs.pC = p->apCsr[pOp->p1];
-  assert( u.bs.pC!=0 );
-  assert( u.bs.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
   pIn2 = &aMem[pOp->p2];
   assert( pIn2->flags & MEM_Blob );
-  u.bs.pCrsr = u.bs.pC->pCursor;
-  if( ALWAYS(u.bs.pCrsr!=0) ){
-    assert( u.bs.pC->isTable==0 );
-    rc = ExpandBlob(pIn2);
-    if( rc==SQLITE_OK ){
-      if( isSorter(u.bs.pC) ){
-        rc = sqlite3VdbeSorterWrite(db, u.bs.pC, pIn2);
-      }else{
-        u.bs.nKey = pIn2->n;
-        u.bs.zKey = pIn2->z;
-        rc = sqlite3BtreeInsert(u.bs.pCrsr, u.bs.zKey, u.bs.nKey, "", 0, 0, pOp->p3,
-            ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bs.pC->seekResult : 0)
-            );
-        assert( u.bs.pC->deferredMoveto==0 );
-        u.bs.pC->cacheStatus = CACHE_STALE;
-      }
+  pCrsr = pC->pCursor;
+  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
+  assert( pCrsr!=0 );
+  assert( pC->isTable==0 );
+  rc = ExpandBlob(pIn2);
+  if( rc==SQLITE_OK ){
+    if( isSorter(pC) ){
+      rc = sqlite3VdbeSorterWrite(db, pC, pIn2);
+    }else{
+      nKey = pIn2->n;
+      zKey = pIn2->z;
+      rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3, 
+          ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
+          );
+      assert( pC->deferredMoveto==0 );
+      pC->cacheStatus = CACHE_STALE;
     }
   }
   break;
 }
 
 /* Opcode: IdxDelete P1 P2 P3 * *
+** Synopsis: key=r[P2 at P3]
 **
 ** The content of P3 registers starting at register P2 form
 ** an unpacked index key. This opcode removes that entry from the 
 ** index opened by cursor P1.
 */
 case OP_IdxDelete: {
-#if 0  /* local variables moved into u.bt */
   VdbeCursor *pC;
   BtCursor *pCrsr;
   int res;
   UnpackedRecord r;
-#endif /* local variables moved into u.bt */
 
   assert( pOp->p3>0 );
-  assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
+  assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem-p->nCursor)+1 );
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bt.pC = p->apCsr[pOp->p1];
-  assert( u.bt.pC!=0 );
-  u.bt.pCrsr = u.bt.pC->pCursor;
-  if( ALWAYS(u.bt.pCrsr!=0) ){
-    u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
-    u.bt.r.nField = (u16)pOp->p3;
-    u.bt.r.flags = 0;
-    u.bt.r.aMem = &aMem[pOp->p2];
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  pCrsr = pC->pCursor;
+  assert( pCrsr!=0 );
+  assert( pOp->p5==0 );
+  r.pKeyInfo = pC->pKeyInfo;
+  r.nField = (u16)pOp->p3;
+  r.default_rc = 0;
+  r.aMem = &aMem[pOp->p2];
 #ifdef SQLITE_DEBUG
-    { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
+  { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
 #endif
-    rc = sqlite3BtreeMovetoUnpacked(u.bt.pCrsr, &u.bt.r, 0, 0, &u.bt.res);
-    if( rc==SQLITE_OK && u.bt.res==0 ){
-      rc = sqlite3BtreeDelete(u.bt.pCrsr);
-    }
-    assert( u.bt.pC->deferredMoveto==0 );
-    u.bt.pC->cacheStatus = CACHE_STALE;
+  rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
+  if( rc==SQLITE_OK && res==0 ){
+    rc = sqlite3BtreeDelete(pCrsr);
   }
+  assert( pC->deferredMoveto==0 );
+  pC->cacheStatus = CACHE_STALE;
   break;
 }
 
 /* Opcode: IdxRowid P1 P2 * * *
+** Synopsis: r[P2]=rowid
 **
 ** Write into register P2 an integer which is the last entry in the record at
 ** the end of the index key pointed to by cursor P1.  This integer should be
@@ -70022,97 +72795,118 @@ case OP_IdxDelete: {
 ** See also: Rowid, MakeRecord.
 */
 case OP_IdxRowid: {              /* out2-prerelease */
-#if 0  /* local variables moved into u.bu */
   BtCursor *pCrsr;
   VdbeCursor *pC;
   i64 rowid;
-#endif /* local variables moved into u.bu */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bu.pC = p->apCsr[pOp->p1];
-  assert( u.bu.pC!=0 );
-  u.bu.pCrsr = u.bu.pC->pCursor;
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  pCrsr = pC->pCursor;
+  assert( pCrsr!=0 );
   pOut->flags = MEM_Null;
-  if( ALWAYS(u.bu.pCrsr!=0) ){
-    rc = sqlite3VdbeCursorMoveto(u.bu.pC);
-    if( NEVER(rc) ) goto abort_due_to_error;
-    assert( u.bu.pC->deferredMoveto==0 );
-    assert( u.bu.pC->isTable==0 );
-    if( !u.bu.pC->nullRow ){
-      rc = sqlite3VdbeIdxRowid(db, u.bu.pCrsr, &u.bu.rowid);
-      if( rc!=SQLITE_OK ){
-        goto abort_due_to_error;
-      }
-      pOut->u.i = u.bu.rowid;
-      pOut->flags = MEM_Int;
+  rc = sqlite3VdbeCursorMoveto(pC);
+  if( NEVER(rc) ) goto abort_due_to_error;
+  assert( pC->deferredMoveto==0 );
+  assert( pC->isTable==0 );
+  if( !pC->nullRow ){
+    rowid = 0;  /* Not needed.  Only used to silence a warning. */
+    rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid);
+    if( rc!=SQLITE_OK ){
+      goto abort_due_to_error;
     }
+    pOut->u.i = rowid;
+    pOut->flags = MEM_Int;
   }
   break;
 }
 
 /* Opcode: IdxGE P1 P2 P3 P4 P5
+** Synopsis: key=r[P3 at P4]
 **
 ** The P4 register values beginning with P3 form an unpacked index 
-** key that omits the ROWID.  Compare this key value against the index 
-** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
+** key that omits the PRIMARY KEY.  Compare this key value against the index 
+** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID 
+** fields at the end.
 **
 ** If the P1 index entry is greater than or equal to the key value
 ** then jump to P2.  Otherwise fall through to the next instruction.
+*/
+/* Opcode: IdxGT P1 P2 P3 P4 P5
+** Synopsis: key=r[P3 at P4]
+**
+** The P4 register values beginning with P3 form an unpacked index 
+** key that omits the PRIMARY KEY.  Compare this key value against the index 
+** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID 
+** fields at the end.
 **
-** If P5 is non-zero then the key value is increased by an epsilon 
-** prior to the comparison.  This make the opcode work like IdxGT except
-** that if the key from register P3 is a prefix of the key in the cursor,
-** the result is false whereas it would be true with IdxGT.
+** If the P1 index entry is greater than the key value
+** then jump to P2.  Otherwise fall through to the next instruction.
 */
 /* Opcode: IdxLT P1 P2 P3 P4 P5
+** Synopsis: key=r[P3 at P4]
 **
 ** The P4 register values beginning with P3 form an unpacked index 
-** key that omits the ROWID.  Compare this key value against the index 
-** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
+** key that omits the PRIMARY KEY or ROWID.  Compare this key value against
+** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
+** ROWID on the P1 index.
 **
 ** If the P1 index entry is less than the key value then jump to P2.
 ** Otherwise fall through to the next instruction.
+*/
+/* Opcode: IdxLE P1 P2 P3 P4 P5
+** Synopsis: key=r[P3 at P4]
+**
+** The P4 register values beginning with P3 form an unpacked index 
+** key that omits the PRIMARY KEY or ROWID.  Compare this key value against
+** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
+** ROWID on the P1 index.
 **
-** If P5 is non-zero then the key value is increased by an epsilon prior 
-** to the comparison.  This makes the opcode work like IdxLE.
+** If the P1 index entry is less than or equal to the key value then jump
+** to P2. Otherwise fall through to the next instruction.
 */
+case OP_IdxLE:          /* jump */
+case OP_IdxGT:          /* jump */
 case OP_IdxLT:          /* jump */
-case OP_IdxGE: {        /* jump */
-#if 0  /* local variables moved into u.bv */
+case OP_IdxGE:  {       /* jump */
   VdbeCursor *pC;
   int res;
   UnpackedRecord r;
-#endif /* local variables moved into u.bv */
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-  u.bv.pC = p->apCsr[pOp->p1];
-  assert( u.bv.pC!=0 );
-  assert( u.bv.pC->isOrdered );
-  if( ALWAYS(u.bv.pC->pCursor!=0) ){
-    assert( u.bv.pC->deferredMoveto==0 );
-    assert( pOp->p5==0 || pOp->p5==1 );
-    assert( pOp->p4type==P4_INT32 );
-    u.bv.r.pKeyInfo = u.bv.pC->pKeyInfo;
-    u.bv.r.nField = (u16)pOp->p4.i;
-    if( pOp->p5 ){
-      u.bv.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
-    }else{
-      u.bv.r.flags = UNPACKED_PREFIX_MATCH;
-    }
-    u.bv.r.aMem = &aMem[pOp->p3];
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  assert( pC->isOrdered );
+  assert( pC->pCursor!=0);
+  assert( pC->deferredMoveto==0 );
+  assert( pOp->p5==0 || pOp->p5==1 );
+  assert( pOp->p4type==P4_INT32 );
+  r.pKeyInfo = pC->pKeyInfo;
+  r.nField = (u16)pOp->p4.i;
+  if( pOp->opcode<OP_IdxLT ){
+    assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
+    r.default_rc = -1;
+  }else{
+    assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
+    r.default_rc = 0;
+  }
+  r.aMem = &aMem[pOp->p3];
 #ifdef SQLITE_DEBUG
-    { int i; for(i=0; i<u.bv.r.nField; i++) assert( memIsValid(&u.bv.r.aMem[i]) ); }
+  { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
 #endif
-    rc = sqlite3VdbeIdxKeyCompare(u.bv.pC, &u.bv.r, &u.bv.res);
-    if( pOp->opcode==OP_IdxLT ){
-      u.bv.res = -u.bv.res;
-    }else{
-      assert( pOp->opcode==OP_IdxGE );
-      u.bv.res++;
-    }
-    if( u.bv.res>0 ){
-      pc = pOp->p2 - 1 ;
-    }
+  res = 0;  /* Not needed.  Only used to silence a warning. */
+  rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
+  assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
+  if( (pOp->opcode&1)==(OP_IdxLT&1) ){
+    assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
+    res = -res;
+  }else{
+    assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT );
+    res++;
+  }
+  VdbeBranchTaken(res>0,2);
+  if( res>0 ){
+    pc = pOp->p2 - 1 ;
   }
   break;
 }
@@ -70138,40 +72932,42 @@ case OP_IdxGE: {        /* jump */
 ** See also: Clear
 */
 case OP_Destroy: {     /* out2-prerelease */
-#if 0  /* local variables moved into u.bw */
   int iMoved;
   int iCnt;
   Vdbe *pVdbe;
   int iDb;
-#endif /* local variables moved into u.bw */
 
+  assert( p->readOnly==0 );
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  u.bw.iCnt = 0;
-  for(u.bw.pVdbe=db->pVdbe; u.bw.pVdbe; u.bw.pVdbe = u.bw.pVdbe->pNext){
-    if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0 ){
-      u.bw.iCnt++;
+  iCnt = 0;
+  for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){
+    if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader 
+     && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 
+    ){
+      iCnt++;
     }
   }
 #else
-  u.bw.iCnt = db->activeVdbeCnt;
+  iCnt = db->nVdbeRead;
 #endif
   pOut->flags = MEM_Null;
-  if( u.bw.iCnt>1 ){
+  if( iCnt>1 ){
     rc = SQLITE_LOCKED;
     p->errorAction = OE_Abort;
   }else{
-    u.bw.iDb = pOp->p3;
-    assert( u.bw.iCnt==1 );
-    assert( (p->btreeMask & (((yDbMask)1)<<u.bw.iDb))!=0 );
-    rc = sqlite3BtreeDropTable(db->aDb[u.bw.iDb].pBt, pOp->p1, &u.bw.iMoved);
+    iDb = pOp->p3;
+    assert( iCnt==1 );
+    assert( DbMaskTest(p->btreeMask, iDb) );
+    iMoved = 0;  /* Not needed.  Only to silence a warning. */
+    rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
     pOut->flags = MEM_Int;
-    pOut->u.i = u.bw.iMoved;
+    pOut->u.i = iMoved;
 #ifndef SQLITE_OMIT_AUTOVACUUM
-    if( rc==SQLITE_OK && u.bw.iMoved!=0 ){
-      sqlite3RootPageMoved(db, u.bw.iDb, u.bw.iMoved, pOp->p1);
+    if( rc==SQLITE_OK && iMoved!=0 ){
+      sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1);
       /* All OP_Destroy operations occur on the same btree */
-      assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bw.iDb+1 );
-      resetSchemaOnFault = u.bw.iDb+1;
+      assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 );
+      resetSchemaOnFault = iDb+1;
     }
 #endif
   }
@@ -70197,27 +72993,50 @@ case OP_Destroy: {     /* out2-prerelease */
 ** See also: Destroy
 */
 case OP_Clear: {
-#if 0  /* local variables moved into u.bx */
   int nChange;
-#endif /* local variables moved into u.bx */
-
-  u.bx.nChange = 0;
-  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
+ 
+  nChange = 0;
+  assert( p->readOnly==0 );
+  assert( DbMaskTest(p->btreeMask, pOp->p2) );
   rc = sqlite3BtreeClearTable(
-      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0)
+      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
   );
   if( pOp->p3 ){
-    p->nChange += u.bx.nChange;
+    p->nChange += nChange;
     if( pOp->p3>0 ){
       assert( memIsValid(&aMem[pOp->p3]) );
       memAboutToChange(p, &aMem[pOp->p3]);
-      aMem[pOp->p3].u.i += u.bx.nChange;
+      aMem[pOp->p3].u.i += nChange;
     }
   }
   break;
 }
 
+/* Opcode: ResetSorter P1 * * * *
+**
+** Delete all contents from the ephemeral table or sorter
+** that is open on cursor P1.
+**
+** This opcode only works for cursors used for sorting and
+** opened with OP_OpenEphemeral or OP_SorterOpen.
+*/
+case OP_ResetSorter: {
+  VdbeCursor *pC;
+ 
+  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+  pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
+  if( pC->pSorter ){
+    sqlite3VdbeSorterReset(db, pC->pSorter);
+  }else{
+    assert( pC->isEphemeral );
+    rc = sqlite3BtreeClearTableOfCursor(pC->pCursor);
+  }
+  break;
+}
+
 /* Opcode: CreateTable P1 P2 * * *
+** Synopsis: r[P2]=root iDb=P1
 **
 ** Allocate a new table in the main database file if P1==0 or in the
 ** auxiliary database file if P1==1 or in an attached database if
@@ -70231,6 +73050,7 @@ case OP_Clear: {
 ** See also: CreateIndex
 */
 /* Opcode: CreateIndex P1 P2 * * *
+** Synopsis: r[P2]=root iDb=P1
 **
 ** Allocate a new index in the main database file if P1==0 or in the
 ** auxiliary database file if P1==1 or in an attached database if
@@ -70241,25 +73061,24 @@ case OP_Clear: {
 */
 case OP_CreateIndex:            /* out2-prerelease */
 case OP_CreateTable: {          /* out2-prerelease */
-#if 0  /* local variables moved into u.by */
   int pgno;
   int flags;
   Db *pDb;
-#endif /* local variables moved into u.by */
 
-  u.by.pgno = 0;
+  pgno = 0;
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
-  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.by.pDb = &db->aDb[pOp->p1];
-  assert( u.by.pDb->pBt!=0 );
+  assert( DbMaskTest(p->btreeMask, pOp->p1) );
+  assert( p->readOnly==0 );
+  pDb = &db->aDb[pOp->p1];
+  assert( pDb->pBt!=0 );
   if( pOp->opcode==OP_CreateTable ){
-    /* u.by.flags = BTREE_INTKEY; */
-    u.by.flags = BTREE_INTKEY;
+    /* flags = BTREE_INTKEY; */
+    flags = BTREE_INTKEY;
   }else{
-    u.by.flags = BTREE_BLOBKEY;
+    flags = BTREE_BLOBKEY;
   }
-  rc = sqlite3BtreeCreateTable(u.by.pDb->pBt, &u.by.pgno, u.by.flags);
-  pOut->u.i = u.by.pgno;
+  rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
+  pOut->u.i = pgno;
   break;
 }
 
@@ -70272,44 +73091,42 @@ case OP_CreateTable: {          /* out2-prerelease */
 ** then runs the new virtual machine.  It is thus a re-entrant opcode.
 */
 case OP_ParseSchema: {
-#if 0  /* local variables moved into u.bz */
   int iDb;
   const char *zMaster;
   char *zSql;
   InitData initData;
-#endif /* local variables moved into u.bz */
 
   /* Any prepared statement that invokes this opcode will hold mutexes
-  ** on every btree.  This is a prerequisite for invoking
+  ** on every btree.  This is a prerequisite for invoking 
   ** sqlite3InitCallback().
   */
 #ifdef SQLITE_DEBUG
-  for(u.bz.iDb=0; u.bz.iDb<db->nDb; u.bz.iDb++){
-    assert( u.bz.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bz.iDb].pBt) );
+  for(iDb=0; iDb<db->nDb; iDb++){
+    assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
   }
 #endif
 
-  u.bz.iDb = pOp->p1;
-  assert( u.bz.iDb>=0 && u.bz.iDb<db->nDb );
-  assert( DbHasProperty(db, u.bz.iDb, DB_SchemaLoaded) );
+  iDb = pOp->p1;
+  assert( iDb>=0 && iDb<db->nDb );
+  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
   /* Used to be a conditional */ {
-    u.bz.zMaster = SCHEMA_TABLE(u.bz.iDb);
-    u.bz.initData.db = db;
-    u.bz.initData.iDb = pOp->p1;
-    u.bz.initData.pzErrMsg = &p->zErrMsg;
-    u.bz.zSql = sqlite3MPrintf(db,
+    zMaster = SCHEMA_TABLE(iDb);
+    initData.db = db;
+    initData.iDb = pOp->p1;
+    initData.pzErrMsg = &p->zErrMsg;
+    zSql = sqlite3MPrintf(db,
        "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
-       db->aDb[u.bz.iDb].zName, u.bz.zMaster, pOp->p4.z);
-    if( u.bz.zSql==0 ){
+       db->aDb[iDb].zName, zMaster, pOp->p4.z);
+    if( zSql==0 ){
       rc = SQLITE_NOMEM;
     }else{
       assert( db->init.busy==0 );
       db->init.busy = 1;
-      u.bz.initData.rc = SQLITE_OK;
+      initData.rc = SQLITE_OK;
       assert( !db->mallocFailed );
-      rc = sqlite3_exec(db, u.bz.zSql, sqlite3InitCallback, &u.bz.initData, 0);
-      if( rc==SQLITE_OK ) rc = u.bz.initData.rc;
-      sqlite3DbFree(db, u.bz.zSql);
+      rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
+      if( rc==SQLITE_OK ) rc = initData.rc;
+      sqlite3DbFree(db, zSql);
       db->init.busy = 0;
     }
   }
@@ -70317,7 +73134,7 @@ case OP_ParseSchema: {
   if( rc==SQLITE_NOMEM ){
     goto no_mem;
   }
-  break;
+  break;  
 }
 
 #if !defined(SQLITE_OMIT_ANALYZE)
@@ -70338,7 +73155,8 @@ case OP_LoadAnalysis: {
 **
 ** Remove the internal (in-memory) data structures that describe
 ** the table named P4 in database P1.  This is called after a table
-** is dropped in order to keep the internal representation of the
+** is dropped from disk (using the Destroy opcode) in order to keep 
+** the internal representation of the
 ** schema consistent with what is on disk.
 */
 case OP_DropTable: {
@@ -70350,7 +73168,8 @@ case OP_DropTable: {
 **
 ** Remove the internal (in-memory) data structures that describe
 ** the index named P4 in database P1.  This is called after an index
-** is dropped in order to keep the internal representation of the
+** is dropped from disk (using the Destroy opcode)
+** in order to keep the internal representation of the
 ** schema consistent with what is on disk.
 */
 case OP_DropIndex: {
@@ -70362,7 +73181,8 @@ case OP_DropIndex: {
 **
 ** Remove the internal (in-memory) data structures that describe
 ** the trigger named P4 in database P1.  This is called after a trigger
-** is dropped in order to keep the internal representation of the
+** is dropped from disk (using the Destroy opcode) in order to keep 
+** the internal representation of the
 ** schema consistent with what is on disk.
 */
 case OP_DropTrigger: {
@@ -70393,41 +73213,40 @@ case OP_DropTrigger: {
 ** This opcode is used to implement the integrity_check pragma.
 */
 case OP_IntegrityCk: {
-#if 0  /* local variables moved into u.ca */
   int nRoot;      /* Number of tables to check.  (Number of root pages.) */
   int *aRoot;     /* Array of rootpage numbers for tables to be checked */
   int j;          /* Loop counter */
   int nErr;       /* Number of errors reported */
   char *z;        /* Text of the error report */
   Mem *pnErr;     /* Register keeping track of errors remaining */
-#endif /* local variables moved into u.ca */
-
-  u.ca.nRoot = pOp->p2;
-  assert( u.ca.nRoot>0 );
-  u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) );
-  if( u.ca.aRoot==0 ) goto no_mem;
-  assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.ca.pnErr = &aMem[pOp->p3];
-  assert( (u.ca.pnErr->flags & MEM_Int)!=0 );
-  assert( (u.ca.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
+
+  assert( p->bIsReader );
+  nRoot = pOp->p2;
+  assert( nRoot>0 );
+  aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) );
+  if( aRoot==0 ) goto no_mem;
+  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
+  pnErr = &aMem[pOp->p3];
+  assert( (pnErr->flags & MEM_Int)!=0 );
+  assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
   pIn1 = &aMem[pOp->p1];
-  for(u.ca.j=0; u.ca.j<u.ca.nRoot; u.ca.j++){
-    u.ca.aRoot[u.ca.j] = (int)sqlite3VdbeIntValue(&pIn1[u.ca.j]);
+  for(j=0; j<nRoot; j++){
+    aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]);
   }
-  u.ca.aRoot[u.ca.j] = 0;
+  aRoot[j] = 0;
   assert( pOp->p5<db->nDb );
-  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
-  u.ca.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.ca.aRoot, u.ca.nRoot,
-                                 (int)u.ca.pnErr->u.i, &u.ca.nErr);
-  sqlite3DbFree(db, u.ca.aRoot);
-  u.ca.pnErr->u.i -= u.ca.nErr;
+  assert( DbMaskTest(p->btreeMask, pOp->p5) );
+  z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
+                                 (int)pnErr->u.i, &nErr);
+  sqlite3DbFree(db, aRoot);
+  pnErr->u.i -= nErr;
   sqlite3VdbeMemSetNull(pIn1);
-  if( u.ca.nErr==0 ){
-    assert( u.ca.z==0 );
-  }else if( u.ca.z==0 ){
+  if( nErr==0 ){
+    assert( z==0 );
+  }else if( z==0 ){
     goto no_mem;
   }else{
-    sqlite3VdbeMemSetStr(pIn1, u.ca.z, -1, SQLITE_UTF8, sqlite3_free);
+    sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
   }
   UPDATE_MAX_BLOBSIZE(pIn1);
   sqlite3VdbeChangeEncoding(pIn1, encoding);
@@ -70436,6 +73255,7 @@ case OP_IntegrityCk: {
 #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
 
 /* Opcode: RowSetAdd P1 P2 * * *
+** Synopsis:  rowset(P1)=r[P2]
 **
 ** Insert the integer value held by register P2 into a boolean index
 ** held in register P1.
@@ -70455,31 +73275,33 @@ case OP_RowSetAdd: {       /* in1, in2 */
 }
 
 /* Opcode: RowSetRead P1 P2 P3 * *
+** Synopsis:  r[P3]=rowset(P1)
 **
 ** Extract the smallest value from boolean index P1 and put that value into
 ** register P3.  Or, if boolean index P1 is initially empty, leave P3
 ** unchanged and jump to instruction P2.
 */
 case OP_RowSetRead: {       /* jump, in1, out3 */
-#if 0  /* local variables moved into u.cb */
   i64 val;
-#endif /* local variables moved into u.cb */
-  CHECK_FOR_INTERRUPT;
+
   pIn1 = &aMem[pOp->p1];
-  if( (pIn1->flags & MEM_RowSet)==0
-   || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0
+  if( (pIn1->flags & MEM_RowSet)==0 
+   || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0
   ){
     /* The boolean index is empty */
     sqlite3VdbeMemSetNull(pIn1);
     pc = pOp->p2 - 1;
+    VdbeBranchTaken(1,2);
   }else{
     /* A value was pulled from the index */
-    sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val);
+    sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val);
+    VdbeBranchTaken(0,2);
   }
-  break;
+  goto check_for_interrupt;
 }
 
 /* Opcode: RowSetTest P1 P2 P3 P4
+** Synopsis: if r[P3] in rowset(P1) goto P2
 **
 ** Register P3 is assumed to hold a 64-bit integer value. If register P1
 ** contains a RowSet object and that RowSet object contains
@@ -70503,14 +73325,12 @@ case OP_RowSetRead: {       /* jump, in1, out3 */
 ** inserted as part of some other set).
 */
 case OP_RowSetTest: {                     /* jump, in1, in3 */
-#if 0  /* local variables moved into u.cc */
   int iSet;
   int exists;
-#endif /* local variables moved into u.cc */
 
   pIn1 = &aMem[pOp->p1];
   pIn3 = &aMem[pOp->p3];
-  u.cc.iSet = pOp->p4.i;
+  iSet = pOp->p4.i;
   assert( pIn3->flags&MEM_Int );
 
   /* If there is anything other than a rowset object in memory cell P1,
@@ -70522,17 +73342,16 @@ case OP_RowSetTest: {                     /* jump, in1, in3 */
   }
 
   assert( pOp->p4type==P4_INT32 );
-  assert( u.cc.iSet==-1 || u.cc.iSet>=0 );
-  if( u.cc.iSet ){
-    u.cc.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
-                               (u8)(u.cc.iSet>=0 ? u.cc.iSet & 0xf : 0xff),
-                               pIn3->u.i);
-    if( u.cc.exists ){
+  assert( iSet==-1 || iSet>=0 );
+  if( iSet ){
+    exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i);
+    VdbeBranchTaken(exists!=0,2);
+    if( exists ){
       pc = pOp->p2 - 1;
       break;
     }
   }
-  if( u.cc.iSet>=0 ){
+  if( iSet>=0 ){
     sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
   }
   break;
@@ -70541,7 +73360,7 @@ case OP_RowSetTest: {                     /* jump, in1, in3 */
 
 #ifndef SQLITE_OMIT_TRIGGER
 
-/* Opcode: Program P1 P2 P3 P4 *
+/* Opcode: Program P1 P2 P3 P4 P5
 **
 ** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). 
 **
@@ -70553,9 +73372,10 @@ case OP_RowSetTest: {                     /* jump, in1, in3 */
 ** memory required by the sub-vdbe at runtime.
 **
 ** P4 is a pointer to the VM containing the trigger program.
+**
+** If P5 is non-zero, then recursive program invocation is enabled.
 */
 case OP_Program: {        /* jump */
-#if 0  /* local variables moved into u.cd */
   int nMem;               /* Number of memory registers for sub-program */
   int nByte;              /* Bytes of runtime space required for sub-program */
   Mem *pRt;               /* Register to allocate runtime space */
@@ -70564,27 +73384,26 @@ case OP_Program: {        /* jump */
   VdbeFrame *pFrame;      /* New vdbe frame to execute in */
   SubProgram *pProgram;   /* Sub-program to execute */
   void *t;                /* Token identifying trigger */
-#endif /* local variables moved into u.cd */
-
-  u.cd.pProgram = pOp->p4.pProgram;
-  u.cd.pRt = &aMem[pOp->p3];
-  assert( u.cd.pProgram->nOp>0 );
 
-  /* If the p5 flag is clear, then recursive invocation of triggers is
+  pProgram = pOp->p4.pProgram;
+  pRt = &aMem[pOp->p3];
+  assert( pProgram->nOp>0 );
+  
+  /* If the p5 flag is clear, then recursive invocation of triggers is 
   ** disabled for backwards compatibility (p5 is set if this sub-program
   ** is really a trigger, not a foreign key action, and the flag set
   ** and cleared by the "PRAGMA recursive_triggers" command is clear).
-  **
-  ** It is recursive invocation of triggers, at the SQL level, that is
-  ** disabled. In some cases a single trigger may generate more than one
-  ** SubProgram (if the trigger may be executed with more than one different
+  ** 
+  ** It is recursive invocation of triggers, at the SQL level, that is 
+  ** disabled. In some cases a single trigger may generate more than one 
+  ** SubProgram (if the trigger may be executed with more than one different 
   ** ON CONFLICT algorithm). SubProgram structures associated with a
-  ** single trigger all have the same value for the SubProgram.token
+  ** single trigger all have the same value for the SubProgram.token 
   ** variable.  */
   if( pOp->p5 ){
-    u.cd.t = u.cd.pProgram->token;
-    for(u.cd.pFrame=p->pFrame; u.cd.pFrame && u.cd.pFrame->token!=u.cd.t; u.cd.pFrame=u.cd.pFrame->pParent);
-    if( u.cd.pFrame ) break;
+    t = pProgram->token;
+    for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent);
+    if( pFrame ) break;
   }
 
   if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
@@ -70593,69 +73412,69 @@ case OP_Program: {        /* jump */
     break;
   }
 
-  /* Register u.cd.pRt is used to store the memory required to save the state
+  /* Register pRt is used to store the memory required to save the state
   ** of the current program, and the memory required at runtime to execute
-  ** the trigger program. If this trigger has been fired before, then u.cd.pRt
+  ** the trigger program. If this trigger has been fired before, then pRt 
   ** is already allocated. Otherwise, it must be initialized.  */
-  if( (u.cd.pRt->flags&MEM_Frame)==0 ){
-    /* SubProgram.nMem is set to the number of memory cells used by the
+  if( (pRt->flags&MEM_Frame)==0 ){
+    /* SubProgram.nMem is set to the number of memory cells used by the 
     ** program stored in SubProgram.aOp. As well as these, one memory
     ** cell is required for each cursor used by the program. Set local
-    ** variable u.cd.nMem (and later, VdbeFrame.nChildMem) to this value.
+    ** variable nMem (and later, VdbeFrame.nChildMem) to this value.
     */
-    u.cd.nMem = u.cd.pProgram->nMem + u.cd.pProgram->nCsr;
-    u.cd.nByte = ROUND8(sizeof(VdbeFrame))
-              + u.cd.nMem * sizeof(Mem)
-              + u.cd.pProgram->nCsr * sizeof(VdbeCursor *)
-              + u.cd.pProgram->nOnce * sizeof(u8);
-    u.cd.pFrame = sqlite3DbMallocZero(db, u.cd.nByte);
-    if( !u.cd.pFrame ){
+    nMem = pProgram->nMem + pProgram->nCsr;
+    nByte = ROUND8(sizeof(VdbeFrame))
+              + nMem * sizeof(Mem)
+              + pProgram->nCsr * sizeof(VdbeCursor *)
+              + pProgram->nOnce * sizeof(u8);
+    pFrame = sqlite3DbMallocZero(db, nByte);
+    if( !pFrame ){
       goto no_mem;
     }
-    sqlite3VdbeMemRelease(u.cd.pRt);
-    u.cd.pRt->flags = MEM_Frame;
-    u.cd.pRt->u.pFrame = u.cd.pFrame;
+    sqlite3VdbeMemRelease(pRt);
+    pRt->flags = MEM_Frame;
+    pRt->u.pFrame = pFrame;
 
-    u.cd.pFrame->v = p;
-    u.cd.pFrame->nChildMem = u.cd.nMem;
-    u.cd.pFrame->nChildCsr = u.cd.pProgram->nCsr;
-    u.cd.pFrame->pc = pc;
-    u.cd.pFrame->aMem = p->aMem;
-    u.cd.pFrame->nMem = p->nMem;
-    u.cd.pFrame->apCsr = p->apCsr;
-    u.cd.pFrame->nCursor = p->nCursor;
-    u.cd.pFrame->aOp = p->aOp;
-    u.cd.pFrame->nOp = p->nOp;
-    u.cd.pFrame->token = u.cd.pProgram->token;
-    u.cd.pFrame->aOnceFlag = p->aOnceFlag;
-    u.cd.pFrame->nOnceFlag = p->nOnceFlag;
+    pFrame->v = p;
+    pFrame->nChildMem = nMem;
+    pFrame->nChildCsr = pProgram->nCsr;
+    pFrame->pc = pc;
+    pFrame->aMem = p->aMem;
+    pFrame->nMem = p->nMem;
+    pFrame->apCsr = p->apCsr;
+    pFrame->nCursor = p->nCursor;
+    pFrame->aOp = p->aOp;
+    pFrame->nOp = p->nOp;
+    pFrame->token = pProgram->token;
+    pFrame->aOnceFlag = p->aOnceFlag;
+    pFrame->nOnceFlag = p->nOnceFlag;
 
-    u.cd.pEnd = &VdbeFrameMem(u.cd.pFrame)[u.cd.pFrame->nChildMem];
-    for(u.cd.pMem=VdbeFrameMem(u.cd.pFrame); u.cd.pMem!=u.cd.pEnd; u.cd.pMem++){
-      u.cd.pMem->flags = MEM_Invalid;
-      u.cd.pMem->db = db;
+    pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
+    for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
+      pMem->flags = MEM_Undefined;
+      pMem->db = db;
     }
   }else{
-    u.cd.pFrame = u.cd.pRt->u.pFrame;
-    assert( u.cd.pProgram->nMem+u.cd.pProgram->nCsr==u.cd.pFrame->nChildMem );
-    assert( u.cd.pProgram->nCsr==u.cd.pFrame->nChildCsr );
-    assert( pc==u.cd.pFrame->pc );
+    pFrame = pRt->u.pFrame;
+    assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem );
+    assert( pProgram->nCsr==pFrame->nChildCsr );
+    assert( pc==pFrame->pc );
   }
 
   p->nFrame++;
-  u.cd.pFrame->pParent = p->pFrame;
-  u.cd.pFrame->lastRowid = lastRowid;
-  u.cd.pFrame->nChange = p->nChange;
+  pFrame->pParent = p->pFrame;
+  pFrame->lastRowid = lastRowid;
+  pFrame->nChange = p->nChange;
   p->nChange = 0;
-  p->pFrame = u.cd.pFrame;
-  p->aMem = aMem = &VdbeFrameMem(u.cd.pFrame)[-1];
-  p->nMem = u.cd.pFrame->nChildMem;
-  p->nCursor = (u16)u.cd.pFrame->nChildCsr;
+  p->pFrame = pFrame;
+  p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
+  p->nMem = pFrame->nChildMem;
+  p->nCursor = (u16)pFrame->nChildCsr;
   p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
-  p->aOp = aOp = u.cd.pProgram->aOp;
-  p->nOp = u.cd.pProgram->nOp;
+  p->aOp = aOp = pProgram->aOp;
+  p->nOp = pProgram->nOp;
   p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
-  p->nOnceFlag = u.cd.pProgram->nOnce;
+  p->nOnceFlag = pProgram->nOnce;
   pc = -1;
   memset(p->aOnceFlag, 0, p->nOnceFlag);
 
@@ -70675,13 +73494,11 @@ case OP_Program: {        /* jump */
 ** calling OP_Program instruction.
 */
 case OP_Param: {           /* out2-prerelease */
-#if 0  /* local variables moved into u.ce */
   VdbeFrame *pFrame;
   Mem *pIn;
-#endif /* local variables moved into u.ce */
-  u.ce.pFrame = p->pFrame;
-  u.ce.pIn = &u.ce.pFrame->aMem[pOp->p1 + u.ce.pFrame->aOp[u.ce.pFrame->pc].p1];
-  sqlite3VdbeMemShallowCopy(pOut, u.ce.pIn, MEM_Ephem);
+  pFrame = p->pFrame;
+  pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1];   
+  sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem);
   break;
 }
 
@@ -70689,6 +73506,7 @@ case OP_Param: {           /* out2-prerelease */
 
 #ifndef SQLITE_OMIT_FOREIGN_KEY
 /* Opcode: FkCounter P1 P2 * * *
+** Synopsis: fkctr[P1]+=P2
 **
 ** Increment a "constraint counter" by P2 (P2 may be negative or positive).
 ** If P1 is non-zero, the database constraint counter is incremented 
@@ -70696,7 +73514,9 @@ case OP_Param: {           /* out2-prerelease */
 ** statement counter is incremented (immediate foreign key constraints).
 */
 case OP_FkCounter: {
-  if( pOp->p1 ){
+  if( db->flags & SQLITE_DeferFKs ){
+    db->nDeferredImmCons += pOp->p2;
+  }else if( pOp->p1 ){
     db->nDeferredCons += pOp->p2;
   }else{
     p->nFkConstraint += pOp->p2;
@@ -70705,6 +73525,7 @@ case OP_FkCounter: {
 }
 
 /* Opcode: FkIfZero P1 P2 * * *
+** Synopsis: if fkctr[P1]==0 goto P2
 **
 ** This opcode tests if a foreign key constraint-counter is currently zero.
 ** If so, jump to instruction P2. Otherwise, fall through to the next 
@@ -70717,9 +73538,11 @@ case OP_FkCounter: {
 */
 case OP_FkIfZero: {         /* jump */
   if( pOp->p1 ){
-    if( db->nDeferredCons==0 ) pc = pOp->p2-1;
+    VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2);
+    if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
   }else{
-    if( p->nFkConstraint==0 ) pc = pOp->p2-1;
+    VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2);
+    if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
   }
   break;
 }
@@ -70727,6 +73550,7 @@ case OP_FkIfZero: {         /* jump */
 
 #ifndef SQLITE_OMIT_AUTOINCREMENT
 /* Opcode: MemMax P1 P2 * * *
+** Synopsis: r[P1]=max(r[P1],r[P2])
 **
 ** P1 is a register in the root frame of this VM (the root frame is
 ** different from the current frame if this instruction is being executed
@@ -70737,28 +73561,26 @@ case OP_FkIfZero: {         /* jump */
 ** an integer.
 */
 case OP_MemMax: {        /* in2 */
-#if 0  /* local variables moved into u.cf */
-  Mem *pIn1;
   VdbeFrame *pFrame;
-#endif /* local variables moved into u.cf */
   if( p->pFrame ){
-    for(u.cf.pFrame=p->pFrame; u.cf.pFrame->pParent; u.cf.pFrame=u.cf.pFrame->pParent);
-    u.cf.pIn1 = &u.cf.pFrame->aMem[pOp->p1];
+    for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
+    pIn1 = &pFrame->aMem[pOp->p1];
   }else{
-    u.cf.pIn1 = &aMem[pOp->p1];
+    pIn1 = &aMem[pOp->p1];
   }
-  assert( memIsValid(u.cf.pIn1) );
-  sqlite3VdbeMemIntegerify(u.cf.pIn1);
+  assert( memIsValid(pIn1) );
+  sqlite3VdbeMemIntegerify(pIn1);
   pIn2 = &aMem[pOp->p2];
   sqlite3VdbeMemIntegerify(pIn2);
-  if( u.cf.pIn1->u.i<pIn2->u.i){
-    u.cf.pIn1->u.i = pIn2->u.i;
+  if( pIn1->u.i<pIn2->u.i){
+    pIn1->u.i = pIn2->u.i;
   }
   break;
 }
 #endif /* SQLITE_OMIT_AUTOINCREMENT */
 
 /* Opcode: IfPos P1 P2 * * *
+** Synopsis: if r[P1]>0 goto P2
 **
 ** If the value of register P1 is 1 or greater, jump to P2.
 **
@@ -70768,22 +73590,24 @@ case OP_MemMax: {        /* in2 */
 case OP_IfPos: {        /* jump, in1 */
   pIn1 = &aMem[pOp->p1];
   assert( pIn1->flags&MEM_Int );
+  VdbeBranchTaken( pIn1->u.i>0, 2);
   if( pIn1->u.i>0 ){
      pc = pOp->p2 - 1;
   }
   break;
 }
 
-/* Opcode: IfNeg P1 P2 * * *
+/* Opcode: IfNeg P1 P2 P3 * *
+** Synopsis: r[P1]+=P3, if r[P1]<0 goto P2
 **
-** If the value of register P1 is less than zero, jump to P2. 
-**
-** It is illegal to use this instruction on a register that does
-** not contain an integer.  An assertion fault will result if you try.
+** Register P1 must contain an integer.  Add literal P3 to the value in
+** register P1 then if the value of register P1 is less than zero, jump to P2. 
 */
 case OP_IfNeg: {        /* jump, in1 */
   pIn1 = &aMem[pOp->p1];
   assert( pIn1->flags&MEM_Int );
+  pIn1->u.i += pOp->p3;
+  VdbeBranchTaken(pIn1->u.i<0, 2);
   if( pIn1->u.i<0 ){
      pc = pOp->p2 - 1;
   }
@@ -70791,17 +73615,16 @@ case OP_IfNeg: {        /* jump, in1 */
 }
 
 /* Opcode: IfZero P1 P2 P3 * *
+** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2
 **
 ** The register P1 must contain an integer.  Add literal P3 to the
 ** value in register P1.  If the result is exactly 0, jump to P2. 
-**
-** It is illegal to use this instruction on a register that does
-** not contain an integer.  An assertion fault will result if you try.
 */
 case OP_IfZero: {        /* jump, in1 */
   pIn1 = &aMem[pOp->p1];
   assert( pIn1->flags&MEM_Int );
   pIn1->u.i += pOp->p3;
+  VdbeBranchTaken(pIn1->u.i==0, 2);
   if( pIn1->u.i==0 ){
      pc = pOp->p2 - 1;
   }
@@ -70809,6 +73632,7 @@ case OP_IfZero: {        /* jump, in1 */
 }
 
 /* Opcode: AggStep * P2 P3 P4 P5
+** Synopsis: accum=r[P3] step(r[P2 at P5])
 **
 ** Execute the step function for an aggregate.  The
 ** function has P5 arguments.   P4 is a pointer to the FuncDef
@@ -70819,61 +73643,59 @@ case OP_IfZero: {        /* jump, in1 */
 ** successors.
 */
 case OP_AggStep: {
-#if 0  /* local variables moved into u.cg */
   int n;
   int i;
   Mem *pMem;
   Mem *pRec;
   sqlite3_context ctx;
   sqlite3_value **apVal;
-#endif /* local variables moved into u.cg */
-
-  u.cg.n = pOp->p5;
-  assert( u.cg.n>=0 );
-  u.cg.pRec = &aMem[pOp->p2];
-  u.cg.apVal = p->apArg;
-  assert( u.cg.apVal || u.cg.n==0 );
-  for(u.cg.i=0; u.cg.i<u.cg.n; u.cg.i++, u.cg.pRec++){
-    assert( memIsValid(u.cg.pRec) );
-    u.cg.apVal[u.cg.i] = u.cg.pRec;
-    memAboutToChange(p, u.cg.pRec);
-    sqlite3VdbeMemStoreType(u.cg.pRec);
-  }
-  u.cg.ctx.pFunc = pOp->p4.pFunc;
-  assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.cg.ctx.pMem = u.cg.pMem = &aMem[pOp->p3];
-  u.cg.pMem->n++;
-  u.cg.ctx.s.flags = MEM_Null;
-  u.cg.ctx.s.z = 0;
-  u.cg.ctx.s.zMalloc = 0;
-  u.cg.ctx.s.xDel = 0;
-  u.cg.ctx.s.db = db;
-  u.cg.ctx.isError = 0;
-  u.cg.ctx.pColl = 0;
-  u.cg.ctx.skipFlag = 0;
-  if( u.cg.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+
+  n = pOp->p5;
+  assert( n>=0 );
+  pRec = &aMem[pOp->p2];
+  apVal = p->apArg;
+  assert( apVal || n==0 );
+  for(i=0; i<n; i++, pRec++){
+    assert( memIsValid(pRec) );
+    apVal[i] = pRec;
+    memAboutToChange(p, pRec);
+  }
+  ctx.pFunc = pOp->p4.pFunc;
+  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
+  ctx.pMem = pMem = &aMem[pOp->p3];
+  pMem->n++;
+  ctx.s.flags = MEM_Null;
+  ctx.s.z = 0;
+  ctx.s.zMalloc = 0;
+  ctx.s.xDel = 0;
+  ctx.s.db = db;
+  ctx.isError = 0;
+  ctx.pColl = 0;
+  ctx.skipFlag = 0;
+  if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
     assert( pOp>p->aOp );
     assert( pOp[-1].p4type==P4_COLLSEQ );
     assert( pOp[-1].opcode==OP_CollSeq );
-    u.cg.ctx.pColl = pOp[-1].p4.pColl;
+    ctx.pColl = pOp[-1].p4.pColl;
   }
-  (u.cg.ctx.pFunc->xStep)(&u.cg.ctx, u.cg.n, u.cg.apVal); /* IMP: R-24505-23230 */
-  if( u.cg.ctx.isError ){
-    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cg.ctx.s));
-    rc = u.cg.ctx.isError;
+  (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */
+  if( ctx.isError ){
+    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s));
+    rc = ctx.isError;
   }
-  if( u.cg.ctx.skipFlag ){
+  if( ctx.skipFlag ){
     assert( pOp[-1].opcode==OP_CollSeq );
-    u.cg.i = pOp[-1].p1;
-    if( u.cg.i ) sqlite3VdbeMemSetInt64(&aMem[u.cg.i], 1);
+    i = pOp[-1].p1;
+    if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1);
   }
 
-  sqlite3VdbeMemRelease(&u.cg.ctx.s);
+  sqlite3VdbeMemRelease(&ctx.s);
 
   break;
 }
 
 /* Opcode: AggFinal P1 P2 * P4 *
+** Synopsis: accum=r[P1] N=P2
 **
 ** Execute the finalizer function for an aggregate.  P1 is
 ** the memory location that is the accumulator for the aggregate.
@@ -70886,19 +73708,17 @@ case OP_AggStep: {
 ** the step function was not previously called.
 */
 case OP_AggFinal: {
-#if 0  /* local variables moved into u.ch */
   Mem *pMem;
-#endif /* local variables moved into u.ch */
-  assert( pOp->p1>0 && pOp->p1<=p->nMem );
-  u.ch.pMem = &aMem[pOp->p1];
-  assert( (u.ch.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
-  rc = sqlite3VdbeMemFinalize(u.ch.pMem, pOp->p4.pFunc);
+  assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
+  pMem = &aMem[pOp->p1];
+  assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
+  rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
   if( rc ){
-    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.ch.pMem));
+    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(pMem));
   }
-  sqlite3VdbeChangeEncoding(u.ch.pMem, encoding);
-  UPDATE_MAX_BLOBSIZE(u.ch.pMem);
-  if( sqlite3VdbeMemTooBig(u.ch.pMem) ){
+  sqlite3VdbeChangeEncoding(pMem, encoding);
+  UPDATE_MAX_BLOBSIZE(pMem);
+  if( sqlite3VdbeMemTooBig(pMem) ){
     goto too_big;
   }
   break;
@@ -70917,32 +73737,31 @@ case OP_AggFinal: {
 ** mem[P3+2] are initialized to -1.
 */
 case OP_Checkpoint: {
-#if 0  /* local variables moved into u.ci */
   int i;                          /* Loop counter */
   int aRes[3];                    /* Results */
   Mem *pMem;                      /* Write results here */
-#endif /* local variables moved into u.ci */
 
-  u.ci.aRes[0] = 0;
-  u.ci.aRes[1] = u.ci.aRes[2] = -1;
+  assert( p->readOnly==0 );
+  aRes[0] = 0;
+  aRes[1] = aRes[2] = -1;
   assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
        || pOp->p2==SQLITE_CHECKPOINT_FULL
        || pOp->p2==SQLITE_CHECKPOINT_RESTART
   );
-  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.ci.aRes[1], &u.ci.aRes[2]);
+  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]);
   if( rc==SQLITE_BUSY ){
     rc = SQLITE_OK;
-    u.ci.aRes[0] = 1;
-  }
-  for(u.ci.i=0, u.ci.pMem = &aMem[pOp->p3]; u.ci.i<3; u.ci.i++, u.ci.pMem++){
-    sqlite3VdbeMemSetInt64(u.ci.pMem, (i64)u.ci.aRes[u.ci.i]);
+    aRes[0] = 1;
   }
+  for(i=0, pMem = &aMem[pOp->p3]; i<3; i++, pMem++){
+    sqlite3VdbeMemSetInt64(pMem, (i64)aRes[i]);
+  }    
   break;
 };  
 #endif
 
 #ifndef SQLITE_OMIT_PRAGMA
-/* Opcode: JournalMode P1 P2 P3 * P5
+/* Opcode: JournalMode P1 P2 P3 * *
 **
 ** Change the journal mode of database P1 to P3. P3 must be one of the
 ** PAGER_JOURNALMODE_XXX values. If changing between the various rollback
@@ -70954,7 +73773,6 @@ case OP_Checkpoint: {
 ** Write a string containing the final journal-mode to register P2.
 */
 case OP_JournalMode: {    /* out2-prerelease */
-#if 0  /* local variables moved into u.cj */
   Btree *pBt;                     /* Btree to change journal mode of */
   Pager *pPager;                  /* Pager associated with pBt */
   int eNew;                       /* New journal mode */
@@ -70962,85 +73780,85 @@ case OP_JournalMode: {    /* out2-prerelease */
 #ifndef SQLITE_OMIT_WAL
   const char *zFilename;          /* Name of database file for pPager */
 #endif
-#endif /* local variables moved into u.cj */
 
-  u.cj.eNew = pOp->p3;
-  assert( u.cj.eNew==PAGER_JOURNALMODE_DELETE
-       || u.cj.eNew==PAGER_JOURNALMODE_TRUNCATE
-       || u.cj.eNew==PAGER_JOURNALMODE_PERSIST
-       || u.cj.eNew==PAGER_JOURNALMODE_OFF
-       || u.cj.eNew==PAGER_JOURNALMODE_MEMORY
-       || u.cj.eNew==PAGER_JOURNALMODE_WAL
-       || u.cj.eNew==PAGER_JOURNALMODE_QUERY
+  eNew = pOp->p3;
+  assert( eNew==PAGER_JOURNALMODE_DELETE 
+       || eNew==PAGER_JOURNALMODE_TRUNCATE 
+       || eNew==PAGER_JOURNALMODE_PERSIST 
+       || eNew==PAGER_JOURNALMODE_OFF
+       || eNew==PAGER_JOURNALMODE_MEMORY
+       || eNew==PAGER_JOURNALMODE_WAL
+       || eNew==PAGER_JOURNALMODE_QUERY
   );
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
+  assert( p->readOnly==0 );
 
-  u.cj.pBt = db->aDb[pOp->p1].pBt;
-  u.cj.pPager = sqlite3BtreePager(u.cj.pBt);
-  u.cj.eOld = sqlite3PagerGetJournalMode(u.cj.pPager);
-  if( u.cj.eNew==PAGER_JOURNALMODE_QUERY ) u.cj.eNew = u.cj.eOld;
-  if( !sqlite3PagerOkToChangeJournalMode(u.cj.pPager) ) u.cj.eNew = u.cj.eOld;
+  pBt = db->aDb[pOp->p1].pBt;
+  pPager = sqlite3BtreePager(pBt);
+  eOld = sqlite3PagerGetJournalMode(pPager);
+  if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;
+  if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;
 
 #ifndef SQLITE_OMIT_WAL
-  u.cj.zFilename = sqlite3PagerFilename(u.cj.pPager, 1);
+  zFilename = sqlite3PagerFilename(pPager, 1);
 
   /* Do not allow a transition to journal_mode=WAL for a database
-  ** in temporary storage or if the VFS does not support shared memory
+  ** in temporary storage or if the VFS does not support shared memory 
   */
-  if( u.cj.eNew==PAGER_JOURNALMODE_WAL
-   && (sqlite3Strlen30(u.cj.zFilename)==0           /* Temp file */
-       || !sqlite3PagerWalSupported(u.cj.pPager))   /* No shared-memory support */
+  if( eNew==PAGER_JOURNALMODE_WAL
+   && (sqlite3Strlen30(zFilename)==0           /* Temp file */
+       || !sqlite3PagerWalSupported(pPager))   /* No shared-memory support */
   ){
-    u.cj.eNew = u.cj.eOld;
+    eNew = eOld;
   }
 
-  if( (u.cj.eNew!=u.cj.eOld)
-   && (u.cj.eOld==PAGER_JOURNALMODE_WAL || u.cj.eNew==PAGER_JOURNALMODE_WAL)
+  if( (eNew!=eOld)
+   && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL)
   ){
-    if( !db->autoCommit || db->activeVdbeCnt>1 ){
+    if( !db->autoCommit || db->nVdbeRead>1 ){
       rc = SQLITE_ERROR;
-      sqlite3SetString(&p->zErrMsg, db,
+      sqlite3SetString(&p->zErrMsg, db, 
           "cannot change %s wal mode from within a transaction",
-          (u.cj.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
+          (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
       );
       break;
     }else{
-
-      if( u.cj.eOld==PAGER_JOURNALMODE_WAL ){
+ 
+      if( eOld==PAGER_JOURNALMODE_WAL ){
         /* If leaving WAL mode, close the log file. If successful, the call
-        ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
-        ** file. An EXCLUSIVE lock may still be held on the database file
-        ** after a successful return.
+        ** to PagerCloseWal() checkpoints and deletes the write-ahead-log 
+        ** file. An EXCLUSIVE lock may still be held on the database file 
+        ** after a successful return. 
         */
-        rc = sqlite3PagerCloseWal(u.cj.pPager);
+        rc = sqlite3PagerCloseWal(pPager);
         if( rc==SQLITE_OK ){
-          sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew);
+          sqlite3PagerSetJournalMode(pPager, eNew);
         }
-      }else if( u.cj.eOld==PAGER_JOURNALMODE_MEMORY ){
+      }else if( eOld==PAGER_JOURNALMODE_MEMORY ){
         /* Cannot transition directly from MEMORY to WAL.  Use mode OFF
         ** as an intermediate */
-        sqlite3PagerSetJournalMode(u.cj.pPager, PAGER_JOURNALMODE_OFF);
+        sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF);
       }
-
+  
       /* Open a transaction on the database file. Regardless of the journal
       ** mode, this transaction always uses a rollback journal.
       */
-      assert( sqlite3BtreeIsInTrans(u.cj.pBt)==0 );
+      assert( sqlite3BtreeIsInTrans(pBt)==0 );
       if( rc==SQLITE_OK ){
-        rc = sqlite3BtreeSetVersion(u.cj.pBt, (u.cj.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
+        rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
       }
     }
   }
 #endif /* ifndef SQLITE_OMIT_WAL */
 
   if( rc ){
-    u.cj.eNew = u.cj.eOld;
+    eNew = eOld;
   }
-  u.cj.eNew = sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew);
+  eNew = sqlite3PagerSetJournalMode(pPager, eNew);
 
   pOut = &aMem[pOp->p2];
   pOut->flags = MEM_Str|MEM_Static|MEM_Term;
-  pOut->z = (char *)sqlite3JournalModename(u.cj.eNew);
+  pOut->z = (char *)sqlite3JournalModename(eNew);
   pOut->n = sqlite3Strlen30(pOut->z);
   pOut->enc = SQLITE_UTF8;
   sqlite3VdbeChangeEncoding(pOut, encoding);
@@ -71056,6 +73874,7 @@ case OP_JournalMode: {    /* out2-prerelease */
 ** a transaction.
 */
 case OP_Vacuum: {
+  assert( p->readOnly==0 );
   rc = sqlite3RunVacuum(&p->zErrMsg, db);
   break;
 }
@@ -71069,14 +73888,14 @@ case OP_Vacuum: {
 ** P2. Otherwise, fall through to the next instruction.
 */
 case OP_IncrVacuum: {        /* jump */
-#if 0  /* local variables moved into u.ck */
   Btree *pBt;
-#endif /* local variables moved into u.ck */
 
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
-  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
-  u.ck.pBt = db->aDb[pOp->p1].pBt;
-  rc = sqlite3BtreeIncrVacuum(u.ck.pBt);
+  assert( DbMaskTest(p->btreeMask, pOp->p1) );
+  assert( p->readOnly==0 );
+  pBt = db->aDb[pOp->p1].pBt;
+  rc = sqlite3BtreeIncrVacuum(pBt);
+  VdbeBranchTaken(rc==SQLITE_DONE,2);
   if( rc==SQLITE_DONE ){
     pc = pOp->p2 - 1;
     rc = SQLITE_OK;
@@ -71087,12 +73906,13 @@ case OP_IncrVacuum: {        /* jump */
 
 /* Opcode: Expire P1 * * * *
 **
-** Cause precompiled statements to become expired. An expired statement
-** fails with an error code of SQLITE_SCHEMA if it is ever executed 
-** (via sqlite3_step()).
+** Cause precompiled statements to expire.  When an expired statement
+** is executed using sqlite3_step() it will either automatically
+** reprepare itself (if it was originally created using sqlite3_prepare_v2())
+** or it will fail with SQLITE_SCHEMA.
 ** 
 ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
-** then only the currently executing statement is affected. 
+** then only the currently executing statement is expired.
 */
 case OP_Expire: {
   if( !pOp->p1 ){
@@ -71105,6 +73925,7 @@ case OP_Expire: {
 
 #ifndef SQLITE_OMIT_SHARED_CACHE
 /* Opcode: TableLock P1 P2 P3 P4 *
+** Synopsis: iDb=P1 root=P2 write=P3
 **
 ** Obtain a lock on a particular table. This instruction is only used when
 ** the shared-cache feature is enabled. 
@@ -71123,7 +73944,7 @@ case OP_TableLock: {
   if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
     int p1 = pOp->p1; 
     assert( p1>=0 && p1<db->nDb );
-    assert( (p->btreeMask & (((yDbMask)1)<<p1))!=0 );
+    assert( DbMaskTest(p->btreeMask, p1) );
     assert( isWriteLock==0 || isWriteLock==1 );
     rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
     if( (rc&0xFF)==SQLITE_LOCKED ){
@@ -71146,12 +73967,10 @@ case OP_TableLock: {
 ** code will be set to SQLITE_LOCKED.
 */
 case OP_VBegin: {
-#if 0  /* local variables moved into u.cl */
   VTable *pVTab;
-#endif /* local variables moved into u.cl */
-  u.cl.pVTab = pOp->p4.pVtab;
-  rc = sqlite3VtabBegin(db, u.cl.pVTab);
-  if( u.cl.pVTab ) importVtabErrMsg(p, u.cl.pVTab->pVtab);
+  pVTab = pOp->p4.pVtab;
+  rc = sqlite3VtabBegin(db, pVTab);
+  if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab);
   break;
 }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -71190,32 +74009,30 @@ case OP_VDestroy: {
 ** table and stores that cursor in P1.
 */
 case OP_VOpen: {
-#if 0  /* local variables moved into u.cm */
   VdbeCursor *pCur;
   sqlite3_vtab_cursor *pVtabCursor;
   sqlite3_vtab *pVtab;
   sqlite3_module *pModule;
-#endif /* local variables moved into u.cm */
-
-  u.cm.pCur = 0;
-  u.cm.pVtabCursor = 0;
-  u.cm.pVtab = pOp->p4.pVtab->pVtab;
-  u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
-  assert(u.cm.pVtab && u.cm.pModule);
-  rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor);
-  importVtabErrMsg(p, u.cm.pVtab);
+
+  assert( p->bIsReader );
+  pCur = 0;
+  pVtabCursor = 0;
+  pVtab = pOp->p4.pVtab->pVtab;
+  pModule = (sqlite3_module *)pVtab->pModule;
+  assert(pVtab && pModule);
+  rc = pModule->xOpen(pVtab, &pVtabCursor);
+  sqlite3VtabImportErrmsg(p, pVtab);
   if( SQLITE_OK==rc ){
     /* Initialize sqlite3_vtab_cursor base class */
-    u.cm.pVtabCursor->pVtab = u.cm.pVtab;
+    pVtabCursor->pVtab = pVtab;
 
     /* Initialize vdbe cursor object */
-    u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
-    if( u.cm.pCur ){
-      u.cm.pCur->pVtabCursor = u.cm.pVtabCursor;
-      u.cm.pCur->pModule = u.cm.pVtabCursor->pVtab->pModule;
+    pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
+    if( pCur ){
+      pCur->pVtabCursor = pVtabCursor;
     }else{
       db->mallocFailed = 1;
-      u.cm.pModule->xClose(u.cm.pVtabCursor);
+      pModule->xClose(pVtabCursor);
     }
   }
   break;
@@ -71224,6 +74041,7 @@ case OP_VOpen: {
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 /* Opcode: VFilter P1 P2 P3 P4 *
+** Synopsis: iplan=r[P3] zplan='P4'
 **
 ** P1 is a cursor opened using VOpen.  P2 is an address to jump to if
 ** the filtered result set is empty.
@@ -71242,7 +74060,6 @@ case OP_VOpen: {
 ** A jump is made to P2 if the result set after filtering would be empty.
 */
 case OP_VFilter: {   /* jump */
-#if 0  /* local variables moved into u.cn */
   int nArg;
   int iQuery;
   const sqlite3_module *pModule;
@@ -71254,45 +74071,43 @@ case OP_VFilter: {   /* jump */
   int res;
   int i;
   Mem **apArg;
-#endif /* local variables moved into u.cn */
-
-  u.cn.pQuery = &aMem[pOp->p3];
-  u.cn.pArgc = &u.cn.pQuery[1];
-  u.cn.pCur = p->apCsr[pOp->p1];
-  assert( memIsValid(u.cn.pQuery) );
-  REGISTER_TRACE(pOp->p3, u.cn.pQuery);
-  assert( u.cn.pCur->pVtabCursor );
-  u.cn.pVtabCursor = u.cn.pCur->pVtabCursor;
-  u.cn.pVtab = u.cn.pVtabCursor->pVtab;
-  u.cn.pModule = u.cn.pVtab->pModule;
+
+  pQuery = &aMem[pOp->p3];
+  pArgc = &pQuery[1];
+  pCur = p->apCsr[pOp->p1];
+  assert( memIsValid(pQuery) );
+  REGISTER_TRACE(pOp->p3, pQuery);
+  assert( pCur->pVtabCursor );
+  pVtabCursor = pCur->pVtabCursor;
+  pVtab = pVtabCursor->pVtab;
+  pModule = pVtab->pModule;
 
   /* Grab the index number and argc parameters */
-  assert( (u.cn.pQuery->flags&MEM_Int)!=0 && u.cn.pArgc->flags==MEM_Int );
-  u.cn.nArg = (int)u.cn.pArgc->u.i;
-  u.cn.iQuery = (int)u.cn.pQuery->u.i;
+  assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int );
+  nArg = (int)pArgc->u.i;
+  iQuery = (int)pQuery->u.i;
 
   /* Invoke the xFilter method */
   {
-    u.cn.res = 0;
-    u.cn.apArg = p->apArg;
-    for(u.cn.i = 0; u.cn.i<u.cn.nArg; u.cn.i++){
-      u.cn.apArg[u.cn.i] = &u.cn.pArgc[u.cn.i+1];
-      sqlite3VdbeMemStoreType(u.cn.apArg[u.cn.i]);
+    res = 0;
+    apArg = p->apArg;
+    for(i = 0; i<nArg; i++){
+      apArg[i] = &pArgc[i+1];
     }
 
     p->inVtabMethod = 1;
-    rc = u.cn.pModule->xFilter(u.cn.pVtabCursor, u.cn.iQuery, pOp->p4.z, u.cn.nArg, u.cn.apArg);
+    rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
     p->inVtabMethod = 0;
-    importVtabErrMsg(p, u.cn.pVtab);
+    sqlite3VtabImportErrmsg(p, pVtab);
     if( rc==SQLITE_OK ){
-      u.cn.res = u.cn.pModule->xEof(u.cn.pVtabCursor);
+      res = pModule->xEof(pVtabCursor);
     }
-
-    if( u.cn.res ){
+    VdbeBranchTaken(res!=0,2);
+    if( res ){
       pc = pOp->p2 - 1;
     }
   }
-  u.cn.pCur->nullRow = 0;
+  pCur->nullRow = 0;
 
   break;
 }
@@ -71300,57 +74115,56 @@ case OP_VFilter: {   /* jump */
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 /* Opcode: VColumn P1 P2 P3 * *
+** Synopsis: r[P3]=vcolumn(P2)
 **
 ** Store the value of the P2-th column of
 ** the row of the virtual-table that the 
 ** P1 cursor is pointing to into register P3.
 */
 case OP_VColumn: {
-#if 0  /* local variables moved into u.co */
   sqlite3_vtab *pVtab;
   const sqlite3_module *pModule;
   Mem *pDest;
   sqlite3_context sContext;
-#endif /* local variables moved into u.co */
 
   VdbeCursor *pCur = p->apCsr[pOp->p1];
   assert( pCur->pVtabCursor );
-  assert( pOp->p3>0 && pOp->p3<=p->nMem );
-  u.co.pDest = &aMem[pOp->p3];
-  memAboutToChange(p, u.co.pDest);
+  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
+  pDest = &aMem[pOp->p3];
+  memAboutToChange(p, pDest);
   if( pCur->nullRow ){
-    sqlite3VdbeMemSetNull(u.co.pDest);
+    sqlite3VdbeMemSetNull(pDest);
     break;
   }
-  u.co.pVtab = pCur->pVtabCursor->pVtab;
-  u.co.pModule = u.co.pVtab->pModule;
-  assert( u.co.pModule->xColumn );
-  memset(&u.co.sContext, 0, sizeof(u.co.sContext));
+  pVtab = pCur->pVtabCursor->pVtab;
+  pModule = pVtab->pModule;
+  assert( pModule->xColumn );
+  memset(&sContext, 0, sizeof(sContext));
 
   /* The output cell may already have a buffer allocated. Move
-  ** the current contents to u.co.sContext.s so in case the user-function
-  ** can use the already allocated buffer instead of allocating a
+  ** the current contents to sContext.s so in case the user-function 
+  ** can use the already allocated buffer instead of allocating a 
   ** new one.
   */
-  sqlite3VdbeMemMove(&u.co.sContext.s, u.co.pDest);
-  MemSetTypeFlag(&u.co.sContext.s, MEM_Null);
+  sqlite3VdbeMemMove(&sContext.s, pDest);
+  MemSetTypeFlag(&sContext.s, MEM_Null);
 
-  rc = u.co.pModule->xColumn(pCur->pVtabCursor, &u.co.sContext, pOp->p2);
-  importVtabErrMsg(p, u.co.pVtab);
-  if( u.co.sContext.isError ){
-    rc = u.co.sContext.isError;
+  rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
+  sqlite3VtabImportErrmsg(p, pVtab);
+  if( sContext.isError ){
+    rc = sContext.isError;
   }
 
   /* Copy the result of the function to the P3 register. We
   ** do this regardless of whether or not an error occurred to ensure any
-  ** dynamic allocation in u.co.sContext.s (a Mem struct) is  released.
+  ** dynamic allocation in sContext.s (a Mem struct) is  released.
   */
-  sqlite3VdbeChangeEncoding(&u.co.sContext.s, encoding);
-  sqlite3VdbeMemMove(u.co.pDest, &u.co.sContext.s);
-  REGISTER_TRACE(pOp->p3, u.co.pDest);
-  UPDATE_MAX_BLOBSIZE(u.co.pDest);
+  sqlite3VdbeChangeEncoding(&sContext.s, encoding);
+  sqlite3VdbeMemMove(pDest, &sContext.s);
+  REGISTER_TRACE(pOp->p3, pDest);
+  UPDATE_MAX_BLOBSIZE(pDest);
 
-  if( sqlite3VdbeMemTooBig(u.co.pDest) ){
+  if( sqlite3VdbeMemTooBig(pDest) ){
     goto too_big;
   }
   break;
@@ -71365,42 +74179,40 @@ case OP_VColumn: {
 ** the end of its result set, then fall through to the next instruction.
 */
 case OP_VNext: {   /* jump */
-#if 0  /* local variables moved into u.cp */
   sqlite3_vtab *pVtab;
   const sqlite3_module *pModule;
   int res;
   VdbeCursor *pCur;
-#endif /* local variables moved into u.cp */
 
-  u.cp.res = 0;
-  u.cp.pCur = p->apCsr[pOp->p1];
-  assert( u.cp.pCur->pVtabCursor );
-  if( u.cp.pCur->nullRow ){
+  res = 0;
+  pCur = p->apCsr[pOp->p1];
+  assert( pCur->pVtabCursor );
+  if( pCur->nullRow ){
     break;
   }
-  u.cp.pVtab = u.cp.pCur->pVtabCursor->pVtab;
-  u.cp.pModule = u.cp.pVtab->pModule;
-  assert( u.cp.pModule->xNext );
+  pVtab = pCur->pVtabCursor->pVtab;
+  pModule = pVtab->pModule;
+  assert( pModule->xNext );
 
   /* Invoke the xNext() method of the module. There is no way for the
   ** underlying implementation to return an error if one occurs during
-  ** xNext(). Instead, if an error occurs, true is returned (indicating that
+  ** xNext(). Instead, if an error occurs, true is returned (indicating that 
   ** data is available) and the error code returned when xColumn or
   ** some other method is next invoked on the save virtual table cursor.
   */
   p->inVtabMethod = 1;
-  rc = u.cp.pModule->xNext(u.cp.pCur->pVtabCursor);
+  rc = pModule->xNext(pCur->pVtabCursor);
   p->inVtabMethod = 0;
-  importVtabErrMsg(p, u.cp.pVtab);
+  sqlite3VtabImportErrmsg(p, pVtab);
   if( rc==SQLITE_OK ){
-    u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor);
+    res = pModule->xEof(pCur->pVtabCursor);
   }
-
-  if( !u.cp.res ){
+  VdbeBranchTaken(!res,2);
+  if( !res ){
     /* If there is data, jump to P2 */
     pc = pOp->p2 - 1;
   }
-  break;
+  goto check_for_interrupt;
 }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
@@ -71412,24 +74224,23 @@ case OP_VNext: {   /* jump */
 ** in register P1 is passed as the zName argument to the xRename method.
 */
 case OP_VRename: {
-#if 0  /* local variables moved into u.cq */
   sqlite3_vtab *pVtab;
   Mem *pName;
-#endif /* local variables moved into u.cq */
-
-  u.cq.pVtab = pOp->p4.pVtab->pVtab;
-  u.cq.pName = &aMem[pOp->p1];
-  assert( u.cq.pVtab->pModule->xRename );
-  assert( memIsValid(u.cq.pName) );
-  REGISTER_TRACE(pOp->p1, u.cq.pName);
-  assert( u.cq.pName->flags & MEM_Str );
-  testcase( u.cq.pName->enc==SQLITE_UTF8 );
-  testcase( u.cq.pName->enc==SQLITE_UTF16BE );
-  testcase( u.cq.pName->enc==SQLITE_UTF16LE );
-  rc = sqlite3VdbeChangeEncoding(u.cq.pName, SQLITE_UTF8);
+
+  pVtab = pOp->p4.pVtab->pVtab;
+  pName = &aMem[pOp->p1];
+  assert( pVtab->pModule->xRename );
+  assert( memIsValid(pName) );
+  assert( p->readOnly==0 );
+  REGISTER_TRACE(pOp->p1, pName);
+  assert( pName->flags & MEM_Str );
+  testcase( pName->enc==SQLITE_UTF8 );
+  testcase( pName->enc==SQLITE_UTF16BE );
+  testcase( pName->enc==SQLITE_UTF16LE );
+  rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
   if( rc==SQLITE_OK ){
-    rc = u.cq.pVtab->pModule->xRename(u.cq.pVtab, u.cq.pName->z);
-    importVtabErrMsg(p, u.cq.pVtab);
+    rc = pVtab->pModule->xRename(pVtab, pName->z);
+    sqlite3VtabImportErrmsg(p, pVtab);
     p->expired = 0;
   }
   break;
@@ -71437,7 +74248,8 @@ case OP_VRename: {
 #endif
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VUpdate P1 P2 P3 P4 *
+/* Opcode: VUpdate P1 P2 P3 P4 P5
+** Synopsis: data=r[P3 at P2]
 **
 ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
 ** This opcode invokes the corresponding xUpdate method. P2 values
@@ -71459,9 +74271,11 @@ case OP_VRename: {
 ** P1 is a boolean flag. If it is set to true and the xUpdate call
 ** is successful, then the value returned by sqlite3_last_insert_rowid() 
 ** is set to the value of the rowid for the row just inserted.
+**
+** P5 is the error actions (OE_Replace, OE_Fail, OE_Ignore, etc) to
+** apply in the case of a constraint failure on an insert or update.
 */
 case OP_VUpdate: {
-#if 0  /* local variables moved into u.cr */
   sqlite3_vtab *pVtab;
   sqlite3_module *pModule;
   int nArg;
@@ -71469,33 +74283,32 @@ case OP_VUpdate: {
   sqlite_int64 rowid;
   Mem **apArg;
   Mem *pX;
-#endif /* local variables moved into u.cr */
 
-  assert( pOp->p2==1        || pOp->p5==OE_Fail   || pOp->p5==OE_Rollback
+  assert( pOp->p2==1        || pOp->p5==OE_Fail   || pOp->p5==OE_Rollback 
        || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
   );
-  u.cr.pVtab = pOp->p4.pVtab->pVtab;
-  u.cr.pModule = (sqlite3_module *)u.cr.pVtab->pModule;
-  u.cr.nArg = pOp->p2;
+  assert( p->readOnly==0 );
+  pVtab = pOp->p4.pVtab->pVtab;
+  pModule = (sqlite3_module *)pVtab->pModule;
+  nArg = pOp->p2;
   assert( pOp->p4type==P4_VTAB );
-  if( ALWAYS(u.cr.pModule->xUpdate) ){
+  if( ALWAYS(pModule->xUpdate) ){
     u8 vtabOnConflict = db->vtabOnConflict;
-    u.cr.apArg = p->apArg;
-    u.cr.pX = &aMem[pOp->p3];
-    for(u.cr.i=0; u.cr.i<u.cr.nArg; u.cr.i++){
-      assert( memIsValid(u.cr.pX) );
-      memAboutToChange(p, u.cr.pX);
-      sqlite3VdbeMemStoreType(u.cr.pX);
-      u.cr.apArg[u.cr.i] = u.cr.pX;
-      u.cr.pX++;
+    apArg = p->apArg;
+    pX = &aMem[pOp->p3];
+    for(i=0; i<nArg; i++){
+      assert( memIsValid(pX) );
+      memAboutToChange(p, pX);
+      apArg[i] = pX;
+      pX++;
     }
     db->vtabOnConflict = pOp->p5;
-    rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid);
+    rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
     db->vtabOnConflict = vtabOnConflict;
-    importVtabErrMsg(p, u.cr.pVtab);
+    sqlite3VtabImportErrmsg(p, pVtab);
     if( rc==SQLITE_OK && pOp->p1 ){
-      assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
-      db->lastRowid = lastRowid = u.cr.rowid;
+      assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
+      db->lastRowid = lastRowid = rowid;
     }
     if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
       if( pOp->p5==OE_Ignore ){
@@ -71548,36 +74361,54 @@ case OP_MaxPgcnt: {            /* out2-prerelease */
 #endif
 
 
-#ifndef SQLITE_OMIT_TRACE
-/* Opcode: Trace * * * P4 *
+/* Opcode: Init * P2 * P4 *
+** Synopsis:  Start at P2
+**
+** Programs contain a single instance of this opcode as the very first
+** opcode.
 **
 ** If tracing is enabled (by the sqlite3_trace()) interface, then
 ** the UTF-8 string contained in P4 is emitted on the trace callback.
+** Or if P4 is blank, use the string returned by sqlite3_sql().
+**
+** If P2 is not zero, jump to instruction P2.
 */
-case OP_Trace: {
-#if 0  /* local variables moved into u.cs */
+case OP_Init: {          /* jump */
   char *zTrace;
   char *z;
-#endif /* local variables moved into u.cs */
 
+  if( pOp->p2 ){
+    pc = pOp->p2 - 1;
+  }
+#ifndef SQLITE_OMIT_TRACE
   if( db->xTrace
    && !p->doingRerun
-   && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+   && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
   ){
-    u.cs.z = sqlite3VdbeExpandSql(p, u.cs.zTrace);
-    db->xTrace(db->pTraceArg, u.cs.z);
-    sqlite3DbFree(db, u.cs.z);
+    z = sqlite3VdbeExpandSql(p, zTrace);
+    db->xTrace(db->pTraceArg, z);
+    sqlite3DbFree(db, z);
   }
+#ifdef SQLITE_USE_FCNTL_TRACE
+  zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
+  if( zTrace ){
+    int i;
+    for(i=0; i<db->nDb; i++){
+      if( DbMaskTest(p->btreeMask, i)==0 ) continue;
+      sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
+    }
+  }
+#endif /* SQLITE_USE_FCNTL_TRACE */
 #ifdef SQLITE_DEBUG
   if( (db->flags & SQLITE_SqlTrace)!=0
-   && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+   && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
   ){
-    sqlite3DebugPrintf("SQL-trace: %s\n", u.cs.zTrace);
+    sqlite3DebugPrintf("SQL-trace: %s\n", zTrace);
   }
 #endif /* SQLITE_DEBUG */
+#endif /* SQLITE_OMIT_TRACE */
   break;
 }
-#endif
 
 
 /* Opcode: Noop * * * * *
@@ -71606,13 +74437,9 @@ default: {          /* This is really OP_Noop and OP_Explain */
 
 #ifdef VDBE_PROFILE
     {
-      u64 elapsed = sqlite3Hwtime() - start;
-      pOp->cycles += elapsed;
+      u64 endTime = sqlite3Hwtime();
+      if( endTime>start ) pOp->cycles += endTime - start;
       pOp->cnt++;
-#if 0
-        fprintf(stdout, "%10llu ", elapsed);
-        sqlite3VdbePrintOp(stdout, origPc, &aOp[origPc]);
-#endif
     }
 #endif
 
@@ -71625,13 +74452,13 @@ default: {          /* This is really OP_Noop and OP_Explain */
     assert( pc>=-1 && pc<p->nOp );
 
 #ifdef SQLITE_DEBUG
-    if( p->trace ){
-      if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc);
+    if( db->flags & SQLITE_VdbeTrace ){
+      if( rc!=0 ) printf("rc=%d\n",rc);
       if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){
-        registerTrace(p->trace, pOp->p2, &aMem[pOp->p2]);
+        registerTrace(pOp->p2, &aMem[pOp->p2]);
       }
       if( pOp->opflags & OPFLG_OUT3 ){
-        registerTrace(p->trace, pOp->p3, &aMem[pOp->p3]);
+        registerTrace(pOp->p3, &aMem[pOp->p3]);
       }
     }
 #endif  /* SQLITE_DEBUG */
@@ -71659,6 +74486,8 @@ vdbe_error_halt:
   ** top. */
 vdbe_return:
   db->lastRowid = lastRowid;
+  testcase( nVmStep>0 );
+  p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
   sqlite3VdbeLeave(p);
   return rc;
 
@@ -71700,6 +74529,7 @@ abort_due_to_interrupt:
   goto vdbe_error_halt;
 }
 
+
 /************** End of vdbe.c ************************************************/
 /************** Begin file vdbeblob.c ****************************************/
 /*
@@ -71766,7 +74596,8 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
 
   rc = sqlite3_step(p->pStmt);
   if( rc==SQLITE_ROW ){
-    u32 type = v->apCsr[0]->aType[p->iCol];
+    VdbeCursor *pC = v->apCsr[0];
+    u32 type = pC->aType[p->iCol];
     if( type<12 ){
       zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
           type==0?"null": type==7?"real": "integer"
@@ -71775,12 +74606,10 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
       sqlite3_finalize(p->pStmt);
       p->pStmt = 0;
     }else{
-      p->iOffset = v->apCsr[0]->aOffset[p->iCol];
+      p->iOffset = pC->aType[p->iCol + pC->nField];
       p->nByte = sqlite3VdbeSerialTypeLen(type);
-      p->pCsr =  v->apCsr[0]->pCursor;
-      sqlite3BtreeEnterCursor(p->pCsr);
-      sqlite3BtreeCacheOverflow(p->pCsr);
-      sqlite3BtreeLeaveCursor(p->pCsr);
+      p->pCsr =  pC->pCursor;
+      sqlite3BtreeIncrblobCursor(p->pCsr);
     }
   }
 
@@ -71834,22 +74663,20 @@ SQLITE_API int sqlite3_blob_open(
   ** which closes the b-tree cursor and (possibly) commits the 
   ** transaction.
   */
+  static const int iLn = VDBE_OFFSET_LINENO(4);
   static const VdbeOpList openBlob[] = {
-    {OP_Transaction, 0, 0, 0},     /* 0: Start a transaction */
-    {OP_VerifyCookie, 0, 0, 0},    /* 1: Check the schema cookie */
-    {OP_TableLock, 0, 0, 0},       /* 2: Acquire a read or write lock */
-
+    /* {OP_Transaction, 0, 0, 0},  // 0: Inserted separately */
+    {OP_TableLock, 0, 0, 0},       /* 1: Acquire a read or write lock */
     /* One of the following two instructions is replaced by an OP_Noop. */
-    {OP_OpenRead, 0, 0, 0},        /* 3: Open cursor 0 for reading */
-    {OP_OpenWrite, 0, 0, 0},       /* 4: Open cursor 0 for read/write */
-
-    {OP_Variable, 1, 1, 1},        /* 5: Push the rowid to the stack */
-    {OP_NotExists, 0, 10, 1},      /* 6: Seek the cursor */
-    {OP_Column, 0, 0, 1},          /* 7  */
-    {OP_ResultRow, 1, 0, 0},       /* 8  */
-    {OP_Goto, 0, 5, 0},            /* 9  */
-    {OP_Close, 0, 0, 0},           /* 10 */
-    {OP_Halt, 0, 0, 0},            /* 11 */
+    {OP_OpenRead, 0, 0, 0},        /* 2: Open cursor 0 for reading */
+    {OP_OpenWrite, 0, 0, 0},       /* 3: Open cursor 0 for read/write */
+    {OP_Variable, 1, 1, 1},        /* 4: Push the rowid to the stack */
+    {OP_NotExists, 0, 10, 1},      /* 5: Seek the cursor */
+    {OP_Column, 0, 0, 1},          /* 6  */
+    {OP_ResultRow, 1, 0, 0},       /* 7  */
+    {OP_Goto, 0, 4, 0},            /* 8  */
+    {OP_Close, 0, 0, 0},           /* 9  */
+    {OP_Halt, 0, 0, 0},            /* 10 */
   };
 
   int rc = SQLITE_OK;
@@ -71880,6 +74707,10 @@ SQLITE_API int sqlite3_blob_open(
       pTab = 0;
       sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable);
     }
+    if( pTab && !HasRowid(pTab) ){
+      pTab = 0;
+      sqlite3ErrorMsg(pParse, "cannot open table without rowid: %s", zTable);
+    }
 #ifndef SQLITE_OMIT_VIEW
     if( pTab && pTab->pSelect ){
       pTab = 0;
@@ -71937,7 +74768,7 @@ SQLITE_API int sqlite3_blob_open(
 #endif
       for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
         int j;
-        for(j=0; j<pIdx->nColumn; j++){
+        for(j=0; j<pIdx->nKeyCol; j++){
           if( pIdx->aiColumn[j]==iCol ){
             zFault = "indexed";
           }
@@ -71952,42 +74783,37 @@ SQLITE_API int sqlite3_blob_open(
       }
     }
 
-    pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(db);
+    pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse);
     assert( pBlob->pStmt || db->mallocFailed );
     if( pBlob->pStmt ){
       Vdbe *v = (Vdbe *)pBlob->pStmt;
       int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
 
-      sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob);
 
-
-      /* Configure the OP_Transaction */
-      sqlite3VdbeChangeP1(v, 0, iDb);
-      sqlite3VdbeChangeP2(v, 0, flags);
-
-      /* Configure the OP_VerifyCookie */
-      sqlite3VdbeChangeP1(v, 1, iDb);
-      sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
-      sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration);
+      sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags, 
+                           pTab->pSchema->schema_cookie,
+                           pTab->pSchema->iGeneration);
+      sqlite3VdbeChangeP5(v, 1);     
+      sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
 
       /* Make sure a mutex is held on the table to be accessed */
       sqlite3VdbeUsesBtree(v, iDb); 
 
       /* Configure the OP_TableLock instruction */
 #ifdef SQLITE_OMIT_SHARED_CACHE
-      sqlite3VdbeChangeToNoop(v, 2);
+      sqlite3VdbeChangeToNoop(v, 1);
 #else
-      sqlite3VdbeChangeP1(v, 2, iDb);
-      sqlite3VdbeChangeP2(v, 2, pTab->tnum);
-      sqlite3VdbeChangeP3(v, 2, flags);
-      sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
+      sqlite3VdbeChangeP1(v, 1, iDb);
+      sqlite3VdbeChangeP2(v, 1, pTab->tnum);
+      sqlite3VdbeChangeP3(v, 1, flags);
+      sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
 #endif
 
       /* Remove either the OP_OpenWrite or OpenRead. Set the P2 
       ** parameter of the other to pTab->tnum.  */
-      sqlite3VdbeChangeToNoop(v, 4 - flags);
-      sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
-      sqlite3VdbeChangeP3(v, 3 + flags, iDb);
+      sqlite3VdbeChangeToNoop(v, 3 - flags);
+      sqlite3VdbeChangeP2(v, 2 + flags, pTab->tnum);
+      sqlite3VdbeChangeP3(v, 2 + flags, iDb);
 
       /* Configure the number of columns. Configure the cursor to
       ** think that the table has one more column than it really
@@ -71996,8 +74822,8 @@ SQLITE_API int sqlite3_blob_open(
       ** we can invoke OP_Column to fill in the vdbe cursors type 
       ** and offset cache without causing any IO.
       */
-      sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
-      sqlite3VdbeChangeP2(v, 7, pTab->nCol);
+      sqlite3VdbeChangeP4(v, 2+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
+      sqlite3VdbeChangeP2(v, 6, pTab->nCol);
       if( !db->mallocFailed ){
         pParse->nVar = 1;
         pParse->nMem = 1;
@@ -72026,6 +74852,7 @@ blob_open_out:
   }
   sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr);
   sqlite3DbFree(db, zErr);
+  sqlite3ParserReset(pParse);
   sqlite3StackFree(db, pParse);
   rc = sqlite3ApiExit(db, rc);
   sqlite3_mutex_leave(db->mutex);
@@ -72226,7 +75053,7 @@ typedef struct FileWriter FileWriter;
 ** other key value. If the keys are equal (only possible with two EOF
 ** values), it doesn't matter which index is stored.
 **
-** The (N/4) elements of aTree[] that preceed the final (N/2) described 
+** The (N/4) elements of aTree[] that precede the final (N/2) described 
 ** above contains the index of the smallest of each block of 4 iterators.
 ** And so on. So that aTree[1] contains the index of the iterator that 
 ** currently points to the smallest key value. aTree[0] is unused.
@@ -72522,7 +75349,6 @@ static int vdbeSorterIterInit(
       rc = sqlite3OsRead(
           pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart
       );
-      assert( rc!=SQLITE_IOERR_SHORT_READ );
     }
 
     if( rc==SQLITE_OK ){
@@ -72558,7 +75384,7 @@ static int vdbeSorterIterInit(
 */
 static void vdbeSorterCompare(
   const VdbeCursor *pCsr,         /* Cursor object (for pKeyInfo) */
-  int bOmitRowid,                 /* Ignore rowid field at end of keys */
+  int nKeyCol,                    /* Num of columns. 0 means "all" */
   const void *pKey1, int nKey1,   /* Left side of comparison */
   const void *pKey2, int nKey2,   /* Right side of comparison */
   int *pRes                       /* OUT: Result of comparison */
@@ -72572,19 +75398,18 @@ static void vdbeSorterCompare(
     sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
   }
 
-  if( bOmitRowid ){
-    r2->nField = pKeyInfo->nField;
-    assert( r2->nField>0 );
-    for(i=0; i<r2->nField; i++){
+  if( nKeyCol ){
+    r2->nField = nKeyCol;
+    for(i=0; i<nKeyCol; i++){
       if( r2->aMem[i].flags & MEM_Null ){
         *pRes = -1;
         return;
       }
     }
-    r2->flags |= UNPACKED_PREFIX_MATCH;
+    assert( r2->default_rc==0 );
   }
 
-  *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
+  *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2, 0);
 }
 
 /*
@@ -72677,22 +75502,39 @@ static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
 }
 
 /*
+** Reset a sorting cursor back to its original empty state.
+*/
+SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
+  if( pSorter->aIter ){
+    int i;
+    for(i=0; i<pSorter->nTree; i++){
+      vdbeSorterIterZero(db, &pSorter->aIter[i]);
+    }
+    sqlite3DbFree(db, pSorter->aIter);
+    pSorter->aIter = 0;
+  }
+  if( pSorter->pTemp1 ){
+    sqlite3OsCloseFree(pSorter->pTemp1);
+    pSorter->pTemp1 = 0;
+  }
+  vdbeSorterRecordFree(db, pSorter->pRecord);
+  pSorter->pRecord = 0;
+  pSorter->iWriteOff = 0;
+  pSorter->iReadOff = 0;
+  pSorter->nInMemory = 0;
+  pSorter->nTree = 0;
+  pSorter->nPMA = 0;
+  pSorter->aTree = 0;
+}
+
+
+/*
 ** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
 */
 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
   VdbeSorter *pSorter = pCsr->pSorter;
   if( pSorter ){
-    if( pSorter->aIter ){
-      int i;
-      for(i=0; i<pSorter->nTree; i++){
-        vdbeSorterIterZero(db, &pSorter->aIter[i]);
-      }
-      sqlite3DbFree(db, pSorter->aIter);
-    }
-    if( pSorter->pTemp1 ){
-      sqlite3OsCloseFree(pSorter->pTemp1);
-    }
-    vdbeSorterRecordFree(db, pSorter->pRecord);
+    sqlite3VdbeSorterReset(db, pSorter);
     sqlite3DbFree(db, pSorter->pUnpacked);
     sqlite3DbFree(db, pSorter);
     pCsr->pSorter = 0;
@@ -73128,14 +75970,55 @@ SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, in
 
   if( pSorter->aTree ){
     int iPrev = pSorter->aTree[1];/* Index of iterator to advance */
-    int i;                        /* Index of aTree[] to recalculate */
-
     rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
-    for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
-      rc = vdbeSorterDoCompare(pCsr, i);
-    }
+    if( rc==SQLITE_OK ){
+      int i;                      /* Index of aTree[] to recalculate */
+      VdbeSorterIter *pIter1;     /* First iterator to compare */
+      VdbeSorterIter *pIter2;     /* Second iterator to compare */
+      u8 *pKey2;                  /* To pIter2->aKey, or 0 if record cached */
+
+      /* Find the first two iterators to compare. The one that was just
+      ** advanced (iPrev) and the one next to it in the array.  */
+      pIter1 = &pSorter->aIter[(iPrev & 0xFFFE)];
+      pIter2 = &pSorter->aIter[(iPrev | 0x0001)];
+      pKey2 = pIter2->aKey;
+
+      for(i=(pSorter->nTree+iPrev)/2; i>0; i=i/2){
+        /* Compare pIter1 and pIter2. Store the result in variable iRes. */
+        int iRes;
+        if( pIter1->pFile==0 ){
+          iRes = +1;
+        }else if( pIter2->pFile==0 ){
+          iRes = -1;
+        }else{
+          vdbeSorterCompare(pCsr, 0, 
+              pIter1->aKey, pIter1->nKey, pKey2, pIter2->nKey, &iRes
+          );
+        }
+
+        /* If pIter1 contained the smaller value, set aTree[i] to its index.
+        ** Then set pIter2 to the next iterator to compare to pIter1. In this
+        ** case there is no cache of pIter2 in pSorter->pUnpacked, so set
+        ** pKey2 to point to the record belonging to pIter2.
+        **
+        ** Alternatively, if pIter2 contains the smaller of the two values,
+        ** set aTree[i] to its index and update pIter1. If vdbeSorterCompare()
+        ** was actually called above, then pSorter->pUnpacked now contains
+        ** a value equivalent to pIter2. So set pKey2 to NULL to prevent
+        ** vdbeSorterCompare() from decoding pIter2 again.  */
+        if( iRes<=0 ){
+          pSorter->aTree[i] = (int)(pIter1 - pSorter->aIter);
+          pIter2 = &pSorter->aIter[ pSorter->aTree[i ^ 0x0001] ];
+          pKey2 = pIter2->aKey;
+        }else{
+          if( pIter1->pFile ) pKey2 = 0;
+          pSorter->aTree[i] = (int)(pIter2 - pSorter->aIter);
+          pIter1 = &pSorter->aIter[ pSorter->aTree[i ^ 0x0001] ];
+        }
 
-    *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
+      }
+      *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
+    }
   }else{
     SorterRecord *pFree = pSorter->pRecord;
     pSorter->pRecord = pFree->pNext;
@@ -73199,13 +76082,14 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
 SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
   const VdbeCursor *pCsr,         /* Sorter cursor */
   Mem *pVal,                      /* Value to compare to current sorter key */
+  int nKeyCol,                    /* Only compare this many fields */
   int *pRes                       /* OUT: Result of comparison */
 ){
   VdbeSorter *pSorter = pCsr->pSorter;
   void *pKey; int nKey;           /* Sorter key to compare pVal with */
 
   pKey = vdbeSorterRowkey(pSorter, &nKey);
-  vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
+  vdbeSorterCompare(pCsr, nKeyCol, pVal->z, pVal->n, pKey, nKey, pRes);
   return SQLITE_OK;
 }
 
@@ -73501,12 +76385,6 @@ typedef struct FileChunk FileChunk;
 */
 #define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*)))
 
-/* Macro to find the minimum of two numeric values.
-*/
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
 /*
 ** The rollback journal is composed of a linked list of these structures.
 */
@@ -73776,7 +76654,7 @@ SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
   testcase( ExprHasProperty(pExpr, EP_Reduced) );
   rc = pWalker->xExprCallback(pWalker, pExpr);
   if( rc==WRC_Continue
-              && !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){
+              && !ExprHasProperty(pExpr,EP_TokenOnly) ){
     if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
     if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
     if( ExprHasProperty(pExpr, EP_xIsSelect) ){
@@ -73846,9 +76724,12 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
 /*
 ** 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.  Invoke the xSelectCallback()
-** either before or after the walk of expressions and FROM clause, depending
-** on whether pWalker->bSelectDepthFirst is false or true, respectively.
+** on the compound select chain, p->pPrior. 
+**
+** If it is not NULL, the xSelectCallback() callback is invoked before
+** the walk of the expressions and FROM clause. The xSelectCallback2()
+** method, if it is not NULL, is invoked following the walk of the 
+** expressions and FROM clause.
 **
 ** Return WRC_Continue under normal conditions.  Return WRC_Abort if
 ** there is an abort request.
@@ -73858,11 +76739,13 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
 */
 SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
   int rc;
-  if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
+  if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){
+    return WRC_Continue;
+  }
   rc = WRC_Continue;
   pWalker->walkerDepth++;
   while( p ){
-    if( !pWalker->bSelectDepthFirst ){
+    if( pWalker->xSelectCallback ){
        rc = pWalker->xSelectCallback(pWalker, p);
        if( rc ) break;
     }
@@ -73872,12 +76755,8 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
       pWalker->walkerDepth--;
       return WRC_Abort;
     }
-    if( pWalker->bSelectDepthFirst ){
-      rc = pWalker->xSelectCallback(pWalker, p);
-      /* Depth-first search is currently only used for
-      ** selectAddSubqueryTypeInfo() and that routine always returns
-      ** WRC_Continue (0).  So the following branch is never taken. */
-      if( NEVER(rc) ) break;
+    if( pWalker->xSelectCallback2 ){
+      pWalker->xSelectCallback2(pWalker, p);
     }
     p = p->pPrior;
   }
@@ -73943,7 +76822,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
 ** 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
+** 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
@@ -73953,8 +76832,9 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
 **     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...
+** from the result in the result-set.  On the other hand Standard SQL does
+** not allow the GROUP BY clause to contain references to result-set columns.
+** So this should never come up in well-formed queries.
 **
 ** If the reference is followed by a COLLATE operator, then make sure
 ** the COLLATE operator is preserved.  For example:
@@ -73994,10 +76874,11 @@ static void resolveAlias(
     incrAggFunctionDepth(pDup, nSubquery);
     pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
     if( pDup==0 ) return;
-    if( pEList->a[iCol].iAlias==0 ){
-      pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
+    ExprSetProperty(pDup, EP_Skip);
+    if( pEList->a[iCol].u.x.iAlias==0 ){
+      pEList->a[iCol].u.x.iAlias = (u16)(++pParse->nAlias);
     }
-    pDup->iTable = pEList->a[iCol].iAlias;
+    pDup->iTable = pEList->a[iCol].u.x.iAlias;
   }
   if( pExpr->op==TK_COLLATE ){
     pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
@@ -74016,7 +76897,7 @@ static void resolveAlias(
   if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
     assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
     pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
-    pExpr->flags2 |= EP2_MallocedToken;
+    pExpr->flags |= EP_MemToken;
   }
   sqlite3DbFree(db, pDup);
 }
@@ -74112,27 +76993,38 @@ static int lookupName(
   struct SrcList_item *pMatch = 0;  /* The matching pSrcList item */
   NameContext *pTopNC = pNC;        /* First namecontext in the list */
   Schema *pSchema = 0;              /* Schema of the expression */
-  int isTrigger = 0;
+  int isTrigger = 0;                /* True if resolved to a trigger column */
+  Table *pTab = 0;                  /* Table hold the row */
+  Column *pCol;                     /* A column of pTab */
 
   assert( pNC );     /* the name context cannot be NULL. */
   assert( zCol );    /* The Z in X.Y.Z cannot be NULL */
-  assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+  assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
 
   /* Initialize the node to no-match */
   pExpr->iTable = -1;
   pExpr->pTab = 0;
-  ExprSetIrreducible(pExpr);
+  ExprSetVVAProperty(pExpr, EP_NoReduce);
 
   /* Translate the schema name in zDb into a pointer to the corresponding
   ** schema.  If not found, pSchema will remain NULL and nothing will match
   ** resulting in an appropriate error message toward the end of this routine
   */
   if( zDb ){
-    for(i=0; i<db->nDb; i++){
-      assert( db->aDb[i].zName );
-      if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
-        pSchema = db->aDb[i].pSchema;
-        break;
+    testcase( pNC->ncFlags & NC_PartIdx );
+    testcase( pNC->ncFlags & NC_IsCheck );
+    if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){
+      /* Silently ignore database qualifiers inside CHECK constraints and partial
+      ** indices.  Do not raise errors because that might break legacy and
+      ** because it does not hurt anything to just ignore the database name. */
+      zDb = 0;
+    }else{
+      for(i=0; i<db->nDb; i++){
+        assert( db->aDb[i].zName );
+        if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
+          pSchema = db->aDb[i].pSchema;
+          break;
+        }
       }
     }
   }
@@ -74144,9 +77036,6 @@ static int lookupName(
 
     if( pSrcList ){
       for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
-        Table *pTab;
-        Column *pCol;
-  
         pTab = pItem->pTab;
         assert( pTab!=0 && pTab->zName!=0 );
         assert( pTab->nCol>0 );
@@ -74206,9 +77095,8 @@ static int lookupName(
     /* 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->pTriggerTab!=0 ){
+    if( zDb==0 && zTab!=0 && cntTab==0 && pParse->pTriggerTab!=0 ){
       int op = pParse->eTriggerOp;
-      Table *pTab = 0;
       assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
       if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){
         pExpr->iTable = 1;
@@ -74216,14 +77104,15 @@ static int lookupName(
       }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
         pExpr->iTable = 0;
         pTab = pParse->pTriggerTab;
+      }else{
+        pTab = 0;
       }
 
       if( pTab ){ 
         int iCol;
         pSchema = pTab->pSchema;
         cntTab++;
-        for(iCol=0; iCol<pTab->nCol; iCol++){
-          Column *pCol = &pTab->aCol[iCol];
+        for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
           if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
             if( iCol==pTab->iPKey ){
               iCol = -1;
@@ -74231,8 +77120,10 @@ static int lookupName(
             break;
           }
         }
-        if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) ){
-          iCol = -1;        /* IMP: R-44911-55124 */
+        if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && HasRowid(pTab) ){
+          /* IMP: R-51414-32910 */
+          /* IMP: R-44911-55124 */
+          iCol = -1;
         }
         if( iCol<pTab->nCol ){
           cnt++;
@@ -74258,7 +77149,8 @@ static int lookupName(
     /*
     ** Perhaps the name is a reference to the ROWID
     */
-    if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
+    if( cnt==0 && cntTab==1 && pMatch && sqlite3IsRowid(zCol)
+     && HasRowid(pMatch->pTab) ){
       cnt = 1;
       pExpr->iColumn = -1;     /* IMP: R-44911-55124 */
       pExpr->affinity = SQLITE_AFF_INTEGER;
@@ -74275,10 +77167,16 @@ static int lookupName(
     ** 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.
+    **
+    ** The ability to use an output result-set column in the WHERE, GROUP BY,
+    ** or HAVING clauses, or as part of a larger expression in the ORDRE BY
+    ** clause is not standard SQL.  This is a (goofy) SQLite extension, that
+    ** is supported for backwards compatibility only.  TO DO: Issue a warning
+    ** on sqlite3_log() whenever the capability is used.
     */
     if( (pEList = pNC->pEList)!=0
      && zTab==0
-     && ((pNC->ncFlags & NC_AsMaybe)==0 || cnt==0)
+     && cnt==0
     ){
       for(j=0; j<pEList->nExpr; j++){
         char *zAs = pEList->a[j].zName;
@@ -74411,6 +77309,52 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
 }
 
 /*
+** Report an error that an expression is not valid for a partial index WHERE
+** clause.
+*/
+static void notValidPartIdxWhere(
+  Parse *pParse,       /* Leave error message here */
+  NameContext *pNC,    /* The name context */
+  const char *zMsg     /* Type of error */
+){
+  if( (pNC->ncFlags & NC_PartIdx)!=0 ){
+    sqlite3ErrorMsg(pParse, "%s prohibited in partial index WHERE clauses",
+                    zMsg);
+  }
+}
+
+#ifndef SQLITE_OMIT_CHECK
+/*
+** Report an error that an expression is not valid for a CHECK constraint.
+*/
+static void notValidCheckConstraint(
+  Parse *pParse,       /* Leave error message here */
+  NameContext *pNC,    /* The name context */
+  const char *zMsg     /* Type of error */
+){
+  if( (pNC->ncFlags & NC_IsCheck)!=0 ){
+    sqlite3ErrorMsg(pParse,"%s prohibited in CHECK constraints", zMsg);
+  }
+}
+#else
+# define notValidCheckConstraint(P,N,M)
+#endif
+
+/*
+** Expression p should encode a floating point value between 1.0 and 0.0.
+** Return 1024 times this value.  Or return -1 if p is not a floating point
+** value between 1.0 and 0.0.
+*/
+static int exprProbability(Expr *p){
+  double r = -1.0;
+  if( p->op!=TK_FLOAT ) return -1;
+  sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
+  assert( r>=0.0 );
+  if( r>1.0 ) return -1;
+  return (int)(r*1000.0);
+}
+
+/*
 ** This routine is callback for sqlite3WalkExpr().
 **
 ** Resolve symbolic names into TK_COLUMN operators for the current
@@ -74430,7 +77374,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
   pParse = pNC->pParse;
   assert( pParse==pWalker->pParse );
 
-  if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;
+  if( ExprHasProperty(pExpr, EP_Resolved) ) return WRC_Prune;
   ExprSetProperty(pExpr, EP_Resolved);
 #ifndef NDEBUG
   if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
@@ -74494,7 +77438,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
 
     /* Resolve function names
     */
-    case TK_CONST_FUNC:
     case TK_FUNCTION: {
       ExprList *pList = pExpr->x.pList;    /* The argument list */
       int n = pList ? pList->nExpr : 0;    /* Number of arguments */
@@ -74507,8 +77450,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
       FuncDef *pDef;              /* Information about the function */
       u8 enc = ENC(pParse->db);   /* The database encoding */
 
-      testcase( pExpr->op==TK_CONST_FUNC );
       assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+      notValidPartIdxWhere(pParse, pNC, "functions");
       zId = pExpr->u.zToken;
       nId = sqlite3Strlen30(zId);
       pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
@@ -74521,6 +77464,28 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
         }
       }else{
         is_agg = pDef->xFunc==0;
+        if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
+          ExprSetProperty(pExpr, EP_Unlikely|EP_Skip);
+          if( n==2 ){
+            pExpr->iTable = exprProbability(pList->a[1].pExpr);
+            if( pExpr->iTable<0 ){
+              sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a "
+                                      "constant between 0.0 and 1.0");
+              pNC->nErr++;
+            }
+          }else{
+            /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
+            ** likelihood(X, 0.0625).
+            ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
+            ** likelihood(X,0.0625).
+            ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand for
+            ** likelihood(X,0.9375).
+            ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to
+            ** likelihood(X,0.9375). */
+            /* TUNING: unlikely() probability is 0.0625.  likely() is 0.9375 */
+            pExpr->iTable = pDef->zName[0]=='u' ? 62 : 938;
+          }             
+        }
       }
 #ifndef SQLITE_OMIT_AUTHORIZATION
       if( pDef ){
@@ -74534,6 +77499,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
           pExpr->op = TK_NULL;
           return WRC_Prune;
         }
+        if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant);
       }
 #endif
       if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
@@ -74574,11 +77540,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
       testcase( pExpr->op==TK_IN );
       if( ExprHasProperty(pExpr, EP_xIsSelect) ){
         int nRef = pNC->nRef;
-#ifndef SQLITE_OMIT_CHECK
-        if( (pNC->ncFlags & NC_IsCheck)!=0 ){
-          sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
-        }
-#endif
+        notValidCheckConstraint(pParse, pNC, "subqueries");
+        notValidPartIdxWhere(pParse, pNC, "subqueries");
         sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
         assert( pNC->nRef>=nRef );
         if( nRef!=pNC->nRef ){
@@ -74587,14 +77550,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
       }
       break;
     }
-#ifndef SQLITE_OMIT_CHECK
     case TK_VARIABLE: {
-      if( (pNC->ncFlags & NC_IsCheck)!=0 ){
-        sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
-      }
+      notValidCheckConstraint(pParse, pNC, "parameters");
+      notValidPartIdxWhere(pParse, pNC, "parameters");
       break;
     }
-#endif
   }
   return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
 }
@@ -74685,7 +77645,7 @@ static int resolveOrderByTermToExprList(
   ** result-set entry.
   */
   for(i=0; i<pEList->nExpr; i++){
-    if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){
+    if( sqlite3ExprCompare(pEList->a[i].pExpr, pE, -1)<2 ){
       return i+1;
     }
   }
@@ -74791,7 +77751,7 @@ static int resolveCompoundOrderBy(
           pItem->pExpr->pLeft = pNew;
         }
         sqlite3ExprDelete(db, pE);
-        pItem->iOrderByCol = (u16)iCol;
+        pItem->u.x.iOrderByCol = (u16)iCol;
         pItem->done = 1;
       }else{
         moreToDo = 1;
@@ -74812,8 +77772,8 @@ static int resolveCompoundOrderBy(
 /*
 ** 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
+** result set expression (as determined by the ExprList.a.u.x.iOrderByCol
+** 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
@@ -74840,12 +77800,12 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
   pEList = pSelect->pEList;
   assert( pEList!=0 );  /* sqlite3SelectNew() guarantees this */
   for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
-    if( pItem->iOrderByCol ){
-      if( pItem->iOrderByCol>pEList->nExpr ){
+    if( pItem->u.x.iOrderByCol ){
+      if( pItem->u.x.iOrderByCol>pEList->nExpr ){
         resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
         return 1;
       }
-      resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType,0);
+      resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, zType,0);
     }
   }
   return 0;
@@ -74860,7 +77820,7 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
 ** 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
+** the order-by term is an identifier 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().
@@ -74886,16 +77846,19 @@ static int resolveOrderGroupBy(
   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 ){
-      /* 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->iOrderByCol = (u16)iCol;
-      continue;
+    Expr *pE2 = sqlite3ExprSkipCollate(pE);
+    if( zType[0]!='G' ){
+      iCol = resolveAsName(pParse, pSelect->pEList, pE2);
+      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->u.x.iOrderByCol = (u16)iCol;
+        continue;
+      }
     }
-    if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
+    if( sqlite3ExprIsInteger(pE2, &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 */
@@ -74903,18 +77866,18 @@ static int resolveOrderGroupBy(
         resolveOutOfRangeError(pParse, zType, i+1, nResult);
         return 1;
       }
-      pItem->iOrderByCol = (u16)iCol;
+      pItem->u.x.iOrderByCol = (u16)iCol;
       continue;
     }
 
     /* Otherwise, treat the ORDER BY term as an ordinary expression */
-    pItem->iOrderByCol = 0;
+    pItem->u.x.iOrderByCol = 0;
     if( sqlite3ResolveExprNames(pNC, pE) ){
       return 1;
     }
     for(j=0; j<pSelect->pEList->nExpr; j++){
-      if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr)==0 ){
-        pItem->iOrderByCol = j+1;
+      if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
+        pItem->u.x.iOrderByCol = j+1;
       }
     }
   }
@@ -75038,7 +78001,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
       return WRC_Abort;
     }
   
-    /* Add the expression list to the name-context before parsing the
+    /* Add the output column 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.
@@ -75047,10 +78010,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
     ** re-evaluated for each reference to it.
     */
     sNC.pEList = p->pEList;
-    sNC.ncFlags |= NC_AsMaybe;
     if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
     if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
-    sNC.ncFlags &= ~NC_AsMaybe;
 
     /* The ORDER BY and GROUP BY clauses may not refer to terms in
     ** outer queries 
@@ -75220,6 +78181,48 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
   sqlite3WalkSelect(&w, p);
 }
 
+/*
+** Resolve names in expressions that can only reference a single table:
+**
+**    *   CHECK constraints
+**    *   WHERE clauses on partial indices
+**
+** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression
+** is set to -1 and the Expr.iColumn value is set to the column number.
+**
+** Any errors cause an error message to be set in pParse.
+*/
+SQLITE_PRIVATE void sqlite3ResolveSelfReference(
+  Parse *pParse,      /* Parsing context */
+  Table *pTab,        /* The table being referenced */
+  int type,           /* NC_IsCheck or NC_PartIdx */
+  Expr *pExpr,        /* Expression to resolve.  May be NULL. */
+  ExprList *pList     /* Expression list to resolve.  May be NUL. */
+){
+  SrcList sSrc;                   /* Fake SrcList for pParse->pNewTable */
+  NameContext sNC;                /* Name context for pParse->pNewTable */
+  int i;                          /* Loop counter */
+
+  assert( type==NC_IsCheck || type==NC_PartIdx );
+  memset(&sNC, 0, sizeof(sNC));
+  memset(&sSrc, 0, sizeof(sSrc));
+  sSrc.nSrc = 1;
+  sSrc.a[0].zName = pTab->zName;
+  sSrc.a[0].pTab = pTab;
+  sSrc.a[0].iCursor = -1;
+  sNC.pParse = pParse;
+  sNC.pSrcList = &sSrc;
+  sNC.ncFlags = type;
+  if( sqlite3ResolveExprNames(&sNC, pExpr) ) return;
+  if( pList ){
+    for(i=0; i<pList->nExpr; i++){
+      if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
+        return;
+      }
+    }
+  }
+}
+
 /************** End of resolve.c *********************************************/
 /************** Begin file expr.c ********************************************/
 /*
@@ -75256,6 +78259,7 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
 SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
   int op;
   pExpr = sqlite3ExprSkipCollate(pExpr);
+  if( pExpr->flags & EP_Generic ) return 0;
   op = pExpr->op;
   if( op==TK_SELECT ){
     assert( pExpr->flags&EP_xIsSelect );
@@ -75264,7 +78268,7 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
 #ifndef SQLITE_OMIT_CAST
   if( op==TK_CAST ){
     assert( !ExprHasProperty(pExpr, EP_IntValue) );
-    return sqlite3AffinityType(pExpr->u.zToken);
+    return sqlite3AffinityType(pExpr->u.zToken, 0);
   }
 #endif
   if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) 
@@ -75288,12 +78292,16 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
 ** If a memory allocation error occurs, that fact is recorded in pParse->db
 ** and the pExpr parameter is returned unchanged.
 */
-SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(
+  Parse *pParse,           /* Parsing context */
+  Expr *pExpr,             /* Add the "COLLATE" clause to this expression */
+  const Token *pCollName   /* Name of collating sequence */
+){
   if( pCollName->n>0 ){
     Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
     if( pNew ){
       pNew->pLeft = pExpr;
-      pNew->flags |= EP_Collate;
+      pNew->flags |= EP_Collate|EP_Skip;
       pExpr = pNew;
     }
   }
@@ -75308,13 +78316,21 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, con
 }
 
 /*
-** Skip over any TK_COLLATE and/or TK_AS operators at the root of
-** an expression.
+** Skip over any TK_COLLATE or TK_AS operators and any unlikely()
+** or likelihood() function at the root of an expression.
 */
 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
-  while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
-    pExpr = pExpr->pLeft;
-  }
+  while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
+    if( ExprHasProperty(pExpr, EP_Unlikely) ){
+      assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+      assert( pExpr->x.pList->nExpr>0 );
+      assert( pExpr->op==TK_FUNCTION );
+      pExpr = pExpr->x.pList->a[0].pExpr;
+    }else{
+      assert( pExpr->op==TK_COLLATE || pExpr->op==TK_AS );
+      pExpr = pExpr->pLeft;
+    }
+  }   
   return pExpr;
 }
 
@@ -75333,12 +78349,12 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
   Expr *p = pExpr;
   while( p ){
     int op = p->op;
+    if( p->flags & EP_Generic ) break;
     if( op==TK_CAST || op==TK_UPLUS ){
       p = p->pLeft;
       continue;
     }
-    assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
-    if( op==TK_COLLATE ){
+    if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
       pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
       break;
     }
@@ -75739,16 +78755,25 @@ SQLITE_PRIVATE Expr *sqlite3PExpr(
 }
 
 /*
-** Return 1 if an expression must be FALSE in all cases and 0 if the
-** expression might be true.  This is an optimization.  If is OK to
-** return 0 here even if the expression really is always false (a 
-** false negative).  But it is a bug to return 1 if the expression
-** might be true in some rare circumstances (a false positive.)
+** If the expression is always either TRUE or FALSE (respectively),
+** then return 1.  If one cannot determine the truth value of the
+** expression at compile-time return 0.
+**
+** This is an optimization.  If is OK to return 0 here even if
+** the expression really is always false or false (a false negative).
+** But it is a bug to return 1 if the expression might have different
+** boolean values in different circumstances (a false positive.)
 **
 ** Note that if the expression is part of conditional for a
 ** LEFT JOIN, then we cannot determine at compile-time whether or not
 ** is it true or false, so always return 0.
 */
+static int exprAlwaysTrue(Expr *p){
+  int v = 0;
+  if( ExprHasProperty(p, EP_FromJoin) ) return 0;
+  if( !sqlite3ExprIsInteger(p, &v) ) return 0;
+  return v!=0;
+}
 static int exprAlwaysFalse(Expr *p){
   int v = 0;
   if( ExprHasProperty(p, EP_FromJoin) ) return 0;
@@ -75820,7 +78845,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
   const char *z;
 
   if( pExpr==0 ) return;
-  assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
+  assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
   z = pExpr->u.zToken;
   assert( z!=0 );
   assert( z[0]!=0 );
@@ -75890,12 +78915,12 @@ SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
   if( p==0 ) return;
   /* Sanity check: Assert that the IntValue is non-negative if it exists */
   assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
-  if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
+  if( !ExprHasProperty(p, EP_TokenOnly) ){
+    /* The Expr.x union is never used at the same time as Expr.pRight */
+    assert( p->x.pList==0 || p->pRight==0 );
     sqlite3ExprDelete(db, p->pLeft);
     sqlite3ExprDelete(db, p->pRight);
-    if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){
-      sqlite3DbFree(db, p->u.zToken);
-    }
+    if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
     if( ExprHasProperty(p, EP_xIsSelect) ){
       sqlite3SelectDelete(db, p->x.pSelect);
     }else{
@@ -75955,16 +78980,19 @@ static int exprStructSize(Expr *p){
 static int dupedExprStructSize(Expr *p, int flags){
   int nSize;
   assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
+  assert( EXPR_FULLSIZE<=0xfff );
+  assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
   if( 0==(flags&EXPRDUP_REDUCE) ){
     nSize = EXPR_FULLSIZE;
   }else{
-    assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
+    assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
     assert( !ExprHasProperty(p, EP_FromJoin) ); 
-    assert( (p->flags2 & EP2_MallocedToken)==0 );
-    assert( (p->flags2 & EP2_Irreducible)==0 );
-    if( p->pLeft || p->pRight || p->x.pList ){
+    assert( !ExprHasProperty(p, EP_MemToken) );
+    assert( !ExprHasProperty(p, EP_NoReduce) );
+    if( p->pLeft || p->x.pList ){
       nSize = EXPR_REDUCEDSIZE | EP_Reduced;
     }else{
+      assert( p->pRight==0 );
       nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
     }
   }
@@ -76058,7 +79086,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
       }
 
       /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
-      pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static);
+      pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
       pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
       pNew->flags |= staticFlag;
 
@@ -76078,7 +79106,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
       }
 
       /* Fill in pNew->pLeft and pNew->pRight. */
-      if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){
+      if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
         zAlloc += dupedExprNodeSize(p, flags);
         if( ExprHasProperty(pNew, EP_Reduced) ){
           pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
@@ -76088,8 +79116,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
           *pzBuffer = zAlloc;
         }
       }else{
-        pNew->flags2 = 0;
-        if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
+        if( !ExprHasProperty(p, EP_TokenOnly) ){
           pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
           pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
         }
@@ -76101,6 +79128,33 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
 }
 
 /*
+** Create and return a deep copy of the object passed as the second 
+** argument. If an OOM condition is encountered, NULL is returned
+** and the db->mallocFailed flag set.
+*/
+#ifndef SQLITE_OMIT_CTE
+static With *withDup(sqlite3 *db, With *p){
+  With *pRet = 0;
+  if( p ){
+    int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
+    pRet = sqlite3DbMallocZero(db, nByte);
+    if( pRet ){
+      int i;
+      pRet->nCte = p->nCte;
+      for(i=0; i<p->nCte; i++){
+        pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0);
+        pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0);
+        pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName);
+      }
+    }
+  }
+  return pRet;
+}
+#else
+# define withDup(x,y) 0
+#endif
+
+/*
 ** The following group of routines make deep copies of expressions,
 ** expression lists, ID lists, and select statements.  The copies can
 ** be deleted (by being passed to their respective ...Delete() routines)
@@ -76127,7 +79181,6 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags)
   if( p==0 ) return 0;
   pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
   if( pNew==0 ) return 0;
-  pNew->iECursor = 0;
   pNew->nExpr = i = p->nExpr;
   if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){}
   pNew->a = pItem = sqlite3DbMallocRaw(db,  i*sizeof(p->a[0]) );
@@ -76143,8 +79196,8 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags)
     pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
     pItem->sortOrder = pOldItem->sortOrder;
     pItem->done = 0;
-    pItem->iOrderByCol = pOldItem->iOrderByCol;
-    pItem->iAlias = pOldItem->iAlias;
+    pItem->bSpanIsTab = pOldItem->bSpanIsTab;
+    pItem->u = pOldItem->u;
   }
   return pNew;
 }
@@ -76180,6 +79233,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
     pNewItem->regReturn = pOldItem->regReturn;
     pNewItem->isCorrelated = pOldItem->isCorrelated;
     pNewItem->viaCoroutine = pOldItem->viaCoroutine;
+    pNewItem->isRecursive = pOldItem->isRecursive;
     pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
     pNewItem->notIndexed = pOldItem->notIndexed;
     pNewItem->pIndex = pOldItem->pIndex;
@@ -76237,10 +79291,10 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
   pNew->iLimit = 0;
   pNew->iOffset = 0;
   pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
-  pNew->pRightmost = 0;
   pNew->addrOpenEphm[0] = -1;
   pNew->addrOpenEphm[1] = -1;
-  pNew->addrOpenEphm[2] = -1;
+  pNew->nSelectRow = p->nSelectRow;
+  pNew->pWith = withDup(db, p->pWith);
   return pNew;
 }
 #else
@@ -76398,16 +79452,19 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
   /* 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( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
+  if( pWalker->u.i==3 && ExprHasProperty(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 pWalker->u.i==2 */
+    ** and either pWalker->u.i==2 or the function as the SQLITE_FUNC_CONST
+    ** flag. */
     case TK_FUNCTION:
-      if( pWalker->u.i==2 ) return 0;
+      if( pWalker->u.i==2 || ExprHasProperty(pExpr,EP_Constant) ){
+        return WRC_Continue;
+      }
       /* Fall through */
     case TK_ID:
     case TK_COLUMN:
@@ -76501,6 +79558,7 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){
     case TK_UMINUS: {
       int v;
       if( sqlite3ExprIsInteger(p->pLeft, &v) ){
+        assert( v!=(-2147483647-1) );
         *pValue = -v;
         rc = 1;
       }
@@ -76536,30 +79594,15 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
     case TK_FLOAT:
     case TK_BLOB:
       return 0;
+    case TK_COLUMN:
+      assert( p->pTab!=0 );
+      return p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0;
     default:
       return 1;
   }
 }
 
 /*
-** Generate an OP_IsNull instruction that tests register iReg and jumps
-** to location iDest if the value in iReg is NULL.  The value in iReg 
-** was computed by pExpr.  If we can look at pExpr at compile-time and
-** determine that it can never generate a NULL, then the OP_IsNull operation
-** can be omitted.
-*/
-SQLITE_PRIVATE void sqlite3ExprCodeIsNullJump(
-  Vdbe *v,            /* The VDBE under construction */
-  const Expr *pExpr,  /* Only generate OP_IsNull if this expr can be NULL */
-  int iReg,           /* Test the value in this register for NULL */
-  int iDest           /* Jump here if the value is null */
-){
-  if( sqlite3ExprCanBeNull(pExpr) ){
-    sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iDest);
-  }
-}
-
-/*
 ** Return TRUE if the given expression is a constant which would be
 ** unchanged by OP_Affinity with the affinity given in the second
 ** argument.
@@ -76662,6 +79705,40 @@ SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
 }
 
 /*
+** Generate code that checks the left-most column of index table iCur to see if
+** it contains any NULL entries.  Cause the register at regHasNull to be set
+** to a non-NULL value if iCur contains no NULLs.  Cause register regHasNull
+** to be set to NULL if iCur contains one or more NULL values.
+*/
+static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
+  int j1;
+  sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull);
+  j1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
+  sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull);
+  sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+  VdbeComment((v, "first_entry_in(%d)", iCur));
+  sqlite3VdbeJumpHere(v, j1);
+}
+
+
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** The argument is an IN operator with a list (not a subquery) on the 
+** right-hand side.  Return TRUE if that list is constant.
+*/
+static int sqlite3InRhsIsConstant(Expr *pIn){
+  Expr *pLHS;
+  int res;
+  assert( !ExprHasProperty(pIn, EP_xIsSelect) );
+  pLHS = pIn->pLeft;
+  pIn->pLeft = 0;
+  res = sqlite3ExprIsConstant(pIn);
+  pIn->pLeft = pLHS;
+  return res;
+}
+#endif
+
+/*
 ** This function is used by the implementation of the IN (...) operator.
 ** The pX parameter is the expression on the RHS of the IN operator, which
 ** might be either a list of expressions or a subquery.
@@ -76670,7 +79747,7 @@ SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
 ** be used either to test for membership in the RHS set or to iterate through
 ** all members of the RHS set, skipping duplicates.
 **
-** A cursor is opened on the b-tree object that the RHS of the IN operator
+** A cursor is opened on the b-tree object that is the RHS of the IN operator
 ** and pX->iTable is set to the index of that cursor.
 **
 ** The returned value of this function indicates the b-tree type, as follows:
@@ -76680,6 +79757,8 @@ SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
 **   IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
 **   IN_INDEX_EPH        - The cursor was opened on a specially created and
 **                         populated epheremal table.
+**   IN_INDEX_NOOP       - No cursor was allocated.  The IN operator must be
+**                         implemented as a sequence of comparisons.
 **
 ** An existing b-tree might be used if the RHS expression pX is a simple
 ** subquery such as:
@@ -76689,51 +79768,56 @@ SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
 ** If the RHS of the IN operator is a list or a more complex subquery, then
 ** an ephemeral table might need to be generated from the RHS and then
 ** pX->iTable made to point to the ephermeral table instead of an
-** existing table.  
-**
-** If the prNotFound parameter is 0, then the b-tree will be used to iterate
-** through the set members, skipping any duplicates. In this case an
-** epheremal table must be used unless the selected <column> is guaranteed
+** existing table.
+**
+** The inFlags parameter must contain exactly one of the bits
+** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP.  If inFlags contains
+** IN_INDEX_MEMBERSHIP, then the generated table will be used for a
+** fast membership test.  When the IN_INDEX_LOOP bit is set, the
+** IN index will be used to loop over all values of the RHS of the
+** IN operator.
+**
+** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate
+** through the set members) then the b-tree must not contain duplicates.
+** An epheremal table must be used unless the selected <column> is guaranteed
 ** to be unique - either because it is an INTEGER PRIMARY KEY or it
 ** has a UNIQUE constraint or UNIQUE index.
 **
-** If the prNotFound parameter is not 0, then the b-tree will be used 
-** for fast set membership tests. In this case an epheremal table must 
+** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used 
+** for fast set membership tests) then an epheremal table must 
 ** be used unless <column> is an INTEGER PRIMARY KEY or an index can 
 ** be found with <column> as its left-most column.
 **
+** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and
+** if the RHS of the IN operator is a list (not a subquery) then this
+** routine might decide that creating an ephemeral b-tree for membership
+** testing is too expensive and return IN_INDEX_NOOP.  In that case, the
+** calling routine should implement the IN operator using a sequence
+** of Eq or Ne comparison operations.
+**
 ** When the b-tree is being used for membership tests, the calling function
-** needs to know whether or not the structure contains an SQL NULL 
-** value in order to correctly evaluate expressions like "X IN (Y, Z)".
-** If there is any chance that the (...) might contain a NULL value at
+** might need to know whether or not the RHS side of the IN operator
+** contains a NULL.  If prRhsHasNull is not a NULL pointer and 
+** if there is any chance that the (...) might contain a NULL value at
 ** runtime, then a register is allocated and the register number written
-** to *prNotFound. If there is no chance that the (...) contains a
-** NULL value, then *prNotFound is left unchanged.
-**
-** If a register is allocated and its location stored in *prNotFound, then
-** its initial value is NULL.  If the (...) does not remain constant
-** for the duration of the query (i.e. the SELECT within the (...)
-** is a correlated subquery) then the value of the allocated register is
-** reset to NULL each time the subquery is rerun. This allows the
-** caller to use vdbe code equivalent to the following:
-**
-**   if( register==NULL ){
-**     has_null = <test if data structure contains null>
-**     register = 1
-**   }
+** to *prRhsHasNull. If there is no chance that the (...) contains a
+** NULL value, then *prRhsHasNull is left unchanged.
 **
-** in order to avoid running the <test if data structure contains null>
-** test more often than is necessary.
+** If a register is allocated and its location stored in *prRhsHasNull, then
+** the value in that register will be NULL if the b-tree contains one or more
+** NULL values, and it will be some non-NULL value if the b-tree contains no
+** NULL values.
 */
 #ifndef SQLITE_OMIT_SUBQUERY
-SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
+SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){
   Select *p;                            /* SELECT to the right of IN operator */
   int eType = 0;                        /* Type of RHS table. IN_INDEX_* */
   int iTab = pParse->nTab++;            /* Cursor of the RHS table */
-  int mustBeUnique = (prNotFound==0);   /* True if RHS must be unique */
+  int mustBeUnique;                     /* True if RHS must be unique */
   Vdbe *v = sqlite3GetVdbe(pParse);     /* Virtual machine being coded */
 
   assert( pX->op==TK_IN );
+  mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
 
   /* Check to see if an existing table or index can be used to
   ** satisfy the query.  This is preferable to generating a new 
@@ -76744,8 +79828,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
     sqlite3 *db = pParse->db;              /* Database connection */
     Table *pTab;                           /* Table <table>. */
     Expr *pExpr;                           /* Expression <column> */
-    int iCol;                              /* Index of column <column> */
-    int iDb;                               /* Database idx for pTab */
+    i16 iCol;                              /* Index of column <column> */
+    i16 iDb;                               /* Database idx for pTab */
 
     assert( p );                        /* Because of isCandidateForInOpt(p) */
     assert( p->pEList!=0 );             /* Because of isCandidateForInOpt(p) */
@@ -76753,9 +79837,9 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
     assert( p->pSrc!=0 );               /* Because of isCandidateForInOpt(p) */
     pTab = p->pSrc->a[0].pTab;
     pExpr = p->pEList->a[0].pExpr;
-    iCol = pExpr->iColumn;
+    iCol = (i16)pExpr->iColumn;
    
-    /* Code an OP_VerifyCookie and OP_TableLock for <table>. */
+    /* Code an OP_Transaction and OP_TableLock for <table>. */
     iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
     sqlite3CodeVerifySchema(pParse, iDb);
     sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
@@ -76766,9 +79850,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
     */
     assert(v);
     if( iCol<0 ){
-      int iAddr;
-
-      iAddr = sqlite3CodeOnce(pParse);
+      int iAddr = sqlite3CodeOnce(pParse);
+      VdbeCoverage(v);
 
       sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
       eType = IN_INDEX_ROWID;
@@ -76791,46 +79874,55 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
       for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
         if( (pIdx->aiColumn[0]==iCol)
          && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
-         && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
+         && (!mustBeUnique || (pIdx->nKeyCol==1 && IsUniqueIndex(pIdx)))
         ){
-          int iAddr;
-          char *pKey;
-  
-          pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
-          iAddr = sqlite3CodeOnce(pParse);
-  
-          sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
-                               pKey,P4_KEYINFO_HANDOFF);
+          int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
+          sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
+          sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
           VdbeComment((v, "%s", pIdx->zName));
           assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
           eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
 
-          sqlite3VdbeJumpHere(v, iAddr);
-          if( prNotFound && !pTab->aCol[iCol].notNull ){
-            *prNotFound = ++pParse->nMem;
-            sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
+          if( prRhsHasNull && !pTab->aCol[iCol].notNull ){
+            *prRhsHasNull = ++pParse->nMem;
+            sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull);
           }
+          sqlite3VdbeJumpHere(v, iAddr);
         }
       }
     }
   }
 
+  /* If no preexisting index is available for the IN clause
+  ** and IN_INDEX_NOOP is an allowed reply
+  ** and the RHS of the IN operator is a list, not a subquery
+  ** and the RHS is not contant or has two or fewer terms,
+  ** then it is not worth creating an ephermeral table to evaluate
+  ** the IN operator so return IN_INDEX_NOOP.
+  */
+  if( eType==0
+   && (inFlags & IN_INDEX_NOOP_OK)
+   && !ExprHasProperty(pX, EP_xIsSelect)
+   && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
+  ){
+    eType = IN_INDEX_NOOP;
+  }
+     
+
   if( eType==0 ){
-    /* Could not found an existing table or index to use as the RHS b-tree.
+    /* Could not find an existing table or index to use as the RHS b-tree.
     ** We will have to generate an ephemeral table to do the job.
     */
-    double savedNQueryLoop = pParse->nQueryLoop;
+    u32 savedNQueryLoop = pParse->nQueryLoop;
     int rMayHaveNull = 0;
     eType = IN_INDEX_EPH;
-    if( prNotFound ){
-      *prNotFound = rMayHaveNull = ++pParse->nMem;
-      sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
-    }else{
-      testcase( pParse->nQueryLoop>(double)1 );
-      pParse->nQueryLoop = (double)1;
-      if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){
+    if( inFlags & IN_INDEX_LOOP ){
+      pParse->nQueryLoop = 0;
+      if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
         eType = IN_INDEX_ROWID;
       }
+    }else if( prRhsHasNull ){
+      *prRhsHasNull = rMayHaveNull = ++pParse->nMem;
     }
     sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
     pParse->nQueryLoop = savedNQueryLoop;
@@ -76861,15 +79953,9 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
 **
 ** If rMayHaveNull is non-zero, that means that the operation is an IN
 ** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
-** Furthermore, the IN is in a WHERE clause and that we really want
-** to iterate over the RHS of the IN operator in order to quickly locate
-** all corresponding LHS elements.  All this routine does is initialize
-** the register given by rMayHaveNull to NULL.  Calling routines will take
-** care of changing this register value to non-NULL if the RHS is NULL-free.
-**
-** If rMayHaveNull is zero, that means that the subquery is being used
-** for membership testing only.  There is no need to initialize any
-** registers to indicate the presense or absence of NULLs on the RHS.
+** All this routine does is initialize the register given by rMayHaveNull
+** to NULL.  Calling routines will take care of changing this register
+** value to non-NULL if the RHS is NULL-free.
 **
 ** For a SELECT or EXISTS operator, return the register that holds the
 ** result.  For IN operators or if an error occurs, the return value is 0.
@@ -76878,10 +79964,10 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
 SQLITE_PRIVATE int sqlite3CodeSubselect(
   Parse *pParse,          /* Parsing context */
   Expr *pExpr,            /* The IN, SELECT, or EXISTS operator */
-  int rMayHaveNull,       /* Register that records whether NULLs exist in RHS */
+  int rHasNullFlag,       /* Register that records whether NULLs exist in RHS */
   int isRowid             /* If true, LHS of IN operator is a rowid */
 ){
-  int testAddr = -1;                      /* One-time test address */
+  int jmpIfDynamic = -1;                      /* One-time test address */
   int rReg = 0;                           /* Register storing resulting */
   Vdbe *v = sqlite3GetVdbe(pParse);
   if( NEVER(v==0) ) return 0;
@@ -76897,14 +79983,14 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
   ** If all of the above are false, then we can run this code just once
   ** save the results, and reuse the same result on subsequent invocations.
   */
-  if( !ExprHasAnyProperty(pExpr, EP_VarSelect) ){
-    testAddr = sqlite3CodeOnce(pParse);
+  if( !ExprHasProperty(pExpr, EP_VarSelect) ){
+    jmpIfDynamic = sqlite3CodeOnce(pParse); VdbeCoverage(v);
   }
 
 #ifndef SQLITE_OMIT_EXPLAIN
   if( pParse->explain==2 ){
     char *zMsg = sqlite3MPrintf(
-        pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
+        pParse->db, "EXECUTE %s%s SUBQUERY %d", jmpIfDynamic>=0?"":"CORRELATED ",
         pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
     );
     sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
@@ -76914,14 +80000,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
   switch( pExpr->op ){
     case TK_IN: {
       char affinity;              /* Affinity of the LHS of the IN */
-      KeyInfo keyInfo;            /* Keyinfo for the generated table */
-      static u8 sortOrder = 0;    /* Fake aSortOrder for keyInfo */
       int addr;                   /* Address of OP_OpenEphemeral instruction */
       Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
-
-      if( rMayHaveNull ){
-        sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull);
-      }
+      KeyInfo *pKeyInfo = 0;      /* Key information */
 
       affinity = sqlite3ExprAffinity(pLeft);
 
@@ -76940,10 +80021,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
       */
       pExpr->iTable = pParse->nTab++;
       addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid);
-      if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
-      memset(&keyInfo, 0, sizeof(keyInfo));
-      keyInfo.nField = 1;
-      keyInfo.aSortOrder = &sortOrder;
+      pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1);
 
       if( ExprHasProperty(pExpr, EP_xIsSelect) ){
         /* Case 1:     expr IN (SELECT ...)
@@ -76951,6 +80029,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
         ** Generate code to write the results of the select into the temporary
         ** table allocated and opened above.
         */
+        Select *pSelect = pExpr->x.pSelect;
         SelectDest dest;
         ExprList *pEList;
 
@@ -76958,15 +80037,21 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
         sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
         dest.affSdst = (u8)affinity;
         assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
-        pExpr->x.pSelect->iLimit = 0;
-        if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
+        pSelect->iLimit = 0;
+        testcase( pSelect->selFlags & SF_Distinct );
+        pSelect->selFlags &= ~SF_Distinct;
+        testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
+        if( sqlite3Select(pParse, pSelect, &dest) ){
+          sqlite3KeyInfoUnref(pKeyInfo);
           return 0;
         }
-        pEList = pExpr->x.pSelect->pEList;
-        if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){ 
-          keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
-              pEList->a[0].pExpr);
-        }
+        pEList = pSelect->pEList;
+        assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
+        assert( pEList!=0 );
+        assert( pEList->nExpr>0 );
+        assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+        pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
+                                                         pEList->a[0].pExpr);
       }else if( ALWAYS(pExpr->x.pList!=0) ){
         /* Case 2:     expr IN (exprlist)
         **
@@ -76983,13 +80068,15 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
         if( !affinity ){
           affinity = SQLITE_AFF_NONE;
         }
-        keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
-        keyInfo.aSortOrder = &sortOrder;
+        if( pKeyInfo ){
+          assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+          pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+        }
 
         /* Loop through each expression in <exprlist>. */
         r1 = sqlite3GetTempReg(pParse);
         r2 = sqlite3GetTempReg(pParse);
-        sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
+        if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
         for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
           Expr *pE2 = pItem->pExpr;
           int iValToIns;
@@ -76999,9 +80086,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
           ** this code only executes once.  Because for a non-constant
           ** expression we need to rerun this code each time.
           */
-          if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
-            sqlite3VdbeChangeToNoop(v, testAddr);
-            testAddr = -1;
+          if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){
+            sqlite3VdbeChangeToNoop(v, jmpIfDynamic);
+            jmpIfDynamic = -1;
           }
 
           /* Evaluate the expression and insert it into the temp table */
@@ -77012,6 +80099,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
             if( isRowid ){
               sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
                                 sqlite3VdbeCurrentAddr(v)+2);
+              VdbeCoverage(v);
               sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
             }else{
               sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
@@ -77023,8 +80111,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
         sqlite3ReleaseTempReg(pParse, r1);
         sqlite3ReleaseTempReg(pParse, r2);
       }
-      if( !isRowid ){
-        sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
+      if( pKeyInfo ){
+        sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
       }
       break;
     }
@@ -77065,15 +80153,19 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
         return 0;
       }
       rReg = dest.iSDParm;
-      ExprSetIrreducible(pExpr);
+      ExprSetVVAProperty(pExpr, EP_NoReduce);
       break;
     }
   }
 
-  if( testAddr>=0 ){
-    sqlite3VdbeJumpHere(v, testAddr);
+  if( rHasNullFlag ){
+    sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag);
+  }
+
+  if( jmpIfDynamic>=0 ){
+    sqlite3VdbeJumpHere(v, jmpIfDynamic);
   }
-  sqlite3ExprCachePop(pParse, 1);
+  sqlite3ExprCachePop(pParse);
 
   return rReg;
 }
@@ -77092,7 +80184,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
 ** if the LHS is NULL or if the LHS is not contained within the RHS and the
 ** RHS contains one or more NULL values.
 **
-** This routine generates code will jump to destIfFalse if the LHS is not 
+** This routine generates code that jumps to destIfFalse if the LHS is not 
 ** contained within the RHS.  If due to NULLs we cannot determine if the LHS
 ** is contained in the RHS then jump to destIfNull.  If the LHS is contained
 ** within the RHS then fall through.
@@ -77115,7 +80207,9 @@ static void sqlite3ExprCodeIN(
   v = pParse->pVdbe;
   assert( v!=0 );       /* OOM detected prior to this routine */
   VdbeNoopComment((v, "begin IN expr"));
-  eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull);
+  eType = sqlite3FindInIndex(pParse, pExpr,
+                             IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK,
+                             destIfFalse==destIfNull ? 0 : &rRhsHasNull);
 
   /* Figure out the affinity to use to create a key from the results
   ** of the expression. affinityStr stores a static string suitable for
@@ -77129,86 +80223,118 @@ static void sqlite3ExprCodeIN(
   r1 = sqlite3GetTempReg(pParse);
   sqlite3ExprCode(pParse, pExpr->pLeft, r1);
 
-  /* If the LHS is NULL, then the result is either false or NULL depending
-  ** on whether the RHS is empty or not, respectively.
+  /* If sqlite3FindInIndex() did not find or create an index that is
+  ** suitable for evaluating the IN operator, then evaluate using a
+  ** sequence of comparisons.
   */
-  if( destIfNull==destIfFalse ){
-    /* Shortcut for the common case where the false and NULL outcomes are
-    ** the same. */
-    sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull);
-  }else{
-    int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1);
-    sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
-    sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
-    sqlite3VdbeJumpHere(v, addr1);
-  }
-
-  if( eType==IN_INDEX_ROWID ){
-    /* In this case, the RHS is the ROWID of table b-tree
-    */
-    sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse);
-    sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
+  if( eType==IN_INDEX_NOOP ){
+    ExprList *pList = pExpr->x.pList;
+    CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+    int labelOk = sqlite3VdbeMakeLabel(v);
+    int r2, regToFree;
+    int regCkNull = 0;
+    int ii;
+    assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+    if( destIfNull!=destIfFalse ){
+      regCkNull = sqlite3GetTempReg(pParse);
+      sqlite3VdbeAddOp3(v, OP_BitAnd, r1, r1, regCkNull);
+    }
+    for(ii=0; ii<pList->nExpr; ii++){
+      r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, &regToFree);
+      if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
+        sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
+      }
+      if( ii<pList->nExpr-1 || destIfNull!=destIfFalse ){
+        sqlite3VdbeAddOp4(v, OP_Eq, r1, labelOk, r2,
+                          (void*)pColl, P4_COLLSEQ);
+        VdbeCoverageIf(v, ii<pList->nExpr-1);
+        VdbeCoverageIf(v, ii==pList->nExpr-1);
+        sqlite3VdbeChangeP5(v, affinity);
+      }else{
+        assert( destIfNull==destIfFalse );
+        sqlite3VdbeAddOp4(v, OP_Ne, r1, destIfFalse, r2,
+                          (void*)pColl, P4_COLLSEQ); VdbeCoverage(v);
+        sqlite3VdbeChangeP5(v, affinity | SQLITE_JUMPIFNULL);
+      }
+      sqlite3ReleaseTempReg(pParse, regToFree);
+    }
+    if( regCkNull ){
+      sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v);
+      sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
+    }
+    sqlite3VdbeResolveLabel(v, labelOk);
+    sqlite3ReleaseTempReg(pParse, regCkNull);
   }else{
-    /* In this case, the RHS is an index b-tree.
-    */
-    sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
-
-    /* If the set membership test fails, then the result of the 
-    ** "x IN (...)" expression must be either 0 or NULL. If the set
-    ** contains no NULL values, then the result is 0. If the set 
-    ** contains one or more NULL values, then the result of the
-    ** expression is also NULL.
+  
+    /* If the LHS is NULL, then the result is either false or NULL depending
+    ** on whether the RHS is empty or not, respectively.
     */
-    if( rRhsHasNull==0 || destIfFalse==destIfNull ){
-      /* This branch runs if it is known at compile time that the RHS
-      ** cannot contain NULL values. This happens as the result
-      ** of a "NOT NULL" constraint in the database schema.
-      **
-      ** Also run this branch if NULL is equivalent to FALSE
-      ** for this particular IN operator.
+    if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
+      if( destIfNull==destIfFalse ){
+        /* Shortcut for the common case where the false and NULL outcomes are
+        ** the same. */
+        sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v);
+      }else{
+        int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v);
+        sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
+        VdbeCoverage(v);
+        sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
+        sqlite3VdbeJumpHere(v, addr1);
+      }
+    }
+  
+    if( eType==IN_INDEX_ROWID ){
+      /* In this case, the RHS is the ROWID of table b-tree
       */
-      sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
-
+      sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); VdbeCoverage(v);
+      sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
+      VdbeCoverage(v);
     }else{
-      /* In this branch, the RHS of the IN might contain a NULL and
-      ** the presence of a NULL on the RHS makes a difference in the
-      ** outcome.
-      */
-      int j1, j2, j3;
-
-      /* First check to see if the LHS is contained in the RHS.  If so,
-      ** then the presence of NULLs in the RHS does not matter, so jump
-      ** over all of the code that follows.
+      /* In this case, the RHS is an index b-tree.
       */
-      j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
-
-      /* Here we begin generating code that runs if the LHS is not
-      ** contained within the RHS.  Generate additional code that
-      ** tests the RHS for NULLs.  If the RHS contains a NULL then
-      ** jump to destIfNull.  If there are no NULLs in the RHS then
-      ** jump to destIfFalse.
-      */
-      j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull);
-      j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1);
-      sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull);
-      sqlite3VdbeJumpHere(v, j3);
-      sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1);
-      sqlite3VdbeJumpHere(v, j2);
-
-      /* Jump to the appropriate target depending on whether or not
-      ** the RHS contains a NULL
-      */
-      sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull);
-      sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
-
-      /* The OP_Found at the top of this branch jumps here when true, 
-      ** causing the overall IN expression evaluation to fall through.
+      sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
+  
+      /* If the set membership test fails, then the result of the 
+      ** "x IN (...)" expression must be either 0 or NULL. If the set
+      ** contains no NULL values, then the result is 0. If the set 
+      ** contains one or more NULL values, then the result of the
+      ** expression is also NULL.
       */
-      sqlite3VdbeJumpHere(v, j1);
+      assert( destIfFalse!=destIfNull || rRhsHasNull==0 );
+      if( rRhsHasNull==0 ){
+        /* This branch runs if it is known at compile time that the RHS
+        ** cannot contain NULL values. This happens as the result
+        ** of a "NOT NULL" constraint in the database schema.
+        **
+        ** Also run this branch if NULL is equivalent to FALSE
+        ** for this particular IN operator.
+        */
+        sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
+        VdbeCoverage(v);
+      }else{
+        /* In this branch, the RHS of the IN might contain a NULL and
+        ** the presence of a NULL on the RHS makes a difference in the
+        ** outcome.
+        */
+        int j1;
+  
+        /* First check to see if the LHS is contained in the RHS.  If so,
+        ** then the answer is TRUE the presence of NULLs in the RHS does
+        ** not matter.  If the LHS is not contained in the RHS, then the
+        ** answer is NULL if the RHS contains NULLs and the answer is
+        ** FALSE if the RHS is NULL-free.
+        */
+        j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
+        VdbeCoverage(v);
+        sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull);
+        VdbeCoverage(v);
+        sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
+        sqlite3VdbeJumpHere(v, j1);
+      }
     }
   }
   sqlite3ReleaseTempReg(pParse, r1);
-  sqlite3ExprCachePop(pParse, 1);
+  sqlite3ExprCachePop(pParse);
   VdbeComment((v, "end IN expr"));
 }
 #endif /* SQLITE_OMIT_SUBQUERY */
@@ -77265,7 +80391,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
     i64 value;
     const char *z = pExpr->u.zToken;
     assert( z!=0 );
-    c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
+    c = sqlite3DecOrHexToI64(z, &value);
     if( c==0 || (c==2 && negFlag) ){
       char *zV;
       if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
@@ -77275,7 +80401,14 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
 #ifdef SQLITE_OMIT_FLOATING_POINT
       sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
 #else
-      codeReal(v, z, negFlag, iMem);
+#ifndef SQLITE_OMIT_HEX_INTEGER
+      if( sqlite3_strnicmp(z,"0x",2)==0 ){
+        sqlite3ErrorMsg(pParse, "hex literal too big: %s", z);
+      }else
+#endif
+      {
+        codeReal(v, z, negFlag, iMem);
+      }
 #endif
     }
   }
@@ -77382,19 +80515,28 @@ SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
 */
 SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){
   pParse->iCacheLevel++;
+#ifdef SQLITE_DEBUG
+  if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
+    printf("PUSH to %d\n", pParse->iCacheLevel);
+  }
+#endif
 }
 
 /*
 ** Remove from the column cache any entries that were added since the
-** the previous N Push operations.  In other words, restore the cache
-** to the state it was in N Pushes ago.
+** the previous sqlite3ExprCachePush operation.  In other words, restore
+** the cache to the state it was in prior the most recent Push.
 */
-SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse, int N){
+SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){
   int i;
   struct yColCache *p;
-  assert( N>0 );
-  assert( pParse->iCacheLevel>=N );
-  pParse->iCacheLevel -= N;
+  assert( pParse->iCacheLevel>=1 );
+  pParse->iCacheLevel--;
+#ifdef SQLITE_DEBUG
+  if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
+    printf("POP  to %d\n", pParse->iCacheLevel);
+  }
+#endif
   for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
     if( p->iReg && p->iLevel>pParse->iCacheLevel ){
       cacheEntryClear(pParse, p);
@@ -77425,15 +80567,19 @@ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
 SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
   Vdbe *v,        /* The VDBE under construction */
   Table *pTab,    /* The table containing the value */
-  int iTabCur,    /* The cursor for this table */
+  int iTabCur,    /* The table cursor.  Or the PK cursor for WITHOUT ROWID */
   int iCol,       /* Index of the column to extract */
-  int regOut      /* Extract the valud into this register */
+  int regOut      /* Extract the value into this register */
 ){
   if( iCol<0 || iCol==pTab->iPKey ){
     sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
   }else{
     int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
-    sqlite3VdbeAddOp3(v, op, iTabCur, iCol, regOut);
+    int x = iCol;
+    if( !HasRowid(pTab) ){
+      x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
+    }
+    sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut);
   }
   if( iCol>=0 ){
     sqlite3ColumnDefault(v, pTab, iCol, regOut);
@@ -77485,6 +80631,11 @@ SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){
   int i;
   struct yColCache *p;
 
+#if SQLITE_DEBUG
+  if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
+    printf("CLEAR\n");
+  }
+#endif
   for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
     if( p->iReg ){
       cacheEntryClear(pParse, p);
@@ -77509,7 +80660,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n
   int i;
   struct yColCache *p;
   assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
-  sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg-1);
+  sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
   for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
     int x = p->iReg;
     if( x>=iFrom && x<iFrom+nReg ){
@@ -77538,6 +80689,16 @@ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
 #endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
 
 /*
+** Convert an expression node to a TK_REGISTER
+*/
+static void exprToRegister(Expr *p, int iReg){
+  p->op2 = p->op;
+  p->op = TK_REGISTER;
+  p->iTable = iReg;
+  ExprClearProperty(p, EP_Skip);
+}
+
+/*
 ** 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.
@@ -77556,6 +80717,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
   int regFree2 = 0;         /* If non-zero free this temporary register */
   int r1, r2, r3, r4;       /* Various register numbers */
   sqlite3 *db = pParse->db; /* The database connection */
+  Expr tempX;               /* Temporary expression node */
 
   assert( target>0 && target<=pParse->nMem );
   if( v==0 ){
@@ -77584,15 +80746,20 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       /* Otherwise, fall thru into the TK_COLUMN case */
     }
     case TK_COLUMN: {
-      if( pExpr->iTable<0 ){
-        /* This only happens when coding check constraints */
-        assert( pParse->ckBase>0 );
-        inReg = pExpr->iColumn + pParse->ckBase;
-      }else{
-        inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
-                                 pExpr->iColumn, pExpr->iTable, target,
-                                 pExpr->op2);
+      int iTab = pExpr->iTable;
+      if( iTab<0 ){
+        if( pParse->ckBase>0 ){
+          /* Generating CHECK constraints or inserting into partial index */
+          inReg = pExpr->iColumn + pParse->ckBase;
+          break;
+        }else{
+          /* Deleting from a partial index */
+          iTab = pParse->iPartIdxTab;
+        }
       }
+      inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
+                               pExpr->iColumn, iTab, target,
+                               pExpr->op2);
       break;
     }
     case TK_INTEGER: {
@@ -77657,7 +80824,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       int aff, to_op;
       inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
       assert( !ExprHasProperty(pExpr, EP_IntValue) );
-      aff = sqlite3AffinityType(pExpr->u.zToken);
+      aff = sqlite3AffinityType(pExpr->u.zToken, 0);
       to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
       assert( to_op==OP_ToText    || aff!=SQLITE_AFF_TEXT    );
       assert( to_op==OP_ToBlob    || aff!=SQLITE_AFF_NONE    );
@@ -77685,22 +80852,16 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
     case TK_GE:
     case TK_NE:
     case TK_EQ: {
-      assert( TK_LT==OP_Lt );
-      assert( TK_LE==OP_Le );
-      assert( TK_GT==OP_Gt );
-      assert( TK_GE==OP_Ge );
-      assert( TK_EQ==OP_Eq );
-      assert( TK_NE==OP_Ne );
-      testcase( op==TK_LT );
-      testcase( op==TK_LE );
-      testcase( op==TK_GT );
-      testcase( op==TK_GE );
-      testcase( op==TK_EQ );
-      testcase( op==TK_NE );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                   r1, r2, inReg, SQLITE_STOREP2);
+      assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
+      assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
+      assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
+      assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
+      assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
+      assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
       testcase( regFree1==0 );
       testcase( regFree2==0 );
       break;
@@ -77714,6 +80875,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       op = (op==TK_IS) ? TK_EQ : TK_NE;
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                   r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
+      VdbeCoverageIf(v, op==TK_EQ);
+      VdbeCoverageIf(v, op==TK_NE);
       testcase( regFree1==0 );
       testcase( regFree2==0 );
       break;
@@ -77730,28 +80893,17 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
     case TK_LSHIFT:
     case TK_RSHIFT: 
     case TK_CONCAT: {
-      assert( TK_AND==OP_And );
-      assert( TK_OR==OP_Or );
-      assert( TK_PLUS==OP_Add );
-      assert( TK_MINUS==OP_Subtract );
-      assert( TK_REM==OP_Remainder );
-      assert( TK_BITAND==OP_BitAnd );
-      assert( TK_BITOR==OP_BitOr );
-      assert( TK_SLASH==OP_Divide );
-      assert( TK_LSHIFT==OP_ShiftLeft );
-      assert( TK_RSHIFT==OP_ShiftRight );
-      assert( TK_CONCAT==OP_Concat );
-      testcase( op==TK_AND );
-      testcase( op==TK_OR );
-      testcase( op==TK_PLUS );
-      testcase( op==TK_MINUS );
-      testcase( op==TK_REM );
-      testcase( op==TK_BITAND );
-      testcase( op==TK_BITOR );
-      testcase( op==TK_SLASH );
-      testcase( op==TK_LSHIFT );
-      testcase( op==TK_RSHIFT );
-      testcase( op==TK_CONCAT );
+      assert( TK_AND==OP_And );            testcase( op==TK_AND );
+      assert( TK_OR==OP_Or );              testcase( op==TK_OR );
+      assert( TK_PLUS==OP_Add );           testcase( op==TK_PLUS );
+      assert( TK_MINUS==OP_Subtract );     testcase( op==TK_MINUS );
+      assert( TK_REM==OP_Remainder );      testcase( op==TK_REM );
+      assert( TK_BITAND==OP_BitAnd );      testcase( op==TK_BITAND );
+      assert( TK_BITOR==OP_BitOr );        testcase( op==TK_BITOR );
+      assert( TK_SLASH==OP_Divide );       testcase( op==TK_SLASH );
+      assert( TK_LSHIFT==OP_ShiftLeft );   testcase( op==TK_LSHIFT );
+      assert( TK_RSHIFT==OP_ShiftRight );  testcase( op==TK_RSHIFT );
+      assert( TK_CONCAT==OP_Concat );      testcase( op==TK_CONCAT );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       sqlite3VdbeAddOp3(v, op, r2, r1, target);
@@ -77770,8 +80922,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
         codeReal(v, pLeft->u.zToken, 1, target);
 #endif
       }else{
-        regFree1 = r1 = sqlite3GetTempReg(pParse);
-        sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
+        tempX.op = TK_INTEGER;
+        tempX.flags = EP_IntValue|EP_TokenOnly;
+        tempX.u.iValue = 0;
+        r1 = sqlite3ExprCodeTemp(pParse, &tempX, &regFree1);
         r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);
         sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
         testcase( regFree2==0 );
@@ -77781,10 +80935,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
     }
     case TK_BITNOT:
     case TK_NOT: {
-      assert( TK_BITNOT==OP_BitNot );
-      assert( TK_NOT==OP_Not );
-      testcase( op==TK_BITNOT );
-      testcase( op==TK_NOT );
+      assert( TK_BITNOT==OP_BitNot );   testcase( op==TK_BITNOT );
+      assert( TK_NOT==OP_Not );         testcase( op==TK_NOT );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       testcase( regFree1==0 );
       inReg = target;
@@ -77794,15 +80946,15 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
     case TK_ISNULL:
     case TK_NOTNULL: {
       int addr;
-      assert( TK_ISNULL==OP_IsNull );
-      assert( TK_NOTNULL==OP_NotNull );
-      testcase( op==TK_ISNULL );
-      testcase( op==TK_NOTNULL );
+      assert( TK_ISNULL==OP_IsNull );   testcase( op==TK_ISNULL );
+      assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
       sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       testcase( regFree1==0 );
       addr = sqlite3VdbeAddOp1(v, op, r1);
-      sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
+      VdbeCoverageIf(v, op==TK_ISNULL);
+      VdbeCoverageIf(v, op==TK_NOTNULL);
+      sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
       sqlite3VdbeJumpHere(v, addr);
       break;
     }
@@ -77816,22 +80968,19 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       }
       break;
     }
-    case TK_CONST_FUNC:
     case TK_FUNCTION: {
       ExprList *pFarg;       /* List of function arguments */
       int nFarg;             /* Number of function arguments */
       FuncDef *pDef;         /* The function definition object */
       int nId;               /* Length of the function name in bytes */
       const char *zId;       /* The function name */
-      int constMask = 0;     /* Mask of function arguments that are constant */
+      u32 constMask = 0;     /* Mask of function arguments that are constant */
       int i;                 /* Loop counter */
       u8 enc = ENC(db);      /* The text encoding used by this database */
       CollSeq *pColl = 0;    /* A collating sequence */
 
       assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
-      testcase( op==TK_CONST_FUNC );
-      testcase( op==TK_FUNCTION );
-      if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
+      if( ExprHasProperty(pExpr, EP_TokenOnly) ){
         pFarg = 0;
       }else{
         pFarg = pExpr->x.pList;
@@ -77841,7 +80990,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       zId = pExpr->u.zToken;
       nId = sqlite3Strlen30(zId);
       pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
-      if( pDef==0 ){
+      if( pDef==0 || pDef->xFunc==0 ){
         sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId);
         break;
       }
@@ -77850,31 +80999,54 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       ** IFNULL() functions.  This avoids unnecessary evalation of
       ** arguments past the first non-NULL argument.
       */
-      if( pDef->flags & SQLITE_FUNC_COALESCE ){
+      if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
         int endCoalesce = sqlite3VdbeMakeLabel(v);
         assert( nFarg>=2 );
         sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
         for(i=1; i<nFarg; i++){
           sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
+          VdbeCoverage(v);
           sqlite3ExprCacheRemove(pParse, target, 1);
           sqlite3ExprCachePush(pParse);
           sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
-          sqlite3ExprCachePop(pParse, 1);
+          sqlite3ExprCachePop(pParse);
         }
         sqlite3VdbeResolveLabel(v, endCoalesce);
         break;
       }
 
+      /* The UNLIKELY() function is a no-op.  The result is the value
+      ** of the first argument.
+      */
+      if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
+        assert( nFarg>=1 );
+        sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
+        break;
+      }
 
+      for(i=0; i<nFarg; i++){
+        if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
+          testcase( i==31 );
+          constMask |= MASKBIT32(i);
+        }
+        if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
+          pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
+        }
+      }
       if( pFarg ){
-        r1 = sqlite3GetTempRange(pParse, nFarg);
+        if( constMask ){
+          r1 = pParse->nMem+1;
+          pParse->nMem += nFarg;
+        }else{
+          r1 = sqlite3GetTempRange(pParse, nFarg);
+        }
 
         /* For length() and typeof() functions with a column argument,
         ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
         ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data
         ** loading.
         */
-        if( (pDef->flags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
+        if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
           u8 exprOp;
           assert( nFarg==1 );
           assert( pFarg->a[0].pExpr!=0 );
@@ -77882,14 +81054,16 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
           if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){
             assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG );
             assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG );
-            testcase( pDef->flags==SQLITE_FUNC_LENGTH );
-            pFarg->a[0].pExpr->op2 = pDef->flags;
+            testcase( pDef->funcFlags & OPFLAG_LENGTHARG );
+            pFarg->a[0].pExpr->op2 = 
+                  pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG);
           }
         }
 
         sqlite3ExprCachePush(pParse);     /* Ticket 2ea2425d34be */
-        sqlite3ExprCodeExprList(pParse, pFarg, r1, 1);
-        sqlite3ExprCachePop(pParse, 1);   /* Ticket 2ea2425d34be */
+        sqlite3ExprCodeExprList(pParse, pFarg, r1,
+                                SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
+        sqlite3ExprCachePop(pParse);      /* Ticket 2ea2425d34be */
       }else{
         r1 = 0;
       }
@@ -77912,22 +81086,14 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
         pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
       }
 #endif
-      for(i=0; i<nFarg; i++){
-        if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
-          constMask |= (1<<i);
-        }
-        if( (pDef->flags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
-          pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
-        }
-      }
-      if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){
+      if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
         if( !pColl ) pColl = db->pDfltColl; 
         sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
       }
       sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
                         (char*)pDef, P4_FUNCDEF);
       sqlite3VdbeChangeP5(v, (u8)nFarg);
-      if( nFarg ){
+      if( nFarg && constMask==0 ){
         sqlite3ReleaseTempRange(pParse, r1, nFarg);
       }
       break;
@@ -77977,13 +81143,14 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       r3 = sqlite3GetTempReg(pParse);
       r4 = sqlite3GetTempReg(pParse);
       codeCompare(pParse, pLeft, pRight, OP_Ge,
-                  r1, r2, r3, SQLITE_STOREP2);
+                  r1, r2, r3, SQLITE_STOREP2);  VdbeCoverage(v);
       pLItem++;
       pRight = pLItem->pExpr;
       sqlite3ReleaseTempReg(pParse, regFree2);
       r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2);
       testcase( regFree2==0 );
       codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2);
+      VdbeCoverage(v);
       sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
       sqlite3ReleaseTempReg(pParse, r3);
       sqlite3ReleaseTempReg(pParse, r4);
@@ -78061,9 +81228,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
     **        WHEN x=eN THEN rN ELSE y END
     **
     ** X (if it exists) is in pExpr->pLeft.
-    ** Y is in pExpr->pRight.  The Y is also optional.  If there is no
-    ** ELSE clause and no other term matches, then the result of the
-    ** exprssion is NULL.
+    ** Y is in the last element of pExpr->x.pList if pExpr->x.pList->nExpr is
+    ** odd.  The Y is also optional.  If the number of elements in x.pList
+    ** is even, then Y is omitted and the "otherwise" result is NULL.
     ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1].
     **
     ** The result of the expression is the Ri for the first matching Ei,
@@ -78078,27 +81245,23 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       ExprList *pEList;                 /* List of WHEN terms */
       struct ExprList_item *aListelem;  /* Array of WHEN terms */
       Expr opCompare;                   /* The X==Ei expression */
-      Expr cacheX;                      /* Cached expression X */
       Expr *pX;                         /* The X expression */
       Expr *pTest = 0;                  /* X==Ei (form A) or just Ei (form B) */
       VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
 
       assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
-      assert((pExpr->x.pList->nExpr % 2) == 0);
       assert(pExpr->x.pList->nExpr > 0);
       pEList = pExpr->x.pList;
       aListelem = pEList->a;
       nExpr = pEList->nExpr;
       endLabel = sqlite3VdbeMakeLabel(v);
       if( (pX = pExpr->pLeft)!=0 ){
-        cacheX = *pX;
+        tempX = *pX;
         testcase( pX->op==TK_COLUMN );
-        testcase( pX->op==TK_REGISTER );
-        cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, &regFree1);
+        exprToRegister(&tempX, sqlite3ExprCodeTemp(pParse, pX, &regFree1));
         testcase( regFree1==0 );
-        cacheX.op = TK_REGISTER;
         opCompare.op = TK_EQ;
-        opCompare.pLeft = &cacheX;
+        opCompare.pLeft = &tempX;
         pTest = &opCompare;
         /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
         ** The value in regFree1 might get SCopy-ed into the file result.
@@ -78106,7 +81269,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
         ** purposes and possibly overwritten.  */
         regFree1 = 0;
       }
-      for(i=0; i<nExpr; i=i+2){
+      for(i=0; i<nExpr-1; i=i+2){
         sqlite3ExprCachePush(pParse);
         if( pX ){
           assert( pTest!=0 );
@@ -78118,16 +81281,15 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
         testcase( pTest->op==TK_COLUMN );
         sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
         testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
-        testcase( aListelem[i+1].pExpr->op==TK_REGISTER );
         sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
         sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
-        sqlite3ExprCachePop(pParse, 1);
+        sqlite3ExprCachePop(pParse);
         sqlite3VdbeResolveLabel(v, nextCase);
       }
-      if( pExpr->pRight ){
+      if( (nExpr&1)!=0 ){
         sqlite3ExprCachePush(pParse);
-        sqlite3ExprCode(pParse, pExpr->pRight, target);
-        sqlite3ExprCachePop(pParse, 1);
+        sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
+        sqlite3ExprCachePop(pParse);
       }else{
         sqlite3VdbeAddOp2(v, OP_Null, 0, target);
       }
@@ -78155,9 +81317,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
       if( pExpr->affinity==OE_Ignore ){
         sqlite3VdbeAddOp4(
             v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
+        VdbeCoverage(v);
       }else{
         sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
-                              pExpr->affinity, pExpr->u.zToken, 0);
+                              pExpr->affinity, pExpr->u.zToken, 0, 0);
       }
 
       break;
@@ -78170,6 +81333,28 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
 }
 
 /*
+** Factor out the code of the given expression to initialization time.
+*/
+SQLITE_PRIVATE void sqlite3ExprCodeAtInit(
+  Parse *pParse,    /* Parsing context */
+  Expr *pExpr,      /* The expression to code when the VDBE initializes */
+  int regDest,      /* Store the value in this register */
+  u8 reusable       /* True if this expression is reusable */
+){
+  ExprList *p;
+  assert( ConstFactorOk(pParse) );
+  p = pParse->pConstExpr;
+  pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
+  p = sqlite3ExprListAppend(pParse, p, pExpr);
+  if( p ){
+     struct ExprList_item *pItem = &p->a[p->nExpr-1];
+     pItem->u.iConstExprReg = regDest;
+     pItem->reusable = reusable;
+  }
+  pParse->pConstExpr = p;
+}
+
+/*
 ** Generate code to evaluate an expression and store the results
 ** into a register.  Return the register number where the results
 ** are stored.
@@ -78177,15 +81362,40 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
 ** If the register is a temporary register that can be deallocated,
 ** then write its number into *pReg.  If the result register is not
 ** a temporary, then set *pReg to zero.
+**
+** If pExpr is a constant, then this routine might generate this
+** code to fill the register in the initialization section of the
+** VDBE program, in order to factor it out of the evaluation loop.
 */
 SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
-  int r1 = sqlite3GetTempReg(pParse);
-  int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
-  if( r2==r1 ){
-    *pReg = r1;
+  int r2;
+  pExpr = sqlite3ExprSkipCollate(pExpr);
+  if( ConstFactorOk(pParse)
+   && pExpr->op!=TK_REGISTER
+   && sqlite3ExprIsConstantNotJoin(pExpr)
+  ){
+    ExprList *p = pParse->pConstExpr;
+    int i;
+    *pReg  = 0;
+    if( p ){
+      struct ExprList_item *pItem;
+      for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
+        if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
+          return pItem->u.iConstExprReg;
+        }
+      }
+    }
+    r2 = ++pParse->nMem;
+    sqlite3ExprCodeAtInit(pParse, pExpr, r2, 1);
   }else{
-    sqlite3ReleaseTempReg(pParse, r1);
-    *pReg = 0;
+    int r1 = sqlite3GetTempReg(pParse);
+    r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
+    if( r2==r1 ){
+      *pReg = r1;
+    }else{
+      sqlite3ReleaseTempReg(pParse, r1);
+      *pReg = 0;
+    }
   }
   return r2;
 }
@@ -78195,7 +81405,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
 ** results in register target.  The results are guaranteed to appear
 ** in register target.
 */
-SQLITE_PRIVATE int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
+SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
   int inReg;
 
   assert( target>0 && target<=pParse->nMem );
@@ -78208,7 +81418,20 @@ SQLITE_PRIVATE int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
       sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
     }
   }
-  return target;
+}
+
+/*
+** Generate code that will evaluate expression pExpr and store the
+** results in register target.  The results are guaranteed to appear
+** in register target.  If the expression is constant, then this routine
+** might choose to code the expression at initialization time.
+*/
+SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
+  if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){
+    sqlite3ExprCodeAtInit(pParse, pExpr, target, 0);
+  }else{
+    sqlite3ExprCode(pParse, pExpr, target);
+  }
 }
 
 /*
@@ -78223,26 +81446,16 @@ SQLITE_PRIVATE int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
 ** times.  They are evaluated once and the results of the expression
 ** are reused.
 */
-SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
+SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
   Vdbe *v = pParse->pVdbe;
-  int inReg;
-  inReg = sqlite3ExprCode(pParse, pExpr, target);
+  int iMem;
+
   assert( target>0 );
-  /* This routine is called for terms to INSERT or UPDATE.  And the only
-  ** other place where expressions can be converted into TK_REGISTER is
-  ** in WHERE clause processing.  So as currently implemented, there is
-  ** no way for a TK_REGISTER to exist here.  But it seems prudent to
-  ** keep the ALWAYS() in case the conditions above change with future
-  ** modifications or enhancements. */
-  if( ALWAYS(pExpr->op!=TK_REGISTER) ){  
-    int iMem;
-    iMem = ++pParse->nMem;
-    sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
-    pExpr->iTable = iMem;
-    pExpr->op2 = pExpr->op;
-    pExpr->op = TK_REGISTER;
-  }
-  return inReg;
+  assert( pExpr->op!=TK_REGISTER );
+  sqlite3ExprCode(pParse, pExpr, target);
+  iMem = ++pParse->nMem;
+  sqlite3VdbeAddOp2(v, OP_Copy, target, iMem);
+  exprToRegister(pExpr, iMem);
 }
 
 #if defined(SQLITE_ENABLE_TREE_EXPLAIN)
@@ -78319,7 +81532,7 @@ SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
     case TK_CAST: {
       /* Expressions of the form:   CAST(pLeft AS token) */
       const char *zAff = "unk";
-      switch( sqlite3AffinityType(pExpr->u.zToken) ){
+      switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){
         case SQLITE_AFF_TEXT:    zAff = "TEXT";     break;
         case SQLITE_AFF_NONE:    zAff = "NONE";     break;
         case SQLITE_AFF_NUMERIC: zAff = "NUMERIC";  break;
@@ -78367,10 +81580,9 @@ SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
     }
 
     case TK_AGG_FUNCTION:
-    case TK_CONST_FUNC:
     case TK_FUNCTION: {
       ExprList *pFarg;       /* List of function arguments */
-      if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
+      if( ExprHasProperty(pExpr, EP_TokenOnly) ){
         pFarg = 0;
       }else{
         pFarg = pExpr->x.pList;
@@ -78519,165 +81731,50 @@ SQLITE_PRIVATE void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
 #endif /* SQLITE_DEBUG */
 
 /*
-** Return TRUE if pExpr is an constant expression that is appropriate
-** for factoring out of a loop.  Appropriate expressions are:
-**
-**    *  Any expression that evaluates to two or more opcodes.
-**
-**    *  Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null, 
-**       or OP_Variable that does not need to be placed in a 
-**       specific register.
-**
-** There is no point in factoring out single-instruction constant
-** expressions that need to be placed in a particular register.  
-** We could factor them out, but then we would end up adding an
-** OP_SCopy instruction to move the value into the correct register
-** later.  We might as well just use the original instruction and
-** avoid the OP_SCopy.
-*/
-static int isAppropriateForFactoring(Expr *p){
-  if( !sqlite3ExprIsConstantNotJoin(p) ){
-    return 0;  /* Only constant expressions are appropriate for factoring */
-  }
-  if( (p->flags & EP_FixedDest)==0 ){
-    return 1;  /* Any constant without a fixed destination is appropriate */
-  }
-  while( p->op==TK_UPLUS ) p = p->pLeft;
-  switch( p->op ){
-#ifndef SQLITE_OMIT_BLOB_LITERAL
-    case TK_BLOB:
-#endif
-    case TK_VARIABLE:
-    case TK_INTEGER:
-    case TK_FLOAT:
-    case TK_NULL:
-    case TK_STRING: {
-      testcase( p->op==TK_BLOB );
-      testcase( p->op==TK_VARIABLE );
-      testcase( p->op==TK_INTEGER );
-      testcase( p->op==TK_FLOAT );
-      testcase( p->op==TK_NULL );
-      testcase( p->op==TK_STRING );
-      /* Single-instruction constants with a fixed destination are
-      ** better done in-line.  If we factor them, they will just end
-      ** up generating an OP_SCopy to move the value to the destination
-      ** register. */
-      return 0;
-    }
-    case TK_UMINUS: {
-      if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){
-        return 0;
-      }
-      break;
-    }
-    default: {
-      break;
-    }
-  }
-  return 1;
-}
-
-/*
-** If pExpr is a constant expression that is appropriate for
-** factoring out of a loop, then evaluate the expression
-** into a register and convert the expression into a TK_REGISTER
-** expression.
-*/
-static int evalConstExpr(Walker *pWalker, Expr *pExpr){
-  Parse *pParse = pWalker->pParse;
-  switch( pExpr->op ){
-    case TK_IN:
-    case TK_REGISTER: {
-      return WRC_Prune;
-    }
-    case TK_COLLATE: {
-      return WRC_Continue;
-    }
-    case TK_FUNCTION:
-    case TK_AGG_FUNCTION:
-    case TK_CONST_FUNC: {
-      /* The arguments to a function have a fixed destination.
-      ** Mark them this way to avoid generated unneeded OP_SCopy
-      ** instructions. 
-      */
-      ExprList *pList = pExpr->x.pList;
-      assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
-      if( pList ){
-        int i = pList->nExpr;
-        struct ExprList_item *pItem = pList->a;
-        for(; i>0; i--, pItem++){
-          if( ALWAYS(pItem->pExpr) ) pItem->pExpr->flags |= EP_FixedDest;
-        }
-      }
-      break;
-    }
-  }
-  if( isAppropriateForFactoring(pExpr) ){
-    int r1 = ++pParse->nMem;
-    int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
-    /* If r2!=r1, it means that register r1 is never used.  That is harmless
-    ** but suboptimal, so we want to know about the situation to fix it.
-    ** Hence the following assert: */
-    assert( r2==r1 );
-    pExpr->op2 = pExpr->op;
-    pExpr->op = TK_REGISTER;
-    pExpr->iTable = r2;
-    return WRC_Prune;
-  }
-  return WRC_Continue;
-}
-
-/*
-** Preevaluate constant subexpressions within pExpr and store the
-** results in registers.  Modify pExpr so that the constant subexpresions
-** are TK_REGISTER opcodes that refer to the precomputed values.
-**
-** This routine is a no-op if the jump to the cookie-check code has
-** already occur.  Since the cookie-check jump is generated prior to
-** any other serious processing, this check ensures that there is no
-** way to accidently bypass the constant initializations.
-**
-** This routine is also a no-op if the SQLITE_FactorOutConst optimization
-** is disabled via the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS)
-** interface.  This allows test logic to verify that the same answer is
-** obtained for queries regardless of whether or not constants are
-** precomputed into registers or if they are inserted in-line.
-*/
-SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
-  Walker w;
-  if( pParse->cookieGoto ) return;
-  if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return;
-  memset(&w, 0, sizeof(w));
-  w.xExprCallback = evalConstExpr;
-  w.pParse = pParse;
-  sqlite3WalkExpr(&w, pExpr);
-}
-
-
-/*
 ** Generate code that pushes the value of every element of the given
 ** expression list into a sequence of registers beginning at target.
 **
 ** Return the number of elements evaluated.
+**
+** The SQLITE_ECEL_DUP flag prevents the arguments from being
+** filled using OP_SCopy.  OP_Copy must be used instead.
+**
+** The SQLITE_ECEL_FACTOR argument allows constant arguments to be
+** factored out into initialization code.
 */
 SQLITE_PRIVATE int sqlite3ExprCodeExprList(
   Parse *pParse,     /* Parsing context */
   ExprList *pList,   /* The expression list to be coded */
   int target,        /* Where to write results */
-  int doHardCopy     /* Make a hard copy of every element */
+  u8 flags           /* SQLITE_ECEL_* flags */
 ){
   struct ExprList_item *pItem;
   int i, n;
+  u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy;
   assert( pList!=0 );
   assert( target>0 );
   assert( pParse->pVdbe!=0 );  /* Never gets this far otherwise */
   n = pList->nExpr;
+  if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
   for(pItem=pList->a, i=0; i<n; i++, pItem++){
     Expr *pExpr = pItem->pExpr;
-    int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
-    if( inReg!=target+i ){
-      sqlite3VdbeAddOp2(pParse->pVdbe, doHardCopy ? OP_Copy : OP_SCopy,
-                        inReg, target+i);
+    if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
+      sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0);
+    }else{
+      int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
+      if( inReg!=target+i ){
+        VdbeOp *pOp;
+        Vdbe *v = pParse->pVdbe;
+        if( copyOp==OP_Copy
+         && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy
+         && pOp->p1+pOp->p3+1==inReg
+         && pOp->p2+pOp->p3+1==target+i
+        ){
+          pOp->p3++;
+        }else{
+          sqlite3VdbeAddOp2(v, copyOp, inReg, target+i);
+        }
+      }
     }
   }
   return n;
@@ -78719,8 +81816,7 @@ static void exprCodeBetween(
   compRight.op = TK_LE;
   compRight.pLeft = &exprX;
   compRight.pRight = pExpr->x.pList->a[1].pExpr;
-  exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, &regFree1);
-  exprX.op = TK_REGISTER;
+  exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, &regFree1));
   if( jumpIfTrue ){
     sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
   }else{
@@ -78768,17 +81864,19 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
     case TK_AND: {
       int d2 = sqlite3VdbeMakeLabel(v);
       testcase( jumpIfNull==0 );
-      sqlite3ExprCachePush(pParse);
       sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
+      sqlite3ExprCachePush(pParse);
       sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
       sqlite3VdbeResolveLabel(v, d2);
-      sqlite3ExprCachePop(pParse, 1);
+      sqlite3ExprCachePop(pParse);
       break;
     }
     case TK_OR: {
       testcase( jumpIfNull==0 );
       sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
+      sqlite3ExprCachePush(pParse);
       sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+      sqlite3ExprCachePop(pParse);
       break;
     }
     case TK_NOT: {
@@ -78792,23 +81890,17 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
     case TK_GE:
     case TK_NE:
     case TK_EQ: {
-      assert( TK_LT==OP_Lt );
-      assert( TK_LE==OP_Le );
-      assert( TK_GT==OP_Gt );
-      assert( TK_GE==OP_Ge );
-      assert( TK_EQ==OP_Eq );
-      assert( TK_NE==OP_Ne );
-      testcase( op==TK_LT );
-      testcase( op==TK_LE );
-      testcase( op==TK_GT );
-      testcase( op==TK_GE );
-      testcase( op==TK_EQ );
-      testcase( op==TK_NE );
       testcase( jumpIfNull==0 );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                   r1, r2, dest, jumpIfNull);
+      assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
+      assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
+      assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
+      assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
+      assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
+      assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
       testcase( regFree1==0 );
       testcase( regFree2==0 );
       break;
@@ -78822,18 +81914,20 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
       op = (op==TK_IS) ? TK_EQ : TK_NE;
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                   r1, r2, dest, SQLITE_NULLEQ);
+      VdbeCoverageIf(v, op==TK_EQ);
+      VdbeCoverageIf(v, op==TK_NE);
       testcase( regFree1==0 );
       testcase( regFree2==0 );
       break;
     }
     case TK_ISNULL:
     case TK_NOTNULL: {
-      assert( TK_ISNULL==OP_IsNull );
-      assert( TK_NOTNULL==OP_NotNull );
-      testcase( op==TK_ISNULL );
-      testcase( op==TK_NOTNULL );
+      assert( TK_ISNULL==OP_IsNull );   testcase( op==TK_ISNULL );
+      assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       sqlite3VdbeAddOp2(v, op, r1, dest);
+      VdbeCoverageIf(v, op==TK_ISNULL);
+      VdbeCoverageIf(v, op==TK_NOTNULL);
       testcase( regFree1==0 );
       break;
     }
@@ -78853,10 +81947,17 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
     }
 #endif
     default: {
-      r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
-      sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
-      testcase( regFree1==0 );
-      testcase( jumpIfNull==0 );
+      if( exprAlwaysTrue(pExpr) ){
+        sqlite3VdbeAddOp2(v, OP_Goto, 0, dest);
+      }else if( exprAlwaysFalse(pExpr) ){
+        /* No-op */
+      }else{
+        r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
+        sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
+        VdbeCoverage(v);
+        testcase( regFree1==0 );
+        testcase( jumpIfNull==0 );
+      }
       break;
     }
   }
@@ -78919,17 +82020,19 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
     case TK_AND: {
       testcase( jumpIfNull==0 );
       sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
+      sqlite3ExprCachePush(pParse);
       sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
+      sqlite3ExprCachePop(pParse);
       break;
     }
     case TK_OR: {
       int d2 = sqlite3VdbeMakeLabel(v);
       testcase( jumpIfNull==0 );
-      sqlite3ExprCachePush(pParse);
       sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
+      sqlite3ExprCachePush(pParse);
       sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
       sqlite3VdbeResolveLabel(v, d2);
-      sqlite3ExprCachePop(pParse, 1);
+      sqlite3ExprCachePop(pParse);
       break;
     }
     case TK_NOT: {
@@ -78943,17 +82046,17 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
     case TK_GE:
     case TK_NE:
     case TK_EQ: {
-      testcase( op==TK_LT );
-      testcase( op==TK_LE );
-      testcase( op==TK_GT );
-      testcase( op==TK_GE );
-      testcase( op==TK_EQ );
-      testcase( op==TK_NE );
       testcase( jumpIfNull==0 );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                   r1, r2, dest, jumpIfNull);
+      assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
+      assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
+      assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
+      assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
+      assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
+      assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
       testcase( regFree1==0 );
       testcase( regFree2==0 );
       break;
@@ -78967,16 +82070,18 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
       op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                   r1, r2, dest, SQLITE_NULLEQ);
+      VdbeCoverageIf(v, op==TK_EQ);
+      VdbeCoverageIf(v, op==TK_NE);
       testcase( regFree1==0 );
       testcase( regFree2==0 );
       break;
     }
     case TK_ISNULL:
     case TK_NOTNULL: {
-      testcase( op==TK_ISNULL );
-      testcase( op==TK_NOTNULL );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       sqlite3VdbeAddOp2(v, op, r1, dest);
+      testcase( op==TK_ISNULL );   VdbeCoverageIf(v, op==TK_ISNULL);
+      testcase( op==TK_NOTNULL );  VdbeCoverageIf(v, op==TK_NOTNULL);
       testcase( regFree1==0 );
       break;
     }
@@ -78998,10 +82103,17 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
     }
 #endif
     default: {
-      r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
-      sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
-      testcase( regFree1==0 );
-      testcase( jumpIfNull==0 );
+      if( exprAlwaysFalse(pExpr) ){
+        sqlite3VdbeAddOp2(v, OP_Goto, 0, dest);
+      }else if( exprAlwaysTrue(pExpr) ){
+        /* no-op */
+      }else{
+        r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
+        sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
+        VdbeCoverage(v);
+        testcase( regFree1==0 );
+        testcase( jumpIfNull==0 );
+      }
       break;
     }
   }
@@ -79015,6 +82127,12 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
 ** by a COLLATE operator at the top level.  Return 2 if there are differences
 ** other than the top-level COLLATE operator.
 **
+** If any subelement of pB has Expr.iTable==(-1) then it is allowed
+** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
+**
+** The pA side might be using TK_REGISTER.  If that is the case and pB is
+** not using TK_REGISTER but is otherwise equivalent, then still return 0.
+**
 ** Sometimes this routine will return 2 even if the two expressions
 ** really are equivalent.  If we cannot prove that the expressions are
 ** identical, we return 2 just to be safe.  So if this routine
@@ -79025,39 +82143,44 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
 ** just might result in some slightly slower code.  But returning
 ** an incorrect 0 or 1 could lead to a malfunction.
 */
-SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
-  if( pA==0||pB==0 ){
+SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
+  u32 combinedFlags;
+  if( pA==0 || pB==0 ){
     return pB==pA ? 0 : 2;
   }
-  assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
-  assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
-  if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
+  combinedFlags = pA->flags | pB->flags;
+  if( combinedFlags & EP_IntValue ){
+    if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
+      return 0;
+    }
     return 2;
   }
-  if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
   if( pA->op!=pB->op ){
-    if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
+    if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){
       return 1;
     }
-    if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
+    if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<2 ){
       return 1;
     }
     return 2;
   }
-  if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
-  if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
-  if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
-  if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
-  if( ExprHasProperty(pA, EP_IntValue) ){
-    if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
-      return 2;
-    }
-  }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
-    if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
+  if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken ){
     if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
       return pA->op==TK_COLLATE ? 1 : 2;
     }
   }
+  if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
+  if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
+    if( combinedFlags & EP_xIsSelect ) return 2;
+    if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
+    if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
+    if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
+    if( ALWAYS((combinedFlags & EP_Reduced)==0) ){
+      if( pA->iColumn!=pB->iColumn ) return 2;
+      if( pA->iTable!=pB->iTable 
+       && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
+    }
+  }
   return 0;
 }
 
@@ -79065,6 +82188,9 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
 ** Compare two ExprList objects.  Return 0 if they are identical and 
 ** non-zero if they differ in any way.
 **
+** If any subelement of pB has Expr.iTable==(-1) then it is allowed
+** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
+**
 ** This routine might return non-zero for equivalent ExprLists.  The
 ** only consequence will be disabled optimizations.  But this routine
 ** must never return 0 if the two ExprList objects are different, or
@@ -79073,7 +82199,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
 ** Two NULL pointers are considered to be the same.  But a NULL pointer
 ** always differs from a non-NULL pointer.
 */
-SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
+SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
   int i;
   if( pA==0 && pB==0 ) return 0;
   if( pA==0 || pB==0 ) return 1;
@@ -79082,7 +82208,46 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
     Expr *pExprA = pA->a[i].pExpr;
     Expr *pExprB = pB->a[i].pExpr;
     if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
-    if( sqlite3ExprCompare(pExprA, pExprB) ) return 1;
+    if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1;
+  }
+  return 0;
+}
+
+/*
+** Return true if we can prove the pE2 will always be true if pE1 is
+** true.  Return false if we cannot complete the proof or if pE2 might
+** be false.  Examples:
+**
+**     pE1: x==5       pE2: x==5             Result: true
+**     pE1: x>0        pE2: x==5             Result: false
+**     pE1: x=21       pE2: x=21 OR y=43     Result: true
+**     pE1: x!=123     pE2: x IS NOT NULL    Result: true
+**     pE1: x!=?1      pE2: x IS NOT NULL    Result: true
+**     pE1: x IS NULL  pE2: x IS NOT NULL    Result: false
+**     pE1: x IS ?2    pE2: x IS NOT NULL    Reuslt: false
+**
+** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
+** Expr.iTable<0 then assume a table number given by iTab.
+**
+** When in doubt, return false.  Returning true might give a performance
+** improvement.  Returning false might cause a performance reduction, but
+** it will always give the correct answer and is hence always safe.
+*/
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
+  if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){
+    return 1;
+  }
+  if( pE2->op==TK_OR
+   && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
+             || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
+  ){
+    return 1;
+  }
+  if( pE2->op==TK_NOTNULL
+   && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
+   && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
+  ){
+    return 1;
   }
   return 0;
 }
@@ -79199,7 +82364,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
         struct SrcList_item *pItem = pSrcList->a;
         for(i=0; i<pSrcList->nSrc; i++, pItem++){
           struct AggInfo_col *pCol;
-          assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+          assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
           if( pExpr->iTable==pItem->iCursor ){
             /* If we reach this point, it means that pExpr refers to a table
             ** that is in the FROM clause of the aggregate query.  
@@ -79248,7 +82413,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
             ** Convert the pExpr to be a TK_AGG_COLUMN referring to that
             ** pAggInfo->aCol[] entry.
             */
-            ExprSetIrreducible(pExpr);
+            ExprSetVVAProperty(pExpr, EP_NoReduce);
             pExpr->pAggInfo = pAggInfo;
             pExpr->op = TK_AGG_COLUMN;
             pExpr->iAgg = (i16)k;
@@ -79267,7 +82432,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
         */
         struct AggInfo_func *pItem = pAggInfo->aFunc;
         for(i=0; i<pAggInfo->nFunc; i++, pItem++){
-          if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){
+          if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){
             break;
           }
         }
@@ -79294,8 +82459,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
         }
         /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
         */
-        assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
-        ExprSetIrreducible(pExpr);
+        assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+        ExprSetVVAProperty(pExpr, EP_NoReduce);
         pExpr->iAgg = (i16)i;
         pExpr->pAggInfo = pAggInfo;
         return WRC_Prune;
@@ -79492,8 +82657,8 @@ static void renameTableFunc(
       assert( len>0 );
     } while( token!=TK_LP && token!=TK_USING );
 
-    zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, 
-       zTableName, tname.z+tname.n);
+    zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
+       zSql, zTableName, tname.z+tname.n);
     sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
   }
 }
@@ -79531,6 +82696,7 @@ static void renameParentFunc(
   int token;                      /* Type of token */
 
   UNUSED_PARAMETER(NotUsed);
+  if( zInput==0 || zOld==0 ) return;
   for(z=zInput; *z; z=z+n){
     n = sqlite3GetToken(z, &token);
     if( token==TK_REFERENCES ){
@@ -79545,7 +82711,7 @@ static void renameParentFunc(
       sqlite3Dequote(zParent);
       if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){
         char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", 
-            (zOutput?zOutput:""), z-zInput, zInput, (const char *)zNew
+            (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew
         );
         sqlite3DbFree(db, zOutput);
         zOutput = zOut;
@@ -79631,8 +82797,8 @@ static void renameTriggerFunc(
     /* Variable tname now contains the token that is the old table-name
     ** in the CREATE TRIGGER statement.
     */
-    zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, 
-       zTableName, tname.z+tname.n);
+    zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
+       zSql, zTableName, tname.z+tname.n);
     sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
   }
 }
@@ -79884,7 +83050,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
   }
 #endif
 
-  /* Begin a transaction and code the VerifyCookie for database iDb. 
+  /* Begin a transaction for database iDb. 
   ** Then modify the schema cookie (since the ALTER TABLE modifies the
   ** schema). Open a statement transaction if the table is a virtual
   ** table.
@@ -80020,6 +83186,7 @@ SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minForm
     sqlite3VdbeUsesBtree(v, iDb);
     sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2);
     j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1);
+    sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v);
     sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2);
     sqlite3VdbeJumpHere(v, j1);
     sqlite3ReleaseTempReg(pParse, r1);
@@ -80102,7 +83269,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
   ** can handle (i.e. not CURRENT_TIME etc.)
   */
   if( pDflt ){
-    sqlite3_value *pVal;
+    sqlite3_value *pVal = 0;
     if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
       db->mallocFailed = 1;
       return;
@@ -80243,7 +83410,7 @@ exit_begin_add_column:
 /************** End of alter.c ***********************************************/
 /************** Begin file analyze.c *****************************************/
 /*
-** 2005 July 8
+** 2005-07-08
 **
 ** The author disclaims copyright to this source code.  In place of
 ** a legal notice, here is a blessing:
@@ -80264,15 +83431,23 @@ exit_begin_add_column:
 **    CREATE TABLE sqlite_stat1(tbl, idx, stat);
 **    CREATE TABLE sqlite_stat2(tbl, idx, sampleno, sample);
 **    CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample);
+**    CREATE TABLE sqlite_stat4(tbl, idx, nEq, nLt, nDLt, sample);
 **
 ** Additional tables might be added in future releases of SQLite.
 ** The sqlite_stat2 table is not created or used unless the SQLite version
 ** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
 ** with SQLITE_ENABLE_STAT2.  The sqlite_stat2 table is deprecated.
-** The sqlite_stat2 table is superceded by sqlite_stat3, which is only
+** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
 ** created and used by SQLite versions 3.7.9 and later and with
-** SQLITE_ENABLE_STAT3 defined.  The fucntionality of sqlite_stat3
-** is a superset of sqlite_stat2.  
+** SQLITE_ENABLE_STAT3 defined.  The functionality of sqlite_stat3
+** is a superset of sqlite_stat2.  The sqlite_stat4 is an enhanced
+** version of sqlite_stat3 and is only available when compiled with
+** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later.  It is
+** not possible to enable both STAT3 and STAT4 at the same time.  If they
+** are both enabled, then STAT4 takes precedence.
+**
+** For most applications, sqlite_stat1 provides all the statisics required
+** for the query planner to make good choices.
 **
 ** Format of sqlite_stat1:
 **
@@ -80280,7 +83455,8 @@ exit_begin_add_column:
 ** name in the idx column.  The tbl column is the name of the table to
 ** which the index belongs.  In each such row, the stat column will be
 ** a string consisting of a list of integers.  The first integer in this
-** list is the number of rows in the index and in the table.  The second
+** list is the number of rows in the index.  (This is the same as the
+** number of rows in the table, except for partial indices.)  The second
 ** integer is the average number of rows in the index that have the same
 ** value in the first column of the index.  The third integer is the average
 ** number of rows in the index that have the same value for the first two
@@ -80327,53 +83503,81 @@ exit_begin_add_column:
 **
 ** Format for sqlite_stat3:
 **
-** The sqlite_stat3 is an enhancement to sqlite_stat2.  A new name is
-** used to avoid compatibility problems.  
+** The sqlite_stat3 format is a subset of sqlite_stat4.  Hence, the
+** sqlite_stat4 format will be described first.  Further information
+** about sqlite_stat3 follows the sqlite_stat4 description.
+**
+** Format for sqlite_stat4:
 **
-** The format of the sqlite_stat3 table is similar to the format of
-** the sqlite_stat2 table.  There are multiple entries for each index.
+** As with sqlite_stat2, the sqlite_stat4 table contains histogram data
+** to aid the query planner in choosing good indices based on the values
+** that indexed columns are compared against in the WHERE clauses of
+** queries.
+**
+** The sqlite_stat4 table contains multiple entries for each index.
 ** The idx column names the index and the tbl column is the table of the
 ** index.  If the idx and tbl columns are the same, then the sample is
-** of the INTEGER PRIMARY KEY.  The sample column is a value taken from
-** the left-most column of the index.  The nEq column is the approximate
-** number of entires in the index whose left-most column exactly matches
-** the sample.  nLt is the approximate number of entires whose left-most
-** column is less than the sample.  The nDLt column is the approximate
-** number of distinct left-most entries in the index that are less than
-** the sample.
-**
-** Future versions of SQLite might change to store a string containing
-** multiple integers values in the nDLt column of sqlite_stat3.  The first
-** integer will be the number of prior index entires that are distinct in
-** the left-most column.  The second integer will be the number of prior index
-** entries that are distinct in the first two columns.  The third integer
-** will be the number of prior index entries that are distinct in the first
-** three columns.  And so forth.  With that extension, the nDLt field is
-** similar in function to the sqlite_stat1.stat field.
-**
-** There can be an arbitrary number of sqlite_stat3 entries per index.
-** The ANALYZE command will typically generate sqlite_stat3 tables
+** of the INTEGER PRIMARY KEY.  The sample column is a blob which is the
+** binary encoding of a key from the index.  The nEq column is a
+** list of integers.  The first integer is the approximate number
+** of entries in the index whose left-most column exactly matches
+** the left-most column of the sample.  The second integer in nEq
+** is the approximate number of entries in the index where the
+** first two columns match the first two columns of the sample.
+** And so forth.  nLt is another list of integers that show the approximate
+** number of entries that are strictly less than the sample.  The first
+** integer in nLt contains the number of entries in the index where the
+** left-most column is less than the left-most column of the sample.
+** The K-th integer in the nLt entry is the number of index entries 
+** where the first K columns are less than the first K columns of the
+** sample.  The nDLt column is like nLt except that it contains the 
+** number of distinct entries in the index that are less than the
+** sample.
+**
+** There can be an arbitrary number of sqlite_stat4 entries per index.
+** The ANALYZE command will typically generate sqlite_stat4 tables
 ** that contain between 10 and 40 samples which are distributed across
 ** the key space, though not uniformly, and which include samples with
-** largest possible nEq values.
+** large nEq values.
+**
+** Format for sqlite_stat3 redux:
+**
+** The sqlite_stat3 table is like sqlite_stat4 except that it only
+** looks at the left-most column of the index.  The sqlite_stat3.sample
+** column contains the actual value of the left-most column instead
+** of a blob encoding of the complete index key as is found in
+** sqlite_stat4.sample.  The nEq, nLt, and nDLt entries of sqlite_stat3
+** all contain just a single integer which is the same as the first
+** integer in the equivalent columns in sqlite_stat4.
 */
 #ifndef SQLITE_OMIT_ANALYZE
 
+#if defined(SQLITE_ENABLE_STAT4)
+# define IsStat4     1
+# define IsStat3     0
+#elif defined(SQLITE_ENABLE_STAT3)
+# define IsStat4     0
+# define IsStat3     1
+#else
+# define IsStat4     0
+# define IsStat3     0
+# undef SQLITE_STAT4_SAMPLES
+# define SQLITE_STAT4_SAMPLES 1
+#endif
+#define IsStat34    (IsStat3+IsStat4)  /* 1 for STAT3 or STAT4. 0 otherwise */
+
 /*
-** This routine generates code that opens the sqlite_stat1 table for
-** writing with cursor iStatCur. If the library was built with the
-** SQLITE_ENABLE_STAT3 macro defined, then the sqlite_stat3 table is
-** opened for writing using cursor (iStatCur+1)
+** This routine generates code that opens the sqlite_statN tables.
+** The sqlite_stat1 table is always relevant.  sqlite_stat2 is now
+** obsolete.  sqlite_stat3 and sqlite_stat4 are only opened when
+** appropriate compile-time options are provided.
 **
-** If the sqlite_stat1 tables does not previously exist, it is created.
-** Similarly, if the sqlite_stat3 table does not exist and the library
-** is compiled with SQLITE_ENABLE_STAT3 defined, it is created. 
+** If the sqlite_statN tables do not previously exist, it is created.
 **
 ** Argument zWhere may be a pointer to a buffer containing a table name,
 ** or it may be a NULL pointer. If it is not NULL, then all entries in
-** the sqlite_stat1 and (if applicable) sqlite_stat3 tables associated
-** with the named table are deleted. If zWhere==0, then code is generated
-** to delete all stat table entries.
+** the sqlite_statN tables associated with the named table are deleted.
+** If zWhere==0, then code is generated to delete all stat table entries.
 */
 static void openStatTable(
   Parse *pParse,          /* Parsing context */
@@ -80387,18 +83591,24 @@ static void openStatTable(
     const char *zCols;
   } aTable[] = {
     { "sqlite_stat1", "tbl,idx,stat" },
-#ifdef SQLITE_ENABLE_STAT3
+#if defined(SQLITE_ENABLE_STAT4)
+    { "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" },
+    { "sqlite_stat3", 0 },
+#elif defined(SQLITE_ENABLE_STAT3)
     { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
+    { "sqlite_stat4", 0 },
+#else
+    { "sqlite_stat3", 0 },
+    { "sqlite_stat4", 0 },
 #endif
   };
-
-  int aRoot[] = {0, 0};
-  u8 aCreateTbl[] = {0, 0};
-
   int i;
   sqlite3 *db = pParse->db;
   Db *pDb;
   Vdbe *v = sqlite3GetVdbe(pParse);
+  int aRoot[ArraySize(aTable)];
+  u8 aCreateTbl[ArraySize(aTable)];
+
   if( v==0 ) return;
   assert( sqlite3BtreeHoldsAllMutexes(db) );
   assert( sqlite3VdbeDb(v)==db );
@@ -80411,258 +83621,738 @@ static void openStatTable(
     const char *zTab = aTable[i].zName;
     Table *pStat;
     if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){
-      /* The sqlite_stat[12] table does not exist. Create it. Note that a 
-      ** side-effect of the CREATE TABLE statement is to leave the rootpage 
-      ** of the new table in register pParse->regRoot. This is important 
-      ** because the OpenWrite opcode below will be needing it. */
-      sqlite3NestedParse(pParse,
-          "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
-      );
-      aRoot[i] = pParse->regRoot;
-      aCreateTbl[i] = OPFLAG_P2ISREG;
+      if( aTable[i].zCols ){
+        /* The sqlite_statN table does not exist. Create it. Note that a 
+        ** side-effect of the CREATE TABLE statement is to leave the rootpage 
+        ** of the new table in register pParse->regRoot. This is important 
+        ** because the OpenWrite opcode below will be needing it. */
+        sqlite3NestedParse(pParse,
+            "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
+        );
+        aRoot[i] = pParse->regRoot;
+        aCreateTbl[i] = OPFLAG_P2ISREG;
+      }
     }else{
       /* The table already exists. If zWhere is not NULL, delete all entries 
       ** associated with the table zWhere. If zWhere is NULL, delete the
       ** entire contents of the table. */
       aRoot[i] = pStat->tnum;
+      aCreateTbl[i] = 0;
       sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
       if( zWhere ){
         sqlite3NestedParse(pParse,
-           "DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere
+           "DELETE FROM %Q.%s WHERE %s=%Q",
+           pDb->zName, zTab, zWhereType, zWhere
         );
       }else{
-        /* The sqlite_stat[12] table already exists.  Delete all rows. */
+        /* The sqlite_stat[134] table already exists.  Delete all rows. */
         sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
       }
     }
   }
 
-  /* Open the sqlite_stat[13] tables for writing. */
-  for(i=0; i<ArraySize(aTable); i++){
-    sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
-    sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32);
+  /* Open the sqlite_stat[134] tables for writing. */
+  for(i=0; aTable[i].zCols; i++){
+    assert( i<ArraySize(aTable) );
+    sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
     sqlite3VdbeChangeP5(v, aCreateTbl[i]);
+    VdbeComment((v, aTable[i].zName));
   }
 }
 
 /*
-** Recommended number of samples for sqlite_stat3
+** Recommended number of samples for sqlite_stat4
 */
-#ifndef SQLITE_STAT3_SAMPLES
-# define SQLITE_STAT3_SAMPLES 24
+#ifndef SQLITE_STAT4_SAMPLES
+# define SQLITE_STAT4_SAMPLES 24
 #endif
 
 /*
-** Three SQL functions - stat3_init(), stat3_push(), and stat3_pop() -
+** Three SQL functions - stat_init(), stat_push(), and stat_get() -
 ** share an instance of the following structure to hold their state
 ** information.
 */
-typedef struct Stat3Accum Stat3Accum;
-struct Stat3Accum {
+typedef struct Stat4Accum Stat4Accum;
+typedef struct Stat4Sample Stat4Sample;
+struct Stat4Sample {
+  tRowcnt *anEq;                  /* sqlite_stat4.nEq */
+  tRowcnt *anDLt;                 /* sqlite_stat4.nDLt */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  tRowcnt *anLt;                  /* sqlite_stat4.nLt */
+  union {
+    i64 iRowid;                     /* Rowid in main table of the key */
+    u8 *aRowid;                     /* Key for WITHOUT ROWID tables */
+  } u;
+  u32 nRowid;                     /* Sizeof aRowid[] */
+  u8 isPSample;                   /* True if a periodic sample */
+  int iCol;                       /* If !isPSample, the reason for inclusion */
+  u32 iHash;                      /* Tiebreaker hash */
+#endif
+};                                                    
+struct Stat4Accum {
   tRowcnt nRow;             /* Number of rows in the entire table */
   tRowcnt nPSample;         /* How often to do a periodic sample */
-  int iMin;                 /* Index of entry with minimum nEq and hash */
+  int nCol;                 /* Number of columns in index + pk/rowid */
+  int nKeyCol;              /* Number of index columns w/o the pk/rowid */
   int mxSample;             /* Maximum number of samples to accumulate */
-  int nSample;              /* Current number of samples */
+  Stat4Sample current;      /* Current row as a Stat4Sample */
   u32 iPrn;                 /* Pseudo-random number used for sampling */
-  struct Stat3Sample {
-    i64 iRowid;                /* Rowid in main table of the key */
-    tRowcnt nEq;               /* sqlite_stat3.nEq */
-    tRowcnt nLt;               /* sqlite_stat3.nLt */
-    tRowcnt nDLt;              /* sqlite_stat3.nDLt */
-    u8 isPSample;              /* True if a periodic sample */
-    u32 iHash;                 /* Tiebreaker hash */
-  } *a;                     /* An array of samples */
+  Stat4Sample *aBest;       /* Array of nCol best samples */
+  int iMin;                 /* Index in a[] of entry with minimum score */
+  int nSample;              /* Current number of samples */
+  int iGet;                 /* Index of current sample accessed by stat_get() */
+  Stat4Sample *a;           /* Array of mxSample Stat4Sample objects */
+  sqlite3 *db;              /* Database connection, for malloc() */
 };
 
-#ifdef SQLITE_ENABLE_STAT3
+/* Reclaim memory used by a Stat4Sample
+*/
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+static void sampleClear(sqlite3 *db, Stat4Sample *p){
+  assert( db!=0 );
+  if( p->nRowid ){
+    sqlite3DbFree(db, p->u.aRowid);
+    p->nRowid = 0;
+  }
+}
+#endif
+
+/* Initialize the BLOB value of a ROWID
+*/
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
+  assert( db!=0 );
+  if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
+  p->u.aRowid = sqlite3DbMallocRaw(db, n);
+  if( p->u.aRowid ){
+    p->nRowid = n;
+    memcpy(p->u.aRowid, pData, n);
+  }else{
+    p->nRowid = 0;
+  }
+}
+#endif
+
+/* Initialize the INTEGER value of a ROWID.
+*/
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
+  assert( db!=0 );
+  if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
+  p->nRowid = 0;
+  p->u.iRowid = iRowid;
+}
+#endif
+
+
 /*
-** Implementation of the stat3_init(C,S) SQL function.  The two parameters
-** are the number of rows in the table or index (C) and the number of samples
-** to accumulate (S).
+** Copy the contents of object (*pFrom) into (*pTo).
+*/
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
+  pTo->isPSample = pFrom->isPSample;
+  pTo->iCol = pFrom->iCol;
+  pTo->iHash = pFrom->iHash;
+  memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol);
+  memcpy(pTo->anLt, pFrom->anLt, sizeof(tRowcnt)*p->nCol);
+  memcpy(pTo->anDLt, pFrom->anDLt, sizeof(tRowcnt)*p->nCol);
+  if( pFrom->nRowid ){
+    sampleSetRowid(p->db, pTo, pFrom->nRowid, pFrom->u.aRowid);
+  }else{
+    sampleSetRowidInt64(p->db, pTo, pFrom->u.iRowid);
+  }
+}
+#endif
+
+/*
+** Reclaim all memory of a Stat4Accum structure.
+*/
+static void stat4Destructor(void *pOld){
+  Stat4Accum *p = (Stat4Accum*)pOld;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  int i;
+  for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
+  for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
+  sampleClear(p->db, &p->current);
+#endif
+  sqlite3DbFree(p->db, p);
+}
+
+/*
+** Implementation of the stat_init(N,K,C) SQL function. The three parameters
+** are:
+**     N:    The number of columns in the index including the rowid/pk (note 1)
+**     K:    The number of columns in the index excluding the rowid/pk.
+**     C:    The number of rows in the index (note 2)
+**
+** Note 1:  In the special case of the covering index that implements a
+** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
+** total number of columns in the table.
+**
+** Note 2:  C is only used for STAT3 and STAT4.
 **
-** This routine allocates the Stat3Accum object.
+** For indexes on ordinary rowid tables, N==K+1.  But for indexes on
+** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
+** PRIMARY KEY of the table.  The covering index that implements the
+** original WITHOUT ROWID table as N==K as a special case.
 **
-** The return value is the Stat3Accum object (P).
+** This routine allocates the Stat4Accum object in heap memory. The return 
+** value is a pointer to the the Stat4Accum object encoded as a blob (i.e. 
+** the size of the blob is sizeof(void*) bytes). 
 */
-static void stat3Init(
+static void statInit(
   sqlite3_context *context,
   int argc,
   sqlite3_value **argv
 ){
-  Stat3Accum *p;
-  tRowcnt nRow;
-  int mxSample;
-  int n;
+  Stat4Accum *p;
+  int nCol;                       /* Number of columns in index being sampled */
+  int nKeyCol;                    /* Number of key columns */
+  int nColUp;                     /* nCol rounded up for alignment */
+  int n;                          /* Bytes of space to allocate */
+  sqlite3 *db;                    /* Database connection */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  int mxSample = SQLITE_STAT4_SAMPLES;
+#endif
 
+  /* Decode the three function arguments */
   UNUSED_PARAMETER(argc);
-  nRow = (tRowcnt)sqlite3_value_int64(argv[0]);
-  mxSample = sqlite3_value_int(argv[1]);
-  n = sizeof(*p) + sizeof(p->a[0])*mxSample;
-  p = sqlite3MallocZero( n );
+  nCol = sqlite3_value_int(argv[0]);
+  assert( nCol>0 );
+  nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol;
+  nKeyCol = sqlite3_value_int(argv[1]);
+  assert( nKeyCol<=nCol );
+  assert( nKeyCol>0 );
+
+  /* Allocate the space required for the Stat4Accum object */
+  n = sizeof(*p) 
+    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anEq */
+    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anDLt */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anLt */
+    + sizeof(Stat4Sample)*(nCol+mxSample)     /* Stat4Accum.aBest[], a[] */
+    + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
+#endif
+  ;
+  db = sqlite3_context_db_handle(context);
+  p = sqlite3DbMallocZero(db, n);
   if( p==0 ){
     sqlite3_result_error_nomem(context);
     return;
   }
-  p->a = (struct Stat3Sample*)&p[1];
-  p->nRow = nRow;
-  p->mxSample = mxSample;
-  p->nPSample = p->nRow/(mxSample/3+1) + 1;
-  sqlite3_randomness(sizeof(p->iPrn), &p->iPrn);
-  sqlite3_result_blob(context, p, sizeof(p), sqlite3_free);
-}
-static const FuncDef stat3InitFuncdef = {
-  2,                /* nArg */
-  SQLITE_UTF8,      /* iPrefEnc */
-  0,                /* flags */
-  0,                /* pUserData */
-  0,                /* pNext */
-  stat3Init,        /* xFunc */
-  0,                /* xStep */
-  0,                /* xFinalize */
-  "stat3_init",     /* zName */
-  0,                /* pHash */
-  0                 /* pDestructor */
+
+  p->db = db;
+  p->nRow = 0;
+  p->nCol = nCol;
+  p->nKeyCol = nKeyCol;
+  p->current.anDLt = (tRowcnt*)&p[1];
+  p->current.anEq = &p->current.anDLt[nColUp];
+
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  {
+    u8 *pSpace;                     /* Allocated space not yet assigned */
+    int i;                          /* Used to iterate through p->aSample[] */
+
+    p->iGet = -1;
+    p->mxSample = mxSample;
+    p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
+    p->current.anLt = &p->current.anEq[nColUp];
+    p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565;
+  
+    /* Set up the Stat4Accum.a[] and aBest[] arrays */
+    p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
+    p->aBest = &p->a[mxSample];
+    pSpace = (u8*)(&p->a[mxSample+nCol]);
+    for(i=0; i<(mxSample+nCol); i++){
+      p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
+      p->a[i].anLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
+      p->a[i].anDLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
+    }
+    assert( (pSpace - (u8*)p)==n );
+  
+    for(i=0; i<nCol; i++){
+      p->aBest[i].iCol = i;
+    }
+  }
+#endif
+
+  /* Return a pointer to the allocated object to the caller */
+  sqlite3_result_blob(context, p, sizeof(p), stat4Destructor);
+}
+static const FuncDef statInitFuncdef = {
+  2+IsStat34,      /* nArg */
+  SQLITE_UTF8,     /* funcFlags */
+  0,               /* pUserData */
+  0,               /* pNext */
+  statInit,        /* xFunc */
+  0,               /* xStep */
+  0,               /* xFinalize */
+  "stat_init",     /* zName */
+  0,               /* pHash */
+  0                /* pDestructor */
 };
 
+#ifdef SQLITE_ENABLE_STAT4
+/*
+** pNew and pOld are both candidate non-periodic samples selected for 
+** the same column (pNew->iCol==pOld->iCol). Ignoring this column and 
+** considering only any trailing columns and the sample hash value, this
+** function returns true if sample pNew is to be preferred over pOld.
+** In other words, if we assume that the cardinalities of the selected
+** column for pNew and pOld are equal, is pNew to be preferred over pOld.
+**
+** This function assumes that for each argument sample, the contents of
+** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. 
+*/
+static int sampleIsBetterPost(
+  Stat4Accum *pAccum, 
+  Stat4Sample *pNew, 
+  Stat4Sample *pOld
+){
+  int nCol = pAccum->nCol;
+  int i;
+  assert( pNew->iCol==pOld->iCol );
+  for(i=pNew->iCol+1; i<nCol; i++){
+    if( pNew->anEq[i]>pOld->anEq[i] ) return 1;
+    if( pNew->anEq[i]<pOld->anEq[i] ) return 0;
+  }
+  if( pNew->iHash>pOld->iHash ) return 1;
+  return 0;
+}
+#endif
 
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
 /*
-** Implementation of the stat3_push(nEq,nLt,nDLt,rowid,P) SQL function.  The
-** arguments describe a single key instance.  This routine makes the 
-** decision about whether or not to retain this key for the sqlite_stat3
-** table.
+** Return true if pNew is to be preferred over pOld.
 **
-** The return value is NULL.
+** This function assumes that for each argument sample, the contents of
+** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. 
 */
-static void stat3Push(
+static int sampleIsBetter(
+  Stat4Accum *pAccum, 
+  Stat4Sample *pNew, 
+  Stat4Sample *pOld
+){
+  tRowcnt nEqNew = pNew->anEq[pNew->iCol];
+  tRowcnt nEqOld = pOld->anEq[pOld->iCol];
+
+  assert( pOld->isPSample==0 && pNew->isPSample==0 );
+  assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) );
+
+  if( (nEqNew>nEqOld) ) return 1;
+#ifdef SQLITE_ENABLE_STAT4
+  if( nEqNew==nEqOld ){
+    if( pNew->iCol<pOld->iCol ) return 1;
+    return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld));
+  }
+  return 0;
+#else
+  return (nEqNew==nEqOld && pNew->iHash>pOld->iHash);
+#endif
+}
+
+/*
+** Copy the contents of sample *pNew into the p->a[] array. If necessary,
+** remove the least desirable sample from p->a[] to make room.
+*/
+static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
+  Stat4Sample *pSample = 0;
+  int i;
+
+  assert( IsStat4 || nEqZero==0 );
+
+#ifdef SQLITE_ENABLE_STAT4
+  if( pNew->isPSample==0 ){
+    Stat4Sample *pUpgrade = 0;
+    assert( pNew->anEq[pNew->iCol]>0 );
+
+    /* This sample is being added because the prefix that ends in column 
+    ** iCol occurs many times in the table. However, if we have already
+    ** added a sample that shares this prefix, there is no need to add
+    ** this one. Instead, upgrade the priority of the highest priority
+    ** existing sample that shares this prefix.  */
+    for(i=p->nSample-1; i>=0; i--){
+      Stat4Sample *pOld = &p->a[i];
+      if( pOld->anEq[pNew->iCol]==0 ){
+        if( pOld->isPSample ) return;
+        assert( pOld->iCol>pNew->iCol );
+        assert( sampleIsBetter(p, pNew, pOld) );
+        if( pUpgrade==0 || sampleIsBetter(p, pOld, pUpgrade) ){
+          pUpgrade = pOld;
+        }
+      }
+    }
+    if( pUpgrade ){
+      pUpgrade->iCol = pNew->iCol;
+      pUpgrade->anEq[pUpgrade->iCol] = pNew->anEq[pUpgrade->iCol];
+      goto find_new_min;
+    }
+  }
+#endif
+
+  /* If necessary, remove sample iMin to make room for the new sample. */
+  if( p->nSample>=p->mxSample ){
+    Stat4Sample *pMin = &p->a[p->iMin];
+    tRowcnt *anEq = pMin->anEq;
+    tRowcnt *anLt = pMin->anLt;
+    tRowcnt *anDLt = pMin->anDLt;
+    sampleClear(p->db, pMin);
+    memmove(pMin, &pMin[1], sizeof(p->a[0])*(p->nSample-p->iMin-1));
+    pSample = &p->a[p->nSample-1];
+    pSample->nRowid = 0;
+    pSample->anEq = anEq;
+    pSample->anDLt = anDLt;
+    pSample->anLt = anLt;
+    p->nSample = p->mxSample-1;
+  }
+
+  /* The "rows less-than" for the rowid column must be greater than that
+  ** for the last sample in the p->a[] array. Otherwise, the samples would
+  ** be out of order. */
+#ifdef SQLITE_ENABLE_STAT4
+  assert( p->nSample==0 
+       || pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] );
+#endif
+
+  /* Insert the new sample */
+  pSample = &p->a[p->nSample];
+  sampleCopy(p, pSample, pNew);
+  p->nSample++;
+
+  /* Zero the first nEqZero entries in the anEq[] array. */
+  memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero);
+
+#ifdef SQLITE_ENABLE_STAT4
+ find_new_min:
+#endif
+  if( p->nSample>=p->mxSample ){
+    int iMin = -1;
+    for(i=0; i<p->mxSample; i++){
+      if( p->a[i].isPSample ) continue;
+      if( iMin<0 || sampleIsBetter(p, &p->a[iMin], &p->a[i]) ){
+        iMin = i;
+      }
+    }
+    assert( iMin>=0 );
+    p->iMin = iMin;
+  }
+}
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
+
+/*
+** Field iChng of the index being scanned has changed. So at this point
+** p->current contains a sample that reflects the previous row of the
+** index. The value of anEq[iChng] and subsequent anEq[] elements are
+** correct at this point.
+*/
+static void samplePushPrevious(Stat4Accum *p, int iChng){
+#ifdef SQLITE_ENABLE_STAT4
+  int i;
+
+  /* Check if any samples from the aBest[] array should be pushed
+  ** into IndexSample.a[] at this point.  */
+  for(i=(p->nCol-2); i>=iChng; i--){
+    Stat4Sample *pBest = &p->aBest[i];
+    pBest->anEq[i] = p->current.anEq[i];
+    if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){
+      sampleInsert(p, pBest, i);
+    }
+  }
+
+  /* Update the anEq[] fields of any samples already collected. */
+  for(i=p->nSample-1; i>=0; i--){
+    int j;
+    for(j=iChng; j<p->nCol; j++){
+      if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
+    }
+  }
+#endif
+
+#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
+  if( iChng==0 ){
+    tRowcnt nLt = p->current.anLt[0];
+    tRowcnt nEq = p->current.anEq[0];
+
+    /* Check if this is to be a periodic sample. If so, add it. */
+    if( (nLt/p->nPSample)!=(nLt+nEq)/p->nPSample ){
+      p->current.isPSample = 1;
+      sampleInsert(p, &p->current, 0);
+      p->current.isPSample = 0;
+    }else 
+
+    /* Or if it is a non-periodic sample. Add it in this case too. */
+    if( p->nSample<p->mxSample 
+     || sampleIsBetter(p, &p->current, &p->a[p->iMin]) 
+    ){
+      sampleInsert(p, &p->current, 0);
+    }
+  }
+#endif
+
+#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
+  UNUSED_PARAMETER( p );
+  UNUSED_PARAMETER( iChng );
+#endif
+}
+
+/*
+** Implementation of the stat_push SQL function:  stat_push(P,C,R)
+** Arguments:
+**
+**    P     Pointer to the Stat4Accum object created by stat_init()
+**    C     Index of left-most column to differ from previous row
+**    R     Rowid for the current row.  Might be a key record for
+**          WITHOUT ROWID tables.
+**
+** This SQL function always returns NULL.  It's purpose it to accumulate
+** statistical data and/or samples in the Stat4Accum object about the
+** index being analyzed.  The stat_get() SQL function will later be used to
+** extract relevant information for constructing the sqlite_statN tables.
+**
+** The R parameter is only used for STAT3 and STAT4
+*/
+static void statPush(
   sqlite3_context *context,
   int argc,
   sqlite3_value **argv
 ){
-  Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[4]);
-  tRowcnt nEq = sqlite3_value_int64(argv[0]);
-  tRowcnt nLt = sqlite3_value_int64(argv[1]);
-  tRowcnt nDLt = sqlite3_value_int64(argv[2]);
-  i64 rowid = sqlite3_value_int64(argv[3]);
-  u8 isPSample = 0;
-  u8 doInsert = 0;
-  int iMin = p->iMin;
-  struct Stat3Sample *pSample;
   int i;
-  u32 h;
 
-  UNUSED_PARAMETER(context);
-  UNUSED_PARAMETER(argc);
-  if( nEq==0 ) return;
-  h = p->iPrn = p->iPrn*1103515245 + 12345;
-  if( (nLt/p->nPSample)!=((nEq+nLt)/p->nPSample) ){
-    doInsert = isPSample = 1;
-  }else if( p->nSample<p->mxSample ){
-    doInsert = 1;
+  /* The three function arguments */
+  Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
+  int iChng = sqlite3_value_int(argv[1]);
+
+  UNUSED_PARAMETER( argc );
+  UNUSED_PARAMETER( context );
+  assert( p->nCol>0 );
+  assert( iChng<p->nCol );
+
+  if( p->nRow==0 ){
+    /* This is the first call to this function. Do initialization. */
+    for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
   }else{
-    if( nEq>p->a[iMin].nEq || (nEq==p->a[iMin].nEq && h>p->a[iMin].iHash) ){
-      doInsert = 1;
+    /* Second and subsequent calls get processed here */
+    samplePushPrevious(p, iChng);
+
+    /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
+    ** to the current row of the index. */
+    for(i=0; i<iChng; i++){
+      p->current.anEq[i]++;
+    }
+    for(i=iChng; i<p->nCol; i++){
+      p->current.anDLt[i]++;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+      p->current.anLt[i] += p->current.anEq[i];
+#endif
+      p->current.anEq[i] = 1;
     }
   }
-  if( !doInsert ) return;
-  if( p->nSample==p->mxSample ){
-    assert( p->nSample - iMin - 1 >= 0 );
-    memmove(&p->a[iMin], &p->a[iMin+1], sizeof(p->a[0])*(p->nSample-iMin-1));
-    pSample = &p->a[p->nSample-1];
+  p->nRow++;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
+    sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
   }else{
-    pSample = &p->a[p->nSample++];
+    sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
+                                       sqlite3_value_blob(argv[2]));
   }
-  pSample->iRowid = rowid;
-  pSample->nEq = nEq;
-  pSample->nLt = nLt;
-  pSample->nDLt = nDLt;
-  pSample->iHash = h;
-  pSample->isPSample = isPSample;
+  p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
+#endif
 
-  /* Find the new minimum */
-  if( p->nSample==p->mxSample ){
-    pSample = p->a;
-    i = 0;
-    while( pSample->isPSample ){
-      i++;
-      pSample++;
-      assert( i<p->nSample );
-    }
-    nEq = pSample->nEq;
-    h = pSample->iHash;
-    iMin = i;
-    for(i++, pSample++; i<p->nSample; i++, pSample++){
-      if( pSample->isPSample ) continue;
-      if( pSample->nEq<nEq
-       || (pSample->nEq==nEq && pSample->iHash<h)
-      ){
-        iMin = i;
-        nEq = pSample->nEq;
-        h = pSample->iHash;
+#ifdef SQLITE_ENABLE_STAT4
+  {
+    tRowcnt nLt = p->current.anLt[p->nCol-1];
+
+    /* Check if this is to be a periodic sample. If so, add it. */
+    if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){
+      p->current.isPSample = 1;
+      p->current.iCol = 0;
+      sampleInsert(p, &p->current, p->nCol-1);
+      p->current.isPSample = 0;
+    }
+
+    /* Update the aBest[] array. */
+    for(i=0; i<(p->nCol-1); i++){
+      p->current.iCol = i;
+      if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){
+        sampleCopy(p, &p->aBest[i], &p->current);
       }
     }
-    p->iMin = iMin;
   }
+#endif
 }
-static const FuncDef stat3PushFuncdef = {
-  5,                /* nArg */
-  SQLITE_UTF8,      /* iPrefEnc */
-  0,                /* flags */
-  0,                /* pUserData */
-  0,                /* pNext */
-  stat3Push,        /* xFunc */
-  0,                /* xStep */
-  0,                /* xFinalize */
-  "stat3_push",     /* zName */
-  0,                /* pHash */
-  0                 /* pDestructor */
+static const FuncDef statPushFuncdef = {
+  2+IsStat34,      /* nArg */
+  SQLITE_UTF8,     /* funcFlags */
+  0,               /* pUserData */
+  0,               /* pNext */
+  statPush,        /* xFunc */
+  0,               /* xStep */
+  0,               /* xFinalize */
+  "stat_push",     /* zName */
+  0,               /* pHash */
+  0                /* pDestructor */
 };
 
+#define STAT_GET_STAT1 0          /* "stat" column of stat1 table */
+#define STAT_GET_ROWID 1          /* "rowid" column of stat[34] entry */
+#define STAT_GET_NEQ   2          /* "neq" column of stat[34] entry */
+#define STAT_GET_NLT   3          /* "nlt" column of stat[34] entry */
+#define STAT_GET_NDLT  4          /* "ndlt" column of stat[34] entry */
+
 /*
-** Implementation of the stat3_get(P,N,...) SQL function.  This routine is
-** used to query the results.  Content is returned for the Nth sqlite_stat3
-** row where N is between 0 and S-1 and S is the number of samples.  The
-** value returned depends on the number of arguments.
+** Implementation of the stat_get(P,J) SQL function.  This routine is
+** used to query statistical information that has been gathered into
+** the Stat4Accum object by prior calls to stat_push().  The P parameter
+** is a BLOB which is decoded into a pointer to the Stat4Accum objects.
+** The content to returned is determined by the parameter J
+** which is one of the STAT_GET_xxxx values defined above.
 **
-**   argc==2    result:  rowid
-**   argc==3    result:  nEq
-**   argc==4    result:  nLt
-**   argc==5    result:  nDLt
+** If neither STAT3 nor STAT4 are enabled, then J is always
+** STAT_GET_STAT1 and is hence omitted and this routine becomes
+** a one-parameter function, stat_get(P), that always returns the
+** stat1 table entry information.
 */
-static void stat3Get(
+static void statGet(
   sqlite3_context *context,
   int argc,
   sqlite3_value **argv
 ){
-  int n = sqlite3_value_int(argv[1]);
-  Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[0]);
+  Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  /* STAT3 and STAT4 have a parameter on this routine. */
+  int eCall = sqlite3_value_int(argv[1]);
+  assert( argc==2 );
+  assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ 
+       || eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT
+       || eCall==STAT_GET_NDLT 
+  );
+  if( eCall==STAT_GET_STAT1 )
+#else
+  assert( argc==1 );
+#endif
+  {
+    /* Return the value to store in the "stat" column of the sqlite_stat1
+    ** table for this index.
+    **
+    ** The value is a string composed of a list of integers describing 
+    ** the index. The first integer in the list is the total number of 
+    ** entries in the index. There is one additional integer in the list 
+    ** for each indexed column. This additional integer is an estimate of
+    ** the number of rows matched by a stabbing query on the index using
+    ** a key with the corresponding number of fields. In other words,
+    ** if the index is on columns (a,b) and the sqlite_stat1 value is 
+    ** "100 10 2", then SQLite estimates that:
+    **
+    **   * the index contains 100 rows,
+    **   * "WHERE a=?" matches 10 rows, and
+    **   * "WHERE a=? AND b=?" matches 2 rows.
+    **
+    ** If D is the count of distinct values and K is the total number of 
+    ** rows, then each estimate is computed as:
+    **
+    **        I = (K+D-1)/D
+    */
+    char *z;
+    int i;
 
-  assert( p!=0 );
-  if( p->nSample<=n ) return;
-  switch( argc ){
-    case 2:  sqlite3_result_int64(context, p->a[n].iRowid); break;
-    case 3:  sqlite3_result_int64(context, p->a[n].nEq);    break;
-    case 4:  sqlite3_result_int64(context, p->a[n].nLt);    break;
-    default: sqlite3_result_int64(context, p->a[n].nDLt);   break;
-  }
-}
-static const FuncDef stat3GetFuncdef = {
-  -1,               /* nArg */
-  SQLITE_UTF8,      /* iPrefEnc */
-  0,                /* flags */
-  0,                /* pUserData */
-  0,                /* pNext */
-  stat3Get,         /* xFunc */
-  0,                /* xStep */
-  0,                /* xFinalize */
-  "stat3_get",     /* zName */
-  0,                /* pHash */
-  0                 /* pDestructor */
-};
-#endif /* SQLITE_ENABLE_STAT3 */
+    char *zRet = sqlite3MallocZero( (p->nKeyCol+1)*25 );
+    if( zRet==0 ){
+      sqlite3_result_error_nomem(context);
+      return;
+    }
+
+    sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
+    z = zRet + sqlite3Strlen30(zRet);
+    for(i=0; i<p->nKeyCol; i++){
+      u64 nDistinct = p->current.anDLt[i] + 1;
+      u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
+      sqlite3_snprintf(24, z, " %llu", iVal);
+      z += sqlite3Strlen30(z);
+      assert( p->current.anEq[i] );
+    }
+    assert( z[0]=='\0' && z>zRet );
 
+    sqlite3_result_text(context, zRet, -1, sqlite3_free);
+  }
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  else if( eCall==STAT_GET_ROWID ){
+    if( p->iGet<0 ){
+      samplePushPrevious(p, 0);
+      p->iGet = 0;
+    }
+    if( p->iGet<p->nSample ){
+      Stat4Sample *pS = p->a + p->iGet;
+      if( pS->nRowid==0 ){
+        sqlite3_result_int64(context, pS->u.iRowid);
+      }else{
+        sqlite3_result_blob(context, pS->u.aRowid, pS->nRowid,
+                            SQLITE_TRANSIENT);
+      }
+    }
+  }else{
+    tRowcnt *aCnt = 0;
+
+    assert( p->iGet<p->nSample );
+    switch( eCall ){
+      case STAT_GET_NEQ:  aCnt = p->a[p->iGet].anEq; break;
+      case STAT_GET_NLT:  aCnt = p->a[p->iGet].anLt; break;
+      default: {
+        aCnt = p->a[p->iGet].anDLt; 
+        p->iGet++;
+        break;
+      }
+    }
 
+    if( IsStat3 ){
+      sqlite3_result_int64(context, (i64)aCnt[0]);
+    }else{
+      char *zRet = sqlite3MallocZero(p->nCol * 25);
+      if( zRet==0 ){
+        sqlite3_result_error_nomem(context);
+      }else{
+        int i;
+        char *z = zRet;
+        for(i=0; i<p->nCol; i++){
+          sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
+          z += sqlite3Strlen30(z);
+        }
+        assert( z[0]=='\0' && z>zRet );
+        z[-1] = '\0';
+        sqlite3_result_text(context, zRet, -1, sqlite3_free);
+      }
+    }
+  }
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
+#ifndef SQLITE_DEBUG
+  UNUSED_PARAMETER( argc );
+#endif
+}
+static const FuncDef statGetFuncdef = {
+  1+IsStat34,      /* nArg */
+  SQLITE_UTF8,     /* funcFlags */
+  0,               /* pUserData */
+  0,               /* pNext */
+  statGet,         /* xFunc */
+  0,               /* xStep */
+  0,               /* xFinalize */
+  "stat_get",      /* zName */
+  0,               /* pHash */
+  0                /* pDestructor */
+};
 
+static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
+  assert( regOut!=regStat4 && regOut!=regStat4+1 );
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
+#elif SQLITE_DEBUG
+  assert( iParam==STAT_GET_STAT1 );
+#else
+  UNUSED_PARAMETER( iParam );
+#endif
+  sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut);
+  sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF);
+  sqlite3VdbeChangeP5(v, 1 + IsStat34);
+}
 
 /*
 ** Generate code to do an analysis of all indices associated with
@@ -80673,41 +84363,31 @@ static void analyzeOneTable(
   Table *pTab,     /* Table whose indices are to be analyzed */
   Index *pOnlyIdx, /* If not NULL, only analyze this one index */
   int iStatCur,    /* Index of VdbeCursor that writes the sqlite_stat1 table */
-  int iMem         /* Available memory locations begin here */
+  int iMem,        /* Available memory locations begin here */
+  int iTab         /* Next available cursor */
 ){
   sqlite3 *db = pParse->db;    /* Database handle */
   Index *pIdx;                 /* An index to being analyzed */
   int iIdxCur;                 /* Cursor open on index being analyzed */
+  int iTabCur;                 /* Table cursor */
   Vdbe *v;                     /* The virtual machine being built up */
   int i;                       /* Loop counter */
-  int topOfLoop;               /* The top of the loop */
-  int endOfLoop;               /* The end of the loop */
   int jZeroRows = -1;          /* Jump from here if number of rows is zero */
   int iDb;                     /* Index of database containing pTab */
+  u8 needTableCnt = 1;         /* True to count the table */
+  int regNewRowid = iMem++;    /* Rowid for the inserted record */
+  int regStat4 = iMem++;       /* Register to hold Stat4Accum object */
+  int regChng = iMem++;        /* Index of changed index field */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  int regRowid = iMem++;       /* Rowid argument passed to stat_push() */
+#endif
+  int regTemp = iMem++;        /* Temporary use register */
   int regTabname = iMem++;     /* Register containing table name */
   int regIdxname = iMem++;     /* Register containing index name */
-  int regStat1 = iMem++;       /* The stat column of sqlite_stat1 */
-#ifdef SQLITE_ENABLE_STAT3
-  int regNumEq = regStat1;     /* Number of instances.  Same as regStat1 */
-  int regNumLt = iMem++;       /* Number of keys less than regSample */
-  int regNumDLt = iMem++;      /* Number of distinct keys less than regSample */
-  int regSample = iMem++;      /* The next sample value */
-  int regRowid = regSample;    /* Rowid of a sample */
-  int regAccum = iMem++;       /* Register to hold Stat3Accum object */
-  int regLoop = iMem++;        /* Loop counter */
-  int regCount = iMem++;       /* Number of rows in the table or index */
-  int regTemp1 = iMem++;       /* Intermediate register */
-  int regTemp2 = iMem++;       /* Intermediate register */
-  int once = 1;                /* One-time initialization */
-  int shortJump = 0;           /* Instruction address */
-  int iTabCur = pParse->nTab++; /* Table cursor */
-#endif
-  int regCol = iMem++;         /* Content of a column in analyzed table */
-  int regRec = iMem++;         /* Register holding completed record */
-  int regTemp = iMem++;        /* Temporary use register */
-  int regNewRowid = iMem++;    /* Rowid for the inserted record */
-
+  int regStat1 = iMem++;       /* Value for the stat column of sqlite_stat1 */
+  int regPrev = iMem;          /* MUST BE LAST (see below) */
 
+  pParse->nMem = MAX(pParse->nMem, iMem);
   v = sqlite3GetVdbe(pParse);
   if( v==0 || NEVER(pTab==0) ){
     return;
@@ -80731,215 +84411,271 @@ static void analyzeOneTable(
   }
 #endif
 
-  /* Establish a read-lock on the table at the shared-cache level. */
+  /* Establish a read-lock on the table at the shared-cache level. 
+  ** Open a read-only cursor on the table. Also allocate a cursor number
+  ** to use for scanning indexes (iIdxCur). No index cursor is opened at
+  ** this time though.  */
   sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
-
-  iIdxCur = pParse->nTab++;
+  iTabCur = iTab++;
+  iIdxCur = iTab++;
+  pParse->nTab = MAX(pParse->nTab, iTab);
+  sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
   sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
+
   for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
-    int nCol;
-    KeyInfo *pKey;
-    int addrIfNot = 0;           /* address of OP_IfNot */
-    int *aChngAddr;              /* Array of jump instruction addresses */
+    int nCol;                     /* Number of columns in pIdx. "N" */
+    int addrRewind;               /* Address of "OP_Rewind iIdxCur" */
+    int addrNextRow;              /* Address of "next_row:" */
+    const char *zIdxName;         /* Name of the index */
+    int nColTest;                 /* Number of columns to test for changes */
 
     if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
-    VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
-    nCol = pIdx->nColumn;
-    aChngAddr = sqlite3DbMallocRaw(db, sizeof(int)*nCol);
-    if( aChngAddr==0 ) continue;
-    pKey = sqlite3IndexKeyinfo(pParse, pIdx);
-    if( iMem+1+(nCol*2)>pParse->nMem ){
-      pParse->nMem = iMem+1+(nCol*2);
+    if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
+    if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){
+      nCol = pIdx->nKeyCol;
+      zIdxName = pTab->zName;
+      nColTest = nCol - 1;
+    }else{
+      nCol = pIdx->nColumn;
+      zIdxName = pIdx->zName;
+      nColTest = pIdx->uniqNotNull ? pIdx->nKeyCol-1 : nCol-1;
     }
 
-    /* Open a cursor to the index to be analyzed. */
-    assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
-    sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb,
-        (char *)pKey, P4_KEYINFO_HANDOFF);
-    VdbeComment((v, "%s", pIdx->zName));
-
     /* Populate the register containing the index name. */
-    sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0);
+    sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, zIdxName, 0);
+    VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName));
 
-#ifdef SQLITE_ENABLE_STAT3
-    if( once ){
-      once = 0;
-      sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
-    }
-    sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regCount);
-    sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_STAT3_SAMPLES, regTemp1);
-    sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumEq);
-    sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumLt);
-    sqlite3VdbeAddOp2(v, OP_Integer, -1, regNumDLt);
-    sqlite3VdbeAddOp3(v, OP_Null, 0, regSample, regAccum);
-    sqlite3VdbeAddOp4(v, OP_Function, 1, regCount, regAccum,
-                      (char*)&stat3InitFuncdef, P4_FUNCDEF);
-    sqlite3VdbeChangeP5(v, 2);
-#endif /* SQLITE_ENABLE_STAT3 */
-
-    /* The block of memory cells initialized here is used as follows.
+    /*
+    ** Pseudo-code for loop that calls stat_push():
+    **
+    **   Rewind csr
+    **   if eof(csr) goto end_of_scan;
+    **   regChng = 0
+    **   goto chng_addr_0;
     **
-    **    iMem:                
-    **        The total number of rows in the table.
+    **  next_row:
+    **   regChng = 0
+    **   if( idx(0) != regPrev(0) ) goto chng_addr_0
+    **   regChng = 1
+    **   if( idx(1) != regPrev(1) ) goto chng_addr_1
+    **   ...
+    **   regChng = N
+    **   goto chng_addr_N
     **
-    **    iMem+1 .. iMem+nCol: 
-    **        Number of distinct entries in index considering the 
-    **        left-most N columns only, where N is between 1 and nCol, 
-    **        inclusive.
+    **  chng_addr_0:
+    **   regPrev(0) = idx(0)
+    **  chng_addr_1:
+    **   regPrev(1) = idx(1)
+    **  ...
     **
-    **    iMem+nCol+1 .. Mem+2*nCol:  
-    **        Previous value of indexed columns, from left to right.
+    **  endDistinctTest:
+    **   regRowid = idx(rowid)
+    **   stat_push(P, regChng, regRowid)
+    **   Next csr
+    **   if !eof(csr) goto next_row;
     **
-    ** Cells iMem through iMem+nCol are initialized to 0. The others are 
-    ** initialized to contain an SQL NULL.
+    **  end_of_scan:
     */
-    for(i=0; i<=nCol; i++){
-      sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem+i);
-    }
-    for(i=0; i<nCol; i++){
-      sqlite3VdbeAddOp2(v, OP_Null, 0, iMem+nCol+i+1);
-    }
 
-    /* Start the analysis loop. This loop runs through all the entries in
-    ** the index b-tree.  */
-    endOfLoop = sqlite3VdbeMakeLabel(v);
-    sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop);
-    topOfLoop = sqlite3VdbeCurrentAddr(v);
-    sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1);  /* Increment row counter */
+    /* Make sure there are enough memory cells allocated to accommodate 
+    ** the regPrev array and a trailing rowid (the rowid slot is required
+    ** when building a record to insert into the sample column of 
+    ** the sqlite_stat4 table.  */
+    pParse->nMem = MAX(pParse->nMem, regPrev+nColTest);
 
-    for(i=0; i<nCol; i++){
-      CollSeq *pColl;
-      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol);
-      if( i==0 ){
-        /* Always record the very first row */
-        addrIfNot = sqlite3VdbeAddOp1(v, OP_IfNot, iMem+1);
-      }
-      assert( pIdx->azColl!=0 );
-      assert( pIdx->azColl[i]!=0 );
-      pColl = sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
-      aChngAddr[i] = sqlite3VdbeAddOp4(v, OP_Ne, regCol, 0, iMem+nCol+i+1,
-                                      (char*)pColl, P4_COLLSEQ);
-      sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
-      VdbeComment((v, "jump if column %d changed", i));
-#ifdef SQLITE_ENABLE_STAT3
-      if( i==0 ){
-        sqlite3VdbeAddOp2(v, OP_AddImm, regNumEq, 1);
-        VdbeComment((v, "incr repeat count"));
-      }
-#endif
-    }
-    sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop);
-    for(i=0; i<nCol; i++){
-      sqlite3VdbeJumpHere(v, aChngAddr[i]);  /* Set jump dest for the OP_Ne */
-      if( i==0 ){
-        sqlite3VdbeJumpHere(v, addrIfNot);   /* Jump dest for OP_IfNot */
-#ifdef SQLITE_ENABLE_STAT3
-        sqlite3VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2,
-                          (char*)&stat3PushFuncdef, P4_FUNCDEF);
-        sqlite3VdbeChangeP5(v, 5);
-        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, pIdx->nColumn, regRowid);
-        sqlite3VdbeAddOp3(v, OP_Add, regNumEq, regNumLt, regNumLt);
-        sqlite3VdbeAddOp2(v, OP_AddImm, regNumDLt, 1);
-        sqlite3VdbeAddOp2(v, OP_Integer, 1, regNumEq);
-#endif        
-      }
-      sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
-      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
-    }
-    sqlite3DbFree(db, aChngAddr);
-
-    /* Always jump here after updating the iMem+1...iMem+1+nCol counters */
-    sqlite3VdbeResolveLabel(v, endOfLoop);
+    /* Open a read-only cursor on the index being analyzed. */
+    assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
+    sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb);
+    sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
+    VdbeComment((v, "%s", pIdx->zName));
 
-    sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
-    sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
-#ifdef SQLITE_ENABLE_STAT3
-    sqlite3VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2,
-                      (char*)&stat3PushFuncdef, P4_FUNCDEF);
-    sqlite3VdbeChangeP5(v, 5);
-    sqlite3VdbeAddOp2(v, OP_Integer, -1, regLoop);
-    shortJump = 
-    sqlite3VdbeAddOp2(v, OP_AddImm, regLoop, 1);
-    sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regTemp1,
-                      (char*)&stat3GetFuncdef, P4_FUNCDEF);
-    sqlite3VdbeChangeP5(v, 2);
-    sqlite3VdbeAddOp1(v, OP_IsNull, regTemp1);
-    sqlite3VdbeAddOp3(v, OP_NotExists, iTabCur, shortJump, regTemp1);
-    sqlite3VdbeAddOp3(v, OP_Column, iTabCur, pIdx->aiColumn[0], regSample);
-    sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[0], regSample);
-    sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumEq,
-                      (char*)&stat3GetFuncdef, P4_FUNCDEF);
-    sqlite3VdbeChangeP5(v, 3);
-    sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumLt,
-                      (char*)&stat3GetFuncdef, P4_FUNCDEF);
-    sqlite3VdbeChangeP5(v, 4);
-    sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumDLt,
-                      (char*)&stat3GetFuncdef, P4_FUNCDEF);
-    sqlite3VdbeChangeP5(v, 5);
-    sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regRec, "bbbbbb", 0);
-    sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
-    sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regNewRowid);
-    sqlite3VdbeAddOp2(v, OP_Goto, 0, shortJump);
-    sqlite3VdbeJumpHere(v, shortJump+2);
-#endif        
-
-    /* Store the results in sqlite_stat1.
+    /* Invoke the stat_init() function. The arguments are:
+    ** 
+    **    (1) the number of columns in the index including the rowid
+    **        (or for a WITHOUT ROWID table, the number of PK columns),
+    **    (2) the number of columns in the key without the rowid/pk
+    **    (3) the number of rows in the index,
     **
-    ** The result is a single row of the sqlite_stat1 table.  The first
-    ** two columns are the names of the table and index.  The third column
-    ** is a string composed of a list of integer statistics about the
-    ** index.  The first integer in the list is the total number of entries
-    ** in the index.  There is one additional integer in the list for each
-    ** column of the table.  This additional integer is a guess of how many
-    ** rows of the table the index will select.  If D is the count of distinct
-    ** values and K is the total number of rows, then the integer is computed
-    ** as:
     **
-    **        I = (K+D-1)/D
+    ** The third argument is only used for STAT3 and STAT4
+    */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+    sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
+#endif
+    sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
+    sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
+    sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4+1, regStat4);
+    sqlite3VdbeChangeP4(v, -1, (char*)&statInitFuncdef, P4_FUNCDEF);
+    sqlite3VdbeChangeP5(v, 2+IsStat34);
+
+    /* Implementation of the following:
+    **
+    **   Rewind csr
+    **   if eof(csr) goto end_of_scan;
+    **   regChng = 0
+    **   goto next_push_0;
     **
-    ** If K==0 then no entry is made into the sqlite_stat1 table.  
-    ** If K>0 then it is always the case the D>0 so division by zero
-    ** is never possible.
     */
-    sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regStat1);
-    if( jZeroRows<0 ){
-      jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem);
+    addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
+    VdbeCoverage(v);
+    sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
+    addrNextRow = sqlite3VdbeCurrentAddr(v);
+
+    if( nColTest>0 ){
+      int endDistinctTest = sqlite3VdbeMakeLabel(v);
+      int *aGotoChng;               /* Array of jump instruction addresses */
+      aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest);
+      if( aGotoChng==0 ) continue;
+
+      /*
+      **  next_row:
+      **   regChng = 0
+      **   if( idx(0) != regPrev(0) ) goto chng_addr_0
+      **   regChng = 1
+      **   if( idx(1) != regPrev(1) ) goto chng_addr_1
+      **   ...
+      **   regChng = N
+      **   goto endDistinctTest
+      */
+      sqlite3VdbeAddOp0(v, OP_Goto);
+      addrNextRow = sqlite3VdbeCurrentAddr(v);
+      if( nColTest==1 && pIdx->nKeyCol==1 && IsUniqueIndex(pIdx) ){
+        /* For a single-column UNIQUE index, once we have found a non-NULL
+        ** row, we know that all the rest will be distinct, so skip 
+        ** subsequent distinctness tests. */
+        sqlite3VdbeAddOp2(v, OP_NotNull, regPrev, endDistinctTest);
+        VdbeCoverage(v);
+      }
+      for(i=0; i<nColTest; i++){
+        char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
+        sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
+        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
+        aGotoChng[i] = 
+        sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
+        sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+        VdbeCoverage(v);
+      }
+      sqlite3VdbeAddOp2(v, OP_Integer, nColTest, regChng);
+      sqlite3VdbeAddOp2(v, OP_Goto, 0, endDistinctTest);
+  
+  
+      /*
+      **  chng_addr_0:
+      **   regPrev(0) = idx(0)
+      **  chng_addr_1:
+      **   regPrev(1) = idx(1)
+      **  ...
+      */
+      sqlite3VdbeJumpHere(v, addrNextRow-1);
+      for(i=0; i<nColTest; i++){
+        sqlite3VdbeJumpHere(v, aGotoChng[i]);
+        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
+      }
+      sqlite3VdbeResolveLabel(v, endDistinctTest);
+      sqlite3DbFree(db, aGotoChng);
     }
-    for(i=0; i<nCol; i++){
-      sqlite3VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0);
-      sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
-      sqlite3VdbeAddOp3(v, OP_Add, iMem, iMem+i+1, regTemp);
-      sqlite3VdbeAddOp2(v, OP_AddImm, regTemp, -1);
-      sqlite3VdbeAddOp3(v, OP_Divide, iMem+i+1, regTemp, regTemp);
-      sqlite3VdbeAddOp1(v, OP_ToInt, regTemp);
-      sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
-    }
-    sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
+  
+    /*
+    **  chng_addr_N:
+    **   regRowid = idx(rowid)            // STAT34 only
+    **   stat_push(P, regChng, regRowid)  // 3rd parameter STAT34 only
+    **   Next csr
+    **   if !eof(csr) goto next_row;
+    */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+    assert( regRowid==(regStat4+2) );
+    if( HasRowid(pTab) ){
+      sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
+    }else{
+      Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
+      int j, k, regKey;
+      regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
+      for(j=0; j<pPk->nKeyCol; j++){
+        k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
+        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
+        VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
+      }
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
+      sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
+    }
+#endif
+    assert( regChng==(regStat4+1) );
+    sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regTemp);
+    sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF);
+    sqlite3VdbeChangeP5(v, 2+IsStat34);
+    sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
+
+    /* Add the entry to the stat1 table. */
+    callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
+    sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
     sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
-    sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
+    sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
     sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+
+    /* Add the entries to the stat3 or stat4 table. */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+    {
+      int regEq = regStat1;
+      int regLt = regStat1+1;
+      int regDLt = regStat1+2;
+      int regSample = regStat1+3;
+      int regCol = regStat1+4;
+      int regSampleRowid = regCol + nCol;
+      int addrNext;
+      int addrIsNull;
+      u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
+
+      pParse->nMem = MAX(pParse->nMem, regCol+nCol);
+
+      addrNext = sqlite3VdbeCurrentAddr(v);
+      callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
+      addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
+      VdbeCoverage(v);
+      callStatGet(v, regStat4, STAT_GET_NEQ, regEq);
+      callStatGet(v, regStat4, STAT_GET_NLT, regLt);
+      callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
+      sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
+      /* We know that the regSampleRowid row exists because it was read by
+      ** the previous loop.  Thus the not-found jump of seekOp will never
+      ** be taken */
+      VdbeCoverageNeverTaken(v);
+#ifdef SQLITE_ENABLE_STAT3
+      sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, 
+                                      pIdx->aiColumn[0], regSample);
+#else
+      for(i=0; i<nCol; i++){
+        i16 iCol = pIdx->aiColumn[i];
+        sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regCol+i);
+      }
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol, regSample);
+#endif
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp);
+      sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
+      sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid);
+      sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */
+      sqlite3VdbeJumpHere(v, addrIsNull);
+    }
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
+
+    /* End of analysis */
+    sqlite3VdbeJumpHere(v, addrRewind);
   }
 
-  /* If the table has no indices, create a single sqlite_stat1 entry
-  ** containing NULL as the index name and the row count as the content.
+
+  /* Create a single sqlite_stat1 entry containing NULL as the index
+  ** name and the row count as the content.
   */
-  if( pTab->pIndex==0 ){
-    sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pTab->tnum, iDb);
+  if( pOnlyIdx==0 && needTableCnt ){
     VdbeComment((v, "%s", pTab->zName));
-    sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat1);
-    sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
-    jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1);
-  }else{
+    sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1);
+    jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v);
+    sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
+    sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
+    sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
+    sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
+    sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
     sqlite3VdbeJumpHere(v, jZeroRows);
-    jZeroRows = sqlite3VdbeAddOp0(v, OP_Goto);
   }
-  sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
-  sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
-  sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
-  sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
-  sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
-  if( pParse->nMem<regRec ) pParse->nMem = regRec;
-  sqlite3VdbeJumpHere(v, jZeroRows);
 }
 
 
@@ -80963,16 +84699,18 @@ static void analyzeDatabase(Parse *pParse, int iDb){
   HashElem *k;
   int iStatCur;
   int iMem;
+  int iTab;
 
   sqlite3BeginWriteOperation(pParse, 0, iDb);
   iStatCur = pParse->nTab;
   pParse->nTab += 3;
   openStatTable(pParse, iDb, iStatCur, 0, 0);
   iMem = pParse->nMem+1;
+  iTab = pParse->nTab;
   assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
     Table *pTab = (Table*)sqliteHashData(k);
-    analyzeOneTable(pParse, pTab, 0, iStatCur, iMem);
+    analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab);
   }
   loadAnalysis(pParse, iDb);
 }
@@ -80997,7 +84735,7 @@ static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){
   }else{
     openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl");
   }
-  analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem+1);
+  analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur,pParse->nMem+1,pParse->nTab);
   loadAnalysis(pParse, iDb);
 }
 
@@ -81021,6 +84759,7 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
   Table *pTab;
   Index *pIdx;
   Token *pTableName;
+  Vdbe *v;
 
   /* Read the database schema. If an error occurs, leave an error message
   ** and code in pParse and return NULL. */
@@ -81068,6 +84807,8 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
       }
     }   
   }
+  v = sqlite3GetVdbe(pParse);
+  if( v ) sqlite3VdbeAddOp0(v, OP_Expire);
 }
 
 /*
@@ -81081,6 +84822,68 @@ struct analysisInfo {
 };
 
 /*
+** The first argument points to a nul-terminated string containing a
+** list of space separated integers. Read the first nOut of these into
+** the array aOut[].
+*/
+static void decodeIntArray(
+  char *zIntArray,       /* String containing int array to decode */
+  int nOut,              /* Number of slots in aOut[] */
+  tRowcnt *aOut,         /* Store integers here */
+  LogEst *aLog,          /* Or, if aOut==0, here */
+  Index *pIndex          /* Handle extra flags for this index, if not NULL */
+){
+  char *z = zIntArray;
+  int c;
+  int i;
+  tRowcnt v;
+
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  if( z==0 ) z = "";
+#else
+  if( NEVER(z==0) ) z = "";
+#endif
+  for(i=0; *z && i<nOut; i++){
+    v = 0;
+    while( (c=z[0])>='0' && c<='9' ){
+      v = v*10 + c - '0';
+      z++;
+    }
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+    if( aOut ){
+      aOut[i] = v;
+    }else
+#else
+    assert( aOut==0 );
+    UNUSED_PARAMETER(aOut);
+#endif
+    {
+      aLog[i] = sqlite3LogEst(v);
+    }
+    if( *z==' ' ) z++;
+  }
+#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
+  assert( pIndex!=0 );
+#else
+  if( pIndex )
+#endif
+  while( z[0] ){
+    if( sqlite3_strglob("unordered*", z)==0 ){
+      pIndex->bUnordered = 1;
+    }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
+      pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
+    }
+#ifdef SQLITE_ENABLE_COSTMULT
+    else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
+      pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9));
+    }
+#endif
+    while( z[0]!=0 && z[0]!=' ' ) z++;
+    while( z[0]==' ' ) z++;
+  }
+}
+
+/*
 ** This callback is invoked once for each index when reading the
 ** sqlite_stat1 table.  
 **
@@ -81095,8 +84898,6 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
   analysisInfo *pInfo = (analysisInfo*)pData;
   Index *pIndex;
   Table *pTable;
-  int i, c, n;
-  tRowcnt v;
   const char *z;
 
   assert( argc==3 );
@@ -81109,28 +84910,29 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
   if( pTable==0 ){
     return 0;
   }
-  if( argv[1] ){
-    pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
-  }else{
+  if( argv[1]==0 ){
     pIndex = 0;
+  }else if( sqlite3_stricmp(argv[0],argv[1])==0 ){
+    pIndex = sqlite3PrimaryKeyIndex(pTable);
+  }else{
+    pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
   }
-  n = pIndex ? pIndex->nColumn : 0;
   z = argv[2];
-  for(i=0; *z && i<=n; i++){
-    v = 0;
-    while( (c=z[0])>='0' && c<='9' ){
-      v = v*10 + c - '0';
-      z++;
-    }
-    if( i==0 ) pTable->nRowEst = v;
-    if( pIndex==0 ) break;
-    pIndex->aiRowEst[i] = v;
-    if( *z==' ' ) z++;
-    if( strcmp(z, "unordered")==0 ){
-      pIndex->bUnordered = 1;
-      break;
-    }
+
+  if( pIndex ){
+    pIndex->bUnordered = 0;
+    decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex);
+    if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
+  }else{
+    Index fakeIdx;
+    fakeIdx.szIdxRow = pTable->szTabRow;
+#ifdef SQLITE_ENABLE_COSTMULT
+    fakeIdx.pTable = pTable;
+#endif
+    decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
+    pTable->szTabRow = fakeIdx.szIdxRow;
   }
+
   return 0;
 }
 
@@ -81139,14 +84941,12 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
 ** and its contents.
 */
 SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
   if( pIdx->aSample ){
     int j;
     for(j=0; j<pIdx->nSample; j++){
       IndexSample *p = &pIdx->aSample[j];
-      if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){
-        sqlite3DbFree(db, p->u.z);
-      }
+      sqlite3DbFree(db, p->p);
     }
     sqlite3DbFree(db, pIdx->aSample);
   }
@@ -81157,31 +84957,100 @@ SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
 #else
   UNUSED_PARAMETER(db);
   UNUSED_PARAMETER(pIdx);
-#endif
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
+}
+
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+/*
+** Populate the pIdx->aAvgEq[] array based on the samples currently
+** stored in pIdx->aSample[]. 
+*/
+static void initAvgEq(Index *pIdx){
+  if( pIdx ){
+    IndexSample *aSample = pIdx->aSample;
+    IndexSample *pFinal = &aSample[pIdx->nSample-1];
+    int iCol;
+    int nCol = 1;
+    if( pIdx->nSampleCol>1 ){
+      /* If this is stat4 data, then calculate aAvgEq[] values for all
+      ** sample columns except the last. The last is always set to 1, as
+      ** once the trailing PK fields are considered all index keys are
+      ** unique.  */
+      nCol = pIdx->nSampleCol-1;
+      pIdx->aAvgEq[nCol] = 1;
+    }
+    for(iCol=0; iCol<nCol; iCol++){
+      int i;                    /* Used to iterate through samples */
+      tRowcnt sumEq = 0;        /* Sum of the nEq values */
+      tRowcnt nSum = 0;         /* Number of terms contributing to sumEq */
+      tRowcnt avgEq = 0;
+      tRowcnt nDLt = pFinal->anDLt[iCol];
+
+      /* Set nSum to the number of distinct (iCol+1) field prefixes that
+      ** occur in the stat4 table for this index before pFinal. Set
+      ** sumEq to the sum of the nEq values for column iCol for the same
+      ** set (adding the value only once where there exist dupicate 
+      ** prefixes).  */
+      for(i=0; i<(pIdx->nSample-1); i++){
+        if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){
+          sumEq += aSample[i].anEq[iCol];
+          nSum++;
+        }
+      }
+      if( nDLt>nSum ){
+        avgEq = (pFinal->anLt[iCol] - sumEq)/(nDLt - nSum);
+      }
+      if( avgEq==0 ) avgEq = 1;
+      pIdx->aAvgEq[iCol] = avgEq;
+    }
+  }
 }
 
-#ifdef SQLITE_ENABLE_STAT3
 /*
-** Load content from the sqlite_stat3 table into the Index.aSample[]
-** arrays of all indices.
+** Look up an index by name.  Or, if the name of a WITHOUT ROWID table
+** is supplied instead, find the PRIMARY KEY index for that table.
 */
-static int loadStat3(sqlite3 *db, const char *zDb){
+static Index *findIndexOrPrimaryKey(
+  sqlite3 *db,
+  const char *zName,
+  const char *zDb
+){
+  Index *pIdx = sqlite3FindIndex(db, zName, zDb);
+  if( pIdx==0 ){
+    Table *pTab = sqlite3FindTable(db, zName, zDb);
+    if( pTab && !HasRowid(pTab) ) pIdx = sqlite3PrimaryKeyIndex(pTab);
+  }
+  return pIdx;
+}
+
+/*
+** Load the content from either the sqlite_stat4 or sqlite_stat3 table 
+** into the relevant Index.aSample[] arrays.
+**
+** Arguments zSql1 and zSql2 must point to SQL statements that return
+** data equivalent to the following (statements are different for stat3,
+** see the caller of this function for details):
+**
+**    zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx
+**    zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4
+**
+** where %Q is replaced with the database name before the SQL is executed.
+*/
+static int loadStatTbl(
+  sqlite3 *db,                  /* Database handle */
+  int bStat3,                   /* Assume single column records only */
+  const char *zSql1,            /* SQL statement 1 (see above) */
+  const char *zSql2,            /* SQL statement 2 (see above) */
+  const char *zDb               /* Database name (e.g. "main") */
+){
   int rc;                       /* Result codes from subroutines */
   sqlite3_stmt *pStmt = 0;      /* An SQL statement being run */
   char *zSql;                   /* Text of the SQL statement */
   Index *pPrevIdx = 0;          /* Previous index in the loop */
-  int idx = 0;                  /* slot in pIdx->aSample[] for next sample */
-  int eType;                    /* Datatype of a sample */
   IndexSample *pSample;         /* A slot in pIdx->aSample[] */
 
   assert( db->lookaside.bEnabled==0 );
-  if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){
-    return SQLITE_OK;
-  }
-
-  zSql = sqlite3MPrintf(db, 
-      "SELECT idx,count(*) FROM %Q.sqlite_stat3"
-      " GROUP BY idx", zDb);
+  zSql = sqlite3MPrintf(db, zSql1, zDb);
   if( !zSql ){
     return SQLITE_NOMEM;
   }
@@ -81190,30 +85059,54 @@ static int loadStat3(sqlite3 *db, const char *zDb){
   if( rc ) return rc;
 
   while( sqlite3_step(pStmt)==SQLITE_ROW ){
+    int nIdxCol = 1;              /* Number of columns in stat4 records */
+
     char *zIndex;   /* Index name */
     Index *pIdx;    /* Pointer to the index object */
     int nSample;    /* Number of samples */
+    int nByte;      /* Bytes of space required */
+    int i;          /* Bytes of space required */
+    tRowcnt *pSpace;
 
     zIndex = (char *)sqlite3_column_text(pStmt, 0);
     if( zIndex==0 ) continue;
     nSample = sqlite3_column_int(pStmt, 1);
-    pIdx = sqlite3FindIndex(db, zIndex, zDb);
-    if( pIdx==0 ) continue;
-    assert( pIdx->nSample==0 );
-    pIdx->nSample = nSample;
-    pIdx->aSample = sqlite3DbMallocZero(db, nSample*sizeof(IndexSample));
-    pIdx->avgEq = pIdx->aiRowEst[1];
+    pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
+    assert( pIdx==0 || bStat3 || pIdx->nSample==0 );
+    /* Index.nSample is non-zero at this point if data has already been
+    ** loaded from the stat4 table. In this case ignore stat3 data.  */
+    if( pIdx==0 || pIdx->nSample ) continue;
+    if( bStat3==0 ){
+      assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 );
+      if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
+        nIdxCol = pIdx->nKeyCol;
+      }else{
+        nIdxCol = pIdx->nColumn;
+      }
+    }
+    pIdx->nSampleCol = nIdxCol;
+    nByte = sizeof(IndexSample) * nSample;
+    nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
+    nByte += nIdxCol * sizeof(tRowcnt);     /* Space for Index.aAvgEq[] */
+
+    pIdx->aSample = sqlite3DbMallocZero(db, nByte);
     if( pIdx->aSample==0 ){
-      db->mallocFailed = 1;
       sqlite3_finalize(pStmt);
       return SQLITE_NOMEM;
     }
+    pSpace = (tRowcnt*)&pIdx->aSample[nSample];
+    pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
+    for(i=0; i<nSample; i++){
+      pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
+      pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol;
+      pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol;
+    }
+    assert( ((u8*)pSpace)-nByte==(u8*)(pIdx->aSample) );
   }
   rc = sqlite3_finalize(pStmt);
   if( rc ) return rc;
 
-  zSql = sqlite3MPrintf(db, 
-      "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb);
+  zSql = sqlite3MPrintf(db, zSql2, zDb);
   if( !zSql ){
     return SQLITE_NOMEM;
   }
@@ -81222,86 +85115,88 @@ static int loadStat3(sqlite3 *db, const char *zDb){
   if( rc ) return rc;
 
   while( sqlite3_step(pStmt)==SQLITE_ROW ){
-    char *zIndex;   /* Index name */
-    Index *pIdx;    /* Pointer to the index object */
-    int i;          /* Loop counter */
-    tRowcnt sumEq;  /* Sum of the nEq values */
+    char *zIndex;                 /* Index name */
+    Index *pIdx;                  /* Pointer to the index object */
+    int nCol = 1;                 /* Number of columns in index */
 
     zIndex = (char *)sqlite3_column_text(pStmt, 0);
     if( zIndex==0 ) continue;
-    pIdx = sqlite3FindIndex(db, zIndex, zDb);
+    pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
     if( pIdx==0 ) continue;
-    if( pIdx==pPrevIdx ){
-      idx++;
-    }else{
+    /* This next condition is true if data has already been loaded from 
+    ** the sqlite_stat4 table. In this case ignore stat3 data.  */
+    nCol = pIdx->nSampleCol;
+    if( bStat3 && nCol>1 ) continue;
+    if( pIdx!=pPrevIdx ){
+      initAvgEq(pPrevIdx);
       pPrevIdx = pIdx;
-      idx = 0;
-    }
-    assert( idx<pIdx->nSample );
-    pSample = &pIdx->aSample[idx];
-    pSample->nEq = (tRowcnt)sqlite3_column_int64(pStmt, 1);
-    pSample->nLt = (tRowcnt)sqlite3_column_int64(pStmt, 2);
-    pSample->nDLt = (tRowcnt)sqlite3_column_int64(pStmt, 3);
-    if( idx==pIdx->nSample-1 ){
-      if( pSample->nDLt>0 ){
-        for(i=0, sumEq=0; i<=idx-1; i++) sumEq += pIdx->aSample[i].nEq;
-        pIdx->avgEq = (pSample->nLt - sumEq)/pSample->nDLt;
-      }
-      if( pIdx->avgEq<=0 ) pIdx->avgEq = 1;
-    }
-    eType = sqlite3_column_type(pStmt, 4);
-    pSample->eType = (u8)eType;
-    switch( eType ){
-      case SQLITE_INTEGER: {
-        pSample->u.i = sqlite3_column_int64(pStmt, 4);
-        break;
-      }
-      case SQLITE_FLOAT: {
-        pSample->u.r = sqlite3_column_double(pStmt, 4);
-        break;
-      }
-      case SQLITE_NULL: {
-        break;
-      }
-      default: assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); {
-        const char *z = (const char *)(
-              (eType==SQLITE_BLOB) ?
-              sqlite3_column_blob(pStmt, 4):
-              sqlite3_column_text(pStmt, 4)
-           );
-        int n = z ? sqlite3_column_bytes(pStmt, 4) : 0;
-        pSample->nByte = n;
-        if( n < 1){
-          pSample->u.z = 0;
-        }else{
-          pSample->u.z = sqlite3DbMallocRaw(db, n);
-          if( pSample->u.z==0 ){
-            db->mallocFailed = 1;
-            sqlite3_finalize(pStmt);
-            return SQLITE_NOMEM;
-          }
-          memcpy(pSample->u.z, z, n);
-        }
-      }
     }
+    pSample = &pIdx->aSample[pIdx->nSample];
+    decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0);
+    decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0);
+    decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0);
+
+    /* Take a copy of the sample. Add two 0x00 bytes the end of the buffer.
+    ** This is in case the sample record is corrupted. In that case, the
+    ** sqlite3VdbeRecordCompare() may read up to two varints past the
+    ** end of the allocated buffer before it realizes it is dealing with
+    ** a corrupt record. Adding the two 0x00 bytes prevents this from causing
+    ** a buffer overread.  */
+    pSample->n = sqlite3_column_bytes(pStmt, 4);
+    pSample->p = sqlite3DbMallocZero(db, pSample->n + 2);
+    if( pSample->p==0 ){
+      sqlite3_finalize(pStmt);
+      return SQLITE_NOMEM;
+    }
+    memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
+    pIdx->nSample++;
   }
-  return sqlite3_finalize(pStmt);
+  rc = sqlite3_finalize(pStmt);
+  if( rc==SQLITE_OK ) initAvgEq(pPrevIdx);
+  return rc;
 }
-#endif /* SQLITE_ENABLE_STAT3 */
 
 /*
-** Load the content of the sqlite_stat1 and sqlite_stat3 tables. The
+** Load content from the sqlite_stat4 and sqlite_stat3 tables into 
+** the Index.aSample[] arrays of all indices.
+*/
+static int loadStat4(sqlite3 *db, const char *zDb){
+  int rc = SQLITE_OK;             /* Result codes from subroutines */
+
+  assert( db->lookaside.bEnabled==0 );
+  if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
+    rc = loadStatTbl(db, 0,
+      "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", 
+      "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4",
+      zDb
+    );
+  }
+
+  if( rc==SQLITE_OK && sqlite3FindTable(db, "sqlite_stat3", zDb) ){
+    rc = loadStatTbl(db, 1,
+      "SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx", 
+      "SELECT idx,neq,nlt,ndlt,sqlite_record(sample) FROM %Q.sqlite_stat3",
+      zDb
+    );
+  }
+
+  return rc;
+}
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
+
+/*
+** Load the content of the sqlite_stat1 and sqlite_stat3/4 tables. The
 ** contents of sqlite_stat1 are used to populate the Index.aiRowEst[]
-** arrays. The contents of sqlite_stat3 are used to populate the
+** arrays. The contents of sqlite_stat3/4 are used to populate the
 ** Index.aSample[] arrays.
 **
 ** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
-** is returned. In this case, even if SQLITE_ENABLE_STAT3 was defined 
-** during compilation and the sqlite_stat3 table is present, no data is 
+** is returned. In this case, even if SQLITE_ENABLE_STAT3/4 was defined 
+** during compilation and the sqlite_stat3/4 table is present, no data is 
 ** read from it.
 **
-** If SQLITE_ENABLE_STAT3 was defined during compilation and the 
-** sqlite_stat3 table is not present in the database, SQLITE_ERROR is
+** If SQLITE_ENABLE_STAT3/4 was defined during compilation and the 
+** sqlite_stat4 table is not present in the database, SQLITE_ERROR is
 ** returned. However, in this case, data is read from the sqlite_stat1
 ** table (if it is present) before returning.
 **
@@ -81323,7 +85218,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
   for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
     Index *pIdx = sqliteHashData(i);
     sqlite3DefaultRowEst(pIdx);
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
     sqlite3DeleteIndexSamples(db, pIdx);
     pIdx->aSample = 0;
 #endif
@@ -81347,12 +85242,12 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
   }
 
 
-  /* Load the statistics from the sqlite_stat3 table. */
-#ifdef SQLITE_ENABLE_STAT3
+  /* Load the statistics from the sqlite_stat4 table. */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
   if( rc==SQLITE_OK ){
     int lookasideEnabled = db->lookaside.bEnabled;
     db->lookaside.bEnabled = 0;
-    rc = loadStat3(db, sInfo.zDatabase);
+    rc = loadStat4(db, sInfo.zDatabase);
     db->lookaside.bEnabled = lookasideEnabled;
   }
 #endif
@@ -81407,10 +85302,6 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
   if( pExpr ){
     if( pExpr->op!=TK_ID ){
       rc = sqlite3ResolveExprNames(pName, pExpr);
-      if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
-        sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken);
-        return SQLITE_ERROR;
-      }
     }else{
       pExpr->op = TK_STRING;
     }
@@ -81527,6 +85418,9 @@ static void attachFunc(
     sqlite3PagerLockingMode(pPager, db->dfltLockMode);
     sqlite3BtreeSecureDelete(aNew->pBt,
                              sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+    sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
+#endif
   }
   aNew->safety_level = 3;
   aNew->zName = sqlite3DbStrDup(db, zName);
@@ -81745,8 +85639,7 @@ attach_end:
 SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){
   static const FuncDef detach_func = {
     1,                /* nArg */
-    SQLITE_UTF8,      /* iPrefEnc */
-    0,                /* flags */
+    SQLITE_UTF8,      /* funcFlags */
     0,                /* pUserData */
     0,                /* pNext */
     detachFunc,       /* xFunc */
@@ -81767,8 +85660,7 @@ SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){
 SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
   static const FuncDef attach_func = {
     3,                /* nArg */
-    SQLITE_UTF8,      /* iPrefEnc */
-    0,                /* flags */
+    SQLITE_UTF8,      /* funcFlags */
     0,                /* pUserData */
     0,                /* pNext */
     attachFunc,       /* xFunc */
@@ -81785,11 +85677,8 @@ SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *p
 /*
 ** Initialize a DbFixer structure.  This routine must be called prior
 ** to passing the structure to one of the sqliteFixAAAA() routines below.
-**
-** The return value indicates whether or not fixation is required.  TRUE
-** means we do need to fix the database references, FALSE means we do not.
 */
-SQLITE_PRIVATE int sqlite3FixInit(
+SQLITE_PRIVATE void sqlite3FixInit(
   DbFixer *pFix,      /* The fixer to be initialized */
   Parse *pParse,      /* Error messages will be written here */
   int iDb,            /* This is the database that must be used */
@@ -81798,7 +85687,6 @@ SQLITE_PRIVATE int sqlite3FixInit(
 ){
   sqlite3 *db;
 
-  if( NEVER(iDb<0) || iDb==1 ) return 0;
   db = pParse->db;
   assert( db->nDb>iDb );
   pFix->pParse = pParse;
@@ -81806,7 +85694,7 @@ SQLITE_PRIVATE int sqlite3FixInit(
   pFix->pSchema = db->aDb[iDb].pSchema;
   pFix->zType = zType;
   pFix->pName = pName;
-  return 1;
+  pFix->bVarOnly = (iDb==1);
 }
 
 /*
@@ -81834,15 +85722,17 @@ SQLITE_PRIVATE int sqlite3FixSrcList(
   if( NEVER(pList==0) ) return 0;
   zDb = pFix->zDb;
   for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
-    if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
-      sqlite3ErrorMsg(pFix->pParse,
-         "%s %T cannot reference objects in database %s",
-         pFix->zType, pFix->pName, pItem->zDatabase);
-      return 1;
+    if( pFix->bVarOnly==0 ){
+      if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
+        sqlite3ErrorMsg(pFix->pParse,
+            "%s %T cannot reference objects in database %s",
+            pFix->zType, pFix->pName, pItem->zDatabase);
+        return 1;
+      }
+      sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
+      pItem->zDatabase = 0;
+      pItem->pSchema = pFix->pSchema;
     }
-    sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
-    pItem->zDatabase = 0;
-    pItem->pSchema = pFix->pSchema;
 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
     if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
     if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
@@ -81865,9 +85755,21 @@ SQLITE_PRIVATE int sqlite3FixSelect(
     if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
       return 1;
     }
+    if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
+      return 1;
+    }
     if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
       return 1;
     }
+    if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
+      return 1;
+    }
+    if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
+      return 1;
+    }
+    if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
+      return 1;
+    }
     pSelect = pSelect->pPrior;
   }
   return 0;
@@ -81877,7 +85779,15 @@ SQLITE_PRIVATE int sqlite3FixExpr(
   Expr *pExpr        /* The expression to be fixed to one database */
 ){
   while( pExpr ){
-    if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break;
+    if( pExpr->op==TK_VARIABLE ){
+      if( pFix->pParse->db->init.busy ){
+        pExpr->op = TK_NULL;
+      }else{
+        sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
+        return 1;
+      }
+    }
+    if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
     if( ExprHasProperty(pExpr, EP_xIsSelect) ){
       if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
     }else{
@@ -82295,6 +86205,19 @@ static void codeTableLocks(Parse *pParse){
 #endif
 
 /*
+** Return TRUE if the given yDbMask object is empty - if it contains no
+** 1 bits.  This routine is used by the DbMaskAllZero() and DbMaskNotZero()
+** macros when SQLITE_MAX_ATTACHED is greater than 30.
+*/
+#if SQLITE_MAX_ATTACHED>30
+SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask m){
+  int i;
+  for(i=0; i<sizeof(yDbMask); i++) if( m[i] ) return 0;
+  return 1;
+}
+#endif
+
+/*
 ** This routine is called after a single SQL statement has been
 ** parsed and a VDBE program to execute that statement has been
 ** prepared.  This routine puts the finishing touches on the
@@ -82321,6 +86244,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
   assert( !pParse->isMultiWrite 
        || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
   if( v ){
+    while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){}
     sqlite3VdbeAddOp0(v, OP_Halt);
 
     /* The cookie mask contains one bit for each database file open.
@@ -82329,30 +86253,30 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
     ** transaction on each used database and to verify the schema cookie
     ** on each used database.
     */
-    if( pParse->cookieGoto>0 ){
-      yDbMask mask;
-      int iDb;
-      sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
-      for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
-        if( (mask & pParse->cookieMask)==0 ) continue;
+    if( db->mallocFailed==0 
+     && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr)
+    ){
+      int iDb, i;
+      assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
+      sqlite3VdbeJumpHere(v, 0);
+      for(iDb=0; iDb<db->nDb; iDb++){
+        if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
         sqlite3VdbeUsesBtree(v, iDb);
-        sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
-        if( db->init.busy==0 ){
-          assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
-          sqlite3VdbeAddOp3(v, OP_VerifyCookie,
-                            iDb, pParse->cookieValue[iDb],
-                            db->aDb[iDb].pSchema->iGeneration);
-        }
+        sqlite3VdbeAddOp4Int(v,
+          OP_Transaction,                    /* Opcode */
+          iDb,                               /* P1 */
+          DbMaskTest(pParse->writeMask,iDb), /* P2 */
+          pParse->cookieValue[iDb],          /* P3 */
+          db->aDb[iDb].pSchema->iGeneration  /* P4 */
+        );
+        if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
       }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-      {
-        int i;
-        for(i=0; i<pParse->nVtabLock; i++){
-          char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
-          sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
-        }
-        pParse->nVtabLock = 0;
+      for(i=0; i<pParse->nVtabLock; i++){
+        char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
+        sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
       }
+      pParse->nVtabLock = 0;
 #endif
 
       /* Once all the cookies have been verified and transactions opened, 
@@ -82365,8 +86289,17 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
       */
       sqlite3AutoincrementBegin(pParse);
 
+      /* Code constant expressions that where factored out of inner loops */
+      if( pParse->pConstExpr ){
+        ExprList *pEL = pParse->pConstExpr;
+        pParse->okConstFactor = 0;
+        for(i=0; i<pEL->nExpr; i++){
+          sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
+        }
+      }
+
       /* Finally, jump back to the beginning of the executable code. */
-      sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto);
+      sqlite3VdbeAddOp2(v, OP_Goto, 0, 1);
     }
   }
 
@@ -82374,10 +86307,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
   /* Get the VDBE program ready for execution
   */
   if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){
-#ifdef SQLITE_DEBUG
-    FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
-    sqlite3VdbeTrace(v, trace);
-#endif
     assert( pParse->iCacheLevel==0 );  /* Disables and re-enables match */
     /* A minimum of one cursor is required if autoincrement is used
     *  See ticket [a696379c1f08866] */
@@ -82392,8 +86321,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
   pParse->nMem = 0;
   pParse->nSet = 0;
   pParse->nVar = 0;
-  pParse->cookieMask = 0;
-  pParse->cookieGoto = 0;
+  DbMaskZero(pParse->cookieMask);
 }
 
 /*
@@ -82563,7 +86491,10 @@ static void freeIndex(sqlite3 *db, Index *p){
 #ifndef SQLITE_OMIT_ANALYZE
   sqlite3DeleteIndexSamples(db, p);
 #endif
+  if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo);
+  sqlite3ExprDelete(db, p->pPartIdxWhere);
   sqlite3DbFree(db, p->zColAff);
+  if( p->isResized ) sqlite3DbFree(db, p->azColl);
   sqlite3DbFree(db, p);
 }
 
@@ -82821,8 +86752,7 @@ SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
 SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){
   Vdbe *v = sqlite3GetVdbe(p);
   sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
-  sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
-  sqlite3VdbeChangeP4(v, -1, (char *)5, P4_INT32);  /* 5 column table */
+  sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
   if( p->nTab==0 ){
     p->nTab = 1;
   }
@@ -82928,6 +86858,27 @@ SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){
 }
 
 /*
+** Return the PRIMARY KEY index of a table
+*/
+SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table *pTab){
+  Index *p;
+  for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){}
+  return p;
+}
+
+/*
+** Return the column of index pIdx that corresponds to table
+** column iCol.  Return -1 if not found.
+*/
+SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){
+  int i;
+  for(i=0; i<pIdx->nColumn; i++){
+    if( iCol==pIdx->aiColumn[i] ) return i;
+  }
+  return -1;
+}
+
+/*
 ** Begin constructing a new table representation in memory.  This is
 ** the first of several action routines that get called in response
 ** to a CREATE TABLE statement.  In particular, this routine is called
@@ -83059,7 +87010,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
   pTable->iPKey = -1;
   pTable->pSchema = db->aDb[iDb].pSchema;
   pTable->nRef = 1;
-  pTable->nRowEst = 1000000;
+  pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
   assert( pParse->pNewTable==0 );
   pParse->pNewTable = pTable;
 
@@ -83102,7 +87053,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
     reg3 = ++pParse->nMem;
     sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT);
     sqlite3VdbeUsesBtree(v, iDb);
-    j1 = sqlite3VdbeAddOp1(v, OP_If, reg3);
+    j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v);
     fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
                   1 : SQLITE_MAX_FILE_FORMAT;
     sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3);
@@ -83126,7 +87077,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
     }else
 #endif
     {
-      sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2);
+      pParse->addrCrTab = sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2);
     }
     sqlite3OpenMasterTable(pParse, iDb);
     sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
@@ -83206,6 +87157,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName){
   ** be called next to set pCol->affinity correctly.
   */
   pCol->affinity = SQLITE_AFF_NONE;
+  pCol->szEst = 1;
   p->nCol++;
 }
 
@@ -83247,15 +87199,18 @@ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){
 ** If none of the substrings in the above table are found,
 ** SQLITE_AFF_NUMERIC is returned.
 */
-SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
+SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){
   u32 h = 0;
   char aff = SQLITE_AFF_NUMERIC;
+  const char *zChar = 0;
 
-  if( zIn ) while( zIn[0] ){
+  if( zIn==0 ) return aff;
+  while( zIn[0] ){
     h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
     zIn++;
     if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){             /* CHAR */
-      aff = SQLITE_AFF_TEXT; 
+      aff = SQLITE_AFF_TEXT;
+      zChar = zIn;
     }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){       /* CLOB */
       aff = SQLITE_AFF_TEXT;
     }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){       /* TEXT */
@@ -83263,6 +87218,7 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
     }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b')          /* BLOB */
         && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
       aff = SQLITE_AFF_NONE;
+      if( zIn[0]=='(' ) zChar = zIn;
 #ifndef SQLITE_OMIT_FLOATING_POINT
     }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l')          /* REAL */
         && aff==SQLITE_AFF_NUMERIC ){
@@ -83280,6 +87236,28 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
     }
   }
 
+  /* If pszEst is not NULL, store an estimate of the field size.  The
+  ** estimate is scaled so that the size of an integer is 1.  */
+  if( pszEst ){
+    *pszEst = 1;   /* default size is approx 4 bytes */
+    if( aff<=SQLITE_AFF_NONE ){
+      if( zChar ){
+        while( zChar[0] ){
+          if( sqlite3Isdigit(zChar[0]) ){
+            int v = 0;
+            sqlite3GetInt32(zChar, &v);
+            v = v/4 + 1;
+            if( v>255 ) v = 255;
+            *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */
+            break;
+          }
+          zChar++;
+        }
+      }else{
+        *pszEst = 5;   /* BLOB, TEXT, CLOB -> r=5  (approx 20 bytes)*/
+      }
+    }
+  }
   return aff;
 }
 
@@ -83301,7 +87279,7 @@ SQLITE_PRIVATE void sqlite3AddColumnType(Parse *pParse, Token *pType){
   pCol = &p->aCol[p->nCol-1];
   assert( pCol->zType==0 );
   pCol->zType = sqlite3NameFromToken(pParse->db, pType);
-  pCol->affinity = sqlite3AffinityType(pCol->zType);
+  pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst);
 }
 
 /*
@@ -83367,6 +87345,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
   Table *pTab = pParse->pNewTable;
   char *zType = 0;
   int iCol = -1, i;
+  int nTerm;
   if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
   if( pTab->tabFlags & TF_HasPrimaryKey ){
     sqlite3ErrorMsg(pParse, 
@@ -83377,38 +87356,43 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
   if( pList==0 ){
     iCol = pTab->nCol - 1;
     pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
+    zType = pTab->aCol[iCol].zType;
+    nTerm = 1;
   }else{
-    for(i=0; i<pList->nExpr; i++){
+    nTerm = pList->nExpr;
+    for(i=0; i<nTerm; i++){
       for(iCol=0; iCol<pTab->nCol; iCol++){
         if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){
+          pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
+          zType = pTab->aCol[iCol].zType;
           break;
         }
       }
-      if( iCol<pTab->nCol ){
-        pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
-      }
     }
-    if( pList->nExpr>1 ) iCol = -1;
-  }
-  if( iCol>=0 && iCol<pTab->nCol ){
-    zType = pTab->aCol[iCol].zType;
   }
-  if( zType && sqlite3StrICmp(zType, "INTEGER")==0
-        && sortOrder==SQLITE_SO_ASC ){
+  if( nTerm==1
+   && zType && sqlite3StrICmp(zType, "INTEGER")==0
+   && sortOrder==SQLITE_SO_ASC
+  ){
     pTab->iPKey = iCol;
     pTab->keyConf = (u8)onError;
     assert( autoInc==0 || autoInc==1 );
     pTab->tabFlags |= autoInc*TF_Autoincrement;
+    if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder;
   }else if( autoInc ){
 #ifndef SQLITE_OMIT_AUTOINCREMENT
     sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
        "INTEGER PRIMARY KEY");
 #endif
   }else{
+    Vdbe *v = pParse->pVdbe;
     Index *p;
-    p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0);
+    if( v ) pParse->addrSkipPK = sqlite3VdbeAddOp0(v, OP_Noop);
+    p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
+                           0, sortOrder, 0);
     if( p ){
-      p->autoIndex = 2;
+      p->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
+      if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK);
     }
     pList = 0;
   }
@@ -83427,7 +87411,10 @@ SQLITE_PRIVATE void sqlite3AddCheckConstraint(
 ){
 #ifndef SQLITE_OMIT_CHECK
   Table *pTab = pParse->pNewTable;
-  if( pTab && !IN_DECLARE_VTAB ){
+  sqlite3 *db = pParse->db;
+  if( pTab && !IN_DECLARE_VTAB
+   && !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt)
+  ){
     pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
     if( pParse->constraintName.n ){
       sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
@@ -83457,6 +87444,7 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
 
   if( sqlite3LocateCollSeq(pParse, zColl) ){
     Index *pIdx;
+    sqlite3DbFree(db, p->aCol[i].zColl);
     p->aCol[i].zColl = zColl;
   
     /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
@@ -83464,7 +87452,7 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
     ** collation type was added. Correct this if it is the case.
     */
     for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
-      assert( pIdx->nColumn==1 );
+      assert( pIdx->nKeyCol==1 );
       if( pIdx->aiColumn[0]==i ){
         pIdx->azColl[0] = p->aCol[i].zColl;
       }
@@ -83572,10 +87560,10 @@ static void identPut(char *z, int *pIdx, char *zSignedIdent){
   for(j=0; zIdent[j]; j++){
     if( !sqlite3Isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
   }
-  needQuote = sqlite3Isdigit(zIdent[0]) || sqlite3KeywordCode(zIdent, j)!=TK_ID;
-  if( !needQuote ){
-    needQuote = zIdent[j];
-  }
+  needQuote = sqlite3Isdigit(zIdent[0])
+            || sqlite3KeywordCode(zIdent, j)!=TK_ID
+            || zIdent[j]!=0
+            || j==0;
 
   if( needQuote ) z[i++] = '"';
   for(j=0; zIdent[j]; j++){
@@ -83647,7 +87635,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){
     zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
     len = sqlite3Strlen30(zType);
     assert( pCol->affinity==SQLITE_AFF_NONE 
-            || pCol->affinity==sqlite3AffinityType(zType) );
+            || pCol->affinity==sqlite3AffinityType(zType, 0) );
     memcpy(&zStmt[k], zType, len);
     k += len;
     assert( k<=n );
@@ -83657,6 +87645,191 @@ static char *createTableStmt(sqlite3 *db, Table *p){
 }
 
 /*
+** Resize an Index object to hold N columns total.  Return SQLITE_OK
+** on success and SQLITE_NOMEM on an OOM error.
+*/
+static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
+  char *zExtra;
+  int nByte;
+  if( pIdx->nColumn>=N ) return SQLITE_OK;
+  assert( pIdx->isResized==0 );
+  nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
+  zExtra = sqlite3DbMallocZero(db, nByte);
+  if( zExtra==0 ) return SQLITE_NOMEM;
+  memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
+  pIdx->azColl = (char**)zExtra;
+  zExtra += sizeof(char*)*N;
+  memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
+  pIdx->aiColumn = (i16*)zExtra;
+  zExtra += sizeof(i16)*N;
+  memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn);
+  pIdx->aSortOrder = (u8*)zExtra;
+  pIdx->nColumn = N;
+  pIdx->isResized = 1;
+  return SQLITE_OK;
+}
+
+/*
+** Estimate the total row width for a table.
+*/
+static void estimateTableWidth(Table *pTab){
+  unsigned wTable = 0;
+  const Column *pTabCol;
+  int i;
+  for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){
+    wTable += pTabCol->szEst;
+  }
+  if( pTab->iPKey<0 ) wTable++;
+  pTab->szTabRow = sqlite3LogEst(wTable*4);
+}
+
+/*
+** Estimate the average size of a row for an index.
+*/
+static void estimateIndexWidth(Index *pIdx){
+  unsigned wIndex = 0;
+  int i;
+  const Column *aCol = pIdx->pTable->aCol;
+  for(i=0; i<pIdx->nColumn; i++){
+    i16 x = pIdx->aiColumn[i];
+    assert( x<pIdx->pTable->nCol );
+    wIndex += x<0 ? 1 : aCol[pIdx->aiColumn[i]].szEst;
+  }
+  pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
+}
+
+/* Return true if value x is found any of the first nCol entries of aiCol[]
+*/
+static int hasColumn(const i16 *aiCol, int nCol, int x){
+  while( nCol-- > 0 ) if( x==*(aiCol++) ) return 1;
+  return 0;
+}
+
+/*
+** This routine runs at the end of parsing a CREATE TABLE statement that
+** has a WITHOUT ROWID clause.  The job of this routine is to convert both
+** internal schema data structures and the generated VDBE code so that they
+** are appropriate for a WITHOUT ROWID table instead of a rowid table.
+** Changes include:
+**
+**     (1)  Convert the OP_CreateTable into an OP_CreateIndex.  There is
+**          no rowid btree for a WITHOUT ROWID.  Instead, the canonical
+**          data storage is a covering index btree.
+**     (2)  Bypass the creation of the sqlite_master table entry
+**          for the PRIMARY KEY as the the primary key index is now
+**          identified by the sqlite_master table entry of the table itself.
+**     (3)  Set the Index.tnum of the PRIMARY KEY Index object in the
+**          schema to the rootpage from the main table.
+**     (4)  Set all columns of the PRIMARY KEY schema object to be NOT NULL.
+**     (5)  Add all table columns to the PRIMARY KEY Index object
+**          so that the PRIMARY KEY is a covering index.  The surplus
+**          columns are part of KeyInfo.nXField and are not used for
+**          sorting or lookup or uniqueness checks.
+**     (6)  Replace the rowid tail on all automatically generated UNIQUE
+**          indices with the PRIMARY KEY columns.
+*/
+static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
+  Index *pIdx;
+  Index *pPk;
+  int nPk;
+  int i, j;
+  sqlite3 *db = pParse->db;
+  Vdbe *v = pParse->pVdbe;
+
+  /* Convert the OP_CreateTable opcode that would normally create the
+  ** root-page for the table into a OP_CreateIndex opcode.  The index
+  ** created will become the PRIMARY KEY index.
+  */
+  if( pParse->addrCrTab ){
+    assert( v );
+    sqlite3VdbeGetOp(v, pParse->addrCrTab)->opcode = OP_CreateIndex;
+  }
+
+  /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
+  ** table entry.
+  */
+  if( pParse->addrSkipPK ){
+    assert( v );
+    sqlite3VdbeGetOp(v, pParse->addrSkipPK)->opcode = OP_Goto;
+  }
+
+  /* Locate the PRIMARY KEY index.  Or, if this table was originally
+  ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. 
+  */
+  if( pTab->iPKey>=0 ){
+    ExprList *pList;
+    pList = sqlite3ExprListAppend(pParse, 0, 0);
+    if( pList==0 ) return;
+    pList->a[0].zName = sqlite3DbStrDup(pParse->db,
+                                        pTab->aCol[pTab->iPKey].zName);
+    pList->a[0].sortOrder = pParse->iPkSortOrder;
+    assert( pParse->pNewTable==pTab );
+    pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0);
+    if( pPk==0 ) return;
+    pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
+    pTab->iPKey = -1;
+  }else{
+    pPk = sqlite3PrimaryKeyIndex(pTab);
+  }
+  pPk->isCovering = 1;
+  assert( pPk!=0 );
+  nPk = pPk->nKeyCol;
+
+  /* Make sure every column of the PRIMARY KEY is NOT NULL */
+  for(i=0; i<nPk; i++){
+    pTab->aCol[pPk->aiColumn[i]].notNull = 1;
+  }
+  pPk->uniqNotNull = 1;
+
+  /* The root page of the PRIMARY KEY is the table root page */
+  pPk->tnum = pTab->tnum;
+
+  /* Update the in-memory representation of all UNIQUE indices by converting
+  ** the final rowid column into one or more columns of the PRIMARY KEY.
+  */
+  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+    int n;
+    if( IsPrimaryKeyIndex(pIdx) ) continue;
+    for(i=n=0; i<nPk; i++){
+      if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++;
+    }
+    if( n==0 ){
+      /* This index is a superset of the primary key */
+      pIdx->nColumn = pIdx->nKeyCol;
+      continue;
+    }
+    if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
+    for(i=0, j=pIdx->nKeyCol; i<nPk; i++){
+      if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ){
+        pIdx->aiColumn[j] = pPk->aiColumn[i];
+        pIdx->azColl[j] = pPk->azColl[i];
+        j++;
+      }
+    }
+    assert( pIdx->nColumn>=pIdx->nKeyCol+n );
+    assert( pIdx->nColumn>=j );
+  }
+
+  /* Add all table columns to the PRIMARY KEY index
+  */
+  if( nPk<pTab->nCol ){
+    if( resizeIndexObject(db, pPk, pTab->nCol) ) return;
+    for(i=0, j=nPk; i<pTab->nCol; i++){
+      if( !hasColumn(pPk->aiColumn, j, i) ){
+        assert( j<pPk->nColumn );
+        pPk->aiColumn[j] = i;
+        pPk->azColl[j] = "BINARY";
+        j++;
+      }
+    }
+    assert( pPk->nColumn==j );
+    assert( pTab->nCol==j );
+  }else{
+    pPk->nColumn = pTab->nCol;
+  }
+}
+
+/*
 ** This routine is called to report the final ")" that terminates
 ** a CREATE TABLE statement.
 **
@@ -83679,12 +87852,14 @@ static char *createTableStmt(sqlite3 *db, Table *p){
 SQLITE_PRIVATE void sqlite3EndTable(
   Parse *pParse,          /* Parse context */
   Token *pCons,           /* The ',' token after the last column defn. */
-  Token *pEnd,            /* The final ')' token in the CREATE TABLE */
+  Token *pEnd,            /* The ')' before options in the CREATE TABLE */
+  u8 tabOpts,             /* Extra table options. Usually 0. */
   Select *pSelect         /* Select from a "CREATE ... AS SELECT" */
 ){
-  Table *p;
-  sqlite3 *db = pParse->db;
-  int iDb;
+  Table *p;                 /* The new table */
+  sqlite3 *db = pParse->db; /* The database connection */
+  int iDb;                  /* Database in which the table lives */
+  Index *pIdx;              /* An implied index of the table */
 
   if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
     return;
@@ -83694,43 +87869,45 @@ SQLITE_PRIVATE void sqlite3EndTable(
 
   assert( !db->init.busy || !pSelect );
 
+  /* If the db->init.busy is 1 it means we are reading the SQL off the
+  ** "sqlite_master" or "sqlite_temp_master" table on the disk.
+  ** So do not write to the disk again.  Extract the root page number
+  ** for the table from the db->init.newTnum field.  (The page number
+  ** should have been put there by the sqliteOpenCb routine.)
+  */
+  if( db->init.busy ){
+    p->tnum = db->init.newTnum;
+  }
+
+  /* Special processing for WITHOUT ROWID Tables */
+  if( tabOpts & TF_WithoutRowid ){
+    if( (p->tabFlags & TF_Autoincrement) ){
+      sqlite3ErrorMsg(pParse,
+          "AUTOINCREMENT not allowed on WITHOUT ROWID tables");
+      return;
+    }
+    if( (p->tabFlags & TF_HasPrimaryKey)==0 ){
+      sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName);
+    }else{
+      p->tabFlags |= TF_WithoutRowid;
+      convertToWithoutRowidTable(pParse, p);
+    }
+  }
+
   iDb = sqlite3SchemaToIndex(db, p->pSchema);
 
 #ifndef SQLITE_OMIT_CHECK
   /* Resolve names in all CHECK constraint expressions.
   */
   if( p->pCheck ){
-    SrcList sSrc;                   /* Fake SrcList for pParse->pNewTable */
-    NameContext sNC;                /* Name context for pParse->pNewTable */
-    ExprList *pList;                /* List of all CHECK constraints */
-    int i;                          /* Loop counter */
-
-    memset(&sNC, 0, sizeof(sNC));
-    memset(&sSrc, 0, sizeof(sSrc));
-    sSrc.nSrc = 1;
-    sSrc.a[0].zName = p->zName;
-    sSrc.a[0].pTab = p;
-    sSrc.a[0].iCursor = -1;
-    sNC.pParse = pParse;
-    sNC.pSrcList = &sSrc;
-    sNC.ncFlags = NC_IsCheck;
-    pList = p->pCheck;
-    for(i=0; i<pList->nExpr; i++){
-      if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
-        return;
-      }
-    }
+    sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
   }
 #endif /* !defined(SQLITE_OMIT_CHECK) */
 
-  /* If the db->init.busy is 1 it means we are reading the SQL off the
-  ** "sqlite_master" or "sqlite_temp_master" table on the disk.
-  ** So do not write to the disk again.  Extract the root page number
-  ** for the table from the db->init.newTnum field.  (The page number
-  ** should have been put there by the sqliteOpenCb routine.)
-  */
-  if( db->init.busy ){
-    p->tnum = db->init.newTnum;
+  /* Estimate the average row size for the table and for all implied indices */
+  estimateTableWidth(p);
+  for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
+    estimateIndexWidth(pIdx);
   }
 
   /* If not initializing, then create a record for the new table
@@ -83806,7 +87983,9 @@ SQLITE_PRIVATE void sqlite3EndTable(
     if( pSelect ){
       zStmt = createTableStmt(db, p);
     }else{
-      n = (int)(pEnd->z - pParse->sNameToken.z) + 1;
+      Token *pEnd2 = tabOpts ? &pParse->sLastToken : pEnd;
+      n = (int)(pEnd2->z - pParse->sNameToken.z);
+      if( pEnd2->z[0]!=';' ) n += pEnd2->n;
       zStmt = sqlite3MPrintf(db, 
           "CREATE %s %.*s", zType2, n, pParse->sNameToken.z
       );
@@ -83849,7 +88028,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
 
     /* Reparse everything to update our internal data structures */
     sqlite3VdbeAddParseSchemaOp(v, iDb,
-               sqlite3MPrintf(db, "tbl_name='%q'", p->zName));
+           sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
   }
 
 
@@ -83919,9 +88098,8 @@ SQLITE_PRIVATE void sqlite3CreateView(
   }
   sqlite3TwoPartName(pParse, pName1, pName2, &pName);
   iDb = sqlite3SchemaToIndex(db, p->pSchema);
-  if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
-    && sqlite3FixSelect(&sFix, pSelect)
-  ){
+  sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
+  if( sqlite3FixSelect(&sFix, pSelect) ){
     sqlite3SelectDelete(db, pSelect);
     return;
   }
@@ -83955,7 +88133,7 @@ SQLITE_PRIVATE void sqlite3CreateView(
   sEnd.n = 1;
 
   /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
-  sqlite3EndTable(pParse, 0, &sEnd, 0);
+  sqlite3EndTable(pParse, 0, &sEnd, 0, 0);
   return;
 }
 #endif /* SQLITE_OMIT_VIEW */
@@ -84043,7 +88221,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
       pSelTab->aCol = 0;
       sqlite3DeleteTable(db, pSelTab);
       assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
-      pTable->pSchema->flags |= DB_UnresetViews;
+      pTable->pSchema->schemaFlags |= DB_UnresetViews;
     }else{
       pTable->nCol = 0;
       nErr++;
@@ -84221,7 +88399,7 @@ static void sqlite3ClearStatTables(
 ){
   int i;
   const char *zDbName = pParse->db->aDb[iDb].zName;
-  for(i=1; i<=3; i++){
+  for(i=1; i<=4; i++){
     char zTab[24];
     sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i);
     if( sqlite3FindTable(pParse->db, zTab, zDbName) ){
@@ -84410,8 +88588,8 @@ exit_drop_table:
 ** currently under construction.  pFromCol determines which columns
 ** in the current table point to the foreign key.  If pFromCol==0 then
 ** connect the key to the last column inserted.  pTo is the name of
-** the table referred to.  pToCol is a list of tables in the other
-** pTo table that the foreign key points to.  flags contains all
+** the table referred to (a.k.a the "parent" table).  pToCol is a list
+** of tables in the parent pTo table.  flags contains all
 ** information about the conflict resolution algorithms specified
 ** in the ON DELETE, ON UPDATE and ON INSERT clauses.
 **
@@ -84571,6 +88749,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   int addr1;                     /* Address of top of loop */
   int addr2;                     /* Address to jump to for next iteration */
   int tnum;                      /* Root page of index */
+  int iPartIdxLabel;             /* Jump to this label to skip a row */
   Vdbe *v;                       /* Generate code into this virtual machine */
   KeyInfo *pKey;                 /* KeyInfo for index */
   int regRecord;                 /* Register holding assemblied index record */
@@ -84593,36 +88772,39 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
     tnum = memRootPage;
   }else{
     tnum = pIndex->tnum;
-    sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
   }
-  pKey = sqlite3IndexKeyinfo(pParse, pIndex);
-  sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
-                    (char *)pKey, P4_KEYINFO_HANDOFF);
-  sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
+  pKey = sqlite3KeyInfoOfIndex(pParse, pIndex);
 
   /* Open the sorter cursor if we are to use one. */
   iSorter = pParse->nTab++;
-  sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
+  sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)
+                    sqlite3KeyInfoRef(pKey), P4_KEYINFO);
 
   /* Open the table. Loop through all rows of the table, inserting index
   ** records into the sorter. */
   sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
-  addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
+  addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v);
   regRecord = sqlite3GetTempReg(pParse);
 
-  sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
+  sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
   sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
-  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
+  sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
+  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
   sqlite3VdbeJumpHere(v, addr1);
-  addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
-  if( pIndex->onError!=OE_None ){
+  if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
+  sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
+                    (char *)pKey, P4_KEYINFO);
+  sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
+
+  addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
+  assert( pKey!=0 || db->mallocFailed || pParse->nErr );
+  if( IsUniqueIndex(pIndex) && pKey!=0 ){
     int j2 = sqlite3VdbeCurrentAddr(v) + 3;
     sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
     addr2 = sqlite3VdbeCurrentAddr(v);
-    sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
-    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
-        OE_Abort, "indexed columns are not unique", P4_STATIC
-    );
+    sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
+                         pIndex->nKeyCol); VdbeCoverage(v);
+    sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
   }else{
     addr2 = sqlite3VdbeCurrentAddr(v);
   }
@@ -84630,7 +88812,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
   sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
   sqlite3ReleaseTempReg(pParse, regRecord);
-  sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
+  sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
   sqlite3VdbeJumpHere(v, addr1);
 
   sqlite3VdbeAddOp1(v, OP_Close, iTab);
@@ -84639,6 +88821,41 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
 }
 
 /*
+** Allocate heap space to hold an Index object with nCol columns.
+**
+** Increase the allocation size to provide an extra nExtra bytes
+** of 8-byte aligned space after the Index object and return a
+** pointer to this extra space in *ppExtra.
+*/
+SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(
+  sqlite3 *db,         /* Database connection */
+  i16 nCol,            /* Total number of columns in the index */
+  int nExtra,          /* Number of bytes of extra space to alloc */
+  char **ppExtra       /* Pointer to the "extra" space */
+){
+  Index *p;            /* Allocated index object */
+  int nByte;           /* Bytes of space for Index object + arrays */
+
+  nByte = ROUND8(sizeof(Index)) +              /* Index structure  */
+          ROUND8(sizeof(char*)*nCol) +         /* Index.azColl     */
+          ROUND8(sizeof(LogEst)*(nCol+1) +     /* Index.aiRowLogEst   */
+                 sizeof(i16)*nCol +            /* Index.aiColumn   */
+                 sizeof(u8)*nCol);             /* Index.aSortOrder */
+  p = sqlite3DbMallocZero(db, nByte + nExtra);
+  if( p ){
+    char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
+    p->azColl = (char**)pExtra;       pExtra += ROUND8(sizeof(char*)*nCol);
+    p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
+    p->aiColumn = (i16*)pExtra;       pExtra += sizeof(i16)*nCol;
+    p->aSortOrder = (u8*)pExtra;
+    p->nColumn = nCol;
+    p->nKeyCol = nCol - 1;
+    *ppExtra = ((char*)p) + nByte;
+  }
+  return p;
+}
+
+/*
 ** Create a new index for an SQL table.  pName1.pName2 is the name of the index 
 ** and pTblList is the name of the table that is to be indexed.  Both will 
 ** be NULL for a primary key or an index that is created to satisfy a
@@ -84652,7 +88869,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
 **
 ** If the index is created successfully, return a pointer to the new Index
 ** structure. This is used by sqlite3AddPrimaryKey() to mark the index
-** as the tables primary key (Index.autoIndex==2).
+** as the tables primary key (Index.idxType==SQLITE_IDXTYPE_PRIMARYKEY)
 */
 SQLITE_PRIVATE Index *sqlite3CreateIndex(
   Parse *pParse,     /* All information about this parse */
@@ -84662,7 +88879,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
   ExprList *pList,   /* A list of columns to be indexed */
   int onError,       /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
   Token *pStart,     /* The CREATE token that begins this statement */
-  Token *pEnd,       /* The ")" that closes the CREATE INDEX statement */
+  Expr *pPIWhere,    /* WHERE clause for partial indices */
   int sortOrder,     /* Sort order of primary key when pList==NULL */
   int ifNotExist     /* Omit error if index already exists */
 ){
@@ -84672,7 +88889,6 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
   char *zName = 0;     /* Name of the index */
   int nName;           /* Number of characters in zName */
   int i, j;
-  Token nullId;        /* Fake token for an empty ID list */
   DbFixer sFix;        /* For assigning database names to pTable */
   int sortOrderMask;   /* 1 to honor DESC in index.  0 to ignore. */
   sqlite3 *db = pParse->db;
@@ -84680,11 +88896,12 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
   int iDb;             /* Index of the database that is being written */
   Token *pName = 0;    /* Unqualified name of the index to create */
   struct ExprList_item *pListItem; /* For looping over pList */
-  int nCol;
-  int nExtra = 0;
-  char *zExtra;
+  const Column *pTabCol;           /* A column in the table */
+  int nExtra = 0;                  /* Space allocated for zExtra[] */
+  int nExtraCol;                   /* Number of extra columns needed */
+  char *zExtra = 0;                /* Extra space after the Index object */
+  Index *pPk = 0;      /* PRIMARY KEY index for WITHOUT ROWID tables */
 
-  assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */
   assert( pParse->nErr==0 );      /* Never called with prior errors */
   if( db->mallocFailed || IN_DECLARE_VTAB ){
     goto exit_create_index;
@@ -84720,9 +88937,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
     }
 #endif
 
-    if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
-        sqlite3FixSrcList(&sFix, pTblName)
-    ){
+    sqlite3FixInit(&sFix, pParse, iDb, "index", pName);
+    if( sqlite3FixSrcList(&sFix, pTblName) ){
       /* Because the parser constructs pTblName from a single identifier,
       ** sqlite3FixSrcList can never fail. */
       assert(0);
@@ -84730,7 +88946,13 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
     pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
     assert( db->mallocFailed==0 || pTab==0 );
     if( pTab==0 ) goto exit_create_index;
-    assert( db->aDb[iDb].pSchema==pTab->pSchema );
+    if( iDb==1 && db->aDb[iDb].pSchema!=pTab->pSchema ){
+      sqlite3ErrorMsg(pParse, 
+           "cannot create a TEMP index on non-TEMP table \"%s\"",
+           pTab->zName);
+      goto exit_create_index;
+    }
+    if( !HasRowid(pTab) ) pPk = sqlite3PrimaryKeyIndex(pTab);
   }else{
     assert( pName==0 );
     assert( pStart==0 );
@@ -84826,11 +89048,10 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
   ** So create a fake list to simulate this.
   */
   if( pList==0 ){
-    nullId.z = pTab->aCol[pTab->nCol-1].zName;
-    nullId.n = sqlite3Strlen30((char*)nullId.z);
     pList = sqlite3ExprListAppend(pParse, 0, 0);
     if( pList==0 ) goto exit_create_index;
-    sqlite3ExprListSetName(pParse, pList, &nullId, 0);
+    pList->a[0].zName = sqlite3DbStrDup(pParse->db,
+                                        pTab->aCol[pTab->nCol-1].zName);
     pList->a[0].sortOrder = (u8)sortOrder;
   }
 
@@ -84849,35 +89070,28 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
   ** Allocate the index structure. 
   */
   nName = sqlite3Strlen30(zName);
-  nCol = pList->nExpr;
-  pIndex = sqlite3DbMallocZero(db, 
-      ROUND8(sizeof(Index)) +              /* Index structure  */
-      ROUND8(sizeof(tRowcnt)*(nCol+1)) +   /* Index.aiRowEst   */
-      sizeof(char *)*nCol +                /* Index.azColl     */
-      sizeof(int)*nCol +                   /* Index.aiColumn   */
-      sizeof(u8)*nCol +                    /* Index.aSortOrder */
-      nName + 1 +                          /* Index.zName      */
-      nExtra                               /* Collation sequence names */
-  );
+  nExtraCol = pPk ? pPk->nKeyCol : 1;
+  pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + nExtraCol,
+                                      nName + nExtra + 1, &zExtra);
   if( db->mallocFailed ){
     goto exit_create_index;
   }
-  zExtra = (char*)pIndex;
-  pIndex->aiRowEst = (tRowcnt*)&zExtra[ROUND8(sizeof(Index))];
-  pIndex->azColl = (char**)
-     ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1));
-  assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) );
+  assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowLogEst) );
   assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
-  pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]);
-  pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]);
-  pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]);
-  zExtra = (char *)(&pIndex->zName[nName+1]);
+  pIndex->zName = zExtra;
+  zExtra += nName + 1;
   memcpy(pIndex->zName, zName, nName+1);
   pIndex->pTable = pTab;
-  pIndex->nColumn = pList->nExpr;
   pIndex->onError = (u8)onError;
-  pIndex->autoIndex = (u8)(pName==0);
+  pIndex->uniqNotNull = onError!=OE_None;
+  pIndex->idxType = pName ? SQLITE_IDXTYPE_APPDEF : SQLITE_IDXTYPE_UNIQUE;
   pIndex->pSchema = db->aDb[iDb].pSchema;
+  pIndex->nKeyCol = pList->nExpr;
+  if( pPIWhere ){
+    sqlite3ResolveSelfReference(pParse, pTab, NC_PartIdx, pPIWhere, 0);
+    pIndex->pPartIdxWhere = pPIWhere;
+    pPIWhere = 0;
+  }
   assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
 
   /* Check to see if we should honor DESC requests on index columns
@@ -84900,7 +89114,6 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
   */
   for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
     const char *zColName = pListItem->zName;
-    Column *pTabCol;
     int requestedSortOrder;
     char *zColl;                   /* Collation sequence name */
 
@@ -84913,7 +89126,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
       pParse->checkSchema = 1;
       goto exit_create_index;
     }
-    pIndex->aiColumn[i] = j;
+    assert( pTab->nCol<=0x7fff && j<=0x7fff );
+    pIndex->aiColumn[i] = (i16)j;
     if( pListItem->pExpr ){
       int nColl;
       assert( pListItem->pExpr->op==TK_COLLATE );
@@ -84934,8 +89148,27 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
     pIndex->azColl[i] = zColl;
     requestedSortOrder = pListItem->sortOrder & sortOrderMask;
     pIndex->aSortOrder[i] = (u8)requestedSortOrder;
+    if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
+  }
+  if( pPk ){
+    for(j=0; j<pPk->nKeyCol; j++){
+      int x = pPk->aiColumn[j];
+      if( hasColumn(pIndex->aiColumn, pIndex->nKeyCol, x) ){
+        pIndex->nColumn--; 
+      }else{
+        pIndex->aiColumn[i] = x;
+        pIndex->azColl[i] = pPk->azColl[j];
+        pIndex->aSortOrder[i] = pPk->aSortOrder[j];
+        i++;
+      }
+    }
+    assert( i==pIndex->nColumn );
+  }else{
+    pIndex->aiColumn[i] = -1;
+    pIndex->azColl[i] = "BINARY";
   }
   sqlite3DefaultRowEst(pIndex);
+  if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
 
   if( pTab==pParse->pNewTable ){
     /* This routine has been called to create an automatic index as a
@@ -84962,12 +89195,12 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
     Index *pIdx;
     for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
       int k;
-      assert( pIdx->onError!=OE_None );
-      assert( pIdx->autoIndex );
-      assert( pIndex->onError!=OE_None );
+      assert( IsUniqueIndex(pIdx) );
+      assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF );
+      assert( IsUniqueIndex(pIndex) );
 
-      if( pIdx->nColumn!=pIndex->nColumn ) continue;
-      for(k=0; k<pIdx->nColumn; k++){
+      if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
+      for(k=0; k<pIdx->nKeyCol; k++){
         const char *z1;
         const char *z2;
         if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break;
@@ -84975,7 +89208,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
         z2 = pIndex->azColl[k];
         if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break;
       }
-      if( k==pIdx->nColumn ){
+      if( k==pIdx->nKeyCol ){
         if( pIdx->onError!=pIndex->onError ){
           /* This constraint creates the same index as a previous
           ** constraint specified somewhere in the CREATE TABLE statement.
@@ -85017,22 +89250,20 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
     }
   }
 
-  /* If the db->init.busy is 0 then create the index on disk.  This
-  ** involves writing the index into the master table and filling in the
-  ** index with the current table contents.
-  **
-  ** The db->init.busy is 0 when the user first enters a CREATE INDEX 
-  ** command.  db->init.busy is 1 when a database is opened and 
-  ** CREATE INDEX statements are read out of the master table.  In
-  ** the latter case the index already exists on disk, which is why
-  ** we don't want to recreate it.
+  /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
+  ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
+  ** emit code to allocate the index rootpage on disk and make an entry for
+  ** the index in the sqlite_master table and populate the index with
+  ** content.  But, do not do this if we are simply reading the sqlite_master
+  ** table to parse the schema, or if this index is the PRIMARY KEY index
+  ** of a WITHOUT ROWID table.
   **
-  ** If pTblName==0 it means this index is generated as a primary key
-  ** or UNIQUE constraint of a CREATE TABLE statement.  Since the table
+  ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY
+  ** or UNIQUE index in a CREATE TABLE statement.  Since the table
   ** has just been created, it contains no data and the index initialization
   ** step can be skipped.
   */
-  else{ /* if( db->init.busy==0 ) */
+  else if( pParse->nErr==0 && (HasRowid(pTab) || pTblName!=0) ){
     Vdbe *v;
     char *zStmt;
     int iMem = ++pParse->nMem;
@@ -85050,12 +89281,11 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
     ** the zStmt variable
     */
     if( pStart ){
-      assert( pEnd!=0 );
+      int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
+      if( pName->z[n-1]==';' ) n--;
       /* A named index with an explicit CREATE INDEX statement */
       zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
-        onError==OE_None ? "" : " UNIQUE",
-        (int)(pEnd->z - pName->z) + 1,
-        pName->z);
+        onError==OE_None ? "" : " UNIQUE", n, pName->z);
     }else{
       /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
       /* zStmt = sqlite3MPrintf(""); */
@@ -85111,10 +89341,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
 
   /* Clean up before exiting */
 exit_create_index:
-  if( pIndex ){
-    sqlite3DbFree(db, pIndex->zColAff);
-    sqlite3DbFree(db, pIndex);
-  }
+  if( pIndex ) freeIndex(db, pIndex);
+  sqlite3ExprDelete(db, pPIWhere);
   sqlite3ExprListDelete(db, pList);
   sqlite3SrcListDelete(db, pTblName);
   sqlite3DbFree(db, zName);
@@ -85129,7 +89357,7 @@ exit_create_index:
 ** Since we do not know, guess 1 million.  aiRowEst[1] is an estimate of the
 ** number of rows in the table that match any particular value of the
 ** first column of the index.  aiRowEst[2] is an estimate of the number
-** of rows that match any particular combiniation of the first 2 columns
+** of rows that match any particular combination of the first 2 columns
 ** of the index.  And so forth.  It must always be the case that
 *
 **           aiRowEst[N]<=aiRowEst[N-1]
@@ -85140,20 +89368,27 @@ exit_create_index:
 ** are based on typical values found in actual indices.
 */
 SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){
-  tRowcnt *a = pIdx->aiRowEst;
+  /*                10,  9,  8,  7,  6 */
+  LogEst aVal[] = { 33, 32, 30, 28, 26 };
+  LogEst *a = pIdx->aiRowLogEst;
+  int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
   int i;
-  tRowcnt n;
-  assert( a!=0 );
-  a[0] = pIdx->pTable->nRowEst;
-  if( a[0]<10 ) a[0] = 10;
-  n = 10;
-  for(i=1; i<=pIdx->nColumn; i++){
-    a[i] = n;
-    if( n>5 ) n--;
-  }
-  if( pIdx->onError!=OE_None ){
-    a[pIdx->nColumn] = 1;
+
+  /* Set the first entry (number of rows in the index) to the estimated 
+  ** number of rows in the table. Or 10, if the estimated number of rows 
+  ** in the table is less than that.  */
+  a[0] = pIdx->pTable->nRowLogEst;
+  if( a[0]<33 ) a[0] = 33;        assert( 33==sqlite3LogEst(10) );
+
+  /* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
+  ** 6 and each subsequent value (if any) is 5.  */
+  memcpy(&a[1], aVal, nCopy*sizeof(LogEst));
+  for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
+    a[i] = 23;                    assert( 23==sqlite3LogEst(5) );
   }
+
+  assert( 0==sqlite3LogEst(1) );
+  if( IsUniqueIndex(pIdx) ) a[pIdx->nKeyCol] = 0;
 }
 
 /*
@@ -85184,7 +89419,7 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists
     pParse->checkSchema = 1;
     goto exit_drop_index;
   }
-  if( pIndex->autoIndex ){
+  if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
     sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
       "or PRIMARY KEY constraint cannot be dropped", 0);
     goto exit_drop_index;
@@ -85353,7 +89588,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
   assert( iStart<=pSrc->nSrc );
 
   /* Allocate additional space if needed */
-  if( pSrc->nSrc+nExtra>pSrc->nAlloc ){
+  if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
     SrcList *pNew;
     int nAlloc = pSrc->nSrc+nExtra;
     int nGot;
@@ -85365,7 +89600,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
     }
     pSrc = pNew;
     nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
-    pSrc->nAlloc = (u16)nGot;
+    pSrc->nAlloc = nGot;
   }
 
   /* Move existing slots that come after the newly inserted slots
@@ -85373,7 +89608,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
   for(i=pSrc->nSrc-1; i>=iStart; i--){
     pSrc->a[i+nExtra] = pSrc->a[i];
   }
-  pSrc->nSrc += (i16)nExtra;
+  pSrc->nSrc += nExtra;
 
   /* Zero the newly allocated slots */
   memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
@@ -85705,59 +89940,24 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
 }
 
 /*
-** Generate VDBE code that will verify the schema cookie and start
-** a read-transaction for all named database files.
-**
-** It is important that all schema cookies be verified and all
-** read transactions be started before anything else happens in
-** the VDBE program.  But this routine can be called after much other
-** code has been generated.  So here is what we do:
-**
-** The first time this routine is called, we code an OP_Goto that
-** will jump to a subroutine at the end of the program.  Then we
-** record every database that needs its schema verified in the
-** pParse->cookieMask field.  Later, after all other code has been
-** generated, the subroutine that does the cookie verifications and
-** starts the transactions will be coded and the OP_Goto P2 value
-** will be made to point to that subroutine.  The generation of the
-** cookie verification subroutine code happens in sqlite3FinishCoding().
-**
-** If iDb<0 then code the OP_Goto only - don't set flag to verify the
-** schema on any databases.  This can be used to position the OP_Goto
-** early in the code, before we know if any database tables will be used.
+** Record the fact that the schema cookie will need to be verified
+** for database iDb.  The code to actually verify the schema cookie
+** will occur at the end of the top-level VDBE and will be generated
+** later, by sqlite3FinishCoding().
 */
 SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
   Parse *pToplevel = sqlite3ParseToplevel(pParse);
+  sqlite3 *db = pToplevel->db;
 
-#ifndef SQLITE_OMIT_TRIGGER
-  if( pToplevel!=pParse ){
-    /* This branch is taken if a trigger is currently being coded. In this
-    ** case, set cookieGoto to a non-zero value to show that this function
-    ** has been called. This is used by the sqlite3ExprCodeConstants()
-    ** function. */
-    pParse->cookieGoto = -1;
-  }
-#endif
-  if( pToplevel->cookieGoto==0 ){
-    Vdbe *v = sqlite3GetVdbe(pToplevel);
-    if( v==0 ) return;  /* This only happens if there was a prior error */
-    pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1;
-  }
-  if( iDb>=0 ){
-    sqlite3 *db = pToplevel->db;
-    yDbMask mask;
-
-    assert( iDb<db->nDb );
-    assert( db->aDb[iDb].pBt!=0 || iDb==1 );
-    assert( iDb<SQLITE_MAX_ATTACHED+2 );
-    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
-    mask = ((yDbMask)1)<<iDb;
-    if( (pToplevel->cookieMask & mask)==0 ){
-      pToplevel->cookieMask |= mask;
-      pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
-      if( !OMIT_TEMPDB && iDb==1 ){
-        sqlite3OpenTempDatabase(pToplevel);
-      }
+  assert( iDb>=0 && iDb<db->nDb );
+  assert( db->aDb[iDb].pBt!=0 || iDb==1 );
+  assert( iDb<SQLITE_MAX_ATTACHED+2 );
+  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+  if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
+    DbMaskSet(pToplevel->cookieMask, iDb);
+    pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
+    if( !OMIT_TEMPDB && iDb==1 ){
+      sqlite3OpenTempDatabase(pToplevel);
     }
   }
 }
@@ -85793,7 +89993,7 @@ SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb)
 SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
   Parse *pToplevel = sqlite3ParseToplevel(pParse);
   sqlite3CodeVerifySchema(pParse, iDb);
-  pToplevel->writeMask |= ((yDbMask)1)<<iDb;
+  DbMaskSet(pToplevel->writeMask, iDb);
   pToplevel->isMultiWrite |= setStatement;
 }
 
@@ -85840,7 +90040,8 @@ SQLITE_PRIVATE void sqlite3HaltConstraint(
   int errCode,      /* extended error code */
   int onError,      /* Constraint type */
   char *p4,         /* Error message */
-  int p4type        /* P4_STATIC or P4_TRANSIENT */
+  i8 p4type,        /* P4_STATIC or P4_TRANSIENT */
+  u8 p5Errmsg       /* P5_ErrMsg type */
 ){
   Vdbe *v = sqlite3GetVdbe(pParse);
   assert( (errCode&0xff)==SQLITE_CONSTRAINT );
@@ -85848,6 +90049,59 @@ SQLITE_PRIVATE void sqlite3HaltConstraint(
     sqlite3MayAbort(pParse);
   }
   sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
+  if( p5Errmsg ) sqlite3VdbeChangeP5(v, p5Errmsg);
+}
+
+/*
+** Code an OP_Halt due to UNIQUE or PRIMARY KEY constraint violation.
+*/
+SQLITE_PRIVATE void sqlite3UniqueConstraint(
+  Parse *pParse,    /* Parsing context */
+  int onError,      /* Constraint type */
+  Index *pIdx       /* The index that triggers the constraint */
+){
+  char *zErr;
+  int j;
+  StrAccum errMsg;
+  Table *pTab = pIdx->pTable;
+
+  sqlite3StrAccumInit(&errMsg, 0, 0, 200);
+  errMsg.db = pParse->db;
+  for(j=0; j<pIdx->nKeyCol; j++){
+    char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
+    if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2);
+    sqlite3StrAccumAppendAll(&errMsg, pTab->zName);
+    sqlite3StrAccumAppend(&errMsg, ".", 1);
+    sqlite3StrAccumAppendAll(&errMsg, zCol);
+  }
+  zErr = sqlite3StrAccumFinish(&errMsg);
+  sqlite3HaltConstraint(pParse, 
+    IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY 
+                            : SQLITE_CONSTRAINT_UNIQUE,
+    onError, zErr, P4_DYNAMIC, P5_ConstraintUnique);
+}
+
+
+/*
+** Code an OP_Halt due to non-unique rowid.
+*/
+SQLITE_PRIVATE void sqlite3RowidConstraint(
+  Parse *pParse,    /* Parsing context */
+  int onError,      /* Conflict resolution algorithm */
+  Table *pTab       /* The table with the non-unique rowid */ 
+){
+  char *zMsg;
+  int rc;
+  if( pTab->iPKey>=0 ){
+    zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName,
+                          pTab->aCol[pTab->iPKey].zName);
+    rc = SQLITE_CONSTRAINT_PRIMARYKEY;
+  }else{
+    zMsg = sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName);
+    rc = SQLITE_CONSTRAINT_ROWID;
+  }
+  sqlite3HaltConstraint(pParse, rc, onError, zMsg, P4_DYNAMIC,
+                        P5_ConstraintUnique);
 }
 
 /*
@@ -85860,8 +90114,8 @@ static int collationMatch(const char *zColl, Index *pIndex){
   assert( zColl!=0 );
   for(i=0; i<pIndex->nColumn; i++){
     const char *z = pIndex->azColl[i];
-    assert( z!=0 );
-    if( 0==sqlite3StrICmp(z, zColl) ){
+    assert( z!=0 || pIndex->aiColumn[i]<0 );
+    if( pIndex->aiColumn[i]>=0 && 0==sqlite3StrICmp(z, zColl) ){
       return 1;
     }
   }
@@ -85980,42 +90234,122 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
 #endif
 
 /*
-** Return a dynamicly allocated KeyInfo structure that can be used
-** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
+** Return a KeyInfo structure that is appropriate for the given Index.
 **
-** If successful, a pointer to the new structure is returned. In this case
-** the caller is responsible for calling sqlite3DbFree(db, ) on the returned 
-** pointer. If an error occurs (out of memory or missing collation 
-** sequence), NULL is returned and the state of pParse updated to reflect
-** the error.
+** The KeyInfo structure for an index is cached in the Index object.
+** So there might be multiple references to the returned pointer.  The
+** caller should not try to modify the KeyInfo object.
+**
+** The caller should invoke sqlite3KeyInfoUnref() on the returned object
+** when it has finished using it.
 */
-SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
-  int i;
-  int nCol = pIdx->nColumn;
-  int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol;
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
+  if( pParse->nErr ) return 0;
+#ifndef SQLITE_OMIT_SHARED_CACHE
+  if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){
+    sqlite3KeyInfoUnref(pIdx->pKeyInfo);
+    pIdx->pKeyInfo = 0;
+  }
+#endif
+  if( pIdx->pKeyInfo==0 ){
+    int i;
+    int nCol = pIdx->nColumn;
+    int nKey = pIdx->nKeyCol;
+    KeyInfo *pKey;
+    if( pIdx->uniqNotNull ){
+      pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
+    }else{
+      pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
+    }
+    if( pKey ){
+      assert( sqlite3KeyInfoIsWriteable(pKey) );
+      for(i=0; i<nCol; i++){
+        char *zColl = pIdx->azColl[i];
+        assert( zColl!=0 );
+        pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
+                          sqlite3LocateCollSeq(pParse, zColl);
+        pKey->aSortOrder[i] = pIdx->aSortOrder[i];
+      }
+      if( pParse->nErr ){
+        sqlite3KeyInfoUnref(pKey);
+      }else{
+        pIdx->pKeyInfo = pKey;
+      }
+    }
+  }
+  return sqlite3KeyInfoRef(pIdx->pKeyInfo);
+}
+
+#ifndef SQLITE_OMIT_CTE
+/* 
+** This routine is invoked once per CTE by the parser while parsing a 
+** WITH clause. 
+*/
+SQLITE_PRIVATE With *sqlite3WithAdd(
+  Parse *pParse,          /* Parsing context */
+  With *pWith,            /* Existing WITH clause, or NULL */
+  Token *pName,           /* Name of the common-table */
+  ExprList *pArglist,     /* Optional column name list for the table */
+  Select *pQuery          /* Query used to initialize the table */
+){
   sqlite3 *db = pParse->db;
-  KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(db, nBytes);
+  With *pNew;
+  char *zName;
 
-  if( pKey ){
-    pKey->db = pParse->db;
-    pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]);
-    assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) );
-    for(i=0; i<nCol; i++){
-      char *zColl = pIdx->azColl[i];
-      assert( zColl );
-      pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl);
-      pKey->aSortOrder[i] = pIdx->aSortOrder[i];
+  /* Check that the CTE name is unique within this WITH clause. If
+  ** not, store an error in the Parse structure. */
+  zName = sqlite3NameFromToken(pParse->db, pName);
+  if( zName && pWith ){
+    int i;
+    for(i=0; i<pWith->nCte; i++){
+      if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){
+        sqlite3ErrorMsg(pParse, "duplicate WITH table name: %s", zName);
+      }
     }
-    pKey->nField = (u16)nCol;
   }
 
-  if( pParse->nErr ){
-    sqlite3DbFree(db, pKey);
-    pKey = 0;
+  if( pWith ){
+    int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
+    pNew = sqlite3DbRealloc(db, pWith, nByte);
+  }else{
+    pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
   }
-  return pKey;
+  assert( zName!=0 || pNew==0 );
+  assert( db->mallocFailed==0 || pNew==0 );
+
+  if( pNew==0 ){
+    sqlite3ExprListDelete(db, pArglist);
+    sqlite3SelectDelete(db, pQuery);
+    sqlite3DbFree(db, zName);
+    pNew = pWith;
+  }else{
+    pNew->a[pNew->nCte].pSelect = pQuery;
+    pNew->a[pNew->nCte].pCols = pArglist;
+    pNew->a[pNew->nCte].zName = zName;
+    pNew->a[pNew->nCte].zErr = 0;
+    pNew->nCte++;
+  }
+
+  return pNew;
 }
 
+/*
+** Free the contents of the With object passed as the second argument.
+*/
+SQLITE_PRIVATE void sqlite3WithDelete(sqlite3 *db, With *pWith){
+  if( pWith ){
+    int i;
+    for(i=0; i<pWith->nCte; i++){
+      struct Cte *pCte = &pWith->a[i];
+      sqlite3ExprListDelete(db, pCte->pCols);
+      sqlite3SelectDelete(db, pCte->pSelect);
+      sqlite3DbFree(db, pCte->zName);
+    }
+    sqlite3DbFree(db, pWith);
+  }
+}
+#endif /* !defined(SQLITE_OMIT_CTE) */
+
 /************** End of build.c ***********************************************/
 /************** Begin file callback.c ****************************************/
 /*
@@ -86289,9 +90623,9 @@ static int matchQuality(
   }
 
   /* Bonus points if the text encoding matches */
-  if( enc==p->iPrefEnc ){
+  if( enc==(p->funcFlags & SQLITE_FUNC_ENCMASK) ){
     match += 2;  /* Exact encoding match */
-  }else if( (enc & p->iPrefEnc & 2)!=0 ){
+  }else if( (enc & p->funcFlags & 2)!=0 ){
     match += 1;  /* Both are UTF16, but with different byte orders */
   }
 
@@ -86376,7 +90710,6 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
 
   assert( nArg>=(-2) );
   assert( nArg>=(-1) || createFlag==0 );
-  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
   h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
 
   /* First search for a match amongst the application-defined functions.
@@ -86425,7 +90758,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
       (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
     pBest->zName = (char *)&pBest[1];
     pBest->nArg = (u16)nArg;
-    pBest->iPrefEnc = enc;
+    pBest->funcFlags = enc;
     memcpy(pBest->zName, zName, nName);
     pBest->zName[nName] = 0;
     sqlite3FuncDefInsert(&db->aFunc, pBest);
@@ -86467,9 +90800,9 @@ SQLITE_PRIVATE void sqlite3SchemaClear(void *p){
   sqlite3HashClear(&temp1);
   sqlite3HashClear(&pSchema->fkeyHash);
   pSchema->pSeqTab = 0;
-  if( pSchema->flags & DB_SchemaLoaded ){
+  if( pSchema->schemaFlags & DB_SchemaLoaded ){
     pSchema->iGeneration++;
-    pSchema->flags &= ~DB_SchemaLoaded;
+    pSchema->schemaFlags &= ~DB_SchemaLoaded;
   }
 }
 
@@ -86596,10 +90929,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
   SrcList *pFrom;
   sqlite3 *db = pParse->db;
   int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
-
   pWhere = sqlite3ExprDup(db, pWhere, 0);
   pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
-
   if( pFrom ){
     assert( pFrom->nSrc==1 );
     pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
@@ -86607,10 +90938,7 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
     assert( pFrom->a[0].pOn==0 );
     assert( pFrom->a[0].pUsing==0 );
   }
-
   pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
-  if( pSel ) pSel->selFlags |= SF_Materialize;
-
   sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
   sqlite3Select(pParse, pSel, &dest);
   sqlite3SelectDelete(db, pSel);
@@ -86633,7 +90961,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
   ExprList *pOrderBy,          /* The ORDER BY clause.  May be null */
   Expr *pLimit,                /* The LIMIT clause.  May be null */
   Expr *pOffset,               /* The OFFSET clause.  May be null */
-  char *zStmtType              /* Either DELETE or UPDATE.  For error messages. */
+  char *zStmtType              /* Either DELETE or UPDATE.  For err msgs. */
 ){
   Expr *pWhereRowid = NULL;    /* WHERE rowid .. */
   Expr *pInClause = NULL;      /* WHERE rowid IN ( select ) */
@@ -86708,7 +91036,8 @@ limit_where_cleanup_2:
   sqlite3ExprDelete(pParse->db, pOffset);
   return 0;
 }
-#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
+#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */
+       /*      && !defined(SQLITE_OMIT_SUBQUERY) */
 
 /*
 ** Generate code for a DELETE FROM statement.
@@ -86725,18 +91054,34 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
   Vdbe *v;               /* The virtual database engine */
   Table *pTab;           /* The table from which records will be deleted */
   const char *zDb;       /* Name of database holding pTab */
-  int end, addr = 0;     /* A couple addresses of generated code */
   int i;                 /* Loop counter */
   WhereInfo *pWInfo;     /* Information about the WHERE clause */
   Index *pIdx;           /* For looping over indices of the table */
-  int iCur;              /* VDBE Cursor number for pTab */
+  int iTabCur;           /* Cursor number for the table */
+  int iDataCur;          /* VDBE cursor for the canonical data source */
+  int iIdxCur;           /* Cursor number of the first index */
+  int nIdx;              /* Number of indices */
   sqlite3 *db;           /* Main database structure */
   AuthContext sContext;  /* Authorization context */
   NameContext sNC;       /* Name context to resolve expressions in */
   int iDb;               /* Database number */
   int memCnt = -1;       /* Memory cell used for change counting */
   int rcauth;            /* Value returned by authorization callback */
-
+  int okOnePass;         /* True for one-pass algorithm without the FIFO */
+  int aiCurOnePass[2];   /* The write cursors opened by WHERE_ONEPASS */
+  u8 *aToOpen = 0;       /* Open cursor iTabCur+j if aToOpen[j] is true */
+  Index *pPk;            /* The PRIMARY KEY index on the table */
+  int iPk = 0;           /* First of nPk registers holding PRIMARY KEY value */
+  i16 nPk = 1;           /* Number of columns in the PRIMARY KEY */
+  int iKey;              /* Memory cell holding key of row to be deleted */
+  i16 nKey;              /* Number of memory cells in the row key */
+  int iEphCur = 0;       /* Ephemeral table holding all primary key values */
+  int iRowSet = 0;       /* Register for rowset of rows to delete */
+  int addrBypass = 0;    /* Address of jump over the delete logic */
+  int addrLoop = 0;      /* Top of the delete loop */
+  int addrDelete = 0;    /* Jump directly to the delete logic */
+  int addrEphOpen = 0;   /* Instruction to open the Ephermeral table */
+ 
 #ifndef SQLITE_OMIT_TRIGGER
   int isView;                  /* True if attempting to delete from a view */
   Trigger *pTrigger;           /* List of table triggers, if required */
@@ -86791,11 +91136,11 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
   }
   assert(!isView || pTrigger);
 
-  /* Assign  cursor number to the table and all its indices.
+  /* Assign cursor numbers to the table and all its indices.
   */
   assert( pTabList->nSrc==1 );
-  iCur = pTabList->a[0].iCursor = pParse->nTab++;
-  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+  iTabCur = pTabList->a[0].iCursor = pParse->nTab++;
+  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
     pParse->nTab++;
   }
 
@@ -86819,7 +91164,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
   */
 #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
   if( isView ){
-    sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
+    sqlite3MaterializeView(pParse, pTab, pWhere, iTabCur);
+    iDataCur = iIdxCur = iTabCur;
   }
 #endif
 
@@ -86849,78 +91195,171 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
    && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
   ){
     assert( !isView );
-    sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
-                      pTab->zName, P4_STATIC);
+    sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
+    if( HasRowid(pTab) ){
+      sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
+                        pTab->zName, P4_STATIC);
+    }
     for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
       assert( pIdx->pSchema==pTab->pSchema );
       sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
     }
   }else
 #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
-  /* The usual case: There is a WHERE clause so we have to scan through
-  ** the table and pick which records to delete.
-  */
   {
-    int iRowSet = ++pParse->nMem;   /* Register for rowset of rows to delete */
-    int iRowid = ++pParse->nMem;    /* Used for storing rowid values. */
-    int regRowid;                   /* Actual register containing rowids */
-
-    /* Collect rowids of every row to be deleted.
+    if( HasRowid(pTab) ){
+      /* For a rowid table, initialize the RowSet to an empty set */
+      pPk = 0;
+      nPk = 1;
+      iRowSet = ++pParse->nMem;
+      sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
+    }else{
+      /* For a WITHOUT ROWID table, create an ephermeral table used to
+      ** hold all primary keys for rows to be deleted. */
+      pPk = sqlite3PrimaryKeyIndex(pTab);
+      assert( pPk!=0 );
+      nPk = pPk->nKeyCol;
+      iPk = pParse->nMem+1;
+      pParse->nMem += nPk;
+      iEphCur = pParse->nTab++;
+      addrEphOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEphCur, nPk);
+      sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+    }
+  
+    /* Construct a query to find the rowid or primary key for every row
+    ** to be deleted, based on the WHERE clause.
     */
-    sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
-    pWInfo = sqlite3WhereBegin(
-        pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0
-    );
+    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 
+                               WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK,
+                               iTabCur+1);
     if( pWInfo==0 ) goto delete_from_cleanup;
-    regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
-    sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
+    okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+  
+    /* Keep track of the number of rows to be deleted */
     if( db->flags & SQLITE_CountRows ){
       sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
     }
+  
+    /* Extract the rowid or primary key for the current row */
+    if( pPk ){
+      for(i=0; i<nPk; i++){
+        sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
+                                        pPk->aiColumn[i], iPk+i);
+      }
+      iKey = iPk;
+    }else{
+      iKey = pParse->nMem + 1;
+      iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0);
+      if( iKey>pParse->nMem ) pParse->nMem = iKey;
+    }
+  
+    if( okOnePass ){
+      /* For ONEPASS, no need to store the rowid/primary-key.  There is only
+      ** one, so just keep it in its register(s) and fall through to the
+      ** delete code.
+      */
+      nKey = nPk; /* OP_Found will use an unpacked key */
+      aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
+      if( aToOpen==0 ){
+        sqlite3WhereEnd(pWInfo);
+        goto delete_from_cleanup;
+      }
+      memset(aToOpen, 1, nIdx+1);
+      aToOpen[nIdx+1] = 0;
+      if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
+      if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
+      if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
+      addrDelete = sqlite3VdbeAddOp0(v, OP_Goto); /* Jump to DELETE logic */
+    }else if( pPk ){
+      /* Construct a composite key for the row to be deleted and remember it */
+      iKey = ++pParse->nMem;
+      nKey = 0;   /* Zero tells OP_Found to use a composite key */
+      sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
+                        sqlite3IndexAffinityStr(v, pPk), nPk);
+      sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey);
+    }else{
+      /* Get the rowid of the row to be deleted and remember it in the RowSet */
+      nKey = 1;  /* OP_Seek always uses a single rowid */
+      sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
+    }
+  
+    /* End of the WHERE loop */
     sqlite3WhereEnd(pWInfo);
-
-    /* Delete every item whose key was written to the list during the
-    ** database scan.  We have to delete items after the scan is complete
-    ** because deleting an item can change the scan order.  */
-    end = sqlite3VdbeMakeLabel(v);
-
+    if( okOnePass ){
+      /* Bypass the delete logic below if the WHERE loop found zero rows */
+      addrBypass = sqlite3VdbeMakeLabel(v);
+      sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBypass);
+      sqlite3VdbeJumpHere(v, addrDelete);
+    }
+  
     /* Unless this is a view, open cursors for the table we are 
     ** deleting from and all its indices. If this is a view, then the
     ** only effect this statement has is to fire the INSTEAD OF 
-    ** triggers.  */
+    ** triggers.
+    */
     if( !isView ){
-      sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
+      sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
+                                 &iDataCur, &iIdxCur);
+      assert( pPk || iDataCur==iTabCur );
+      assert( pPk || iIdxCur==iDataCur+1 );
     }
-
-    addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
-
+  
+    /* Set up a loop over the rowids/primary-keys that were found in the
+    ** where-clause loop above.
+    */
+    if( okOnePass ){
+      /* Just one row.  Hence the top-of-loop is a no-op */
+      assert( nKey==nPk ); /* OP_Found will use an unpacked key */
+      if( aToOpen[iDataCur-iTabCur] ){
+        assert( pPk!=0 );
+        sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
+        VdbeCoverage(v);
+      }
+    }else if( pPk ){
+      addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
+      sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey);
+      assert( nKey==0 );  /* OP_Found will use a composite key */
+    }else{
+      addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey);
+      VdbeCoverage(v);
+      assert( nKey==1 );
+    }  
+  
     /* Delete the row */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
     if( IsVirtual(pTab) ){
       const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
       sqlite3VtabMakeWritable(pParse, pTab);
-      sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
+      sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
       sqlite3VdbeChangeP5(v, OE_Abort);
       sqlite3MayAbort(pParse);
     }else
 #endif
     {
       int count = (pParse->nested==0);    /* True to count changes */
-      sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, count, pTrigger, OE_Default);
+      sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
+                               iKey, nKey, count, OE_Default, okOnePass);
     }
-
-    /* End of the delete loop */
-    sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
-    sqlite3VdbeResolveLabel(v, end);
-
+  
+    /* End of the loop over all rowids/primary-keys. */
+    if( okOnePass ){
+      sqlite3VdbeResolveLabel(v, addrBypass);
+    }else if( pPk ){
+      sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v);
+      sqlite3VdbeJumpHere(v, addrLoop);
+    }else{
+      sqlite3VdbeAddOp2(v, OP_Goto, 0, addrLoop);
+      sqlite3VdbeJumpHere(v, addrLoop);
+    }     
+  
     /* Close the cursors open on the table and its indexes. */
     if( !isView && !IsVirtual(pTab) ){
-      for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
-        sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum);
+      if( !pPk ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur);
+      for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
+        sqlite3VdbeAddOp1(v, OP_Close, iIdxCur + i);
       }
-      sqlite3VdbeAddOp1(v, OP_Close, iCur);
     }
-  }
+  } /* End non-truncate path */
 
   /* Update the sqlite_sequence table by storing the content of the
   ** maximum rowid counter values recorded while inserting into
@@ -86944,6 +91383,7 @@ delete_from_cleanup:
   sqlite3AuthContextPop(&sContext);
   sqlite3SrcListDelete(db, pTabList);
   sqlite3ExprDelete(db, pWhere);
+  sqlite3DbFree(db, aToOpen);
   return;
 }
 /* Make sure "isView" and other macros defined above are undefined. Otherwise
@@ -86958,50 +91398,63 @@ delete_from_cleanup:
 
 /*
 ** This routine generates VDBE code that causes a single row of a
-** single table to be deleted.
+** single table to be deleted.  Both the original table entry and
+** all indices are removed.
 **
-** The VDBE must be in a particular state when this routine is called.
-** These are the requirements:
+** Preconditions:
 **
-**   1.  A read/write cursor pointing to pTab, the table containing the row
-**       to be deleted, must be opened as cursor number $iCur.
+**   1.  iDataCur is an open cursor on the btree that is the canonical data
+**       store for the table.  (This will be either the table itself,
+**       in the case of a rowid table, or the PRIMARY KEY index in the case
+**       of a WITHOUT ROWID table.)
 **
 **   2.  Read/write cursors for all indices of pTab must be open as
-**       cursor number base+i for the i-th index.
+**       cursor number iIdxCur+i for the i-th index.
 **
-**   3.  The record number of the row to be deleted must be stored in
-**       memory cell iRowid.
-**
-** This routine generates code to remove both the table record and all 
-** index entries that point to that record.
+**   3.  The primary key for the row to be deleted must be stored in a
+**       sequence of nPk memory cells starting at iPk.  If nPk==0 that means
+**       that a search record formed from OP_MakeRecord is contained in the
+**       single memory location iPk.
 */
 SQLITE_PRIVATE void sqlite3GenerateRowDelete(
   Parse *pParse,     /* Parsing context */
   Table *pTab,       /* Table containing the row to be deleted */
-  int iCur,          /* Cursor number for the table */
-  int iRowid,        /* Memory cell that contains the rowid to delete */
-  int count,         /* If non-zero, increment the row change counter */
   Trigger *pTrigger, /* List of triggers to (potentially) fire */
-  int onconf         /* Default ON CONFLICT policy for triggers */
+  int iDataCur,      /* Cursor from which column data is extracted */
+  int iIdxCur,       /* First index cursor */
+  int iPk,           /* First memory cell containing the PRIMARY KEY */
+  i16 nPk,           /* Number of PRIMARY KEY memory cells */
+  u8 count,          /* If non-zero, increment the row change counter */
+  u8 onconf,         /* Default ON CONFLICT policy for triggers */
+  u8 bNoSeek         /* iDataCur is already pointing to the row to delete */
 ){
   Vdbe *v = pParse->pVdbe;        /* Vdbe */
   int iOld = 0;                   /* First register in OLD.* array */
   int iLabel;                     /* Label resolved to end of generated code */
+  u8 opSeek;                      /* Seek opcode */
 
   /* Vdbe is guaranteed to have been allocated by this stage. */
   assert( v );
+  VdbeModuleComment((v, "BEGIN: GenRowDel(%d,%d,%d,%d)",
+                         iDataCur, iIdxCur, iPk, (int)nPk));
 
   /* Seek cursor iCur to the row to delete. If this row no longer exists 
   ** (this can happen if a trigger program has already deleted it), do
   ** not attempt to delete it or fire any DELETE triggers.  */
   iLabel = sqlite3VdbeMakeLabel(v);
-  sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
+  opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
+  if( !bNoSeek ){
+    sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
+    VdbeCoverageIf(v, opSeek==OP_NotExists);
+    VdbeCoverageIf(v, opSeek==OP_NotFound);
+  }
  
   /* If there are any triggers to fire, allocate a range of registers to
   ** use for the old.* references in the triggers.  */
   if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
     u32 mask;                     /* Mask of OLD.* columns in use */
     int iCol;                     /* Iterator used while populating OLD.* */
+    int addrStart;                /* Start of BEFORE trigger programs */
 
     /* TODO: Could use temporary registers here. Also could attempt to
     ** avoid copying the contents of the rowid register.  */
@@ -87014,36 +91467,44 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
 
     /* Populate the OLD.* pseudo-table register array. These values will be 
     ** used by any BEFORE and AFTER triggers that exist.  */
-    sqlite3VdbeAddOp2(v, OP_Copy, iRowid, iOld);
+    sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
     for(iCol=0; iCol<pTab->nCol; iCol++){
-      if( mask==0xffffffff || mask&(1<<iCol) ){
-        sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, iOld+iCol+1);
+      testcase( mask!=0xffffffff && iCol==31 );
+      testcase( mask!=0xffffffff && iCol==32 );
+      if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
+        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
       }
     }
 
     /* Invoke BEFORE DELETE trigger programs. */
+    addrStart = sqlite3VdbeCurrentAddr(v);
     sqlite3CodeRowTrigger(pParse, pTrigger, 
         TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
     );
 
-    /* Seek the cursor to the row to be deleted again. It may be that
-    ** the BEFORE triggers coded above have already removed the row
-    ** being deleted. Do not attempt to delete the row a second time, and 
-    ** do not fire AFTER triggers.  */
-    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
+    /* If any BEFORE triggers were coded, then seek the cursor to the 
+    ** row to be deleted again. It may be that the BEFORE triggers moved
+    ** the cursor or of already deleted the row that the cursor was
+    ** pointing to.
+    */
+    if( addrStart<sqlite3VdbeCurrentAddr(v) ){
+      sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
+      VdbeCoverageIf(v, opSeek==OP_NotExists);
+      VdbeCoverageIf(v, opSeek==OP_NotFound);
+    }
 
     /* Do FK processing. This call checks that any FK constraints that
     ** refer to this table (i.e. constraints attached to other tables) 
     ** are not violated by deleting this row.  */
-    sqlite3FkCheck(pParse, pTab, iOld, 0);
+    sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0);
   }
 
   /* Delete the index and table entries. Skip this step if pTab is really
   ** a view (in which case the only effect of the DELETE statement is to
   ** fire the INSTEAD OF triggers).  */ 
   if( pTab->pSelect==0 ){
-    sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0);
-    sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
+    sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0);
+    sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
     if( count ){
       sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
     }
@@ -87052,7 +91513,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
   /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
   ** handle rows (possibly in other tables) that refer via a foreign key
   ** to the row just deleted. */ 
-  sqlite3FkActions(pParse, pTab, 0, iOld);
+  sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0);
 
   /* Invoke AFTER DELETE trigger programs. */
   sqlite3CodeRowTrigger(pParse, pTrigger, 
@@ -87063,58 +91524,98 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
   ** trigger programs were invoked. Or if a trigger program throws a 
   ** RAISE(IGNORE) exception.  */
   sqlite3VdbeResolveLabel(v, iLabel);
+  VdbeModuleComment((v, "END: GenRowDel()"));
 }
 
 /*
 ** This routine generates VDBE code that causes the deletion of all
-** index entries associated with a single row of a single table.
+** index entries associated with a single row of a single table, pTab
 **
-** The VDBE must be in a particular state when this routine is called.
-** These are the requirements:
+** Preconditions:
 **
-**   1.  A read/write cursor pointing to pTab, the table containing the row
-**       to be deleted, must be opened as cursor number "iCur".
+**   1.  A read/write cursor "iDataCur" must be open on the canonical storage
+**       btree for the table pTab.  (This will be either the table itself
+**       for rowid tables or to the primary key index for WITHOUT ROWID
+**       tables.)
 **
 **   2.  Read/write cursors for all indices of pTab must be open as
-**       cursor number iCur+i for the i-th index.
+**       cursor number iIdxCur+i for the i-th index.  (The pTab->pIndex
+**       index is the 0-th index.)
 **
-**   3.  The "iCur" cursor must be pointing to the row that is to be
-**       deleted.
+**   3.  The "iDataCur" cursor must be already be positioned on the row
+**       that is to be deleted.
 */
 SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(
   Parse *pParse,     /* Parsing and code generating context */
   Table *pTab,       /* Table containing the row to be deleted */
-  int iCur,          /* Cursor number for the table */
+  int iDataCur,      /* Cursor of table holding data. */
+  int iIdxCur,       /* First index cursor */
   int *aRegIdx       /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
 ){
-  int i;
-  Index *pIdx;
-  int r1;
+  int i;             /* Index loop counter */
+  int r1 = -1;       /* Register holding an index key */
+  int iPartIdxLabel; /* Jump destination for skipping partial index entries */
+  Index *pIdx;       /* Current index */
+  Index *pPrior = 0; /* Prior index */
+  Vdbe *v;           /* The prepared statement under construction */
+  Index *pPk;        /* PRIMARY KEY index, or NULL for rowid tables */
 
-  for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
-    if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
-    r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0);
-    sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);
+  v = pParse->pVdbe;
+  pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
+  for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
+    assert( iIdxCur+i!=iDataCur || pPk==pIdx );
+    if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
+    if( pIdx==pPk ) continue;
+    VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
+    r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
+                                 &iPartIdxLabel, pPrior, r1);
+    sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
+                      pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
+    sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
+    pPrior = pIdx;
   }
 }
 
 /*
-** Generate code that will assemble an index key and put it in register
+** Generate code that will assemble an index key and stores it in register
 ** regOut.  The key with be for index pIdx which is an index on pTab.
 ** iCur is the index of a cursor open on the pTab table and pointing to
-** the entry that needs indexing.
+** the entry that needs indexing.  If pTab is a WITHOUT ROWID table, then
+** iCur must be the cursor of the PRIMARY KEY index.
 **
 ** Return a register number which is the first in a block of
 ** registers that holds the elements of the index key.  The
 ** block of registers has already been deallocated by the time
 ** this routine returns.
+**
+** If *piPartIdxLabel is not NULL, fill it in with a label and jump
+** to that label if pIdx is a partial index that should be skipped.
+** The label should be resolved using sqlite3ResolvePartIdxLabel().
+** A partial index should be skipped if its WHERE clause evaluates
+** to false or null.  If pIdx is not a partial index, *piPartIdxLabel
+** will be set to zero which is an empty label that is ignored by
+** sqlite3ResolvePartIdxLabel().
+**
+** The pPrior and regPrior parameters are used to implement a cache to
+** avoid unnecessary register loads.  If pPrior is not NULL, then it is
+** a pointer to a different index for which an index key has just been
+** computed into register regPrior.  If the current pIdx index is generating
+** its key into the same sequence of registers and if pPrior and pIdx share
+** a column in common, then the register corresponding to that column already
+** holds the correct value and the loading of that register is skipped.
+** This optimization is helpful when doing a DELETE or an INTEGRITY_CHECK 
+** on a table with multiple indices, and especially with the ROWID or
+** PRIMARY KEY columns of the index.
 */
 SQLITE_PRIVATE int sqlite3GenerateIndexKey(
-  Parse *pParse,     /* Parsing context */
-  Index *pIdx,       /* The index for which to generate a key */
-  int iCur,          /* Cursor number for the pIdx->pTable table */
-  int regOut,        /* Write the new index key to this register */
-  int doMakeRec      /* Run the OP_MakeRecord instruction if true */
+  Parse *pParse,       /* Parsing context */
+  Index *pIdx,         /* The index for which to generate a key */
+  int iDataCur,        /* Cursor number from which to take column data */
+  int regOut,          /* Put the new key into this register if not 0 */
+  int prefixOnly,      /* Compute only a unique prefix of the key */
+  int *piPartIdxLabel, /* OUT: Jump to this label to skip partial index */
+  Index *pPrior,       /* Previously generated index key */
+  int regPrior         /* Register holding previous generated key */
 ){
   Vdbe *v = pParse->pVdbe;
   int j;
@@ -87122,34 +91623,51 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
   int regBase;
   int nCol;
 
-  nCol = pIdx->nColumn;
-  regBase = sqlite3GetTempRange(pParse, nCol+1);
-  sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);
-  for(j=0; j<nCol; j++){
-    int idx = pIdx->aiColumn[j];
-    if( idx==pTab->iPKey ){
-      sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);
-    }else{
-      sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
-      sqlite3ColumnDefault(v, pTab, idx, -1);
-    }
-  }
-  if( doMakeRec ){
-    const char *zAff;
-    if( pTab->pSelect
-     || OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt)
-    ){
-      zAff = 0;
+  if( piPartIdxLabel ){
+    if( pIdx->pPartIdxWhere ){
+      *piPartIdxLabel = sqlite3VdbeMakeLabel(v);
+      pParse->iPartIdxTab = iDataCur;
+      sqlite3ExprCachePush(pParse);
+      sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, 
+                         SQLITE_JUMPIFNULL);
     }else{
-      zAff = sqlite3IndexAffinityStr(v, pIdx);
+      *piPartIdxLabel = 0;
     }
-    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
-    sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
   }
-  sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
+  nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn;
+  regBase = sqlite3GetTempRange(pParse, nCol);
+  if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0;
+  for(j=0; j<nCol; j++){
+    if( pPrior && pPrior->aiColumn[j]==pIdx->aiColumn[j] ) continue;
+    sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pIdx->aiColumn[j],
+                                    regBase+j);
+    /* If the column affinity is REAL but the number is an integer, then it
+    ** might be stored in the table as an integer (using a compact
+    ** representation) then converted to REAL by an OP_RealAffinity opcode.
+    ** But we are getting ready to store this value back into an index, where
+    ** it should be converted by to INTEGER again.  So omit the OP_RealAffinity
+    ** opcode if it is present */
+    sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
+  }
+  if( regOut ){
+    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
+  }
+  sqlite3ReleaseTempRange(pParse, regBase, nCol);
   return regBase;
 }
 
+/*
+** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label
+** because it was a partial index, then this routine should be called to
+** resolve that label.
+*/
+SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){
+  if( iLabel ){
+    sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel);
+    sqlite3ExprCachePop(pParse);
+  }
+}
+
 /************** End of delete.c **********************************************/
 /************** Begin file func.c ********************************************/
 /*
@@ -87163,12 +91681,9 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This file contains the C functions that implement various SQL
-** functions of SQLite.  
-**
-** There is only one exported symbol in this file - the function
-** sqliteRegisterBuildinFunctions() found at the bottom of the file.
-** All other code has file scope.
+** This file contains the C-language implementions for many of the SQL
+** functions of SQLite.  (Some function, and in particular the date and
+** time functions, are implemented separately.)
 */
 /* #include <stdlib.h> */
 /* #include <assert.h> */
@@ -87289,9 +91804,9 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
     case SQLITE_INTEGER: {
       i64 iVal = sqlite3_value_int64(argv[0]);
       if( iVal<0 ){
-        if( (iVal<<1)==0 ){
-          /* IMP: R-35460-15084 If X is the integer -9223372036854775807 then
-          ** abs(X) throws an integer overflow error since there is no
+        if( iVal==SMALLEST_INT64 ){
+          /* IMP: R-31676-45509 If X is the integer -9223372036854775808
+          ** then abs(X) throws an integer overflow error since there is no
           ** equivalent positive 64-bit two complement value. */
           sqlite3_result_error(context, "integer overflow", -1);
           return;
@@ -87371,6 +91886,32 @@ static void instrFunc(
 }
 
 /*
+** Implementation of the printf() function.
+*/
+static void printfFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  PrintfArguments x;
+  StrAccum str;
+  const char *zFormat;
+  int n;
+
+  if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
+    x.nArg = argc-1;
+    x.nUsed = 0;
+    x.apArg = argv+1;
+    sqlite3StrAccumInit(&str, 0, 0, SQLITE_MAX_LENGTH);
+    str.db = sqlite3_context_db_handle(context);
+    sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x);
+    n = str.nChar;
+    sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
+                        SQLITE_DYNAMIC);
+  }
+}
+
+/*
 ** Implementation of the substr() function.
 **
 ** substr(x,p1,p2)  returns p2 characters of x[] beginning with p1.
@@ -87380,7 +91921,7 @@ static void instrFunc(
 **
 ** If p1 is negative, then we begin abs(p1) from the end of x[].
 **
-** If p2 is negative, return the p2 characters preceeding p1.
+** If p2 is negative, return the p2 characters preceding p1.
 */
 static void substrFunc(
   sqlite3_context *context,
@@ -87570,14 +92111,14 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
 }
 
 /*
-** The COALESCE() and IFNULL() functions are implemented as VDBE code so
-** that unused argument values do not have to be computed.  However, we
-** still need some kind of function implementation for this routines in
-** the function table.  That function implementation will never be called
-** so it doesn't matter what the implementation is.  We might as well use
-** the "version()" function as a substitute.
+** Some functions like COALESCE() and IFNULL() and UNLIKELY() are implemented
+** as VDBE code so that unused argument values do not have to be computed.
+** However, we still need some kind of function implementation for this
+** routines in the function table.  The noopFunc macro provides this.
+** noopFunc will never be called so it doesn't matter what the implementation
+** is.  We might as well use the "version()" function as a substitute.
 */
-#define ifnullFunc versionFunc   /* Substitute function - never called */
+#define noopFunc versionFunc   /* Substitute function - never called */
 
 /*
 ** Implementation of random().  Return a random integer.  
@@ -87696,9 +92237,9 @@ struct compareInfo {
 */
 #if defined(SQLITE_EBCDIC)
 # define sqlite3Utf8Read(A)    (*((*A)++))
-# define GlogUpperToLower(A)   A = sqlite3UpperToLower[A]
+# define GlobUpperToLower(A)   A = sqlite3UpperToLower[A]
 #else
-# define GlogUpperToLower(A)   if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
+# define GlobUpperToLower(A)   if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
 #endif
 
 static const struct compareInfo globInfo = { '*', '?', '[', 0 };
@@ -87777,11 +92318,11 @@ static int patternCompare(
       }
       while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
         if( noCase ){
-          GlogUpperToLower(c2);
-          GlogUpperToLower(c);
+          GlobUpperToLower(c2);
+          GlobUpperToLower(c);
           while( c2 != 0 && c2 != c ){
             c2 = sqlite3Utf8Read(&zString);
-            GlogUpperToLower(c2);
+            GlobUpperToLower(c2);
           }
         }else{
           while( c2 != 0 && c2 != c ){
@@ -87833,8 +92374,8 @@ static int patternCompare(
     }else{
       c2 = sqlite3Utf8Read(&zString);
       if( noCase ){
-        GlogUpperToLower(c);
-        GlogUpperToLower(c2);
+        GlobUpperToLower(c);
+        GlobUpperToLower(c2);
       }
       if( c!=c2 ){
         return 0;
@@ -88039,10 +92580,6 @@ static const char hexdigits[] = {
 };
 
 /*
-** EXPERIMENTAL - This is not an official function.  The interface may
-** change.  This function may disappear.  Do not write code that depends
-** on this function.
-**
 ** Implementation of the QUOTE() function.  This function takes a single
 ** argument.  If the argument is numeric, the return value is the same as
 ** the argument.  If the argument is NULL, the return value is the string
@@ -88147,7 +92684,7 @@ static void charFunc(
 ){
   unsigned char *z, *zOut;
   int i;
-  zOut = z = sqlite3_malloc( argc*4 );
+  zOut = z = sqlite3_malloc( argc*4+1 );
   if( z==0 ){
     sqlite3_result_error_nomem(context);
     return;
@@ -88231,7 +92768,7 @@ static void zeroblobFunc(
 /*
 ** The replace() function.  Three arguments are all strings: call
 ** them A, B, and C. The result is also a string which is derived
-** from A by replacing every occurance of B with C.  The match
+** from A by replacing every occurrence of B with C.  The match
 ** must be exact.  Collating sequences are not used.
 */
 static void replaceFunc(
@@ -88667,20 +93204,20 @@ static void groupConcatStep(
         zSep = ",";
         nSep = 1;
       }
-      sqlite3StrAccumAppend(pAccum, zSep, nSep);
+      if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
     }
     zVal = (char*)sqlite3_value_text(argv[0]);
     nVal = sqlite3_value_bytes(argv[0]);
-    sqlite3StrAccumAppend(pAccum, zVal, nVal);
+    if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal);
   }
 }
 static void groupConcatFinalize(sqlite3_context *context){
   StrAccum *pAccum;
   pAccum = sqlite3_aggregate_context(context, 0);
   if( pAccum ){
-    if( pAccum->tooBig ){
+    if( pAccum->accError==STRACCUM_TOOBIG ){
       sqlite3_result_error_toobig(context);
-    }else if( pAccum->mallocFailed ){
+    }else if( pAccum->accError==STRACCUM_NOMEM ){
       sqlite3_result_error_nomem(context);
     }else{    
       sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, 
@@ -88710,7 +93247,7 @@ static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
   pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName),
                              2, SQLITE_UTF8, 0);
   if( ALWAYS(pDef) ){
-    pDef->flags = flagVal;
+    pDef->funcFlags |= flagVal;
   }
 }
 
@@ -88754,7 +93291,7 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas
   pDef = sqlite3FindFunction(db, pExpr->u.zToken, 
                              sqlite3Strlen30(pExpr->u.zToken),
                              2, SQLITE_UTF8, 0);
-  if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
+  if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
     return 0;
   }
 
@@ -88766,7 +93303,7 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas
   assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
   assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
   assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
-  *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0;
+  *pIsNocase = (pDef->funcFlags & SQLITE_FUNC_CASE)==0;
   return 1;
 }
 
@@ -88804,6 +93341,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
     FUNCTION(instr,              2, 0, 0, instrFunc        ),
     FUNCTION(substr,             2, 0, 0, substrFunc       ),
     FUNCTION(substr,             3, 0, 0, substrFunc       ),
+    FUNCTION(printf,            -1, 0, 0, printfFunc       ),
     FUNCTION(unicode,            1, 0, 0, unicodeFunc      ),
     FUNCTION(char,              -1, 0, 0, charFunc         ),
     FUNCTION(abs,                1, 0, 0, absFunc          ),
@@ -88815,11 +93353,14 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
     FUNCTION(lower,              1, 0, 0, lowerFunc        ),
     FUNCTION(coalesce,           1, 0, 0, 0                ),
     FUNCTION(coalesce,           0, 0, 0, 0                ),
-    FUNCTION2(coalesce,         -1, 0, 0, ifnullFunc,  SQLITE_FUNC_COALESCE),
+    FUNCTION2(coalesce,         -1, 0, 0, noopFunc,  SQLITE_FUNC_COALESCE),
     FUNCTION(hex,                1, 0, 0, hexFunc          ),
-    FUNCTION2(ifnull,            2, 0, 0, ifnullFunc,  SQLITE_FUNC_COALESCE),
-    FUNCTION(random,             0, 0, 0, randomFunc       ),
-    FUNCTION(randomblob,         1, 0, 0, randomBlob       ),
+    FUNCTION2(ifnull,            2, 0, 0, noopFunc,  SQLITE_FUNC_COALESCE),
+    FUNCTION2(unlikely,          1, 0, 0, noopFunc,  SQLITE_FUNC_UNLIKELY),
+    FUNCTION2(likelihood,        2, 0, 0, noopFunc,  SQLITE_FUNC_UNLIKELY),
+    FUNCTION2(likely,            1, 0, 0, noopFunc,  SQLITE_FUNC_UNLIKELY),
+    VFUNCTION(random,            0, 0, 0, randomFunc       ),
+    VFUNCTION(randomblob,        1, 0, 0, randomBlob       ),
     FUNCTION(nullif,             2, 0, 1, nullifFunc       ),
     FUNCTION(sqlite_version,     0, 0, 0, versionFunc      ),
     FUNCTION(sqlite_source_id,   0, 0, 0, sourceidFunc     ),
@@ -88829,9 +93370,9 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
     FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc  ),
 #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
     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    ),
+    VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
+    VFUNCTION(changes,           0, 0, 0, changes          ),
+    VFUNCTION(total_changes,     0, 0, 0, total_changes    ),
     FUNCTION(replace,            3, 0, 0, replaceFunc      ),
     FUNCTION(zeroblob,           1, 0, 0, zeroblobFunc     ),
   #ifdef SQLITE_SOUNDEX
@@ -88845,7 +93386,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
     AGGREGATE(total,             1, 0, 0, sumStep,         totalFinalize    ),
     AGGREGATE(avg,               1, 0, 0, sumStep,         avgFinalize    ),
  /* AGGREGATE(count,             0, 0, 0, countStep,       countFinalize  ), */
-    {0,SQLITE_UTF8,SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0},
+    {0,SQLITE_UTF8|SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0},
     AGGREGATE(count,             1, 0, 0, countStep,       countFinalize  ),
     AGGREGATE(group_concat,      1, 0, 0, groupConcatStep, groupConcatFinalize),
     AGGREGATE(group_concat,      2, 0, 0, groupConcatStep, groupConcatFinalize),
@@ -88871,6 +93412,9 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
 #ifndef SQLITE_OMIT_ALTERTABLE
   sqlite3AlterFunctions();
 #endif
+#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
+  sqlite3AnalyzeFunctions();
+#endif
 }
 
 /************** End of func.c ************************************************/
@@ -89101,7 +93645,7 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex(
   }
 
   for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
-    if( pIdx->nColumn==nCol && pIdx->onError!=OE_None ){ 
+    if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) ){ 
       /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
       ** of columns. If each indexed column corresponds to a foreign key
       ** column of pFKey, then this index is a winner.  */
@@ -89109,8 +93653,8 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex(
       if( zKey==0 ){
         /* If zKey is NULL, then this foreign key is implicitly mapped to 
         ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be 
-        ** identified by the test (Index.autoIndex==2).  */
-        if( pIdx->autoIndex==2 ){
+        ** identified by the test.  */
+        if( IsPrimaryKeyIndex(pIdx) ){
           if( aiCol ){
             int i;
             for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom;
@@ -89124,7 +93668,7 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex(
         ** the default collation sequences for each column. */
         int i, j;
         for(i=0; i<nCol; i++){
-          int iCol = pIdx->aiColumn[i];     /* Index of column in parent tbl */
+          i16 iCol = pIdx->aiColumn[i];     /* Index of column in parent tbl */
           char *zDfltColl;                  /* Def. collation for column */
           char *zIdxCol;                    /* Name of indexed column */
 
@@ -89216,10 +93760,11 @@ static void fkLookupParent(
   ** search for a matching row in the parent table.  */
   if( nIncr<0 ){
     sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk);
+    VdbeCoverage(v);
   }
   for(i=0; i<pFKey->nCol; i++){
     int iReg = aiCol[i] + regData + 1;
-    sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk);
+    sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v);
   }
 
   if( isIgnore==0 ){
@@ -89236,17 +93781,19 @@ static void fkLookupParent(
       ** will have INTEGER affinity applied to it, which may not be correct.  */
       sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
       iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
+      VdbeCoverage(v);
   
       /* If the parent table is the same as the child table, and we are about
       ** to increment the constraint-counter (i.e. this is an INSERT operation),
       ** then check if the row being inserted matches itself. If so, do not
       ** increment the constraint-counter.  */
       if( pTab==pFKey->pFrom && nIncr==1 ){
-        sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp);
+        sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v);
+        sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
       }
   
       sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
-      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp);
+      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v);
       sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
       sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
       sqlite3VdbeJumpHere(v, iMustBeInt);
@@ -89255,10 +93802,9 @@ static void fkLookupParent(
       int nCol = pFKey->nCol;
       int regTemp = sqlite3GetTempRange(pParse, nCol);
       int regRec = sqlite3GetTempReg(pParse);
-      KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
   
       sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
-      sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
+      sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
       for(i=0; i<nCol; i++){
         sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
       }
@@ -89283,30 +93829,32 @@ static void fkLookupParent(
             /* The parent key is a composite key that includes the IPK column */
             iParent = regData;
           }
-          sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
+          sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v);
           sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
         }
         sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
       }
   
-      sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
-      sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
-      sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);
+      sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec,
+                        sqlite3IndexAffinityStr(v,pIdx), nCol);
+      sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v);
   
       sqlite3ReleaseTempReg(pParse, regRec);
       sqlite3ReleaseTempRange(pParse, regTemp, nCol);
     }
   }
 
-  if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
+  if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs)
+   && !pParse->pToplevel 
+   && !pParse->isMultiWrite 
+  ){
     /* Special case: If this is an INSERT statement that will insert exactly
     ** one row into the table, raise a constraint immediately instead of
     ** incrementing a counter. This is necessary as the VM code is being
     ** generated for will not open a statement transaction.  */
     assert( nIncr==1 );
     sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
-        OE_Abort, "foreign key constraint failed", P4_STATIC
-    );
+        OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
   }else{
     if( nIncr>0 && pFKey->isDeferred==0 ){
       sqlite3ParseToplevel(pParse)->mayAbort = 1;
@@ -89318,6 +93866,62 @@ static void fkLookupParent(
   sqlite3VdbeAddOp1(v, OP_Close, iCur);
 }
 
+
+/*
+** Return an Expr object that refers to a memory register corresponding
+** to column iCol of table pTab.
+**
+** regBase is the first of an array of register that contains the data
+** for pTab.  regBase itself holds the rowid.  regBase+1 holds the first
+** column.  regBase+2 holds the second column, and so forth.
+*/
+static Expr *exprTableRegister(
+  Parse *pParse,     /* Parsing and code generating context */
+  Table *pTab,       /* The table whose content is at r[regBase]... */
+  int regBase,       /* Contents of table pTab */
+  i16 iCol           /* Which column of pTab is desired */
+){
+  Expr *pExpr;
+  Column *pCol;
+  const char *zColl;
+  sqlite3 *db = pParse->db;
+
+  pExpr = sqlite3Expr(db, TK_REGISTER, 0);
+  if( pExpr ){
+    if( iCol>=0 && iCol!=pTab->iPKey ){
+      pCol = &pTab->aCol[iCol];
+      pExpr->iTable = regBase + iCol + 1;
+      pExpr->affinity = pCol->affinity;
+      zColl = pCol->zColl;
+      if( zColl==0 ) zColl = db->pDfltColl->zName;
+      pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
+    }else{
+      pExpr->iTable = regBase;
+      pExpr->affinity = SQLITE_AFF_INTEGER;
+    }
+  }
+  return pExpr;
+}
+
+/*
+** Return an Expr object that refers to column iCol of table pTab which
+** has cursor iCur.
+*/
+static Expr *exprTableColumn(
+  sqlite3 *db,      /* The database connection */
+  Table *pTab,      /* The table whose column is desired */
+  int iCursor,      /* The open cursor on the table */
+  i16 iCol          /* The column that is wanted */
+){
+  Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
+  if( pExpr ){
+    pExpr->pTab = pTab;
+    pExpr->iTable = iCursor;
+    pExpr->iColumn = iCol;
+  }
+  return pExpr;
+}
+
 /*
 ** This function is called to generate code executed when a row is deleted
 ** from the parent table of foreign key constraint pFKey and, if pFKey is 
@@ -89333,13 +93937,13 @@ static void fkLookupParent(
 **   --------------------------------------------------------------------------
 **   DELETE      immediate   Increment the "immediate constraint counter".
 **                           Or, if the ON (UPDATE|DELETE) action is RESTRICT,
-**                           throw a "foreign key constraint failed" exception.
+**                           throw a "FOREIGN KEY constraint failed" exception.
 **
 **   INSERT      immediate   Decrement the "immediate constraint counter".
 **
 **   DELETE      deferred    Increment the "deferred constraint counter".
 **                           Or, if the ON (UPDATE|DELETE) action is RESTRICT,
-**                           throw a "foreign key constraint failed" exception.
+**                           throw a "FOREIGN KEY constraint failed" exception.
 **
 **   INSERT      deferred    Decrement the "deferred constraint counter".
 **
@@ -89348,12 +93952,12 @@ static void fkLookupParent(
 */
 static void fkScanChildren(
   Parse *pParse,                  /* Parse context */
-  SrcList *pSrc,                  /* SrcList containing the table to scan */
-  Table *pTab,
-  Index *pIdx,                    /* Foreign key index */
-  FKey *pFKey,                    /* Foreign key relationship */
+  SrcList *pSrc,                  /* The child table to be scanned */
+  Table *pTab,                    /* The parent table */
+  Index *pIdx,                    /* Index on parent covering the foreign key */
+  FKey *pFKey,                    /* The foreign key linking pSrc to pTab */
   int *aiCol,                     /* Map from pIdx cols to child table cols */
-  int regData,                    /* Referenced table data starts here */
+  int regData,                    /* Parent row data starts here */
   int nIncr                       /* Amount to increment deferred counter by */
 ){
   sqlite3 *db = pParse->db;       /* Database handle */
@@ -89364,10 +93968,14 @@ static void fkScanChildren(
   int iFkIfZero = 0;              /* Address of OP_FkIfZero */
   Vdbe *v = sqlite3GetVdbe(pParse);
 
-  assert( !pIdx || pIdx->pTable==pTab );
+  assert( pIdx==0 || pIdx->pTable==pTab );
+  assert( pIdx==0 || pIdx->nKeyCol==pFKey->nCol );
+  assert( pIdx!=0 || pFKey->nCol==1 );
+  assert( pIdx!=0 || HasRowid(pTab) );
 
   if( nIncr<0 ){
     iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0);
+    VdbeCoverage(v);
   }
 
   /* Create an Expr object representing an SQL expression like:
@@ -89382,29 +93990,11 @@ static void fkScanChildren(
     Expr *pLeft;                  /* Value from parent table row */
     Expr *pRight;                 /* Column ref to child table */
     Expr *pEq;                    /* Expression (pLeft = pRight) */
-    int iCol;                     /* Index of column in child table */ 
+    i16 iCol;                     /* Index of column in child table */ 
     const char *zCol;             /* Name of column in child table */
 
-    pLeft = sqlite3Expr(db, TK_REGISTER, 0);
-    if( pLeft ){
-      /* Set the collation sequence and affinity of the LHS of each TK_EQ
-      ** expression to the parent key column defaults.  */
-      if( pIdx ){
-        Column *pCol;
-        const char *zColl;
-        iCol = pIdx->aiColumn[i];
-        pCol = &pTab->aCol[iCol];
-        if( pTab->iPKey==iCol ) iCol = -1;
-        pLeft->iTable = regData+iCol+1;
-        pLeft->affinity = pCol->affinity;
-        zColl = pCol->zColl;
-        if( zColl==0 ) zColl = db->pDfltColl->zName;
-        pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl);
-      }else{
-        pLeft->iTable = regData;
-        pLeft->affinity = SQLITE_AFF_INTEGER;
-      }
-    }
+    iCol = pIdx ? pIdx->aiColumn[i] : -1;
+    pLeft = exprTableRegister(pParse, pTab, regData, iCol);
     iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
     assert( iCol>=0 );
     zCol = pFKey->pFrom->aCol[iCol].zName;
@@ -89413,24 +94003,39 @@ static void fkScanChildren(
     pWhere = sqlite3ExprAnd(db, pWhere, pEq);
   }
 
-  /* If the child table is the same as the parent table, and this scan
-  ** is taking place as part of a DELETE operation (operation D.2), omit the
-  ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE 
-  ** clause, where $rowid is the rowid of the row being deleted.  */
+  /* If the child table is the same as the parent table, then add terms
+  ** to the WHERE clause that prevent this entry from being scanned.
+  ** The added WHERE clause terms are like this:
+  **
+  **     $current_rowid!=rowid
+  **     NOT( $current_a==a AND $current_b==b AND ... )
+  **
+  ** The first form is used for rowid tables.  The second form is used
+  ** for WITHOUT ROWID tables.  In the second form, the primary key is
+  ** (a,b,...)
+  */
   if( pTab==pFKey->pFrom && nIncr>0 ){
-    Expr *pEq;                    /* Expression (pLeft = pRight) */
+    Expr *pNe;                    /* Expression (pLeft != pRight) */
     Expr *pLeft;                  /* Value from parent table row */
     Expr *pRight;                 /* Column ref to child table */
-    pLeft = sqlite3Expr(db, TK_REGISTER, 0);
-    pRight = sqlite3Expr(db, TK_COLUMN, 0);
-    if( pLeft && pRight ){
-      pLeft->iTable = regData;
-      pLeft->affinity = SQLITE_AFF_INTEGER;
-      pRight->iTable = pSrc->a[0].iCursor;
-      pRight->iColumn = -1;
-    }
-    pEq = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0);
-    pWhere = sqlite3ExprAnd(db, pWhere, pEq);
+    if( HasRowid(pTab) ){
+      pLeft = exprTableRegister(pParse, pTab, regData, -1);
+      pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1);
+      pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0);
+    }else{
+      Expr *pEq, *pAll = 0;
+      Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+      assert( pIdx!=0 );
+      for(i=0; i<pPk->nKeyCol; i++){
+        i16 iCol = pIdx->aiColumn[i];
+        pLeft = exprTableRegister(pParse, pTab, regData, iCol);
+        pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
+        pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0);
+        pAll = sqlite3ExprAnd(db, pAll, pEq);
+      }
+      pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0, 0);
+    }
+    pWhere = sqlite3ExprAnd(db, pWhere, pNe);
   }
 
   /* Resolve the references in the WHERE clause. */
@@ -89460,8 +94065,8 @@ static void fkScanChildren(
 }
 
 /*
-** This function returns a pointer to the head of a linked list of FK
-** constraints for which table pTab is the parent table. For example,
+** This function returns a linked list of FKey objects (connected by
+** FKey.pNextTo) holding all children of table pTab.  For example,
 ** given the following schema:
 **
 **   CREATE TABLE t1(a PRIMARY KEY);
@@ -89529,11 +94134,11 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
       ** when this statement is run.  */
       FKey *p;
       for(p=pTab->pFKey; p; p=p->pNextFrom){
-        if( p->isDeferred ) break;
+        if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
       }
       if( !p ) return;
       iSkip = sqlite3VdbeMakeLabel(v);
-      sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip);
+      sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v);
     }
 
     pParse->disableTriggers = 1;
@@ -89543,11 +94148,18 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
     /* If the DELETE has generated immediate foreign key constraint 
     ** violations, halt the VDBE and return an error at this point, before
     ** any modifications to the schema are made. This is because statement
-    ** transactions are not able to rollback schema changes.  */
-    sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
-    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
-        OE_Abort, "foreign key constraint failed", P4_STATIC
-    );
+    ** transactions are not able to rollback schema changes.  
+    **
+    ** If the SQLITE_DeferFKs flag is set, then this is not required, as
+    ** the statement transaction will not be rolled back even if FK
+    ** constraints are violated.
+    */
+    if( (db->flags & SQLITE_DeferFKs)==0 ){
+      sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
+      VdbeCoverage(v);
+      sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+          OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
+    }
 
     if( iSkip ){
       sqlite3VdbeResolveLabel(v, iSkip);
@@ -89555,6 +94167,70 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
   }
 }
 
+
+/*
+** The second argument points to an FKey object representing a foreign key
+** for which pTab is the child table. An UPDATE statement against pTab
+** is currently being processed. For each column of the table that is 
+** actually updated, the corresponding element in the aChange[] array
+** is zero or greater (if a column is unmodified the corresponding element
+** is set to -1). If the rowid column is modified by the UPDATE statement
+** the bChngRowid argument is non-zero.
+**
+** This function returns true if any of the columns that are part of the
+** child key for FK constraint *p are modified.
+*/
+static int fkChildIsModified(
+  Table *pTab,                    /* Table being updated */
+  FKey *p,                        /* Foreign key for which pTab is the child */
+  int *aChange,                   /* Array indicating modified columns */
+  int bChngRowid                  /* True if rowid is modified by this update */
+){
+  int i;
+  for(i=0; i<p->nCol; i++){
+    int iChildKey = p->aCol[i].iFrom;
+    if( aChange[iChildKey]>=0 ) return 1;
+    if( iChildKey==pTab->iPKey && bChngRowid ) return 1;
+  }
+  return 0;
+}
+
+/*
+** The second argument points to an FKey object representing a foreign key
+** for which pTab is the parent table. An UPDATE statement against pTab
+** is currently being processed. For each column of the table that is 
+** actually updated, the corresponding element in the aChange[] array
+** is zero or greater (if a column is unmodified the corresponding element
+** is set to -1). If the rowid column is modified by the UPDATE statement
+** the bChngRowid argument is non-zero.
+**
+** This function returns true if any of the columns that are part of the
+** parent key for FK constraint *p are modified.
+*/
+static int fkParentIsModified(
+  Table *pTab, 
+  FKey *p, 
+  int *aChange, 
+  int bChngRowid
+){
+  int i;
+  for(i=0; i<p->nCol; i++){
+    char *zKey = p->aCol[i].zCol;
+    int iKey;
+    for(iKey=0; iKey<pTab->nCol; iKey++){
+      if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){
+        Column *pCol = &pTab->aCol[iKey];
+        if( zKey ){
+          if( 0==sqlite3StrICmp(pCol->zName, zKey) ) return 1;
+        }else if( pCol->colFlags & COLFLAG_PRIMKEY ){
+          return 1;
+        }
+      }
+    }
+  }
+  return 0;
+}
+
 /*
 ** This function is called when inserting, deleting or updating a row of
 ** table pTab to generate VDBE code to perform foreign key constraint 
@@ -89579,7 +94255,9 @@ SQLITE_PRIVATE void sqlite3FkCheck(
   Parse *pParse,                  /* Parse context */
   Table *pTab,                    /* Row is being deleted from this table */ 
   int regOld,                     /* Previous row data is stored here */
-  int regNew                      /* New row data is stored here */
+  int regNew,                     /* New row data is stored here */
+  int *aChange,                   /* Array indicating UPDATEd columns (or 0) */
+  int bChngRowid                  /* True if rowid is UPDATEd */
 ){
   sqlite3 *db = pParse->db;       /* Database handle */
   FKey *pFKey;                    /* Used to iterate through FKs */
@@ -89607,6 +94285,13 @@ SQLITE_PRIVATE void sqlite3FkCheck(
     int i;
     int isIgnore = 0;
 
+    if( aChange 
+     && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0
+     && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 
+    ){
+      continue;
+    }
+
     /* Find the parent table of this foreign key. Also find a unique index 
     ** on the parent key columns in the parent table. If either of these 
     ** schema items cannot be located, set an error in pParse and return 
@@ -89631,7 +94316,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
         int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
         for(i=0; i<pFKey->nCol; i++){
           int iReg = pFKey->aCol[i].iFrom + regOld + 1;
-          sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump);
+          sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v);
         }
         sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
       }
@@ -89683,13 +94368,20 @@ SQLITE_PRIVATE void sqlite3FkCheck(
     sqlite3DbFree(db, aiFree);
   }
 
-  /* Loop through all the foreign key constraints that refer to this table */
+  /* Loop through all the foreign key constraints that refer to this table.
+  ** (the "child" constraints) */
   for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
     Index *pIdx = 0;              /* Foreign key index for pFKey */
     SrcList *pSrc;
     int *aiCol = 0;
 
-    if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
+    if( aChange && fkParentIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){
+      continue;
+    }
+
+    if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) 
+     && !pParse->pToplevel && !pParse->isMultiWrite 
+    ){
       assert( regOld==0 && regNew!=0 );
       /* Inserting a single row into a parent table cannot cause an immediate
       ** foreign key violation. So do nothing in this case.  */
@@ -89702,9 +94394,8 @@ SQLITE_PRIVATE void sqlite3FkCheck(
     }
     assert( aiCol || pFKey->nCol==1 );
 
-    /* Create a SrcList structure containing a single table (the table 
-    ** the foreign key that refers to this table is attached to). This
-    ** is required for the sqlite3WhereXXX() interface.  */
+    /* Create a SrcList structure containing the child table.  We need the
+    ** child table as a SrcList for sqlite3WhereBegin() */
     pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
     if( pSrc ){
       struct SrcList_item *pItem = pSrc->a;
@@ -89753,13 +94444,14 @@ SQLITE_PRIVATE u32 sqlite3FkOldmask(
       Index *pIdx = 0;
       sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
       if( pIdx ){
-        for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
+        for(i=0; i<pIdx->nKeyCol; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
       }
     }
   }
   return mask;
 }
 
+
 /*
 ** This function is called before generating code to update or delete a 
 ** row contained in table pTab. If the operation is a DELETE, then
@@ -89789,32 +94481,16 @@ SQLITE_PRIVATE int sqlite3FkRequired(
     }else{
       /* This is an UPDATE. Foreign key processing is only required if the
       ** operation modifies one or more child or parent key columns. */
-      int i;
       FKey *p;
 
       /* Check if any child key columns are being modified. */
       for(p=pTab->pFKey; p; p=p->pNextFrom){
-        for(i=0; i<p->nCol; i++){
-          int iChildKey = p->aCol[i].iFrom;
-          if( aChange[iChildKey]>=0 ) return 1;
-          if( iChildKey==pTab->iPKey && chngRowid ) return 1;
-        }
+        if( fkChildIsModified(pTab, p, aChange, chngRowid) ) return 1;
       }
 
       /* Check if any parent key columns are being modified. */
       for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
-        for(i=0; i<p->nCol; i++){
-          char *zKey = p->aCol[i].zCol;
-          int iKey;
-          for(iKey=0; iKey<pTab->nCol; iKey++){
-            Column *pCol = &pTab->aCol[iKey];
-            if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey)
-                      : (pCol->colFlags & COLFLAG_PRIMKEY)!=0) ){
-              if( aChange[iKey]>=0 ) return 1;
-              if( iKey==pTab->iPKey && chngRowid ) return 1;
-            }
-          }
-        }
+        if( fkParentIsModified(pTab, p, aChange, chngRowid) ) return 1;
       }
     }
   }
@@ -89960,7 +94636,7 @@ static Trigger *fkActionTrigger(
 
       tFrom.z = zFrom;
       tFrom.n = nFrom;
-      pRaise = sqlite3Expr(db, TK_RAISE, "foreign key constraint failed");
+      pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
       if( pRaise ){
         pRaise->affinity = OE_Abort;
       }
@@ -90040,7 +94716,9 @@ SQLITE_PRIVATE void sqlite3FkActions(
   Parse *pParse,                  /* Parse context */
   Table *pTab,                    /* Table being updated or deleted from */
   ExprList *pChanges,             /* Change-list for UPDATE, NULL for DELETE */
-  int regOld                      /* Address of array containing old row */
+  int regOld,                     /* Address of array containing old row */
+  int *aChange,                   /* Array indicating UPDATEd columns (or 0) */
+  int bChngRowid                  /* True if rowid is UPDATEd */
 ){
   /* If foreign-key support is enabled, iterate through all FKs that 
   ** refer to table pTab. If there is an action associated with the FK 
@@ -90049,9 +94727,11 @@ SQLITE_PRIVATE void sqlite3FkActions(
   if( pParse->db->flags&SQLITE_ForeignKeys ){
     FKey *pFKey;                  /* Iterator variable */
     for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
-      Trigger *pAction = fkActionTrigger(pParse, pTab, pFKey, pChanges);
-      if( pAction ){
-        sqlite3CodeRowTriggerDirect(pParse, pAction, pTab, regOld, OE_Abort, 0);
+      if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){
+        Trigger *pAct = fkActionTrigger(pParse, pTab, pFKey, pChanges);
+        if( pAct ){
+          sqlite3CodeRowTriggerDirect(pParse, pAct, pTab, regOld, OE_Abort, 0);
+        }
       }
     }
   }
@@ -90120,10 +94800,16 @@ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){
 */
 
 /*
-** Generate code that will open a table for reading.
+** Generate code that will 
+**
+**   (1) acquire a lock for table pTab then
+**   (2) open pTab as cursor iCur.
+**
+** If pTab is a WITHOUT ROWID table, then it is the PRIMARY KEY index
+** for that table that is actually opened.
 */
 SQLITE_PRIVATE void sqlite3OpenTable(
-  Parse *p,       /* Generate code into this VDBE */
+  Parse *pParse,  /* Generate code into this VDBE */
   int iCur,       /* The cursor number of the table */
   int iDb,        /* The database index in sqlite3.aDb[] */
   Table *pTab,    /* The table to be opened */
@@ -90131,12 +94817,21 @@ SQLITE_PRIVATE void sqlite3OpenTable(
 ){
   Vdbe *v;
   assert( !IsVirtual(pTab) );
-  v = sqlite3GetVdbe(p);
+  v = sqlite3GetVdbe(pParse);
   assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
-  sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
-  sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb);
-  sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32);
-  VdbeComment((v, "%s", pTab->zName));
+  sqlite3TableLock(pParse, iDb, pTab->tnum, 
+                   (opcode==OP_OpenWrite)?1:0, pTab->zName);
+  if( HasRowid(pTab) ){
+    sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
+    VdbeComment((v, "%s", pTab->zName));
+  }else{
+    Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+    assert( pPk!=0 );
+    assert( pPk->tnum=pTab->tnum );
+    sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb);
+    sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+    VdbeComment((v, "%s", pTab->zName));
+  }
 }
 
 /*
@@ -90172,15 +94867,15 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
     int n;
     Table *pTab = pIdx->pTable;
     sqlite3 *db = sqlite3VdbeDb(v);
-    pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+2);
+    pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1);
     if( !pIdx->zColAff ){
       db->mallocFailed = 1;
       return 0;
     }
     for(n=0; n<pIdx->nColumn; n++){
-      pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
+      i16 x = pIdx->aiColumn[n];
+      pIdx->zColAff[n] = x<0 ? SQLITE_AFF_INTEGER : pTab->aCol[x].affinity;
     }
-    pIdx->zColAff[n++] = SQLITE_AFF_INTEGER;
     pIdx->zColAff[n] = 0;
   }
  
@@ -90188,10 +94883,16 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
 }
 
 /*
-** Set P4 of the most recently inserted opcode to a column affinity
-** string for table pTab. A column affinity string has one character
-** for each column indexed by the index, according to the affinity of the
-** column:
+** Compute the affinity string for table pTab, if it has not already been
+** computed.  As an optimization, omit trailing SQLITE_AFF_NONE affinities.
+**
+** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and
+** if iReg>0 then code an OP_Affinity opcode that will set the affinities
+** for register iReg and following.  Or if affinities exists and iReg==0,
+** then just set the P4 operand of the previous opcode (which should  be
+** an OP_MakeRecord) to the affinity string.
+**
+** A column affinity string has one character per column:
 **
 **  Character      Column affinity
 **  ------------------------------
@@ -90201,19 +94902,11 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
 **  'd'            INTEGER
 **  'e'            REAL
 */
-SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
-  /* The first time a column affinity string for a particular table
-  ** is required, it is allocated and populated here. It is then 
-  ** stored as a member of the Table structure for subsequent use.
-  **
-  ** The column affinity string will eventually be deleted by
-  ** sqlite3DeleteTable() when the Table structure itself is cleaned up.
-  */
-  if( !pTab->zColAff ){
-    char *zColAff;
-    int i;
+SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
+  int i;
+  char *zColAff = pTab->zColAff;
+  if( zColAff==0 ){
     sqlite3 *db = sqlite3VdbeDb(v);
-
     zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1);
     if( !zColAff ){
       db->mallocFailed = 1;
@@ -90223,22 +94916,28 @@ SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
     for(i=0; i<pTab->nCol; i++){
       zColAff[i] = pTab->aCol[i].affinity;
     }
-    zColAff[pTab->nCol] = '\0';
-
+    do{
+      zColAff[i--] = 0;
+    }while( i>=0 && zColAff[i]==SQLITE_AFF_NONE );
     pTab->zColAff = zColAff;
   }
-
-  sqlite3VdbeChangeP4(v, -1, pTab->zColAff, P4_TRANSIENT);
+  i = sqlite3Strlen30(zColAff);
+  if( i ){
+    if( iReg ){
+      sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i);
+    }else{
+      sqlite3VdbeChangeP4(v, -1, zColAff, i);
+    }
+  }
 }
 
 /*
 ** Return non-zero if the table pTab in database iDb or any of its indices
-** have been opened at any point in the VDBE program beginning at location
-** iStartAddr throught the end of the program.  This is used to see if 
+** have been opened at any point in the VDBE program. This is used to see if 
 ** a statement of the form  "INSERT INTO <iDb, pTab> SELECT ..." can 
-** run without using temporary table for the results of the SELECT. 
+** run without using a temporary table for the results of the SELECT. 
 */
-static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){
+static int readsTable(Parse *p, int iDb, Table *pTab){
   Vdbe *v = sqlite3GetVdbe(p);
   int i;
   int iEnd = sqlite3VdbeCurrentAddr(v);
@@ -90246,7 +94945,7 @@ static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){
   VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, pTab) : 0;
 #endif
 
-  for(i=iStartAddr; i<iEnd; i++){
+  for(i=1; i<iEnd; i++){
     VdbeOp *pOp = sqlite3VdbeGetOp(v, i);
     assert( pOp!=0 );
     if( pOp->opcode==OP_OpenRead && pOp->p3==iDb ){
@@ -90347,14 +95046,14 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){
     sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1);
     addr = sqlite3VdbeCurrentAddr(v);
     sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0);
-    sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9);
+    sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); VdbeCoverage(v);
     sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId);
-    sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId);
+    sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); VdbeCoverage(v);
     sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
     sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1);
     sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId);
     sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9);
-    sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2);
+    sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); VdbeCoverage(v);
     sqlite3VdbeAddOp2(v, OP_Integer, 0, memId);
     sqlite3VdbeAddOp0(v, OP_Close);
   }
@@ -90389,25 +95088,16 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
   assert( v );
   for(p = pParse->pAinc; p; p = p->pNext){
     Db *pDb = &db->aDb[p->iDb];
-    int j1, j2, j3, j4, j5;
+    int j1;
     int iRec;
     int memId = p->regCtr;
 
     iRec = sqlite3GetTempReg(pParse);
     assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
     sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
-    j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
-    j2 = sqlite3VdbeAddOp0(v, OP_Rewind);
-    j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec);
-    j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec);
-    sqlite3VdbeAddOp2(v, OP_Next, 0, j3);
-    sqlite3VdbeJumpHere(v, j2);
+    j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v);
     sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1);
-    j5 = sqlite3VdbeAddOp0(v, OP_Goto);
-    sqlite3VdbeJumpHere(v, j4);
-    sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1);
     sqlite3VdbeJumpHere(v, j1);
-    sqlite3VdbeJumpHere(v, j5);
     sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec);
     sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1);
     sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
@@ -90425,97 +95115,6 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
 #endif /* SQLITE_OMIT_AUTOINCREMENT */
 
 
-/*
-** Generate code for a co-routine that will evaluate a subquery one
-** row at a time.
-**
-** The pSelect parameter is the subquery that the co-routine will evaluation.
-** Information about the location of co-routine and the registers it will use
-** is returned by filling in the pDest object.
-**
-** Registers are allocated as follows:
-**
-**   pDest->iSDParm      The register holding the next entry-point of the
-**                       co-routine.  Run the co-routine to its next breakpoint
-**                       by calling "OP_Yield $X" where $X is pDest->iSDParm.
-**
-**   pDest->iSDParm+1    The register holding the "completed" flag for the
-**                       co-routine. This register is 0 if the previous Yield
-**                       generated a new result row, or 1 if the subquery
-**                       has completed.  If the Yield is called again
-**                       after this register becomes 1, then the VDBE will
-**                       halt with an SQLITE_INTERNAL error.
-**
-**   pDest->iSdst        First result register.
-**
-**   pDest->nSdst        Number of result registers.
-**
-** This routine handles all of the register allocation and fills in the
-** pDest structure appropriately.
-**
-** Here is a schematic of the generated code assuming that X is the 
-** co-routine entry-point register reg[pDest->iSDParm], that EOF is the
-** completed flag reg[pDest->iSDParm+1], and R and S are the range of
-** registers that hold the result set, reg[pDest->iSdst] through
-** reg[pDest->iSdst+pDest->nSdst-1]:
-**
-**         X <- A
-**         EOF <- 0
-**         goto B
-**      A: setup for the SELECT
-**         loop rows in the SELECT
-**           load results into registers R..S
-**           yield X
-**         end loop
-**         cleanup after the SELECT
-**         EOF <- 1
-**         yield X
-**         halt-error
-**      B:
-**
-** To use this subroutine, the caller generates code as follows:
-**
-**         [ Co-routine generated by this subroutine, shown above ]
-**      S: yield X
-**         if EOF goto E
-**         if skip this row, goto C
-**         if terminate loop, goto E
-**         deal with this row
-**      C: goto S
-**      E:
-*/
-SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){
-  int regYield;       /* Register holding co-routine entry-point */
-  int regEof;         /* Register holding co-routine completion flag */
-  int addrTop;        /* Top of the co-routine */
-  int j1;             /* Jump instruction */
-  int rc;             /* Result code */
-  Vdbe *v;            /* VDBE under construction */
-
-  regYield = ++pParse->nMem;
-  regEof = ++pParse->nMem;
-  v = sqlite3GetVdbe(pParse);
-  addrTop = sqlite3VdbeCurrentAddr(v);
-  sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */
-  VdbeComment((v, "Co-routine entry point"));
-  sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof);           /* EOF <- 0 */
-  VdbeComment((v, "Co-routine completion flag"));
-  sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield);
-  j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
-  rc = sqlite3Select(pParse, pSelect, pDest);
-  assert( pParse->nErr==0 || rc );
-  if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM;
-  if( rc ) return rc;
-  sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof);            /* EOF <- 1 */
-  sqlite3VdbeAddOp1(v, OP_Yield, regYield);   /* yield X */
-  sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
-  VdbeComment((v, "End of coroutine"));
-  sqlite3VdbeJumpHere(v, j1);                             /* label B: */
-  return rc;
-}
-
-
-
 /* Forward declaration */
 static int xferOptimization(
   Parse *pParse,        /* Parser context */
@@ -90526,7 +95125,7 @@ static int xferOptimization(
 );
 
 /*
-** This routine is call to handle SQL of the following forms:
+** This routine is called to handle SQL of the following forms:
 **
 **    insert into TABLE (IDLIST) values(EXPRLIST)
 **    insert into TABLE (IDLIST) select
@@ -90541,12 +95140,12 @@ static int xferOptimization(
 ** data for the insert.
 **
 ** The code generated follows one of four templates.  For a simple
-** select with data coming from a VALUES clause, the code executes
+** insert with data coming from a VALUES clause, the code executes
 ** once straight down through.  Pseudo-code follows (we call this
 ** the "1st template"):
 **
 **         open write cursor to <table> and its indices
-**         puts VALUES clause expressions onto the stack
+**         put VALUES clause expressions into registers
 **         write the resulting record into <table>
 **         cleanup
 **
@@ -90578,7 +95177,6 @@ static int xferOptimization(
 ** and the SELECT clause does not read from <table> at any time.
 ** The generated code follows this template:
 **
-**         EOF <- 0
 **         X <- A
 **         goto B
 **      A: setup for the SELECT
@@ -90587,12 +95185,9 @@ static int xferOptimization(
 **           yield X
 **         end loop
 **         cleanup after the SELECT
-**         EOF <- 1
-**         yield X
-**         goto A
+**         end-coroutine X
 **      B: open write cursor to <table> and its indices
-**      C: yield X
-**         if EOF goto D
+**      C: yield X, at EOF goto D
 **         insert the select result into <table> from R..R+n
 **         goto C
 **      D: cleanup
@@ -90603,7 +95198,6 @@ static int xferOptimization(
 ** we have to use a intermediate table to store the results of
 ** the select.  The template is like this:
 **
-**         EOF <- 0
 **         X <- A
 **         goto B
 **      A: setup for the SELECT
@@ -90612,12 +95206,9 @@ static int xferOptimization(
 **           yield X
 **         end loop
 **         cleanup after the SELECT
-**         EOF <- 1
-**         yield X
-**         halt-error
+**         end co-routine R
 **      B: open temp table
-**      L: yield X
-**         if EOF goto M
+**      L: yield X, at EOF goto M
 **         insert row from R..R+n into temp table
 **         goto L
 **      M: open write cursor to <table> and its indices
@@ -90630,7 +95221,6 @@ static int xferOptimization(
 SQLITE_PRIVATE void sqlite3Insert(
   Parse *pParse,        /* Parser context */
   SrcList *pTabList,    /* Name of table into which we are inserting */
-  ExprList *pList,      /* List of values to be inserted */
   Select *pSelect,      /* A SELECT statement to use as the data source */
   IdList *pColumn,      /* Column names corresponding to IDLIST. */
   int onError           /* How to handle constraint errors */
@@ -90644,18 +95234,21 @@ SQLITE_PRIVATE void sqlite3Insert(
   Index *pIdx;          /* For looping over indices of the table */
   int nColumn;          /* Number of columns in the data */
   int nHidden = 0;      /* Number of hidden columns if TABLE is virtual */
-  int baseCur = 0;      /* VDBE Cursor number for pTab */
-  int keyColumn = -1;   /* Column that is the INTEGER PRIMARY KEY */
+  int iDataCur = 0;     /* VDBE cursor that is the main data repository */
+  int iIdxCur = 0;      /* First index cursor */
+  int ipkColumn = -1;   /* Column that is the INTEGER PRIMARY KEY */
   int endOfLoop;        /* Label for the end of the insertion loop */
-  int useTempTable = 0; /* Store SELECT results in intermediate table */
   int srcTab = 0;       /* Data comes from this temporary cursor if >=0 */
   int addrInsTop = 0;   /* Jump to label "D" */
   int addrCont = 0;     /* Top of insert loop. Label "C" in templates 3 and 4 */
-  int addrSelect = 0;   /* Address of coroutine that implements the SELECT */
   SelectDest dest;      /* Destination for SELECT on rhs of INSERT */
   int iDb;              /* Index of database holding TABLE */
   Db *pDb;              /* The database containing table being inserted into */
-  int appendFlag = 0;   /* True if the insert is likely to be an append */
+  u8 useTempTable = 0;  /* Store SELECT results in intermediate table */
+  u8 appendFlag = 0;    /* True if the insert is likely to be an append */
+  u8 withoutRowid;      /* 0 for normal table.  1 for WITHOUT ROWID table */
+  u8 bIdListInOrder = 1; /* True if IDLIST is in table order */
+  ExprList *pList = 0;  /* List of VALUES() to be inserted  */
 
   /* Register allocations */
   int regFromSelect = 0;/* Base register for data coming from SELECT */
@@ -90664,7 +95257,6 @@ SQLITE_PRIVATE void sqlite3Insert(
   int regIns;           /* Block of regs holding rowid+data being inserted */
   int regRowid;         /* registers holding insert rowid */
   int regData;          /* register holding first column to insert */
-  int regEof = 0;       /* Register recording end of SELECT data */
   int *aRegIdx = 0;     /* One register allocated to each index */
 
 #ifndef SQLITE_OMIT_TRIGGER
@@ -90679,6 +95271,17 @@ SQLITE_PRIVATE void sqlite3Insert(
     goto insert_cleanup;
   }
 
+  /* If the Select object is really just a simple VALUES() list with a
+  ** single row values (the common case) then keep that one row of values
+  ** and go ahead and discard the Select object
+  */
+  if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){
+    pList = pSelect->pEList;
+    pSelect->pEList = 0;
+    sqlite3SelectDelete(db, pSelect);
+    pSelect = 0;
+  }
+
   /* Locate the table into which we will be inserting new information.
   */
   assert( pTabList->nSrc==1 );
@@ -90695,6 +95298,7 @@ SQLITE_PRIVATE void sqlite3Insert(
   if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
     goto insert_cleanup;
   }
+  withoutRowid = !HasRowid(pTab);
 
   /* Figure out if we have any triggers and if the table being
   ** inserted into is a view
@@ -90714,16 +95318,13 @@ SQLITE_PRIVATE void sqlite3Insert(
   assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
 
   /* If pTab is really a view, make sure it has been initialized.
-  ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual 
-  ** module table).
+  ** ViewGetColumnNames() is a no-op if pTab is not a view.
   */
   if( sqlite3ViewGetColumnNames(pParse, pTab) ){
     goto insert_cleanup;
   }
 
-  /* Ensure that:
-  *  (a) the table is not read-only, 
-  *  (b) that if it is a view then ON INSERT triggers exist
+  /* Cannot insert into a read-only table.
   */
   if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
     goto insert_cleanup;
@@ -90758,113 +95359,27 @@ SQLITE_PRIVATE void sqlite3Insert(
   */
   regAutoinc = autoIncBegin(pParse, iDb, pTab);
 
-  /* Figure out how many columns of data are supplied.  If the data
-  ** is coming from a SELECT statement, then generate a co-routine that
-  ** produces a single row of the SELECT on each invocation.  The
-  ** co-routine is the common header to the 3rd and 4th templates.
-  */
-  if( pSelect ){
-    /* Data is coming from a SELECT.  Generate a co-routine to run that
-    ** SELECT. */
-    int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest);
-    if( rc ) goto insert_cleanup;
-
-    regEof = dest.iSDParm + 1;
-    regFromSelect = dest.iSdst;
-    assert( pSelect->pEList );
-    nColumn = pSelect->pEList->nExpr;
-    assert( dest.nSdst==nColumn );
-
-    /* Set useTempTable to TRUE if the result of the SELECT statement
-    ** should be written into a temporary table (template 4).  Set to
-    ** FALSE if each* row of the SELECT can be written directly into
-    ** the destination table (template 3).
-    **
-    ** A temp table must be used if the table being updated is also one
-    ** of the tables being read by the SELECT statement.  Also use a 
-    ** temp table in the case of row triggers.
-    */
-    if( pTrigger || readsTable(pParse, addrSelect, iDb, pTab) ){
-      useTempTable = 1;
-    }
-
-    if( useTempTable ){
-      /* Invoke the coroutine to extract information from the SELECT
-      ** and add it to a transient table srcTab.  The code generated
-      ** here is from the 4th template:
-      **
-      **      B: open temp table
-      **      L: yield X
-      **         if EOF goto M
-      **         insert row from R..R+n into temp table
-      **         goto L
-      **      M: ...
-      */
-      int regRec;          /* Register to hold packed record */
-      int regTempRowid;    /* Register to hold temp table ROWID */
-      int addrTop;         /* Label "L" */
-      int addrIf;          /* Address of jump to M */
-
-      srcTab = pParse->nTab++;
-      regRec = sqlite3GetTempReg(pParse);
-      regTempRowid = sqlite3GetTempReg(pParse);
-      sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
-      addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
-      addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof);
-      sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
-      sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
-      sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
-      sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
-      sqlite3VdbeJumpHere(v, addrIf);
-      sqlite3ReleaseTempReg(pParse, regRec);
-      sqlite3ReleaseTempReg(pParse, regTempRowid);
-    }
-  }else{
-    /* This is the case if the data for the INSERT is coming from a VALUES
-    ** clause
-    */
-    NameContext sNC;
-    memset(&sNC, 0, sizeof(sNC));
-    sNC.pParse = pParse;
-    srcTab = -1;
-    assert( useTempTable==0 );
-    nColumn = pList ? pList->nExpr : 0;
-    for(i=0; i<nColumn; i++){
-      if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
-        goto insert_cleanup;
-      }
-    }
-  }
-
-  /* Make sure the number of columns in the source data matches the number
-  ** of columns to be inserted into the table.
+  /* Allocate registers for holding the rowid of the new row,
+  ** the content of the new row, and the assemblied row record.
   */
+  regRowid = regIns = pParse->nMem+1;
+  pParse->nMem += pTab->nCol + 1;
   if( IsVirtual(pTab) ){
-    for(i=0; i<pTab->nCol; i++){
-      nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
-    }
-  }
-  if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
-    sqlite3ErrorMsg(pParse, 
-       "table %S has %d columns but %d values were supplied",
-       pTabList, 0, pTab->nCol-nHidden, nColumn);
-    goto insert_cleanup;
-  }
-  if( pColumn!=0 && nColumn!=pColumn->nId ){
-    sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
-    goto insert_cleanup;
+    regRowid++;
+    pParse->nMem++;
   }
+  regData = regRowid+1;
 
   /* If the INSERT statement included an IDLIST term, then make sure
   ** all elements of the IDLIST really are columns of the table and 
   ** remember the column indices.
   **
   ** If the table has an INTEGER PRIMARY KEY column and that column
-  ** is named in the IDLIST, then record in the keyColumn variable
-  ** the index into IDLIST of the primary key column.  keyColumn is
+  ** is named in the IDLIST, then record in the ipkColumn variable
+  ** the index into IDLIST of the primary key column.  ipkColumn is
   ** the index of the primary key as it appears in IDLIST, not as
-  ** is appears in the original table.  (The index of the primary
-  ** key in the original table is pTab->iPKey.)
+  ** is appears in the original table.  (The index of the INTEGER
+  ** PRIMARY KEY in the original table is pTab->iPKey.)
   */
   if( pColumn ){
     for(i=0; i<pColumn->nId; i++){
@@ -90874,15 +95389,17 @@ SQLITE_PRIVATE void sqlite3Insert(
       for(j=0; j<pTab->nCol; j++){
         if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
           pColumn->a[i].idx = j;
+          if( i!=j ) bIdListInOrder = 0;
           if( j==pTab->iPKey ){
-            keyColumn = i;
+            ipkColumn = i;  assert( !withoutRowid );
           }
           break;
         }
       }
       if( j>=pTab->nCol ){
-        if( sqlite3IsRowid(pColumn->a[i].zName) ){
-          keyColumn = i;
+        if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
+          ipkColumn = i;
+          bIdListInOrder = 0;
         }else{
           sqlite3ErrorMsg(pParse, "table %S has no column named %s",
               pTabList, 0, pColumn->a[i].zName);
@@ -90893,12 +95410,115 @@ SQLITE_PRIVATE void sqlite3Insert(
     }
   }
 
+  /* Figure out how many columns of data are supplied.  If the data
+  ** is coming from a SELECT statement, then generate a co-routine that
+  ** produces a single row of the SELECT on each invocation.  The
+  ** co-routine is the common header to the 3rd and 4th templates.
+  */
+  if( pSelect ){
+    /* Data is coming from a SELECT.  Generate a co-routine to run the SELECT */
+    int regYield;       /* Register holding co-routine entry-point */
+    int addrTop;        /* Top of the co-routine */
+    int rc;             /* Result code */
+
+    regYield = ++pParse->nMem;
+    addrTop = sqlite3VdbeCurrentAddr(v) + 1;
+    sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
+    sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
+    dest.iSdst = bIdListInOrder ? regData : 0;
+    dest.nSdst = pTab->nCol;
+    rc = sqlite3Select(pParse, pSelect, &dest);
+    regFromSelect = dest.iSdst;
+    assert( pParse->nErr==0 || rc );
+    if( rc || db->mallocFailed ) goto insert_cleanup;
+    sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield);
+    sqlite3VdbeJumpHere(v, addrTop - 1);                       /* label B: */
+    assert( pSelect->pEList );
+    nColumn = pSelect->pEList->nExpr;
+
+    /* Set useTempTable to TRUE if the result of the SELECT statement
+    ** should be written into a temporary table (template 4).  Set to
+    ** FALSE if each output row of the SELECT can be written directly into
+    ** the destination table (template 3).
+    **
+    ** A temp table must be used if the table being updated is also one
+    ** of the tables being read by the SELECT statement.  Also use a 
+    ** temp table in the case of row triggers.
+    */
+    if( pTrigger || readsTable(pParse, iDb, pTab) ){
+      useTempTable = 1;
+    }
+
+    if( useTempTable ){
+      /* Invoke the coroutine to extract information from the SELECT
+      ** and add it to a transient table srcTab.  The code generated
+      ** here is from the 4th template:
+      **
+      **      B: open temp table
+      **      L: yield X, goto M at EOF
+      **         insert row from R..R+n into temp table
+      **         goto L
+      **      M: ...
+      */
+      int regRec;          /* Register to hold packed record */
+      int regTempRowid;    /* Register to hold temp table ROWID */
+      int addrL;           /* Label "L" */
+
+      srcTab = pParse->nTab++;
+      regRec = sqlite3GetTempReg(pParse);
+      regTempRowid = sqlite3GetTempReg(pParse);
+      sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
+      addrL = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v);
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
+      sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
+      sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
+      sqlite3VdbeAddOp2(v, OP_Goto, 0, addrL);
+      sqlite3VdbeJumpHere(v, addrL);
+      sqlite3ReleaseTempReg(pParse, regRec);
+      sqlite3ReleaseTempReg(pParse, regTempRowid);
+    }
+  }else{
+    /* This is the case if the data for the INSERT is coming from a VALUES
+    ** clause
+    */
+    NameContext sNC;
+    memset(&sNC, 0, sizeof(sNC));
+    sNC.pParse = pParse;
+    srcTab = -1;
+    assert( useTempTable==0 );
+    nColumn = pList ? pList->nExpr : 0;
+    for(i=0; i<nColumn; i++){
+      if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
+        goto insert_cleanup;
+      }
+    }
+  }
+
   /* If there is no IDLIST term but the table has an integer primary
-  ** key, the set the keyColumn variable to the primary key column index
-  ** in the original table definition.
+  ** key, the set the ipkColumn variable to the integer primary key 
+  ** column index in the original table definition.
   */
   if( pColumn==0 && nColumn>0 ){
-    keyColumn = pTab->iPKey;
+    ipkColumn = pTab->iPKey;
+  }
+
+  /* Make sure the number of columns in the source data matches the number
+  ** of columns to be inserted into the table.
+  */
+  if( IsVirtual(pTab) ){
+    for(i=0; i<pTab->nCol; i++){
+      nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
+    }
+  }
+  if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
+    sqlite3ErrorMsg(pParse, 
+       "table %S has %d columns but %d values were supplied",
+       pTabList, 0, pTab->nCol-nHidden, nColumn);
+    goto insert_cleanup;
+  }
+  if( pColumn!=0 && nColumn!=pColumn->nId ){
+    sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
+    goto insert_cleanup;
   }
     
   /* Initialize the count of rows to be inserted
@@ -90911,9 +95531,8 @@ SQLITE_PRIVATE void sqlite3Insert(
   /* If this is not a view, open the table and and all indices */
   if( !isView ){
     int nIdx;
-
-    baseCur = pParse->nTab;
-    nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite);
+    nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, -1, 0,
+                                      &iDataCur, &iIdxCur);
     aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
     if( aRegIdx==0 ){
       goto insert_cleanup;
@@ -90928,39 +95547,27 @@ SQLITE_PRIVATE void sqlite3Insert(
     /* This block codes the top of loop only.  The complete loop is the
     ** following pseudocode (template 4):
     **
-    **         rewind temp table
+    **         rewind temp table, if empty goto D
     **      C: loop over rows of intermediate table
     **           transfer values form intermediate table into <table>
     **         end loop
     **      D: ...
     */
-    addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab);
+    addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); VdbeCoverage(v);
     addrCont = sqlite3VdbeCurrentAddr(v);
   }else if( pSelect ){
     /* This block codes the top of loop only.  The complete loop is the
     ** following pseudocode (template 3):
     **
-    **      C: yield X
-    **         if EOF goto D
+    **      C: yield X, at EOF goto D
     **         insert the select result into <table> from R..R+n
     **         goto C
     **      D: ...
     */
-    addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
-    addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof);
+    addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
+    VdbeCoverage(v);
   }
 
-  /* Allocate registers for holding the rowid of the new row,
-  ** the content of the new row, and the assemblied row record.
-  */
-  regRowid = regIns = pParse->nMem+1;
-  pParse->nMem += pTab->nCol + 1;
-  if( IsVirtual(pTab) ){
-    regRowid++;
-    pParse->nMem++;
-  }
-  regData = regRowid+1;
-
   /* Run the BEFORE and INSTEAD OF triggers, if there are any
   */
   endOfLoop = sqlite3VdbeMakeLabel(v);
@@ -90973,20 +95580,21 @@ SQLITE_PRIVATE void sqlite3Insert(
     ** we do not know what the unique ID will be (because the insert has
     ** not happened yet) so we substitute a rowid of -1
     */
-    if( keyColumn<0 ){
+    if( ipkColumn<0 ){
       sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
     }else{
       int j1;
+      assert( !withoutRowid );
       if( useTempTable ){
-        sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regCols);
+        sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regCols);
       }else{
         assert( pSelect==0 );  /* Otherwise useTempTable is true */
-        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regCols);
+        sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols);
       }
-      j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols);
+      j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v);
       sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
       sqlite3VdbeJumpHere(v, j1);
-      sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols);
+      sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v);
     }
 
     /* Cannot have triggers on a virtual table. If it were possible,
@@ -91020,8 +95628,7 @@ SQLITE_PRIVATE void sqlite3Insert(
     ** table column affinities.
     */
     if( !isView ){
-      sqlite3VdbeAddOp2(v, OP_Affinity, regCols+1, pTab->nCol);
-      sqlite3TableAffinityStr(v, pTab);
+      sqlite3TableAffinity(v, pTab, regCols+1);
     }
 
     /* Fire BEFORE or INSTEAD OF triggers */
@@ -91031,29 +95638,27 @@ SQLITE_PRIVATE void sqlite3Insert(
     sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
   }
 
-  /* Push the record number for the new entry onto the stack.  The
-  ** record number is a randomly generate integer created by NewRowid
-  ** except when the table has an INTEGER PRIMARY KEY column, in which
-  ** case the record number is the same as that column. 
+  /* Compute the content of the next row to insert into a range of
+  ** registers beginning at regIns.
   */
   if( !isView ){
     if( IsVirtual(pTab) ){
       /* The row that the VUpdate opcode will delete: none */
       sqlite3VdbeAddOp2(v, OP_Null, 0, regIns);
     }
-    if( keyColumn>=0 ){
+    if( ipkColumn>=0 ){
       if( useTempTable ){
-        sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid);
+        sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid);
       }else if( pSelect ){
-        sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid);
+        sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
       }else{
         VdbeOp *pOp;
-        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid);
+        sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid);
         pOp = sqlite3VdbeGetOp(v, -1);
         if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){
           appendFlag = 1;
           pOp->opcode = OP_NewRowid;
-          pOp->p1 = baseCur;
+          pOp->p1 = iDataCur;
           pOp->p2 = regRowid;
           pOp->p3 = regAutoinc;
         }
@@ -91064,24 +95669,24 @@ SQLITE_PRIVATE void sqlite3Insert(
       if( !appendFlag ){
         int j1;
         if( !IsVirtual(pTab) ){
-          j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid);
-          sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
+          j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v);
+          sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
           sqlite3VdbeJumpHere(v, j1);
         }else{
           j1 = sqlite3VdbeCurrentAddr(v);
-          sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2);
+          sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); VdbeCoverage(v);
         }
-        sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);
+        sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v);
       }
-    }else if( IsVirtual(pTab) ){
+    }else if( IsVirtual(pTab) || withoutRowid ){
       sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);
     }else{
-      sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
+      sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
       appendFlag = 1;
     }
     autoIncStep(pParse, regAutoinc, regRowid);
 
-    /* Push onto the stack, data for all columns of the new entry, beginning
+    /* Compute data for all columns of the new entry, beginning
     ** with the first column.
     */
     nHidden = 0;
@@ -91089,10 +95694,11 @@ SQLITE_PRIVATE void sqlite3Insert(
       int iRegStore = regRowid+1+i;
       if( i==pTab->iPKey ){
         /* The value of the INTEGER PRIMARY KEY column is always a NULL.
-        ** Whenever this column is read, the record number will be substituted
-        ** in its place.  So will fill this column with a NULL to avoid
-        ** taking up data space with information that will never be used. */
-        sqlite3VdbeAddOp2(v, OP_Null, 0, iRegStore);
+        ** Whenever this column is read, the rowid will be substituted
+        ** in its place.  Hence, fill this column with a NULL to avoid
+        ** taking up data space with information that will never be used.
+        ** As there may be shallow copies of this value, make it a soft-NULL */
+        sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
         continue;
       }
       if( pColumn==0 ){
@@ -91109,11 +95715,13 @@ SQLITE_PRIVATE void sqlite3Insert(
         }
       }
       if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
-        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore);
+        sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
       }else if( useTempTable ){
         sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); 
       }else if( pSelect ){
-        sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
+        if( regFromSelect!=regData ){
+          sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
+        }
       }else{
         sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
       }
@@ -91133,13 +95741,12 @@ SQLITE_PRIVATE void sqlite3Insert(
 #endif
     {
       int isReplace;    /* Set to true if constraints may cause a replace */
-      sqlite3GenerateConstraintChecks(pParse, pTab, baseCur, regIns, aRegIdx,
-          keyColumn>=0, 0, onError, endOfLoop, &isReplace
-      );
-      sqlite3FkCheck(pParse, pTab, 0, regIns);
-      sqlite3CompleteInsertion(
-          pParse, pTab, baseCur, regIns, aRegIdx, 0, appendFlag, isReplace==0
+      sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
+          regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace
       );
+      sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
+      sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
+                               regIns, aRegIdx, 0, appendFlag, isReplace==0);
     }
   }
 
@@ -91160,7 +95767,7 @@ SQLITE_PRIVATE void sqlite3Insert(
   */
   sqlite3VdbeResolveLabel(v, endOfLoop);
   if( useTempTable ){
-    sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont);
+    sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); VdbeCoverage(v);
     sqlite3VdbeJumpHere(v, addrInsTop);
     sqlite3VdbeAddOp1(v, OP_Close, srcTab);
   }else if( pSelect ){
@@ -91170,9 +95777,9 @@ SQLITE_PRIVATE void sqlite3Insert(
 
   if( !IsVirtual(pTab) && !isView ){
     /* Close all tables opened */
-    sqlite3VdbeAddOp1(v, OP_Close, baseCur);
-    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
-      sqlite3VdbeAddOp1(v, OP_Close, idx+baseCur);
+    if( iDataCur<iIdxCur ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur);
+    for(idx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
+      sqlite3VdbeAddOp1(v, OP_Close, idx+iIdxCur);
     }
   }
 
@@ -91217,36 +95824,48 @@ insert_cleanup:
  #undef tmask
 #endif
 
-
 /*
-** Generate code to do constraint checks prior to an INSERT or an UPDATE.
+** Generate code to do constraint checks prior to an INSERT or an UPDATE
+** on table pTab.
 **
-** The input is a range of consecutive registers as follows:
+** The regNewData parameter is the first register in a range that contains
+** the data to be inserted or the data after the update.  There will be
+** pTab->nCol+1 registers in this range.  The first register (the one
+** that regNewData points to) will contain the new rowid, or NULL in the
+** case of a WITHOUT ROWID table.  The second register in the range will
+** contain the content of the first table column.  The third register will
+** contain the content of the second table column.  And so forth.
 **
-**    1.  The rowid of the row after the update.
+** The regOldData parameter is similar to regNewData except that it contains
+** the data prior to an UPDATE rather than afterwards.  regOldData is zero
+** for an INSERT.  This routine can distinguish between UPDATE and INSERT by
+** checking regOldData for zero.
 **
-**    2.  The data in the first column of the entry after the update.
+** For an UPDATE, the pkChng boolean is true if the true primary key (the
+** rowid for a normal table or the PRIMARY KEY for a WITHOUT ROWID table)
+** might be modified by the UPDATE.  If pkChng is false, then the key of
+** the iDataCur content table is guaranteed to be unchanged by the UPDATE.
 **
-**    i.  Data from middle columns...
+** For an INSERT, the pkChng boolean indicates whether or not the rowid
+** was explicitly specified as part of the INSERT statement.  If pkChng
+** is zero, it means that the either rowid is computed automatically or
+** that the table is a WITHOUT ROWID table and has no rowid.  On an INSERT,
+** pkChng will only be true if the INSERT statement provides an integer
+** value for either the rowid column or its INTEGER PRIMARY KEY alias.
 **
-**    N.  The data in the last column of the entry after the update.
-**
-** The regRowid parameter is the index of the register containing (1).
-**
-** If isUpdate is true and rowidChng is non-zero, then rowidChng contains
-** the address of a register containing the rowid before the update takes
-** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate
-** is false, indicating an INSERT statement, then a non-zero rowidChng 
-** indicates that the rowid was explicitly specified as part of the
-** INSERT statement. If rowidChng is false, it means that  the rowid is
-** computed automatically in an insert or that the rowid value is not 
-** modified by an update.
-**
-** The code generated by this routine store new index entries into
+** The code generated by this routine will store new index entries into
 ** registers identified by aRegIdx[].  No index entry is created for
 ** indices where aRegIdx[i]==0.  The order of indices in aRegIdx[] is
 ** the same as the order of indices on the linked list of indices
-** attached to the table.
+** at pTab->pIndex.
+**
+** The caller must have already opened writeable cursors on the main
+** table and all applicable indices (that is to say, all indices for which
+** aRegIdx[] is not zero).  iDataCur is the cursor for the main table when
+** inserting or updating a rowid table, or the cursor for the PRIMARY KEY
+** index when operating on a WITHOUT ROWID table.  iIdxCur is the cursor
+** for the first index in the pTab->pIndex list.  Cursors for other indices
+** are at iIdxCur+N for the N-th element of the pTab->pIndex list.
 **
 ** This routine also generates code to check constraints.  NOT NULL,
 ** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
@@ -91256,22 +95875,23 @@ insert_cleanup:
 **  Constraint type  Action       What Happens
 **  ---------------  ----------   ----------------------------------------
 **  any              ROLLBACK     The current transaction is rolled back and
-**                                sqlite3_exec() returns immediately with a
+**                                sqlite3_step() returns immediately with a
 **                                return code of SQLITE_CONSTRAINT.
 **
 **  any              ABORT        Back out changes from the current command
 **                                only (do not do a complete rollback) then
-**                                cause sqlite3_exec() to return immediately
+**                                cause sqlite3_step() to return immediately
 **                                with SQLITE_CONSTRAINT.
 **
-**  any              FAIL         Sqlite3_exec() returns immediately with a
+**  any              FAIL         Sqlite3_step() returns immediately with a
 **                                return code of SQLITE_CONSTRAINT.  The
 **                                transaction is not rolled back and any
-**                                prior changes are retained.
+**                                changes to prior rows are retained.
 **
-**  any              IGNORE       The record number and data is popped from
-**                                the stack and there is an immediate jump
-**                                to label ignoreDest.
+**  any              IGNORE       The attempt in insert or update the current
+**                                row is skipped, without throwing an error.
+**                                Processing continues with the next row.
+**                                (There is an immediate jump to ignoreDest.)
 **
 **  NOT NULL         REPLACE      The NULL value is replace by the default
 **                                value for that column.  If the default value
@@ -91286,44 +95906,59 @@ insert_cleanup:
 ** Or if overrideError==OE_Default, then the pParse->onError parameter
 ** is used.  Or if pParse->onError==OE_Default then the onError value
 ** for the constraint is used.
-**
-** The calling routine must open a read/write cursor for pTab with
-** cursor number "baseCur".  All indices of pTab must also have open
-** read/write cursors with cursor number baseCur+i for the i-th cursor.
-** Except, if there is no possibility of a REPLACE action then
-** cursors do not need to be open for indices where aRegIdx[i]==0.
 */
 SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
-  Parse *pParse,      /* The parser context */
-  Table *pTab,        /* the table into which we are inserting */
-  int baseCur,        /* Index of a read/write cursor pointing at pTab */
-  int regRowid,       /* Index of the range of input registers */
-  int *aRegIdx,       /* Register used by each index.  0 for unused indices */
-  int rowidChng,      /* True if the rowid might collide with existing entry */
-  int isUpdate,       /* True for UPDATE, False for INSERT */
-  int overrideError,  /* Override onError to this if not OE_Default */
-  int ignoreDest,     /* Jump to this label on an OE_Ignore resolution */
-  int *pbMayReplace   /* OUT: Set to true if constraint may cause a replace */
-){
-  int i;              /* loop counter */
-  Vdbe *v;            /* VDBE under constrution */
-  int nCol;           /* Number of columns */
-  int onError;        /* Conflict resolution strategy */
-  int j1;             /* Addresss of jump instruction */
-  int j2 = 0, j3;     /* Addresses of jump instructions */
-  int regData;        /* Register containing first data column */
-  int iCur;           /* Table cursor number */
+  Parse *pParse,       /* The parser context */
+  Table *pTab,         /* The table being inserted or updated */
+  int *aRegIdx,        /* Use register aRegIdx[i] for index i.  0 for unused */
+  int iDataCur,        /* Canonical data cursor (main table or PK index) */
+  int iIdxCur,         /* First index cursor */
+  int regNewData,      /* First register in a range holding values to insert */
+  int regOldData,      /* Previous content.  0 for INSERTs */
+  u8 pkChng,           /* Non-zero if the rowid or PRIMARY KEY changed */
+  u8 overrideError,    /* Override onError to this if not OE_Default */
+  int ignoreDest,      /* Jump to this label on an OE_Ignore resolution */
+  int *pbMayReplace    /* OUT: Set to true if constraint may cause a replace */
+){
+  Vdbe *v;             /* VDBE under constrution */
   Index *pIdx;         /* Pointer to one of the indices */
+  Index *pPk = 0;      /* The PRIMARY KEY index */
   sqlite3 *db;         /* Database connection */
+  int i;               /* loop counter */
+  int ix;              /* Index loop counter */
+  int nCol;            /* Number of columns */
+  int onError;         /* Conflict resolution strategy */
+  int j1;              /* Addresss of jump instruction */
   int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
-  int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid;
-
+  int nPkField;        /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
+  int ipkTop = 0;      /* Top of the rowid change constraint check */
+  int ipkBottom = 0;   /* Bottom of the rowid change constraint check */
+  u8 isUpdate;         /* True if this is an UPDATE operation */
+  u8 bAffinityDone = 0;  /* True if the OP_Affinity operation has been run */
+  int regRowid = -1;   /* Register holding ROWID value */
+
+  isUpdate = regOldData!=0;
   db = pParse->db;
   v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
   assert( pTab->pSelect==0 );  /* This table is not a VIEW */
   nCol = pTab->nCol;
-  regData = regRowid + 1;
+  
+  /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
+  ** normal rowid tables.  nPkField is the number of key fields in the 
+  ** pPk index or 1 for a rowid table.  In other words, nPkField is the
+  ** number of fields in the true primary key of the table. */
+  if( HasRowid(pTab) ){
+    pPk = 0;
+    nPkField = 1;
+  }else{
+    pPk = sqlite3PrimaryKeyIndex(pTab);
+    nPkField = pPk->nKeyCol;
+  }
+
+  /* Record that this module has started */
+  VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)",
+                     iDataCur, iIdxCur, regNewData, regOldData, pkChng));
 
   /* Test all NOT NULL constraints.
   */
@@ -91346,24 +95981,26 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
     switch( onError ){
       case OE_Abort:
         sqlite3MayAbort(pParse);
+        /* Fall through */
       case OE_Rollback:
       case OE_Fail: {
-        char *zMsg;
-        sqlite3VdbeAddOp3(v, OP_HaltIfNull,
-                          SQLITE_CONSTRAINT_NOTNULL, onError, regData+i);
-        zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
-                              pTab->zName, pTab->aCol[i].zName);
-        sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
+        char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
+                                    pTab->aCol[i].zName);
+        sqlite3VdbeAddOp4(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
+                          regNewData+1+i, zMsg, P4_DYNAMIC);
+        sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
+        VdbeCoverage(v);
         break;
       }
       case OE_Ignore: {
-        sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest);
+        sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
+        VdbeCoverage(v);
         break;
       }
       default: {
         assert( onError==OE_Replace );
-        j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i);
-        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i);
+        j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); VdbeCoverage(v);
+        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
         sqlite3VdbeJumpHere(v, j1);
         break;
       }
@@ -91375,7 +96012,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
 #ifndef SQLITE_OMIT_CHECK
   if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
     ExprList *pCheck = pTab->pCheck;
-    pParse->ckBase = regData;
+    pParse->ckBase = regNewData+1;
     onError = overrideError!=OE_Default ? overrideError : OE_Abort;
     for(i=0; i<pCheck->nExpr; i++){
       int allOk = sqlite3VdbeMakeLabel(v);
@@ -91383,37 +96020,61 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
       if( onError==OE_Ignore ){
         sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
       }else{
-        char *zConsName = pCheck->a[i].zName;
+        char *zName = pCheck->a[i].zName;
+        if( zName==0 ) zName = pTab->zName;
         if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
-        if( zConsName ){
-          zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
-        }else{
-          zConsName = 0;
-        }
         sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
-                              onError, zConsName, P4_DYNAMIC);
+                              onError, zName, P4_TRANSIENT,
+                              P5_ConstraintCheck);
       }
       sqlite3VdbeResolveLabel(v, allOk);
     }
   }
 #endif /* !defined(SQLITE_OMIT_CHECK) */
 
-  /* If we have an INTEGER PRIMARY KEY, make sure the primary key
-  ** of the new record does not previously exist.  Except, if this
-  ** is an UPDATE and the primary key is not changing, that is OK.
+  /* If rowid is changing, make sure the new rowid does not previously
+  ** exist in the table.
   */
-  if( rowidChng ){
+  if( pkChng && pPk==0 ){
+    int addrRowidOk = sqlite3VdbeMakeLabel(v);
+
+    /* Figure out what action to take in case of a rowid collision */
     onError = pTab->keyConf;
     if( overrideError!=OE_Default ){
       onError = overrideError;
     }else if( onError==OE_Default ){
       onError = OE_Abort;
     }
-    
+
     if( isUpdate ){
-      j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
+      /* pkChng!=0 does not mean that the rowid has change, only that
+      ** it might have changed.  Skip the conflict logic below if the rowid
+      ** is unchanged. */
+      sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
+      sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
+      VdbeCoverage(v);
+    }
+
+    /* If the response to a rowid conflict is REPLACE but the response
+    ** to some other UNIQUE constraint is FAIL or IGNORE, then we need
+    ** to defer the running of the rowid conflict checking until after
+    ** the UNIQUE constraints have run.
+    */
+    if( onError==OE_Replace && overrideError!=OE_Replace ){
+      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+        if( pIdx->onError==OE_Ignore || pIdx->onError==OE_Fail ){
+          ipkTop = sqlite3VdbeAddOp0(v, OP_Goto);
+          break;
+        }
+      }
     }
-    j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
+
+    /* Check to see if the new rowid already exists in the table.  Skip
+    ** the following conflict logic if it does not. */
+    sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
+    VdbeCoverage(v);
+
+    /* Generate code that deals with a rowid collision */
     switch( onError ){
       default: {
         onError = OE_Abort;
@@ -91422,8 +96083,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
       case OE_Rollback:
       case OE_Abort:
       case OE_Fail: {
-        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
-           onError, "PRIMARY KEY must be unique", P4_STATIC);
+        sqlite3RowidConstraint(pParse, onError, pTab);
         break;
       }
       case OE_Replace: {
@@ -91455,57 +96115,93 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
         }
         if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
           sqlite3MultiWrite(pParse);
-          sqlite3GenerateRowDelete(
-              pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
-          );
+          sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
+                                   regNewData, 1, 0, OE_Replace, 1);
         }else if( pTab->pIndex ){
           sqlite3MultiWrite(pParse);
-          sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
+          sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0);
         }
         seenReplace = 1;
         break;
       }
       case OE_Ignore: {
-        assert( seenReplace==0 );
+        /*assert( seenReplace==0 );*/
         sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
         break;
       }
     }
-    sqlite3VdbeJumpHere(v, j3);
-    if( isUpdate ){
-      sqlite3VdbeJumpHere(v, j2);
+    sqlite3VdbeResolveLabel(v, addrRowidOk);
+    if( ipkTop ){
+      ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto);
+      sqlite3VdbeJumpHere(v, ipkTop);
     }
   }
 
   /* Test all UNIQUE constraints by creating entries for each UNIQUE
   ** index and making sure that duplicate entries do not already exist.
-  ** Add the new records to the indices as we go.
-  */
-  for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
-    int regIdx;
-    int regR;
-
-    if( aRegIdx[iCur]==0 ) continue;  /* Skip unused indices */
-
-    /* Create a key for accessing the index entry */
-    regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1);
+  ** Compute the revised record entries for indices as we go.
+  **
+  ** This loop also handles the case of the PRIMARY KEY index for a
+  ** WITHOUT ROWID table.
+  */
+  for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
+    int regIdx;          /* Range of registers hold conent for pIdx */
+    int regR;            /* Range of registers holding conflicting PK */
+    int iThisCur;        /* Cursor for this UNIQUE index */
+    int addrUniqueOk;    /* Jump here if the UNIQUE constraint is satisfied */
+
+    if( aRegIdx[ix]==0 ) continue;  /* Skip indices that do not change */
+    if( bAffinityDone==0 ){
+      sqlite3TableAffinity(v, pTab, regNewData+1);
+      bAffinityDone = 1;
+    }
+    iThisCur = iIdxCur+ix;
+    addrUniqueOk = sqlite3VdbeMakeLabel(v);
+
+    /* Skip partial indices for which the WHERE clause is not true */
+    if( pIdx->pPartIdxWhere ){
+      sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
+      pParse->ckBase = regNewData+1;
+      sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
+                         SQLITE_JUMPIFNULL);
+      pParse->ckBase = 0;
+    }
+
+    /* Create a record for this index entry as it should appear after
+    ** the insert or update.  Store that record in the aRegIdx[ix] register
+    */
+    regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
     for(i=0; i<pIdx->nColumn; i++){
-      int idx = pIdx->aiColumn[i];
-      if( idx==pTab->iPKey ){
-        sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
+      int iField = pIdx->aiColumn[i];
+      int x;
+      if( iField<0 || iField==pTab->iPKey ){
+        if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */
+        x = regNewData;
+        regRowid =  pIdx->pPartIdxWhere ? -1 : regIdx+i;
       }else{
-        sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i);
+        x = iField + regNewData + 1;
       }
+      sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
+      VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName));
     }
-    sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
-    sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
-    sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
-    sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
+    sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
+    VdbeComment((v, "for %s", pIdx->zName));
+    sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn);
 
-    /* Find out what action to take in case there is an indexing conflict */
+    /* In an UPDATE operation, if this index is the PRIMARY KEY index 
+    ** of a WITHOUT ROWID table and there has been no change the
+    ** primary key, then no collision is possible.  The collision detection
+    ** logic below can all be skipped. */
+    if( isUpdate && pPk==pIdx && pkChng==0 ){
+      sqlite3VdbeResolveLabel(v, addrUniqueOk);
+      continue;
+    }
+
+    /* Find out what action to take in case there is a uniqueness conflict */
     onError = pIdx->onError;
     if( onError==OE_None ){ 
-      sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
+      sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
+      sqlite3VdbeResolveLabel(v, addrUniqueOk);
       continue;  /* pIdx is not a UNIQUE index */
     }
     if( overrideError!=OE_Default ){
@@ -91513,18 +96209,64 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
     }else if( onError==OE_Default ){
       onError = OE_Abort;
     }
-    if( seenReplace ){
-      if( onError==OE_Ignore ) onError = OE_Replace;
-      else if( onError==OE_Fail ) onError = OE_Abort;
-    }
     
     /* Check to see if the new index entry will be unique */
-    regR = sqlite3GetTempReg(pParse);
-    sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR);
-    j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0,
-                           regR, SQLITE_INT_TO_PTR(regIdx),
-                           P4_INT32);
-    sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
+    sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
+                         regIdx, pIdx->nKeyCol); VdbeCoverage(v);
+
+    /* Generate code to handle collisions */
+    regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
+    if( isUpdate || onError==OE_Replace ){
+      if( HasRowid(pTab) ){
+        sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
+        /* Conflict only if the rowid of the existing index entry
+        ** is different from old-rowid */
+        if( isUpdate ){
+          sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData);
+          sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
+          VdbeCoverage(v);
+        }
+      }else{
+        int x;
+        /* Extract the PRIMARY KEY from the end of the index entry and
+        ** store it in registers regR..regR+nPk-1 */
+        if( pIdx!=pPk ){
+          for(i=0; i<pPk->nKeyCol; i++){
+            x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
+            sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
+            VdbeComment((v, "%s.%s", pTab->zName,
+                         pTab->aCol[pPk->aiColumn[i]].zName));
+          }
+        }
+        if( isUpdate ){
+          /* If currently processing the PRIMARY KEY of a WITHOUT ROWID 
+          ** table, only conflict if the new PRIMARY KEY values are actually
+          ** different from the old.
+          **
+          ** For a UNIQUE index, only conflict if the PRIMARY KEY values
+          ** of the matched index row are different from the original PRIMARY
+          ** KEY values of this row before the update.  */
+          int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
+          int op = OP_Ne;
+          int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR);
+  
+          for(i=0; i<pPk->nKeyCol; i++){
+            char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
+            x = pPk->aiColumn[i];
+            if( i==(pPk->nKeyCol-1) ){
+              addrJump = addrUniqueOk;
+              op = OP_Eq;
+            }
+            sqlite3VdbeAddOp4(v, op, 
+                regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
+            );
+            sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
+            VdbeCoverageIf(v, op==OP_Eq);
+            VdbeCoverageIf(v, op==OP_Ne);
+          }
+        }
+      }
+    }
 
     /* Generate code that executes if the new index entry is not unique */
     assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
@@ -91533,30 +96275,10 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
       case OE_Rollback:
       case OE_Abort:
       case OE_Fail: {
-        int j;
-        StrAccum errMsg;
-        const char *zSep;
-        char *zErr;
-
-        sqlite3StrAccumInit(&errMsg, 0, 0, 200);
-        errMsg.db = db;
-        zSep = pIdx->nColumn>1 ? "columns " : "column ";
-        for(j=0; j<pIdx->nColumn; j++){
-          char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
-          sqlite3StrAccumAppend(&errMsg, zSep, -1);
-          zSep = ", ";
-          sqlite3StrAccumAppend(&errMsg, zCol, -1);
-        }
-        sqlite3StrAccumAppend(&errMsg,
-            pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
-        zErr = sqlite3StrAccumFinish(&errMsg);
-        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
-                              onError, zErr, 0);
-        sqlite3DbFree(errMsg.db, zErr);
+        sqlite3UniqueConstraint(pParse, onError, pIdx);
         break;
       }
       case OE_Ignore: {
-        assert( seenReplace==0 );
         sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
         break;
       }
@@ -91567,26 +96289,29 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
         if( db->flags&SQLITE_RecTriggers ){
           pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
         }
-        sqlite3GenerateRowDelete(
-            pParse, pTab, baseCur, regR, 0, pTrigger, OE_Replace
-        );
+        sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
+                                 regR, nPkField, 0, OE_Replace, pIdx==pPk);
         seenReplace = 1;
         break;
       }
     }
-    sqlite3VdbeJumpHere(v, j3);
-    sqlite3ReleaseTempReg(pParse, regR);
+    sqlite3VdbeResolveLabel(v, addrUniqueOk);
+    sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
+    if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
   }
-  
-  if( pbMayReplace ){
-    *pbMayReplace = seenReplace;
+  if( ipkTop ){
+    sqlite3VdbeAddOp2(v, OP_Goto, 0, ipkTop+1);
+    sqlite3VdbeJumpHere(v, ipkBottom);
   }
+  
+  *pbMayReplace = seenReplace;
+  VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
 }
 
 /*
 ** This routine generates code to finish the INSERT or UPDATE operation
 ** that was started by a prior call to sqlite3GenerateConstraintChecks.
-** A consecutive range of registers starting at regRowid contains the
+** A consecutive range of registers starting at regNewData contains the
 ** rowid and the content to be inserted.
 **
 ** The arguments to this routine should be the same as the first six
@@ -91595,36 +96320,46 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
 SQLITE_PRIVATE void sqlite3CompleteInsertion(
   Parse *pParse,      /* The parser context */
   Table *pTab,        /* the table into which we are inserting */
-  int baseCur,        /* Index of a read/write cursor pointing at pTab */
-  int regRowid,       /* Range of content */
+  int iDataCur,       /* Cursor of the canonical data source */
+  int iIdxCur,        /* First index cursor */
+  int regNewData,     /* Range of content */
   int *aRegIdx,       /* Register used by each index.  0 for unused indices */
   int isUpdate,       /* True for UPDATE, False for INSERT */
   int appendBias,     /* True if this is likely to be an append */
   int useSeekResult   /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
 ){
-  int i;
-  Vdbe *v;
-  int nIdx;
-  Index *pIdx;
-  u8 pik_flags;
-  int regData;
-  int regRec;
+  Vdbe *v;            /* Prepared statements under construction */
+  Index *pIdx;        /* An index being inserted or updated */
+  u8 pik_flags;       /* flag values passed to the btree insert */
+  int regData;        /* Content registers (after the rowid) */
+  int regRec;         /* Register holding assemblied record for the table */
+  int i;              /* Loop counter */
+  u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */
 
   v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
   assert( pTab->pSelect==0 );  /* This table is not a VIEW */
-  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
-  for(i=nIdx-1; i>=0; i--){
+  for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
     if( aRegIdx[i]==0 ) continue;
-    sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]);
-    if( useSeekResult ){
-      sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+    bAffinityDone = 1;
+    if( pIdx->pPartIdxWhere ){
+      sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
+      VdbeCoverage(v);
+    }
+    sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
+    pik_flags = 0;
+    if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
+    if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
+      assert( pParse->nested==0 );
+      pik_flags |= OPFLAG_NCHANGE;
     }
+    if( pik_flags )  sqlite3VdbeChangeP5(v, pik_flags);
   }
-  regData = regRowid + 1;
+  if( !HasRowid(pTab) ) return;
+  regData = regNewData + 1;
   regRec = sqlite3GetTempReg(pParse);
   sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
-  sqlite3TableAffinityStr(v, pTab);
+  if( !bAffinityDone ) sqlite3TableAffinity(v, pTab, 0);
   sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
   if( pParse->nested ){
     pik_flags = 0;
@@ -91638,7 +96373,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
   if( useSeekResult ){
     pik_flags |= OPFLAG_USESEEKRESULT;
   }
-  sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid);
+  sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData);
   if( !pParse->nested ){
     sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
   }
@@ -91646,39 +96381,71 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
 }
 
 /*
-** Generate code that will open cursors for a table and for all
-** indices of that table.  The "baseCur" parameter is the cursor number used
-** for the table.  Indices are opened on subsequent cursors.
+** Allocate cursors for the pTab table and all its indices and generate
+** code to open and initialized those cursors.
 **
-** Return the number of indices on the table.
+** The cursor for the object that contains the complete data (normally
+** the table itself, but the PRIMARY KEY index in the case of a WITHOUT
+** ROWID table) is returned in *piDataCur.  The first index cursor is
+** returned in *piIdxCur.  The number of indices is returned.
+**
+** Use iBase as the first cursor (either the *piDataCur for rowid tables
+** or the first index for WITHOUT ROWID tables) if it is non-negative.
+** If iBase is negative, then allocate the next available cursor.
+**
+** For a rowid table, *piDataCur will be exactly one less than *piIdxCur.
+** For a WITHOUT ROWID table, *piDataCur will be somewhere in the range
+** of *piIdxCurs, depending on where the PRIMARY KEY index appears on the
+** pTab->pIndex list.
 */
 SQLITE_PRIVATE int sqlite3OpenTableAndIndices(
   Parse *pParse,   /* Parsing context */
   Table *pTab,     /* Table to be opened */
-  int baseCur,     /* Cursor number assigned to the table */
-  int op           /* OP_OpenRead or OP_OpenWrite */
+  int op,          /* OP_OpenRead or OP_OpenWrite */
+  int iBase,       /* Use this for the table cursor, if there is one */
+  u8 *aToOpen,     /* If not NULL: boolean for each table and index */
+  int *piDataCur,  /* Write the database source cursor number here */
+  int *piIdxCur    /* Write the first index cursor number here */
 ){
   int i;
   int iDb;
+  int iDataCur;
   Index *pIdx;
   Vdbe *v;
 
-  if( IsVirtual(pTab) ) return 0;
+  assert( op==OP_OpenRead || op==OP_OpenWrite );
+  if( IsVirtual(pTab) ){
+    assert( aToOpen==0 );
+    *piDataCur = 0;
+    *piIdxCur = 1;
+    return 0;
+  }
   iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
   v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
-  sqlite3OpenTable(pParse, baseCur, iDb, pTab, op);
-  for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
-    KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
-    assert( pIdx->pSchema==pTab->pSchema );
-    sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb,
-                      (char*)pKey, P4_KEYINFO_HANDOFF);
-    VdbeComment((v, "%s", pIdx->zName));
+  if( iBase<0 ) iBase = pParse->nTab;
+  iDataCur = iBase++;
+  if( piDataCur ) *piDataCur = iDataCur;
+  if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){
+    sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op);
+  }else{
+    sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName);
   }
-  if( pParse->nTab<baseCur+i ){
-    pParse->nTab = baseCur+i;
+  if( piIdxCur ) *piIdxCur = iBase;
+  for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+    int iIdxCur = iBase++;
+    assert( pIdx->pSchema==pTab->pSchema );
+    if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){
+      *piDataCur = iIdxCur;
+    }
+    if( aToOpen==0 || aToOpen[i+1] ){
+      sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
+      sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
+      VdbeComment((v, "%s", pIdx->zName));
+    }
   }
-  return i-1;
+  if( iBase>pParse->nTab ) pParse->nTab = iBase;
+  return i;
 }
 
 
@@ -91717,18 +96484,19 @@ static int xferCompatibleCollation(const char *z1, const char *z2){
 **    *   The same DESC and ASC markings occurs on all columns
 **    *   The same onError processing (OE_Abort, OE_Ignore, etc)
 **    *   The same collating sequence on each column
+**    *   The index has the exact same WHERE clause
 */
 static int xferCompatibleIndex(Index *pDest, Index *pSrc){
   int i;
   assert( pDest && pSrc );
   assert( pDest->pTable!=pSrc->pTable );
-  if( pDest->nColumn!=pSrc->nColumn ){
+  if( pDest->nKeyCol!=pSrc->nKeyCol ){
     return 0;   /* Different number of columns */
   }
   if( pDest->onError!=pSrc->onError ){
     return 0;   /* Different conflict resolution strategies */
   }
-  for(i=0; i<pSrc->nColumn; i++){
+  for(i=0; i<pSrc->nKeyCol; i++){
     if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){
       return 0;   /* Different columns indexed */
     }
@@ -91739,6 +96507,9 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
       return 0;   /* Different collating sequences */
     }
   }
+  if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
+    return 0;     /* Different WHERE clauses */
+  }
 
   /* If no test above fails then the indices must be compatible */
   return 1;
@@ -91784,10 +96555,9 @@ static int xferOptimization(
   int iDbSrc;                      /* The database of pSrc */
   int iSrc, iDest;                 /* Cursors from source and destination */
   int addr1, addr2;                /* Loop addresses */
-  int emptyDestTest;               /* Address of test for empty pDest */
-  int emptySrcTest;                /* Address of test for empty pSrc */
+  int emptyDestTest = 0;           /* Address of test for empty pDest */
+  int emptySrcTest = 0;            /* Address of test for empty pSrc */
   Vdbe *v;                         /* The VDBE we are building */
-  KeyInfo *pKey;                   /* Key information for an index */
   int regAutoinc;                  /* Memory register used by AUTOINC */
   int destHasUniqueIdx = 0;        /* True if pDest has a UNIQUE index */
   int regData, regRowid;           /* Registers holding data and rowid */
@@ -91795,6 +96565,12 @@ static int xferOptimization(
   if( pSelect==0 ){
     return 0;   /* Must be of the form  INSERT INTO ... SELECT ... */
   }
+  if( pParse->pWith || pSelect->pWith ){
+    /* Do not attempt to process this query if there are an WITH clauses
+    ** attached to it. Proceeding may generate a false "no such table: xxx"
+    ** error if pSelect reads from a CTE named "xxx".  */
+    return 0;
+  }
   if( sqlite3TriggerList(pParse, pDest) ){
     return 0;   /* tab1 must not have triggers */
   }
@@ -91857,6 +96633,9 @@ static int xferOptimization(
   if( pSrc==pDest ){
     return 0;   /* tab1 and tab2 may not be the same table */
   }
+  if( HasRowid(pDest)!=HasRowid(pSrc) ){
+    return 0;   /* source and destination must both be WITHOUT ROWID or not */
+  }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   if( pSrc->tabFlags & TF_Virtual ){
     return 0;   /* tab2 must not be a virtual table */
@@ -91872,18 +96651,27 @@ static int xferOptimization(
     return 0;   /* Both tables must have the same INTEGER PRIMARY KEY */
   }
   for(i=0; i<pDest->nCol; i++){
-    if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){
+    Column *pDestCol = &pDest->aCol[i];
+    Column *pSrcCol = &pSrc->aCol[i];
+    if( pDestCol->affinity!=pSrcCol->affinity ){
       return 0;    /* Affinity must be the same on all columns */
     }
-    if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){
+    if( !xferCompatibleCollation(pDestCol->zColl, pSrcCol->zColl) ){
       return 0;    /* Collating sequence must be the same on all columns */
     }
-    if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){
+    if( pDestCol->notNull && !pSrcCol->notNull ){
       return 0;    /* tab2 must be NOT NULL if tab1 is */
     }
+    /* Default values for second and subsequent columns need to match. */
+    if( i>0
+     && ((pDestCol->zDflt==0)!=(pSrcCol->zDflt==0) 
+         || (pDestCol->zDflt && strcmp(pDestCol->zDflt, pSrcCol->zDflt)!=0))
+    ){
+      return 0;    /* Default values must be the same for all columns */
+    }
   }
   for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
-    if( pDestIdx->onError!=OE_None ){
+    if( IsUniqueIndex(pDestIdx) ){
       destHasUniqueIdx = 1;
     }
     for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
@@ -91894,7 +96682,7 @@ static int xferOptimization(
     }
   }
 #ifndef SQLITE_OMIT_CHECK
-  if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck, pDest->pCheck) ){
+  if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
     return 0;   /* Tables have different CHECK constraints.  Ticket #2252 */
   }
 #endif
@@ -91927,7 +96715,10 @@ static int xferOptimization(
   iSrc = pParse->nTab++;
   iDest = pParse->nTab++;
   regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
+  regData = sqlite3GetTempReg(pParse);
+  regRowid = sqlite3GetTempReg(pParse);
   sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
+  assert( HasRowid(pDest) || destHasUniqueIdx );
   if( (pDest->iPKey<0 && pDest->pIndex!=0)          /* (1) */
    || destHasUniqueIdx                              /* (2) */
    || (onError!=OE_Abort && onError!=OE_Rollback)   /* (3) */
@@ -91946,60 +96737,60 @@ static int xferOptimization(
     **
     ** (3) onError is something other than OE_Abort and OE_Rollback.
     */
-    addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0);
+    addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v);
     emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
     sqlite3VdbeJumpHere(v, addr1);
-  }else{
-    emptyDestTest = 0;
   }
-  sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
-  emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
-  regData = sqlite3GetTempReg(pParse);
-  regRowid = sqlite3GetTempReg(pParse);
-  if( pDest->iPKey>=0 ){
-    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
-    addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
-    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
-        onError, "PRIMARY KEY must be unique", P4_STATIC);
-    sqlite3VdbeJumpHere(v, addr2);
-    autoIncStep(pParse, regAutoinc, regRowid);
-  }else if( pDest->pIndex==0 ){
-    addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
+  if( HasRowid(pSrc) ){
+    sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
+    emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
+    if( pDest->iPKey>=0 ){
+      addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
+      addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
+      VdbeCoverage(v);
+      sqlite3RowidConstraint(pParse, onError, pDest);
+      sqlite3VdbeJumpHere(v, addr2);
+      autoIncStep(pParse, regAutoinc, regRowid);
+    }else if( pDest->pIndex==0 ){
+      addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
+    }else{
+      addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
+      assert( (pDest->tabFlags & TF_Autoincrement)==0 );
+    }
+    sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
+    sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
+    sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
+    sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
+    sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
+    sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
+    sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
   }else{
-    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
-    assert( (pDest->tabFlags & TF_Autoincrement)==0 );
+    sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName);
+    sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName);
   }
-  sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
-  sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
-  sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
-  sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
-  sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);
   for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
     for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
       if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
     }
     assert( pSrcIdx );
-    sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
-    sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
-    pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx);
-    sqlite3VdbeAddOp4(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc,
-                      (char*)pKey, P4_KEYINFO_HANDOFF);
+    sqlite3VdbeAddOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc);
+    sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx);
     VdbeComment((v, "%s", pSrcIdx->zName));
-    pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
-    sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest,
-                      (char*)pKey, P4_KEYINFO_HANDOFF);
+    sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest);
+    sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx);
+    sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
     VdbeComment((v, "%s", pDestIdx->zName));
-    addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
+    addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
     sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
     sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
-    sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
+    sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
     sqlite3VdbeJumpHere(v, addr1);
+    sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
+    sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
   }
-  sqlite3VdbeJumpHere(v, emptySrcTest);
+  if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest);
   sqlite3ReleaseTempReg(pParse, regRowid);
   sqlite3ReleaseTempReg(pParse, regData);
-  sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
-  sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
   if( emptyDestTest ){
     sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0);
     sqlite3VdbeJumpHere(v, emptyDestTest);
@@ -92110,6 +96901,9 @@ SQLITE_API int sqlite3_exec(
           }
         }
         if( xCallback(pArg, nCol, azVals, azCols) ){
+          /* EVIDENCE-OF: R-38229-40159 If the callback function to
+          ** sqlite3_exec() returns non-zero, then sqlite3_exec() will
+          ** return SQLITE_ABORT. */
           rc = SQLITE_ABORT;
           sqlite3VdbeFinalize((Vdbe *)pStmt);
           pStmt = 0;
@@ -92651,11 +97445,14 @@ struct sqlite3_api_routines {
   ** extension */
 # define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
 # define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;
+# define SQLITE_EXTENSION_INIT3     \
+    extern const sqlite3_api_routines *sqlite3_api;
 #else
   /* This case when the file is being statically linked into the 
   ** application */
 # define SQLITE_EXTENSION_INIT1     /*no-op*/
 # define SQLITE_EXTENSION_INIT2(v)  (void)v; /* unused parameter */
+# define SQLITE_EXTENSION_INIT3     /*no-op*/
 #endif
 
 #endif /* _SQLITE3EXT_H_ */
@@ -93313,6 +98110,35 @@ SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){
 }
 
 /*
+** Cancel a prior call to sqlite3_auto_extension.  Remove xInit from the
+** set of routines that is invoked for each new database connection, if it
+** is currently on the list.  If xInit is not on the list, then this
+** routine is a no-op.
+**
+** Return 1 if xInit was found on the list and removed.  Return 0 if xInit
+** was not on the list.
+*/
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){
+#if SQLITE_THREADSAFE
+  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+  int i;
+  int n = 0;
+  wsdAutoextInit;
+  sqlite3_mutex_enter(mutex);
+  for(i=wsdAutoext.nExt-1; i>=0; i--){
+    if( wsdAutoext.aExt[i]==xInit ){
+      wsdAutoext.nExt--;
+      wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
+      n++;
+      break;
+    }
+  }
+  sqlite3_mutex_leave(mutex);
+  return n;
+}
+
+/*
 ** Reset the automatic extension loading mechanism.
 */
 SQLITE_API void sqlite3_reset_auto_extension(void){
@@ -93388,6 +98214,462 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
 ** This file contains code used to implement the PRAGMA command.
 */
 
+#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
+#  if defined(__APPLE__)
+#    define SQLITE_ENABLE_LOCKING_STYLE 1
+#  else
+#    define SQLITE_ENABLE_LOCKING_STYLE 0
+#  endif
+#endif
+
+/***************************************************************************
+** The next block of code, including the PragTyp_XXXX macro definitions and
+** the aPragmaName[] object is composed of generated code. DO NOT EDIT.
+**
+** To add new pragmas, edit the code in ../tool/mkpragmatab.tcl and rerun
+** that script.  Then copy/paste the output in place of the following:
+*/
+#define PragTyp_HEADER_VALUE                   0
+#define PragTyp_AUTO_VACUUM                    1
+#define PragTyp_FLAG                           2
+#define PragTyp_BUSY_TIMEOUT                   3
+#define PragTyp_CACHE_SIZE                     4
+#define PragTyp_CASE_SENSITIVE_LIKE            5
+#define PragTyp_COLLATION_LIST                 6
+#define PragTyp_COMPILE_OPTIONS                7
+#define PragTyp_DATA_STORE_DIRECTORY           8
+#define PragTyp_DATABASE_LIST                  9
+#define PragTyp_DEFAULT_CACHE_SIZE            10
+#define PragTyp_ENCODING                      11
+#define PragTyp_FOREIGN_KEY_CHECK             12
+#define PragTyp_FOREIGN_KEY_LIST              13
+#define PragTyp_INCREMENTAL_VACUUM            14
+#define PragTyp_INDEX_INFO                    15
+#define PragTyp_INDEX_LIST                    16
+#define PragTyp_INTEGRITY_CHECK               17
+#define PragTyp_JOURNAL_MODE                  18
+#define PragTyp_JOURNAL_SIZE_LIMIT            19
+#define PragTyp_LOCK_PROXY_FILE               20
+#define PragTyp_LOCKING_MODE                  21
+#define PragTyp_PAGE_COUNT                    22
+#define PragTyp_MMAP_SIZE                     23
+#define PragTyp_PAGE_SIZE                     24
+#define PragTyp_SECURE_DELETE                 25
+#define PragTyp_SHRINK_MEMORY                 26
+#define PragTyp_SOFT_HEAP_LIMIT               27
+#define PragTyp_STATS                         28
+#define PragTyp_SYNCHRONOUS                   29
+#define PragTyp_TABLE_INFO                    30
+#define PragTyp_TEMP_STORE                    31
+#define PragTyp_TEMP_STORE_DIRECTORY          32
+#define PragTyp_WAL_AUTOCHECKPOINT            33
+#define PragTyp_WAL_CHECKPOINT                34
+#define PragTyp_ACTIVATE_EXTENSIONS           35
+#define PragTyp_HEXKEY                        36
+#define PragTyp_KEY                           37
+#define PragTyp_REKEY                         38
+#define PragTyp_LOCK_STATUS                   39
+#define PragTyp_PARSER_TRACE                  40
+#define PragFlag_NeedSchema           0x01
+static const struct sPragmaNames {
+  const char *const zName;  /* Name of pragma */
+  u8 ePragTyp;              /* PragTyp_XXX value */
+  u8 mPragFlag;             /* Zero or more PragFlag_XXX values */
+  u32 iArg;                 /* Extra argument */
+} aPragmaNames[] = {
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
+  { /* zName:     */ "activate_extensions",
+    /* ePragTyp:  */ PragTyp_ACTIVATE_EXTENSIONS,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
+  { /* zName:     */ "application_id",
+    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_AUTOVACUUM)
+  { /* zName:     */ "auto_vacuum",
+    /* ePragTyp:  */ PragTyp_AUTO_VACUUM,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
+  { /* zName:     */ "automatic_index",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_AutoIndex },
+#endif
+#endif
+  { /* zName:     */ "busy_timeout",
+    /* ePragTyp:  */ PragTyp_BUSY_TIMEOUT,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+  { /* zName:     */ "cache_size",
+    /* ePragTyp:  */ PragTyp_CACHE_SIZE,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "cache_spill",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_CacheSpill },
+#endif
+  { /* zName:     */ "case_sensitive_like",
+    /* ePragTyp:  */ PragTyp_CASE_SENSITIVE_LIKE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "checkpoint_fullfsync",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_CkptFullFSync },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+  { /* zName:     */ "collation_list",
+    /* ePragTyp:  */ PragTyp_COLLATION_LIST,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
+  { /* zName:     */ "compile_options",
+    /* ePragTyp:  */ PragTyp_COMPILE_OPTIONS,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "count_changes",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_CountRows },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
+  { /* zName:     */ "data_store_directory",
+    /* ePragTyp:  */ PragTyp_DATA_STORE_DIRECTORY,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+  { /* zName:     */ "database_list",
+    /* ePragTyp:  */ PragTyp_DATABASE_LIST,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
+  { /* zName:     */ "default_cache_size",
+    /* ePragTyp:  */ PragTyp_DEFAULT_CACHE_SIZE,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+  { /* zName:     */ "defer_foreign_keys",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_DeferFKs },
+#endif
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "empty_result_callbacks",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_NullCallback },
+#endif
+#if !defined(SQLITE_OMIT_UTF16)
+  { /* zName:     */ "encoding",
+    /* ePragTyp:  */ PragTyp_ENCODING,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+  { /* zName:     */ "foreign_key_check",
+    /* ePragTyp:  */ PragTyp_FOREIGN_KEY_CHECK,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FOREIGN_KEY)
+  { /* zName:     */ "foreign_key_list",
+    /* ePragTyp:  */ PragTyp_FOREIGN_KEY_LIST,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+  { /* zName:     */ "foreign_keys",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_ForeignKeys },
+#endif
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
+  { /* zName:     */ "freelist_count",
+    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "full_column_names",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_FullColNames },
+  { /* zName:     */ "fullfsync",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_FullFSync },
+#endif
+#if defined(SQLITE_HAS_CODEC)
+  { /* zName:     */ "hexkey",
+    /* ePragTyp:  */ PragTyp_HEXKEY,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+  { /* zName:     */ "hexrekey",
+    /* ePragTyp:  */ PragTyp_HEXKEY,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if !defined(SQLITE_OMIT_CHECK)
+  { /* zName:     */ "ignore_check_constraints",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_IgnoreChecks },
+#endif
+#endif
+#if !defined(SQLITE_OMIT_AUTOVACUUM)
+  { /* zName:     */ "incremental_vacuum",
+    /* ePragTyp:  */ PragTyp_INCREMENTAL_VACUUM,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+  { /* zName:     */ "index_info",
+    /* ePragTyp:  */ PragTyp_INDEX_INFO,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+  { /* zName:     */ "index_list",
+    /* ePragTyp:  */ PragTyp_INDEX_LIST,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
+  { /* zName:     */ "integrity_check",
+    /* ePragTyp:  */ PragTyp_INTEGRITY_CHECK,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+  { /* zName:     */ "journal_mode",
+    /* ePragTyp:  */ PragTyp_JOURNAL_MODE,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+  { /* zName:     */ "journal_size_limit",
+    /* ePragTyp:  */ PragTyp_JOURNAL_SIZE_LIMIT,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if defined(SQLITE_HAS_CODEC)
+  { /* zName:     */ "key",
+    /* ePragTyp:  */ PragTyp_KEY,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "legacy_file_format",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_LegacyFileFmt },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
+  { /* zName:     */ "lock_proxy_file",
+    /* ePragTyp:  */ PragTyp_LOCK_PROXY_FILE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+  { /* zName:     */ "lock_status",
+    /* ePragTyp:  */ PragTyp_LOCK_STATUS,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+  { /* zName:     */ "locking_mode",
+    /* ePragTyp:  */ PragTyp_LOCKING_MODE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+  { /* zName:     */ "max_page_count",
+    /* ePragTyp:  */ PragTyp_PAGE_COUNT,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+  { /* zName:     */ "mmap_size",
+    /* ePragTyp:  */ PragTyp_MMAP_SIZE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+  { /* zName:     */ "page_count",
+    /* ePragTyp:  */ PragTyp_PAGE_COUNT,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+  { /* zName:     */ "page_size",
+    /* ePragTyp:  */ PragTyp_PAGE_SIZE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if defined(SQLITE_DEBUG)
+  { /* zName:     */ "parser_trace",
+    /* ePragTyp:  */ PragTyp_PARSER_TRACE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "query_only",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_QueryOnly },
+#endif
+#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
+  { /* zName:     */ "quick_check",
+    /* ePragTyp:  */ PragTyp_INTEGRITY_CHECK,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "read_uncommitted",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_ReadUncommitted },
+  { /* zName:     */ "recursive_triggers",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_RecTriggers },
+#endif
+#if defined(SQLITE_HAS_CODEC)
+  { /* zName:     */ "rekey",
+    /* ePragTyp:  */ PragTyp_REKEY,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "reverse_unordered_selects",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_ReverseOrder },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
+  { /* zName:     */ "schema_version",
+    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+  { /* zName:     */ "secure_delete",
+    /* ePragTyp:  */ PragTyp_SECURE_DELETE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "short_column_names",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_ShortColNames },
+#endif
+  { /* zName:     */ "shrink_memory",
+    /* ePragTyp:  */ PragTyp_SHRINK_MEMORY,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+  { /* zName:     */ "soft_heap_limit",
+    /* ePragTyp:  */ PragTyp_SOFT_HEAP_LIMIT,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if defined(SQLITE_DEBUG)
+  { /* zName:     */ "sql_trace",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_SqlTrace },
+#endif
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+  { /* zName:     */ "stats",
+    /* ePragTyp:  */ PragTyp_STATS,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+  { /* zName:     */ "synchronous",
+    /* ePragTyp:  */ PragTyp_SYNCHRONOUS,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+  { /* zName:     */ "table_info",
+    /* ePragTyp:  */ PragTyp_TABLE_INFO,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+  { /* zName:     */ "temp_store",
+    /* ePragTyp:  */ PragTyp_TEMP_STORE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+  { /* zName:     */ "temp_store_directory",
+    /* ePragTyp:  */ PragTyp_TEMP_STORE_DIRECTORY,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
+  { /* zName:     */ "user_version",
+    /* ePragTyp:  */ PragTyp_HEADER_VALUE,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if defined(SQLITE_DEBUG)
+  { /* zName:     */ "vdbe_addoptrace",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_VdbeAddopTrace },
+  { /* zName:     */ "vdbe_debug",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
+  { /* zName:     */ "vdbe_eqp",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_VdbeEQP },
+  { /* zName:     */ "vdbe_listing",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_VdbeListing },
+  { /* zName:     */ "vdbe_trace",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_VdbeTrace },
+#endif
+#endif
+#if !defined(SQLITE_OMIT_WAL)
+  { /* zName:     */ "wal_autocheckpoint",
+    /* ePragTyp:  */ PragTyp_WAL_AUTOCHECKPOINT,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ 0 },
+  { /* zName:     */ "wal_checkpoint",
+    /* ePragTyp:  */ PragTyp_WAL_CHECKPOINT,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+  { /* zName:     */ "writable_schema",
+    /* ePragTyp:  */ PragTyp_FLAG,
+    /* ePragFlag: */ 0,
+    /* iArg:      */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
+#endif
+};
+/* Number of pragmas: 56 on by default, 69 total. */
+/* End of the automatically generated pragma table.
+***************************************************************************/
+
 /*
 ** Interpret the given string as a safety level.  Return 0 for OFF,
 ** 1 for ON or NORMAL and 2 for FULL.  Return 1 for an empty or 
@@ -93399,7 +98681,7 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
 ** to support legacy SQL code.  The safety level used to be boolean
 ** and older scripts may have used numbers 0 for OFF and 1 for ON.
 */
-static u8 getSafetyLevel(const char *z, int omitFull, int dflt){
+static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){
                              /* 123456789 123456789 */
   static const char zText[] = "onoffalseyestruefull";
   static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
@@ -93421,7 +98703,7 @@ static u8 getSafetyLevel(const char *z, int omitFull, int dflt){
 /*
 ** Interpret the given string as a boolean value.
 */
-SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, int dflt){
+SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, u8 dflt){
   return getSafetyLevel(z,1,dflt)!=0;
 }
 
@@ -93533,92 +98815,35 @@ static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
   sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
 }
 
-#ifndef SQLITE_OMIT_FLAG_PRAGMAS
-/*
-** Check to see if zRight and zLeft refer to a pragma that queries
-** or changes one of the flags in db->flags.  Return 1 if so and 0 if not.
-** Also, implement the pragma.
-*/
-static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
-  static const struct sPragmaType {
-    const char *zName;  /* Name of the pragma */
-    int mask;           /* Mask for the db->flags value */
-  } aPragma[] = {
-    { "full_column_names",        SQLITE_FullColNames  },
-    { "short_column_names",       SQLITE_ShortColNames },
-    { "count_changes",            SQLITE_CountRows     },
-    { "empty_result_callbacks",   SQLITE_NullCallback  },
-    { "legacy_file_format",       SQLITE_LegacyFileFmt },
-    { "fullfsync",                SQLITE_FullFSync     },
-    { "checkpoint_fullfsync",     SQLITE_CkptFullFSync },
-    { "reverse_unordered_selects", SQLITE_ReverseOrder  },
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
-    { "automatic_index",          SQLITE_AutoIndex     },
-#endif
-#ifdef SQLITE_DEBUG
-    { "sql_trace",                SQLITE_SqlTrace      },
-    { "vdbe_listing",             SQLITE_VdbeListing   },
-    { "vdbe_trace",               SQLITE_VdbeTrace     },
-    { "vdbe_addoptrace",          SQLITE_VdbeAddopTrace},
-    { "vdbe_debug",    SQLITE_SqlTrace | SQLITE_VdbeListing
-                               | SQLITE_VdbeTrace      },
-#endif
-#ifndef SQLITE_OMIT_CHECK
-    { "ignore_check_constraints", SQLITE_IgnoreChecks  },
-#endif
-    /* The following is VERY experimental */
-    { "writable_schema",          SQLITE_WriteSchema|SQLITE_RecoveryMode },
-
-    /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
-    ** flag if there are any active statements. */
-    { "read_uncommitted",         SQLITE_ReadUncommitted },
-    { "recursive_triggers",       SQLITE_RecTriggers },
 
-    /* This flag may only be set if both foreign-key and trigger support
-    ** are present in the build.  */
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-    { "foreign_keys",             SQLITE_ForeignKeys },
-#endif
-  };
-  int i;
-  const struct sPragmaType *p;
-  for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){
-    if( sqlite3StrICmp(zLeft, p->zName)==0 ){
-      sqlite3 *db = pParse->db;
-      Vdbe *v;
-      v = sqlite3GetVdbe(pParse);
-      assert( v!=0 );  /* Already allocated by sqlite3Pragma() */
-      if( ALWAYS(v) ){
-        if( zRight==0 ){
-          returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 );
-        }else{
-          int mask = p->mask;          /* Mask of bits to set or clear. */
-          if( db->autoCommit==0 ){
-            /* Foreign key support may not be enabled or disabled while not
-            ** in auto-commit mode.  */
-            mask &= ~(SQLITE_ForeignKeys);
-          }
-
-          if( sqlite3GetBoolean(zRight, 0) ){
-            db->flags |= mask;
-          }else{
-            db->flags &= ~mask;
-          }
-
-          /* Many of the flag-pragmas modify the code generated by the SQL 
-          ** compiler (eg. count_changes). So add an opcode to expire all
-          ** compiled SQL statements after modifying a pragma value.
-          */
-          sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
-        }
+/*
+** Set the safety_level and pager flags for pager iDb.  Or if iDb<0
+** set these values for all pagers.
+*/
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+static void setAllPagerFlags(sqlite3 *db){
+  if( db->autoCommit ){
+    Db *pDb = db->aDb;
+    int n = db->nDb;
+    assert( SQLITE_FullFSync==PAGER_FULLFSYNC );
+    assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC );
+    assert( SQLITE_CacheSpill==PAGER_CACHESPILL );
+    assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL)
+             ==  PAGER_FLAGS_MASK );
+    assert( (pDb->safety_level & PAGER_SYNCHRONOUS_MASK)==pDb->safety_level );
+    while( (n--) > 0 ){
+      if( pDb->pBt ){
+        sqlite3BtreeSetPagerFlags(pDb->pBt,
+                 pDb->safety_level | (db->flags & PAGER_FLAGS_MASK) );
       }
-
-      return 1;
+      pDb++;
     }
   }
-  return 0;
 }
-#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
+#else
+# define setAllPagerFlags(X)  /* no-op */
+#endif
+
 
 /*
 ** Return a human-readable name for a constraint resolution action.
@@ -93689,8 +98914,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
   char *zRight = 0;      /* Nul-terminated UTF-8 string <value>, or NULL */
   const char *zDb = 0;   /* The database name */
   Token *pId;            /* Pointer to <id> token */
-  int iDb;               /* Database index for <database> */
   char *aFcntl[4];       /* Argument to SQLITE_FCNTL_PRAGMA */
+  int iDb;               /* Database index for <database> */
+  int lwr, upr, mid;           /* Binary search bounds */
   int rc;                      /* return value form SQLITE_FCNTL_PRAGMA */
   sqlite3 *db = pParse->db;    /* The database connection */
   Db *pDb;                     /* The specific database being pragmaed */
@@ -93746,16 +98972,41 @@ SQLITE_PRIVATE void sqlite3Pragma(
       sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
       sqlite3_free(aFcntl[0]);
     }
-  }else if( rc!=SQLITE_NOTFOUND ){
+    goto pragma_out;
+  }
+  if( rc!=SQLITE_NOTFOUND ){
     if( aFcntl[0] ){
       sqlite3ErrorMsg(pParse, "%s", aFcntl[0]);
       sqlite3_free(aFcntl[0]);
     }
     pParse->nErr++;
     pParse->rc = rc;
-  }else
-                            
- 
+    goto pragma_out;
+  }
+
+  /* Locate the pragma in the lookup table */
+  lwr = 0;
+  upr = ArraySize(aPragmaNames)-1;
+  while( lwr<=upr ){
+    mid = (lwr+upr)/2;
+    rc = sqlite3_stricmp(zLeft, aPragmaNames[mid].zName);
+    if( rc==0 ) break;
+    if( rc<0 ){
+      upr = mid - 1;
+    }else{
+      lwr = mid + 1;
+    }
+  }
+  if( lwr>upr ) goto pragma_out;
+
+  /* Make sure the database schema is loaded if the pragma requires that */
+  if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){
+    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+  }
+
+  /* Jump to the appropriate pragma handler */
+  switch( aPragmaNames[mid].ePragTyp ){
+  
 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
   /*
   **  PRAGMA [database.]default_cache_size
@@ -93773,7 +99024,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** size.  But continue to take the absolute value of the default cache
   ** size of historical compatibility.
   */
-  if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
+  case PragTyp_DEFAULT_CACHE_SIZE: {
+    static const int iLn = VDBE_OFFSET_LINENO(2);
     static const VdbeOpList getCacheSize[] = {
       { OP_Transaction, 0, 0,        0},                         /* 0 */
       { OP_ReadCookie,  0, 1,        BTREE_DEFAULT_CACHE_SIZE},  /* 1 */
@@ -93786,13 +99038,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
       { OP_ResultRow,   1, 1,        0},
     };
     int addr;
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     sqlite3VdbeUsesBtree(v, iDb);
     if( !zRight ){
       sqlite3VdbeSetNumCols(v, 1);
       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC);
       pParse->nMem += 2;
-      addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
+      addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize,iLn);
       sqlite3VdbeChangeP1(v, addr, iDb);
       sqlite3VdbeChangeP1(v, addr+1, iDb);
       sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE);
@@ -93805,7 +99056,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
       pDb->pSchema->cache_size = size;
       sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
     }
-  }else
+    break;
+  }
 #endif /* !SQLITE_OMIT_PAGER_PRAGMAS && !SQLITE_OMIT_DEPRECATED */
 
 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -93818,7 +99070,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** database page size value.  The value can only be set if
   ** the database has not yet been created.
   */
-  if( sqlite3StrICmp(zLeft,"page_size")==0 ){
+  case PragTyp_PAGE_SIZE: {
     Btree *pBt = pDb->pBt;
     assert( pBt!=0 );
     if( !zRight ){
@@ -93833,7 +99085,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
         db->mallocFailed = 1;
       }
     }
-  }else
+    break;
+  }
 
   /*
   **  PRAGMA [database.]secure_delete
@@ -93843,7 +99096,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** secure_delete flag.  The second form changes the secure_delete
   ** flag setting and reports thenew value.
   */
-  if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
+  case PragTyp_SECURE_DELETE: {
     Btree *pBt = pDb->pBt;
     int b = -1;
     assert( pBt!=0 );
@@ -93858,7 +99111,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
     }
     b = sqlite3BtreeSecureDelete(pBt, b);
     returnSingleInt(pParse, "secure_delete", b);
-  }else
+    break;
+  }
 
   /*
   **  PRAGMA [database.]max_page_count
@@ -93877,11 +99131,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
   **
   ** Return the number of pages in the specified database.
   */
-  if( sqlite3StrICmp(zLeft,"page_count")==0
-   || sqlite3StrICmp(zLeft,"max_page_count")==0
-  ){
+  case PragTyp_PAGE_COUNT: {
     int iReg;
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     sqlite3CodeVerifySchema(pParse, iDb);
     iReg = ++pParse->nMem;
     if( sqlite3Tolower(zLeft[0])=='p' ){
@@ -93893,13 +99144,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
     sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
     sqlite3VdbeSetNumCols(v, 1);
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
-  }else
+    break;
+  }
 
   /*
   **  PRAGMA [database.]locking_mode
   **  PRAGMA [database.]locking_mode = (normal|exclusive)
   */
-  if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){
+  case PragTyp_LOCKING_MODE: {
     const char *zRet = "normal";
     int eMode = getLockingMode(zRight);
 
@@ -93932,7 +99184,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
       eMode = sqlite3PagerLockingMode(pPager, eMode);
     }
 
-    assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE);
+    assert( eMode==PAGER_LOCKINGMODE_NORMAL
+            || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
     if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){
       zRet = "exclusive";
     }
@@ -93940,25 +99193,18 @@ SQLITE_PRIVATE void sqlite3Pragma(
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", SQLITE_STATIC);
     sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0);
     sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
-  }else
+    break;
+  }
 
   /*
   **  PRAGMA [database.]journal_mode
   **  PRAGMA [database.]journal_mode =
   **                      (delete|persist|off|truncate|memory|wal|off)
   */
-  if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
+  case PragTyp_JOURNAL_MODE: {
     int eMode;        /* One of the PAGER_JOURNALMODE_XXX symbols */
     int ii;           /* Loop counter */
 
-    /* Force the schema to be loaded on all databases.  This causes all
-    ** database files to be opened and the journal_modes set.  This is
-    ** necessary because subsequent processing must know if the databases
-    ** are in WAL mode. */
-    if( sqlite3ReadSchema(pParse) ){
-      goto pragma_out;
-    }
-
     sqlite3VdbeSetNumCols(v, 1);
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
 
@@ -93990,7 +99236,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
       }
     }
     sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
-  }else
+    break;
+  }
 
   /*
   **  PRAGMA [database.]journal_size_limit
@@ -93998,16 +99245,17 @@ SQLITE_PRIVATE void sqlite3Pragma(
   **
   ** Get or set the size limit on rollback journal files.
   */
-  if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){
+  case PragTyp_JOURNAL_SIZE_LIMIT: {
     Pager *pPager = sqlite3BtreePager(pDb->pBt);
     i64 iLimit = -2;
     if( zRight ){
-      sqlite3Atoi64(zRight, &iLimit, 1000000, SQLITE_UTF8);
+      sqlite3DecOrHexToI64(zRight, &iLimit);
       if( iLimit<-1 ) iLimit = -1;
     }
     iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
     returnSingleInt(pParse, "journal_size_limit", iLimit);
-  }else
+    break;
+  }
 
 #endif /* SQLITE_OMIT_PAGER_PRAGMAS */
 
@@ -94019,57 +99267,48 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** The value is one of:  0 NONE 1 FULL 2 INCREMENTAL
   */
 #ifndef SQLITE_OMIT_AUTOVACUUM
-  if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){
+  case PragTyp_AUTO_VACUUM: {
     Btree *pBt = pDb->pBt;
     assert( pBt!=0 );
-    if( sqlite3ReadSchema(pParse) ){
-      goto pragma_out;
-    }
     if( !zRight ){
-      int auto_vacuum;
-      if( ALWAYS(pBt) ){
-         auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt);
-      }else{
-         auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM;
-      }
-      returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
+      returnSingleInt(pParse, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt));
     }else{
       int eAuto = getAutoVacuum(zRight);
       assert( eAuto>=0 && eAuto<=2 );
       db->nextAutovac = (u8)eAuto;
-      if( ALWAYS(eAuto>=0) ){
-        /* Call SetAutoVacuum() to set initialize the internal auto and
-        ** incr-vacuum flags. This is required in case this connection
-        ** creates the database file. It is important that it is created
-        ** as an auto-vacuum capable db.
+      /* Call SetAutoVacuum() to set initialize the internal auto and
+      ** incr-vacuum flags. This is required in case this connection
+      ** creates the database file. It is important that it is created
+      ** as an auto-vacuum capable db.
+      */
+      rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
+      if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
+        /* When setting the auto_vacuum mode to either "full" or 
+        ** "incremental", write the value of meta[6] in the database
+        ** file. Before writing to meta[6], check that meta[3] indicates
+        ** that this really is an auto-vacuum capable database.
         */
-        rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
-        if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
-          /* When setting the auto_vacuum mode to either "full" or 
-          ** "incremental", write the value of meta[6] in the database
-          ** file. Before writing to meta[6], check that meta[3] indicates
-          ** that this really is an auto-vacuum capable database.
-          */
-          static const VdbeOpList setMeta6[] = {
-            { OP_Transaction,    0,         1,                 0},    /* 0 */
-            { OP_ReadCookie,     0,         1,         BTREE_LARGEST_ROOT_PAGE},
-            { OP_If,             1,         0,                 0},    /* 2 */
-            { OP_Halt,           SQLITE_OK, OE_Abort,          0},    /* 3 */
-            { OP_Integer,        0,         1,                 0},    /* 4 */
-            { OP_SetCookie,      0,         BTREE_INCR_VACUUM, 1},    /* 5 */
-          };
-          int iAddr;
-          iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
-          sqlite3VdbeChangeP1(v, iAddr, iDb);
-          sqlite3VdbeChangeP1(v, iAddr+1, iDb);
-          sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
-          sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
-          sqlite3VdbeChangeP1(v, iAddr+5, iDb);
-          sqlite3VdbeUsesBtree(v, iDb);
-        }
+        static const int iLn = VDBE_OFFSET_LINENO(2);
+        static const VdbeOpList setMeta6[] = {
+          { OP_Transaction,    0,         1,                 0},    /* 0 */
+          { OP_ReadCookie,     0,         1,         BTREE_LARGEST_ROOT_PAGE},
+          { OP_If,             1,         0,                 0},    /* 2 */
+          { OP_Halt,           SQLITE_OK, OE_Abort,          0},    /* 3 */
+          { OP_Integer,        0,         1,                 0},    /* 4 */
+          { OP_SetCookie,      0,         BTREE_INCR_VACUUM, 1},    /* 5 */
+        };
+        int iAddr;
+        iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn);
+        sqlite3VdbeChangeP1(v, iAddr, iDb);
+        sqlite3VdbeChangeP1(v, iAddr+1, iDb);
+        sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
+        sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
+        sqlite3VdbeChangeP1(v, iAddr+5, iDb);
+        sqlite3VdbeUsesBtree(v, iDb);
       }
     }
-  }else
+    break;
+  }
 #endif
 
   /*
@@ -94078,22 +99317,20 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** Do N steps of incremental vacuuming on a database.
   */
 #ifndef SQLITE_OMIT_AUTOVACUUM
-  if( sqlite3StrICmp(zLeft,"incremental_vacuum")==0 ){
+  case PragTyp_INCREMENTAL_VACUUM: {
     int iLimit, addr;
-    if( sqlite3ReadSchema(pParse) ){
-      goto pragma_out;
-    }
     if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
       iLimit = 0x7fffffff;
     }
     sqlite3BeginWriteOperation(pParse, 0, iDb);
     sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
-    addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb);
+    addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); VdbeCoverage(v);
     sqlite3VdbeAddOp1(v, OP_ResultRow, 1);
     sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
-    sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr);
+    sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); VdbeCoverage(v);
     sqlite3VdbeJumpHere(v, addr);
-  }else
+    break;
+  }
 #endif
 
 #ifndef SQLITE_OMIT_PAGER_PRAGMAS
@@ -94108,8 +99345,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** number of pages is adjusted so that the cache uses -N kibibytes
   ** of memory.
   */
-  if( sqlite3StrICmp(zLeft,"cache_size")==0 ){
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+  case PragTyp_CACHE_SIZE: {
     assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
     if( !zRight ){
       returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
@@ -94118,7 +99354,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
       pDb->pSchema->cache_size = size;
       sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
     }
-  }else
+    break;
+  }
 
   /*
   **  PRAGMA [database.]mmap_size(N)
@@ -94134,12 +99371,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** as little or as much as it wants.  Except, if N is set to 0 then the
   ** upper layers will never invoke the xFetch interfaces to the VFS.
   */
-  if( sqlite3StrICmp(zLeft,"mmap_size")==0 ){
+  case PragTyp_MMAP_SIZE: {
     sqlite3_int64 sz;
+#if SQLITE_MAX_MMAP_SIZE>0
     assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
     if( zRight ){
       int ii;
-      sqlite3Atoi64(zRight, &sz, 1000, SQLITE_UTF8);
+      sqlite3DecOrHexToI64(zRight, &sz);
       if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
       if( pId2->n==0 ) db->szMmap = sz;
       for(ii=db->nDb-1; ii>=0; ii--){
@@ -94149,13 +99387,19 @@ SQLITE_PRIVATE void sqlite3Pragma(
       }
     }
     sz = -1;
-    if( sqlite3_file_control(db,zDb,SQLITE_FCNTL_MMAP_SIZE,&sz)==SQLITE_OK ){
-#if SQLITE_MAX_MMAP_SIZE==0
-      sz = 0;
+    rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_MMAP_SIZE, &sz);
+#else
+    sz = 0;
+    rc = SQLITE_OK;
 #endif
+    if( rc==SQLITE_OK ){
       returnSingleInt(pParse, "mmap_size", sz);
+    }else if( rc!=SQLITE_NOTFOUND ){
+      pParse->nErr++;
+      pParse->rc = rc;
     }
-  }else
+    break;
+  }
 
   /*
   **   PRAGMA temp_store
@@ -94168,13 +99412,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** Note that it is possible for the library compile-time options to
   ** override this setting
   */
-  if( sqlite3StrICmp(zLeft, "temp_store")==0 ){
+  case PragTyp_TEMP_STORE: {
     if( !zRight ){
       returnSingleInt(pParse, "temp_store", db->temp_store);
     }else{
       changeTempStorage(pParse, zRight);
     }
-  }else
+    break;
+  }
 
   /*
   **   PRAGMA temp_store_directory
@@ -94186,7 +99431,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** If temporary directory is changed, then invalidateTempStorage.
   **
   */
-  if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){
+  case PragTyp_TEMP_STORE_DIRECTORY: {
     if( !zRight ){
       if( sqlite3_temp_directory ){
         sqlite3VdbeSetNumCols(v, 1);
@@ -94219,7 +99464,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
       }
 #endif /* SQLITE_OMIT_WSD */
     }
-  }else
+    break;
+  }
 
 #if SQLITE_OS_WIN
   /*
@@ -94235,7 +99481,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** by this setting, regardless of its value.
   **
   */
-  if( sqlite3StrICmp(zLeft, "data_store_directory")==0 ){
+  case PragTyp_DATA_STORE_DIRECTORY: {
     if( !zRight ){
       if( sqlite3_data_directory ){
         sqlite3VdbeSetNumCols(v, 1);
@@ -94262,26 +99508,20 @@ SQLITE_PRIVATE void sqlite3Pragma(
       }
 #endif /* SQLITE_OMIT_WSD */
     }
-  }else
+    break;
+  }
 #endif
 
-#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
-#  if defined(__APPLE__)
-#    define SQLITE_ENABLE_LOCKING_STYLE 1
-#  else
-#    define SQLITE_ENABLE_LOCKING_STYLE 0
-#  endif
-#endif
 #if SQLITE_ENABLE_LOCKING_STYLE
   /*
-   **   PRAGMA [database.]lock_proxy_file
-   **   PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path"
-   **
-   ** Return or set the value of the lock_proxy_file flag.  Changing
-   ** the value sets a specific file to be used for database access locks.
-   **
-   */
-  if( sqlite3StrICmp(zLeft, "lock_proxy_file")==0 ){
+  **   PRAGMA [database.]lock_proxy_file
+  **   PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path"
+  **
+  ** Return or set the value of the lock_proxy_file flag.  Changing
+  ** the value sets a specific file to be used for database access locks.
+  **
+  */
+  case PragTyp_LOCK_PROXY_FILE: {
     if( !zRight ){
       Pager *pPager = sqlite3BtreePager(pDb->pBt);
       char *proxy_file_path = NULL;
@@ -94312,7 +99552,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
         goto pragma_out;
       }
     }
-  }else
+    break;
+  }
 #endif /* SQLITE_ENABLE_LOCKING_STYLE */      
     
   /*
@@ -94324,8 +99565,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** default value will be restored the next time the database is
   ** opened.
   */
-  if( sqlite3StrICmp(zLeft,"synchronous")==0 ){
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+  case PragTyp_SYNCHRONOUS: {
     if( !zRight ){
       returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
     }else{
@@ -94334,16 +99574,42 @@ SQLITE_PRIVATE void sqlite3Pragma(
             "Safety level may not be changed inside a transaction");
       }else{
         pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
+        setAllPagerFlags(db);
       }
     }
-  }else
+    break;
+  }
 #endif /* SQLITE_OMIT_PAGER_PRAGMAS */
 
 #ifndef SQLITE_OMIT_FLAG_PRAGMAS
-  if( flagPragma(pParse, zLeft, zRight) ){
-    /* The flagPragma() subroutine also generates any necessary code
-    ** there is nothing more to do here */
-  }else
+  case PragTyp_FLAG: {
+    if( zRight==0 ){
+      returnSingleInt(pParse, aPragmaNames[mid].zName,
+                     (db->flags & aPragmaNames[mid].iArg)!=0 );
+    }else{
+      int mask = aPragmaNames[mid].iArg;    /* Mask of bits to set or clear. */
+      if( db->autoCommit==0 ){
+        /* Foreign key support may not be enabled or disabled while not
+        ** in auto-commit mode.  */
+        mask &= ~(SQLITE_ForeignKeys);
+      }
+
+      if( sqlite3GetBoolean(zRight, 0) ){
+        db->flags |= mask;
+      }else{
+        db->flags &= ~mask;
+        if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
+      }
+
+      /* Many of the flag-pragmas modify the code generated by the SQL 
+      ** compiler (eg. count_changes). So add an opcode to expire all
+      ** compiled SQL statements after modifying a pragma value.
+      */
+      sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
+      setAllPagerFlags(db);
+    }
+    break;
+  }
 #endif /* SQLITE_OMIT_FLAG_PRAGMAS */
 
 #ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
@@ -94359,16 +99625,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** notnull:    True if 'NOT NULL' is part of column declaration
   ** dflt_value: The default value for the column, if any.
   */
-  if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){
+  case PragTyp_TABLE_INFO: if( zRight ){
     Table *pTab;
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     pTab = sqlite3FindTable(db, zRight, zDb);
     if( pTab ){
       int i, k;
       int nHidden = 0;
       Column *pCol;
-      Index *pPk;
-      for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
+      Index *pPk = sqlite3PrimaryKeyIndex(pTab);
       sqlite3VdbeSetNumCols(v, 6);
       pParse->nMem = 6;
       sqlite3CodeVerifySchema(pParse, iDb);
@@ -94405,12 +99669,44 @@ SQLITE_PRIVATE void sqlite3Pragma(
         sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
       }
     }
-  }else
+  }
+  break;
+
+  case PragTyp_STATS: {
+    Index *pIdx;
+    HashElem *i;
+    v = sqlite3GetVdbe(pParse);
+    sqlite3VdbeSetNumCols(v, 4);
+    pParse->nMem = 4;
+    sqlite3CodeVerifySchema(pParse, iDb);
+    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
+    sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "index", SQLITE_STATIC);
+    sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "width", SQLITE_STATIC);
+    sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "height", SQLITE_STATIC);
+    for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
+      Table *pTab = sqliteHashData(i);
+      sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, pTab->zName, 0);
+      sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
+      sqlite3VdbeAddOp2(v, OP_Integer,
+                           (int)sqlite3LogEstToInt(pTab->szTabRow), 3);
+      sqlite3VdbeAddOp2(v, OP_Integer, 
+          (int)sqlite3LogEstToInt(pTab->nRowLogEst), 4);
+      sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
+      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+        sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
+        sqlite3VdbeAddOp2(v, OP_Integer,
+                             (int)sqlite3LogEstToInt(pIdx->szIdxRow), 3);
+        sqlite3VdbeAddOp2(v, OP_Integer, 
+            (int)sqlite3LogEstToInt(pIdx->aiRowLogEst[0]), 4);
+        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
+      }
+    }
+  }
+  break;
 
-  if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){
+  case PragTyp_INDEX_INFO: if( zRight ){
     Index *pIdx;
     Table *pTab;
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     pIdx = sqlite3FindIndex(db, zRight, zDb);
     if( pIdx ){
       int i;
@@ -94421,8 +99717,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
-      for(i=0; i<pIdx->nColumn; i++){
-        int cnum = pIdx->aiColumn[i];
+      for(i=0; i<pIdx->nKeyCol; i++){
+        i16 cnum = pIdx->aiColumn[i];
         sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
         sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
         assert( pTab->nCol>cnum );
@@ -94430,39 +99726,34 @@ SQLITE_PRIVATE void sqlite3Pragma(
         sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
       }
     }
-  }else
+  }
+  break;
 
-  if( sqlite3StrICmp(zLeft, "index_list")==0 && zRight ){
+  case PragTyp_INDEX_LIST: if( zRight ){
     Index *pIdx;
     Table *pTab;
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+    int i;
     pTab = sqlite3FindTable(db, zRight, zDb);
     if( pTab ){
       v = sqlite3GetVdbe(pParse);
-      pIdx = pTab->pIndex;
-      if( pIdx ){
-        int i = 0; 
-        sqlite3VdbeSetNumCols(v, 3);
-        pParse->nMem = 3;
-        sqlite3CodeVerifySchema(pParse, iDb);
-        sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
-        sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
-        sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
-        while(pIdx){
-          sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
-          sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
-          sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
-          sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
-          ++i;
-          pIdx = pIdx->pNext;
-        }
+      sqlite3VdbeSetNumCols(v, 3);
+      pParse->nMem = 3;
+      sqlite3CodeVerifySchema(pParse, iDb);
+      sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
+      sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
+      sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
+      for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
+        sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
+        sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
+        sqlite3VdbeAddOp2(v, OP_Integer, IsUniqueIndex(pIdx), 3);
+        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
       }
     }
-  }else
+  }
+  break;
 
-  if( sqlite3StrICmp(zLeft, "database_list")==0 ){
+  case PragTyp_DATABASE_LIST: {
     int i;
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     sqlite3VdbeSetNumCols(v, 3);
     pParse->nMem = 3;
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
@@ -94477,9 +99768,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
            sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
       sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
     }
-  }else
+  }
+  break;
 
-  if( sqlite3StrICmp(zLeft, "collation_list")==0 ){
+  case PragTyp_COLLATION_LIST: {
     int i = 0;
     HashElem *p;
     sqlite3VdbeSetNumCols(v, 2);
@@ -94492,14 +99784,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
       sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0);
       sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
     }
-  }else
+  }
+  break;
 #endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */
 
 #ifndef SQLITE_OMIT_FOREIGN_KEY
-  if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){
+  case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
     FKey *pFK;
     Table *pTab;
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     pTab = sqlite3FindTable(db, zRight, zDb);
     if( pTab ){
       v = sqlite3GetVdbe(pParse);
@@ -94539,12 +99831,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
         }
       }
     }
-  }else
+  }
+  break;
 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
 
 #ifndef SQLITE_OMIT_FOREIGN_KEY
 #ifndef SQLITE_OMIT_TRIGGER
-  if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
+  case PragTyp_FOREIGN_KEY_CHECK: {
     FKey *pFK;             /* A foreign key constraint */
     Table *pTab;           /* Child table contain "REFERENCES" keyword */
     Table *pParent;        /* Parent table that child points to */
@@ -94560,7 +99853,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
     int addrOk;            /* Jump here if the key is OK */
     int *aiCols;           /* child to parent column mapping */
 
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     regResult = pParse->nMem+1;
     pParse->nMem += 4;
     regKey = ++pParse->nMem;
@@ -94588,8 +99880,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
       sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
                         P4_TRANSIENT);
       for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
-        pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
-        if( pParent==0 ) break;
+        pParent = sqlite3FindTable(db, pFK->zTo, zDb);
+        if( pParent==0 ) continue;
         pIdx = 0;
         sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
         x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
@@ -94597,51 +99889,54 @@ SQLITE_PRIVATE void sqlite3Pragma(
           if( pIdx==0 ){
             sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
           }else{
-            KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
             sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
-            sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
+            sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
           }
         }else{
           k = 0;
           break;
         }
       }
+      assert( pParse->nErr>0 || pFK==0 );
       if( pFK ) break;
       if( pParse->nTab<i ) pParse->nTab = i;
-      addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
+      addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
       for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
-        pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
-        assert( pParent!=0 );
+        pParent = sqlite3FindTable(db, pFK->zTo, zDb);
         pIdx = 0;
         aiCols = 0;
-        x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
-        assert( x==0 );
+        if( pParent ){
+          x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
+          assert( x==0 );
+        }
         addrOk = sqlite3VdbeMakeLabel(v);
-        if( pIdx==0 ){
+        if( pParent && pIdx==0 ){
           int iKey = pFK->aCol[0].iFrom;
           assert( iKey>=0 && iKey<pTab->nCol );
           if( iKey!=pTab->iPKey ){
             sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
             sqlite3ColumnDefault(v, pTab, iKey, regRow);
-            sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
-            sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
-               sqlite3VdbeCurrentAddr(v)+3);
+            sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v);
+            sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, 
+               sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v);
           }else{
             sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
           }
-          sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
+          sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); VdbeCoverage(v);
           sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
           sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
         }else{
           for(j=0; j<pFK->nCol; j++){
             sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
-                            aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
-            sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
+                            aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j);
+            sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
+          }
+          if( pParent ){
+            sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
+                              sqlite3IndexAffinityStr(v,pIdx), pFK->nCol);
+            sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
+            VdbeCoverage(v);
           }
-          sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
-          sqlite3VdbeChangeP4(v, -1,
-                   sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
-          sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
         }
         sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
         sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, 
@@ -94651,15 +99946,16 @@ SQLITE_PRIVATE void sqlite3Pragma(
         sqlite3VdbeResolveLabel(v, addrOk);
         sqlite3DbFree(db, aiCols);
       }
-      sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
+      sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); VdbeCoverage(v);
       sqlite3VdbeJumpHere(v, addrTop);
     }
-  }else
+  }
+  break;
 #endif /* !defined(SQLITE_OMIT_TRIGGER) */
 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
 
 #ifndef NDEBUG
-  if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
+  case PragTyp_PARSER_TRACE: {
     if( zRight ){
       if( sqlite3GetBoolean(zRight, 0) ){
         sqlite3ParserTrace(stderr, "parser: ");
@@ -94667,40 +99963,40 @@ SQLITE_PRIVATE void sqlite3Pragma(
         sqlite3ParserTrace(0, 0);
       }
     }
-  }else
+  }
+  break;
 #endif
 
   /* Reinstall the LIKE and GLOB functions.  The variant of LIKE
   ** used will be case sensitive or not depending on the RHS.
   */
-  if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
+  case PragTyp_CASE_SENSITIVE_LIKE: {
     if( zRight ){
       sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0));
     }
-  }else
+  }
+  break;
 
 #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
 # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
 #endif
 
 #ifndef SQLITE_OMIT_INTEGRITY_CHECK
-  /* Pragma "quick_check" is an experimental reduced version of 
+  /* Pragma "quick_check" is reduced version of 
   ** integrity_check designed to detect most database corruption
   ** without most of the overhead of a full integrity-check.
   */
-  if( sqlite3StrICmp(zLeft, "integrity_check")==0
-   || sqlite3StrICmp(zLeft, "quick_check")==0 
-  ){
+  case PragTyp_INTEGRITY_CHECK: {
     int i, j, addr, mxErr;
 
     /* Code that appears at the end of the integrity check.  If no error
     ** messages have been generated, output OK.  Otherwise output the
     ** error message
     */
+    static const int iLn = VDBE_OFFSET_LINENO(2);
     static const VdbeOpList endCode[] = {
-      { OP_AddImm,      1, 0,        0},    /* 0 */
-      { OP_IfNeg,       1, 0,        0},    /* 1 */
-      { OP_String8,     0, 3,        0},    /* 2 */
+      { OP_IfNeg,       1, 0,        0},    /* 0 */
+      { OP_String8,     0, 3,        0},    /* 1 */
       { OP_ResultRow,   3, 1,        0},
     };
 
@@ -94720,7 +100016,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
     if( pId2->z==0 ) iDb = -1;
 
     /* Initialize the VDBE program */
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     pParse->nMem = 6;
     sqlite3VdbeSetNumCols(v, 1);
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC);
@@ -94746,6 +100041,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
 
       sqlite3CodeVerifySchema(pParse, i);
       addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
+      VdbeCoverage(v);
       sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
       sqlite3VdbeJumpHere(v, addr);
 
@@ -94759,27 +100055,29 @@ SQLITE_PRIVATE void sqlite3Pragma(
       for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
         Table *pTab = sqliteHashData(x);
         Index *pIdx;
-        sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt);
-        cnt++;
+        if( HasRowid(pTab) ){
+          sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt);
+          VdbeComment((v, "%s", pTab->zName));
+          cnt++;
+        }
         for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
           sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt);
+          VdbeComment((v, "%s", pIdx->zName));
           cnt++;
         }
       }
 
       /* Make sure sufficient number of registers have been allocated */
-      if( pParse->nMem < cnt+4 ){
-        pParse->nMem = cnt+4;
-      }
+      pParse->nMem = MAX( pParse->nMem, cnt+8 );
 
       /* Do the b-tree integrity checks */
       sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
       sqlite3VdbeChangeP5(v, (u8)i);
-      addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2);
+      addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
       sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
          sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
          P4_DYNAMIC);
-      sqlite3VdbeAddOp2(v, OP_Move, 2, 4);
+      sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
       sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
       sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
       sqlite3VdbeJumpHere(v, addr);
@@ -94788,77 +100086,127 @@ SQLITE_PRIVATE void sqlite3Pragma(
       */
       for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
         Table *pTab = sqliteHashData(x);
-        Index *pIdx;
+        Index *pIdx, *pPk;
+        Index *pPrior = 0;
         int loopTop;
+        int iDataCur, iIdxCur;
+        int r1 = -1;
 
         if( pTab->pIndex==0 ) continue;
+        pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
         addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);  /* Stop if out of errors */
+        VdbeCoverage(v);
         sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
         sqlite3VdbeJumpHere(v, addr);
-        sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
-        sqlite3VdbeAddOp2(v, OP_Integer, 0, 2);  /* reg(2) will count entries */
-        loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0);
-        sqlite3VdbeAddOp2(v, OP_AddImm, 2, 1);   /* increment entry count */
+        sqlite3ExprCacheClear(pParse);
+        sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead,
+                                   1, 0, &iDataCur, &iIdxCur);
+        sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
         for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
-          int jmp2;
-          int r1;
-          static const VdbeOpList idxErr[] = {
-            { OP_AddImm,      1, -1,  0},
-            { OP_String8,     0,  3,  0},    /* 1 */
-            { OP_Rowid,       1,  4,  0},
-            { OP_String8,     0,  5,  0},    /* 3 */
-            { OP_String8,     0,  6,  0},    /* 4 */
-            { OP_Concat,      4,  3,  3},
-            { OP_Concat,      5,  3,  3},
-            { OP_Concat,      6,  3,  3},
-            { OP_ResultRow,   3,  1,  0},
-            { OP_IfPos,       1,  0,  0},    /* 9 */
-            { OP_Halt,        0,  0,  0},
-          };
-          r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 0);
-          jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, r1, pIdx->nColumn+1);
-          addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
-          sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
-          sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC);
-          sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_TRANSIENT);
-          sqlite3VdbeJumpHere(v, addr+9);
+          sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
+        }
+        pParse->nMem = MAX(pParse->nMem, 8+j);
+        sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
+        loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
+        /* Verify that all NOT NULL columns really are NOT NULL */
+        for(j=0; j<pTab->nCol; j++){
+          char *zErr;
+          int jmp2, jmp3;
+          if( j==pTab->iPKey ) continue;
+          if( pTab->aCol[j].notNull==0 ) continue;
+          sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
+          sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+          jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
+          sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
+          zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
+                              pTab->aCol[j].zName);
+          sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
+          sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
+          jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
+          sqlite3VdbeAddOp0(v, OP_Halt);
           sqlite3VdbeJumpHere(v, jmp2);
+          sqlite3VdbeJumpHere(v, jmp3);
         }
-        sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1);
-        sqlite3VdbeJumpHere(v, loopTop);
+        /* Validate index entries for the current row */
         for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
-          static const VdbeOpList cntIdx[] = {
-             { OP_Integer,      0,  3,  0},
-             { OP_Rewind,       0,  0,  0},  /* 1 */
-             { OP_AddImm,       3,  1,  0},
-             { OP_Next,         0,  0,  0},  /* 3 */
-             { OP_Eq,           2,  0,  3},  /* 4 */
-             { OP_AddImm,       1, -1,  0},
-             { OP_String8,      0,  2,  0},  /* 6 */
-             { OP_String8,      0,  3,  0},  /* 7 */
-             { OP_Concat,       3,  2,  2},
-             { OP_ResultRow,    2,  1,  0},
-          };
-          addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);
-          sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
-          sqlite3VdbeJumpHere(v, addr);
-          addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
-          sqlite3VdbeChangeP1(v, addr+1, j+2);
-          sqlite3VdbeChangeP2(v, addr+1, addr+4);
-          sqlite3VdbeChangeP1(v, addr+3, j+2);
-          sqlite3VdbeChangeP2(v, addr+3, addr+2);
-          sqlite3VdbeJumpHere(v, addr+4);
-          sqlite3VdbeChangeP4(v, addr+6, 
+          int jmp2, jmp3, jmp4, jmp5;
+          int ckUniq = sqlite3VdbeMakeLabel(v);
+          if( pPk==pIdx ) continue;
+          r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
+                                       pPrior, r1);
+          pPrior = pIdx;
+          sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);  /* increment entry count */
+          /* Verify that an index entry exists for the current table row */
+          jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
+                                      pIdx->nColumn); VdbeCoverage(v);
+          sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
+          sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC);
+          sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
+          sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, 
+                            " missing from index ", P4_STATIC);
+          sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
+          jmp5 = sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0,
+                                   pIdx->zName, P4_TRANSIENT);
+          sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
+          sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
+          jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
+          sqlite3VdbeAddOp0(v, OP_Halt);
+          sqlite3VdbeJumpHere(v, jmp2);
+          /* For UNIQUE indexes, verify that only one entry exists with the
+          ** current key.  The entry is unique if (1) any column is NULL
+          ** or (2) the next entry has a different key */
+          if( IsUniqueIndex(pIdx) ){
+            int uniqOk = sqlite3VdbeMakeLabel(v);
+            int jmp6;
+            int kk;
+            for(kk=0; kk<pIdx->nKeyCol; kk++){
+              int iCol = pIdx->aiColumn[kk];
+              assert( iCol>=0 && iCol<pTab->nCol );
+              if( pTab->aCol[iCol].notNull ) continue;
+              sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
+              VdbeCoverage(v);
+            }
+            jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
+            sqlite3VdbeAddOp2(v, OP_Goto, 0, uniqOk);
+            sqlite3VdbeJumpHere(v, jmp6);
+            sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
+                                 pIdx->nKeyCol); VdbeCoverage(v);
+            sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
+            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
+                              "non-unique entry in index ", P4_STATIC);
+            sqlite3VdbeAddOp2(v, OP_Goto, 0, jmp5);
+            sqlite3VdbeResolveLabel(v, uniqOk);
+          }
+          sqlite3VdbeJumpHere(v, jmp4);
+          sqlite3ResolvePartIdxLabel(pParse, jmp3);
+        }
+        sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
+        sqlite3VdbeJumpHere(v, loopTop-1);
+#ifndef SQLITE_OMIT_BTREECOUNT
+        sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, 
                      "wrong # of entries in index ", P4_STATIC);
-          sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_TRANSIENT);
+        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+          if( pPk==pIdx ) continue;
+          addr = sqlite3VdbeCurrentAddr(v);
+          sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v);
+          sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
+          sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
+          sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v);
+          sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
+          sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
+          sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT);
+          sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
+          sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1);
         }
+#endif /* SQLITE_OMIT_BTREECOUNT */
       } 
     }
-    addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
-    sqlite3VdbeChangeP2(v, addr, -mxErr);
-    sqlite3VdbeJumpHere(v, addr+1);
-    sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
-  }else
+    addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
+    sqlite3VdbeChangeP3(v, addr, -mxErr);
+    sqlite3VdbeJumpHere(v, addr);
+    sqlite3VdbeChangeP4(v, addr+1, "ok", P4_STATIC);
+  }
+  break;
 #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
 
 #ifndef SQLITE_OMIT_UTF16
@@ -94884,7 +100232,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** new database files created using this database handle. It is only
   ** useful if invoked immediately after the main database i
   */
-  if( sqlite3StrICmp(zLeft, "encoding")==0 ){
+  case PragTyp_ENCODING: {
     static const struct EncName {
       char *zName;
       u8 enc;
@@ -94931,7 +100279,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
         }
       }
     }
-  }else
+  }
+  break;
 #endif /* SQLITE_OMIT_UTF16 */
 
 #ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
@@ -94965,11 +100314,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** The user-version is not used internally by SQLite. It may be used by
   ** applications for any purpose.
   */
-  if( sqlite3StrICmp(zLeft, "schema_version")==0 
-   || sqlite3StrICmp(zLeft, "user_version")==0 
-   || sqlite3StrICmp(zLeft, "freelist_count")==0 
-   || sqlite3StrICmp(zLeft, "application_id")==0 
-  ){
+  case PragTyp_HEADER_VALUE: {
     int iCookie;   /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
     sqlite3VdbeUsesBtree(v, iDb);
     switch( zLeft[0] ){
@@ -94994,7 +100339,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
         { OP_Integer,        0,  1,  0},    /* 1 */
         { OP_SetCookie,      0,  0,  1},    /* 2 */
       };
-      int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie);
+      int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0);
       sqlite3VdbeChangeP1(v, addr, iDb);
       sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight));
       sqlite3VdbeChangeP1(v, addr+2, iDb);
@@ -95006,14 +100351,15 @@ SQLITE_PRIVATE void sqlite3Pragma(
         { OP_ReadCookie,      0,  1,  0},    /* 1 */
         { OP_ResultRow,       1,  1,  0}
       };
-      int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie);
+      int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie, 0);
       sqlite3VdbeChangeP1(v, addr, iDb);
       sqlite3VdbeChangeP1(v, addr+1, iDb);
       sqlite3VdbeChangeP3(v, addr+1, iCookie);
       sqlite3VdbeSetNumCols(v, 1);
       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
     }
-  }else
+  }
+  break;
 #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
 
 #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
@@ -95023,7 +100369,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** Return the names of all compile-time options used in this build,
   ** one option per row.
   */
-  if( sqlite3StrICmp(zLeft, "compile_options")==0 ){
+  case PragTyp_COMPILE_OPTIONS: {
     int i = 0;
     const char *zOpt;
     sqlite3VdbeSetNumCols(v, 1);
@@ -95033,7 +100379,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
       sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0);
       sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
     }
-  }else
+  }
+  break;
 #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
 
 #ifndef SQLITE_OMIT_WAL
@@ -95042,7 +100389,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   **
   ** Checkpoint the database.
   */
-  if( sqlite3StrICmp(zLeft, "wal_checkpoint")==0 ){
+  case PragTyp_WAL_CHECKPOINT: {
     int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
     int eMode = SQLITE_CHECKPOINT_PASSIVE;
     if( zRight ){
@@ -95052,7 +100399,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
         eMode = SQLITE_CHECKPOINT_RESTART;
       }
     }
-    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     sqlite3VdbeSetNumCols(v, 3);
     pParse->nMem = 3;
     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
@@ -95061,7 +100407,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
 
     sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1);
     sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
-  }else
+  }
+  break;
 
   /*
   **   PRAGMA wal_autocheckpoint
@@ -95071,14 +100418,15 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** after accumulating N frames in the log. Or query for the current value
   ** of N.
   */
-  if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){
+  case PragTyp_WAL_AUTOCHECKPOINT: {
     if( zRight ){
       sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight));
     }
     returnSingleInt(pParse, "wal_autocheckpoint", 
        db->xWalCallback==sqlite3WalDefaultHook ? 
            SQLITE_PTR_TO_INT(db->pWalArg) : 0);
-  }else
+  }
+  break;
 #endif
 
   /*
@@ -95087,9 +100435,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** This pragma attempts to free as much memory as possible from the
   ** current database connection.
   */
-  if( sqlite3StrICmp(zLeft, "shrink_memory")==0 ){
+  case PragTyp_SHRINK_MEMORY: {
     sqlite3_db_release_memory(db);
-  }else
+    break;
+  }
 
   /*
   **   PRAGMA busy_timeout
@@ -95100,18 +100449,36 @@ SQLITE_PRIVATE void sqlite3Pragma(
   ** then 0 is returned.  Setting the busy_timeout to 0 or negative
   ** disables the timeout.
   */
-  if( sqlite3StrICmp(zLeft, "busy_timeout")==0 ){
+  /*case PragTyp_BUSY_TIMEOUT*/ default: {
+    assert( aPragmaNames[mid].ePragTyp==PragTyp_BUSY_TIMEOUT );
     if( zRight ){
       sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
     }
     returnSingleInt(pParse, "timeout",  db->busyTimeout);
-  }else
+    break;
+  }
+
+  /*
+  **   PRAGMA soft_heap_limit
+  **   PRAGMA soft_heap_limit = N
+  **
+  ** Call sqlite3_soft_heap_limit64(N).  Return the result.  If N is omitted,
+  ** use -1.
+  */
+  case PragTyp_SOFT_HEAP_LIMIT: {
+    sqlite3_int64 N;
+    if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
+      sqlite3_soft_heap_limit64(N);
+    }
+    returnSingleInt(pParse, "soft_heap_limit",  sqlite3_soft_heap_limit64(-1));
+    break;
+  }
 
 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
   /*
   ** Report the current state of file logs for all databases
   */
-  if( sqlite3StrICmp(zLeft, "lock_status")==0 ){
+  case PragTyp_LOCK_STATUS: {
     static const char *const azLockName[] = {
       "unlocked", "shared", "reserved", "pending", "exclusive"
     };
@@ -95136,35 +100503,39 @@ SQLITE_PRIVATE void sqlite3Pragma(
       sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
       sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
     }
-
-  }else
+    break;
+  }
 #endif
 
 #ifdef SQLITE_HAS_CODEC
-  if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){
-    sqlite3_key(db, zRight, sqlite3Strlen30(zRight));
-  }else
-  if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){
-    sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight));
-  }else
-  if( zRight && (sqlite3StrICmp(zLeft, "hexkey")==0 ||
-                 sqlite3StrICmp(zLeft, "hexrekey")==0) ){
-    int i, h1, h2;
-    char zKey[40];
-    for(i=0; (h1 = zRight[i])!=0 && (h2 = zRight[i+1])!=0; i+=2){
-      h1 += 9*(1&(h1>>6));
-      h2 += 9*(1&(h2>>6));
-      zKey[i/2] = (h2 & 0x0f) | ((h1 & 0xf)<<4);
-    }
-    if( (zLeft[3] & 0xf)==0xb ){
-      sqlite3_key(db, zKey, i/2);
-    }else{
-      sqlite3_rekey(db, zKey, i/2);
+  case PragTyp_KEY: {
+    if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
+    break;
+  }
+  case PragTyp_REKEY: {
+    if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
+    break;
+  }
+  case PragTyp_HEXKEY: {
+    if( zRight ){
+      u8 iByte;
+      int i;
+      char zKey[40];
+      for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){
+        iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
+        if( (i&1)!=0 ) zKey[i/2] = iByte;
+      }
+      if( (zLeft[3] & 0xf)==0xb ){
+        sqlite3_key_v2(db, zDb, zKey, i/2);
+      }else{
+        sqlite3_rekey_v2(db, zDb, zKey, i/2);
+      }
     }
-  }else
+    break;
+  }
 #endif
 #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
-  if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){
+  case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){
 #ifdef SQLITE_HAS_CODEC
     if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
       sqlite3_activate_see(&zRight[4]);
@@ -95175,23 +100546,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
       sqlite3_activate_cerod(&zRight[6]);
     }
 #endif
-  }else
+  }
+  break;
 #endif
 
- 
-  {/* Empty ELSE clause */}
+  } /* End of the PRAGMA switch */
 
-  /*
-  ** Reset the safety level, in case the fullfsync flag or synchronous
-  ** setting changed.
-  */
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-  if( db->autoCommit ){
-    sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level,
-               (db->flags&SQLITE_FullFSync)!=0,
-               (db->flags&SQLITE_CkptFullFSync)!=0);
-  }
-#endif
 pragma_out:
   sqlite3DbFree(db, zLeft);
   sqlite3DbFree(db, zRight);
@@ -95727,6 +101087,17 @@ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
 }
 
 /*
+** Free all memory allocations in the pParse object
+*/
+SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){
+  if( pParse ){
+    sqlite3 *db = pParse->db;
+    sqlite3DbFree(db, pParse->aLabel);
+    sqlite3ExprListDelete(db, pParse->pConstExpr);
+  }
+}
+
+/*
 ** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
 */
 static int sqlite3Prepare(
@@ -95794,7 +101165,7 @@ static int sqlite3Prepare(
   sqlite3VtabUnlockList(db);
 
   pParse->db = db;
-  pParse->nQueryLoop = (double)1;
+  pParse->nQueryLoop = 0;  /* Logarithmic, so 0 really means 1 */
   if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
     char *zSqlCopy;
     int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -95816,7 +101187,7 @@ static int sqlite3Prepare(
   }else{
     sqlite3RunParser(pParse, zSql, &zErrMsg);
   }
-  assert( 1==(int)pParse->nQueryLoop );
+  assert( 0==pParse->nQueryLoop );
 
   if( db->mallocFailed ){
     pParse->rc = SQLITE_NOMEM;
@@ -95883,6 +101254,7 @@ static int sqlite3Prepare(
 
 end_prepare:
 
+  sqlite3ParserReset(pParse);
   sqlite3StackFree(db, pParse);
   rc = sqlite3ApiExit(db, rc);
   assert( (rc&db->errMask)==rc );
@@ -96012,6 +101384,12 @@ static int sqlite3Prepare16(
   if( !sqlite3SafetyCheckOk(db) ){
     return SQLITE_MISUSE_BKPT;
   }
+  if( nBytes>=0 ){
+    int sz;
+    const char *z = (const char*)zSql;
+    for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){}
+    nBytes = sz;
+  }
   sqlite3_mutex_enter(db->mutex);
   zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
   if( zSql8 ){
@@ -96085,6 +101463,34 @@ SQLITE_API int sqlite3_prepare16_v2(
 ** to handle SELECT statements in SQLite.
 */
 
+/*
+** An instance of the following object is used to record information about
+** how to process the DISTINCT keyword, to simplify passing that information
+** into the selectInnerLoop() routine.
+*/
+typedef struct DistinctCtx DistinctCtx;
+struct DistinctCtx {
+  u8 isTnct;      /* True if the DISTINCT keyword is present */
+  u8 eTnctType;   /* One of the WHERE_DISTINCT_* operators */
+  int tabTnct;    /* Ephemeral table used for DISTINCT processing */
+  int addrTnct;   /* Address of OP_OpenEphemeral opcode for tabTnct */
+};
+
+/*
+** An instance of the following object is used to record information about
+** the ORDER BY (or GROUP BY) clause of query is being coded.
+*/
+typedef struct SortCtx SortCtx;
+struct SortCtx {
+  ExprList *pOrderBy;   /* The ORDER BY (or GROUP BY clause) */
+  int nOBSat;           /* Number of ORDER BY terms satisfied by indices */
+  int iECursor;         /* Cursor number for the sorter */
+  int regReturn;        /* Register holding block-output return address */
+  int labelBkOut;       /* Start label for the block-output subroutine */
+  int addrSortIndex;    /* Address of the OP_SorterOpen or OP_OpenEphemeral */
+  u8 sortFlags;         /* Zero or more SORTFLAG_* bits */
+};
+#define SORTFLAG_UseSorter  0x01   /* Use SorterOpen instead of OpenEphemeral */
 
 /*
 ** Delete all the content of a Select structure but do not deallocate
@@ -96100,6 +101506,7 @@ static void clearSelect(sqlite3 *db, Select *p){
   sqlite3SelectDelete(db, p->pPrior);
   sqlite3ExprDelete(db, p->pLimit);
   sqlite3ExprDelete(db, p->pOffset);
+  sqlite3WithDelete(db, p->pWith);
 }
 
 /*
@@ -96157,7 +101564,6 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
   assert( pOffset==0 || pLimit!=0 );
   pNew->addrOpenEphm[0] = -1;
   pNew->addrOpenEphm[1] = -1;
-  pNew->addrOpenEphm[2] = -1;
   if( db->mallocFailed ) {
     clearSelect(db, pNew);
     if( pNew!=&standin ) sqlite3DbFree(db, pNew);
@@ -96180,7 +101586,15 @@ SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
 }
 
 /*
-** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the
+** Return a pointer to the right-most SELECT statement in a compound.
+*/
+static Select *findRightmost(Select *p){
+  while( p->pNext ) p = p->pNext;
+  return p;
+}
+
+/*
+** Given 1 to 3 identifiers preceding the JOIN keyword, determine the
 ** type of join.  Return an integer constant that expresses that type
 ** in terms of the following bit values:
 **
@@ -96335,8 +101749,8 @@ static void addWhereTerm(
   pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
   if( pEq && isOuterJoin ){
     ExprSetProperty(pEq, EP_FromJoin);
-    assert( !ExprHasAnyProperty(pEq, EP_TokenOnly|EP_Reduced) );
-    ExprSetIrreducible(pEq);
+    assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
+    ExprSetVVAProperty(pEq, EP_NoReduce);
     pEq->iRightJoinTable = (i16)pE2->iTable;
   }
   *ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq);
@@ -96371,8 +101785,8 @@ static void addWhereTerm(
 static void setJoinExpr(Expr *p, int iTable){
   while( p ){
     ExprSetProperty(p, EP_FromJoin);
-    assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
-    ExprSetIrreducible(p);
+    assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
+    ExprSetVVAProperty(p, EP_NoReduce);
     p->iRightJoinTable = (i16)iTable;
     setJoinExpr(p->pLeft, iTable);
     p = p->pRight;
@@ -96481,34 +101895,73 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
   return 0;
 }
 
+/* Forward reference */
+static KeyInfo *keyInfoFromExprList(
+  Parse *pParse,       /* Parsing context */
+  ExprList *pList,     /* Form the KeyInfo object from this ExprList */
+  int iStart,          /* Begin with this column of pList */
+  int nExtra           /* Add this many extra columns to the end */
+);
+
 /*
-** Insert code into "v" that will push the record on the top of the
-** stack into the sorter.
+** Insert code into "v" that will push the record in register regData
+** into the sorter.
 */
 static void pushOntoSorter(
   Parse *pParse,         /* Parser context */
-  ExprList *pOrderBy,    /* The ORDER BY clause */
+  SortCtx *pSort,        /* Information about the ORDER BY clause */
   Select *pSelect,       /* The whole SELECT statement */
   int regData            /* Register holding data to be sorted */
 ){
   Vdbe *v = pParse->pVdbe;
-  int nExpr = pOrderBy->nExpr;
-  int regBase = sqlite3GetTempRange(pParse, nExpr+2);
-  int regRecord = sqlite3GetTempReg(pParse);
+  int nExpr = pSort->pOrderBy->nExpr;
+  int regRecord = ++pParse->nMem;
+  int regBase = pParse->nMem+1;
+  int nOBSat = pSort->nOBSat;
   int op;
+
+  pParse->nMem += nExpr+2;        /* nExpr+2 registers allocated at regBase */
   sqlite3ExprCacheClear(pParse);
-  sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
-  sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
+  sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, 0);
+  sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
   sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
-  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
-  if( pSelect->selFlags & SF_UseSorter ){
+  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nExpr+2-nOBSat,regRecord);
+  if( nOBSat>0 ){
+    int regPrevKey;   /* The first nOBSat columns of the previous row */
+    int addrFirst;    /* Address of the OP_IfNot opcode */
+    int addrJmp;      /* Address of the OP_Jump opcode */
+    VdbeOp *pOp;      /* Opcode that opens the sorter */
+    int nKey;         /* Number of sorting key columns, including OP_Sequence */
+    KeyInfo *pKI;     /* Original KeyInfo on the sorter table */
+
+    regPrevKey = pParse->nMem+1;
+    pParse->nMem += pSort->nOBSat;
+    nKey = nExpr - pSort->nOBSat + 1;
+    addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); VdbeCoverage(v);
+    sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat);
+    pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
+    if( pParse->db->mallocFailed ) return;
+    pOp->p2 = nKey + 1;
+    pKI = pOp->p4.pKeyInfo;
+    memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */
+    sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
+    pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, 1);
+    addrJmp = sqlite3VdbeCurrentAddr(v);
+    sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
+    pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
+    pSort->regReturn = ++pParse->nMem;
+    sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
+    sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
+    sqlite3VdbeJumpHere(v, addrFirst);
+    sqlite3VdbeAddOp3(v, OP_Move, regBase, regPrevKey, pSort->nOBSat);
+    sqlite3VdbeJumpHere(v, addrJmp);
+  }
+  if( pSort->sortFlags & SORTFLAG_UseSorter ){
     op = OP_SorterInsert;
   }else{
     op = OP_IdxInsert;
   }
-  sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord);
-  sqlite3ReleaseTempReg(pParse, regRecord);
-  sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
+  sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
   if( pSelect->iLimit ){
     int addr1, addr2;
     int iLimit;
@@ -96517,12 +101970,12 @@ static void pushOntoSorter(
     }else{
       iLimit = pSelect->iLimit;
     }
-    addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit);
+    addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v);
     sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
     addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
     sqlite3VdbeJumpHere(v, addr1);
-    sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor);
-    sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor);
+    sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
+    sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
     sqlite3VdbeJumpHere(v, addr2);
   }
 }
@@ -96532,13 +101985,12 @@ static void pushOntoSorter(
 */
 static void codeOffset(
   Vdbe *v,          /* Generate code into this VM */
-  Select *p,        /* The SELECT statement being coded */
+  int iOffset,      /* Register holding the offset counter */
   int iContinue     /* Jump here to skip the current record */
 ){
-  if( p->iOffset && iContinue!=0 ){
+  if( iOffset>0 ){
     int addr;
-    sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1);
-    addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset);
+    addr = sqlite3VdbeAddOp3(v, OP_IfNeg, iOffset, 0, -1); VdbeCoverage(v);
     sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
     VdbeComment((v, "skip OFFSET records"));
     sqlite3VdbeJumpHere(v, addr);
@@ -96566,7 +102018,7 @@ static void codeDistinct(
 
   v = pParse->pVdbe;
   r1 = sqlite3GetTempReg(pParse);
-  sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N);
+  sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
   sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
   sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
   sqlite3ReleaseTempReg(pParse, r1);
@@ -96597,34 +102049,20 @@ static int checkForMultiColumnSelectError(
 #endif
 
 /*
-** An instance of the following object is used to record information about
-** how to process the DISTINCT keyword, to simplify passing that information
-** into the selectInnerLoop() routine.
-*/
-typedef struct DistinctCtx DistinctCtx;
-struct DistinctCtx {
-  u8 isTnct;      /* True if the DISTINCT keyword is present */
-  u8 eTnctType;   /* One of the WHERE_DISTINCT_* operators */
-  int tabTnct;    /* Ephemeral table used for DISTINCT processing */
-  int addrTnct;   /* Address of OP_OpenEphemeral opcode for tabTnct */
-};
-
-/*
 ** This routine generates the code for the inside of the inner loop
 ** of a SELECT.
 **
-** If srcTab and nColumn are both zero, then the pEList expressions
-** are evaluated in order to get the data for this row.  If nColumn>0
-** then data is pulled from srcTab and pEList is used only to get the
-** datatypes for each column.
+** If srcTab is negative, then the pEList expressions
+** are evaluated in order to get the data for this row.  If srcTab is
+** zero or more, then data is pulled from srcTab and pEList is used only 
+** to get number columns and the datatype for each column.
 */
 static void selectInnerLoop(
   Parse *pParse,          /* The parser context */
   Select *p,              /* The complete select statement being coded */
   ExprList *pEList,       /* List of values being extracted */
   int srcTab,             /* Pull data from this table */
-  int nColumn,            /* Number of columns in the source table */
-  ExprList *pOrderBy,     /* If not NULL, sort results using this key */
+  SortCtx *pSort,         /* If not NULL, info on how to process ORDER BY */
   DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
   SelectDest *pDest,      /* How to dispose of the results */
   int iContinue,          /* Jump here to continue with next row */
@@ -96639,48 +102077,49 @@ static void selectInnerLoop(
   int nResultCol;             /* Number of result columns */
 
   assert( v );
-  if( NEVER(v==0) ) return;
   assert( pEList!=0 );
   hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
-  if( pOrderBy==0 && !hasDistinct ){
-    codeOffset(v, p, iContinue);
+  if( pSort && pSort->pOrderBy==0 ) pSort = 0;
+  if( pSort==0 && !hasDistinct ){
+    assert( iContinue!=0 );
+    codeOffset(v, p->iOffset, iContinue);
   }
 
   /* Pull the requested columns.
   */
-  if( nColumn>0 ){
-    nResultCol = nColumn;
-  }else{
-    nResultCol = pEList->nExpr;
-  }
+  nResultCol = pEList->nExpr;
+
   if( pDest->iSdst==0 ){
     pDest->iSdst = pParse->nMem+1;
-    pDest->nSdst = nResultCol;
     pParse->nMem += nResultCol;
-  }else{ 
-    assert( pDest->nSdst==nResultCol );
+  }else if( pDest->iSdst+nResultCol > pParse->nMem ){
+    /* This is an error condition that can result, for example, when a SELECT
+    ** on the right-hand side of an INSERT contains more result columns than
+    ** there are columns in the table on the left.  The error will be caught
+    ** and reported later.  But we need to make sure enough memory is allocated
+    ** to avoid other spurious errors in the meantime. */
+    pParse->nMem += nResultCol;
   }
+  pDest->nSdst = nResultCol;
   regResult = pDest->iSdst;
-  if( nColumn>0 ){
-    for(i=0; i<nColumn; i++){
+  if( srcTab>=0 ){
+    for(i=0; i<nResultCol; i++){
       sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
+      VdbeComment((v, "%s", pEList->a[i].zName));
     }
   }else if( eDest!=SRT_Exists ){
     /* If the destination is an EXISTS(...) expression, the actual
     ** values returned by the SELECT are not required.
     */
-    sqlite3ExprCacheClear(pParse);
-    sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
+    sqlite3ExprCodeExprList(pParse, pEList, regResult,
+                  (eDest==SRT_Output||eDest==SRT_Coroutine)?SQLITE_ECEL_DUP:0);
   }
-  nColumn = nResultCol;
 
   /* If the DISTINCT keyword was present on the SELECT statement
   ** and this row has been seen before, then do not make this row
   ** part of the result.
   */
   if( hasDistinct ){
-    assert( pEList!=0 );
-    assert( pEList->nExpr==nColumn );
     switch( pDistinct->eTnctType ){
       case WHERE_DISTINCT_ORDERED: {
         VdbeOp *pOp;            /* No longer required OpenEphemeral instr. */
@@ -96689,7 +102128,7 @@ static void selectInnerLoop(
 
         /* Allocate space for the previous row */
         regPrev = pParse->nMem+1;
-        pParse->nMem += nColumn;
+        pParse->nMem += nResultCol;
 
         /* Change the OP_OpenEphemeral coded earlier to an OP_Null
         ** sets the MEM_Cleared bit on the first register of the
@@ -96703,19 +102142,21 @@ static void selectInnerLoop(
         pOp->p1 = 1;
         pOp->p2 = regPrev;
 
-        iJump = sqlite3VdbeCurrentAddr(v) + nColumn;
-        for(i=0; i<nColumn; i++){
+        iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
+        for(i=0; i<nResultCol; i++){
           CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr);
-          if( i<nColumn-1 ){
+          if( i<nResultCol-1 ){
             sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i);
+            VdbeCoverage(v);
           }else{
             sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i);
-          }
+            VdbeCoverage(v);
+           }
           sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
           sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
         }
-        assert( sqlite3VdbeCurrentAddr(v)==iJump );
-        sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nColumn-1);
+        assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
+        sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
         break;
       }
 
@@ -96726,12 +102167,12 @@ static void selectInnerLoop(
 
       default: {
         assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
-        codeDistinct(pParse, pDistinct->tabTnct, iContinue, nColumn, regResult);
+        codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, regResult);
         break;
       }
     }
-    if( pOrderBy==0 ){
-      codeOffset(v, p, iContinue);
+    if( pSort==0 ){
+      codeOffset(v, p->iOffset, iContinue);
     }
   }
 
@@ -96743,7 +102184,7 @@ static void selectInnerLoop(
     case SRT_Union: {
       int r1;
       r1 = sqlite3GetTempReg(pParse);
-      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
       sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
       sqlite3ReleaseTempReg(pParse, r1);
       break;
@@ -96754,21 +102195,36 @@ static void selectInnerLoop(
     ** the temporary table iParm.
     */
     case SRT_Except: {
-      sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn);
+      sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol);
       break;
     }
-#endif
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
 
     /* Store the result as data using a unique key.
     */
+    case SRT_Fifo:
+    case SRT_DistFifo:
     case SRT_Table:
     case SRT_EphemTab: {
       int r1 = sqlite3GetTempReg(pParse);
       testcase( eDest==SRT_Table );
       testcase( eDest==SRT_EphemTab );
-      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
-      if( pOrderBy ){
-        pushOntoSorter(pParse, pOrderBy, p, r1);
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
+#ifndef SQLITE_OMIT_CTE
+      if( eDest==SRT_DistFifo ){
+        /* If the destination is DistFifo, then cursor (iParm+1) is open
+        ** on an ephemeral index. If the current row is already present
+        ** in the index, do not write it to the output. If not, add the
+        ** current row to the index and proceed with writing it to the
+        ** output table as well.  */
+        int addr = sqlite3VdbeCurrentAddr(v) + 4;
+        sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v);
+        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
+        assert( pSort==0 );
+      }
+#endif
+      if( pSort ){
+        pushOntoSorter(pParse, pSort, p, r1);
       }else{
         int r2 = sqlite3GetTempReg(pParse);
         sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
@@ -96786,15 +102242,15 @@ static void selectInnerLoop(
     ** item into the set table with bogus data.
     */
     case SRT_Set: {
-      assert( nColumn==1 );
+      assert( nResultCol==1 );
       pDest->affSdst =
                   sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
-      if( pOrderBy ){
+      if( pSort ){
         /* At first glance you would think we could optimize out the
         ** ORDER BY in this case since the order of entries in the set
         ** does not matter.  But there might be a LIMIT clause, in which
         ** case the order does matter */
-        pushOntoSorter(pParse, pOrderBy, p, regResult);
+        pushOntoSorter(pParse, pSort, p, regResult);
       }else{
         int r1 = sqlite3GetTempReg(pParse);
         sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
@@ -96818,9 +102274,9 @@ static void selectInnerLoop(
     ** of the scan loop.
     */
     case SRT_Mem: {
-      assert( nColumn==1 );
-      if( pOrderBy ){
-        pushOntoSorter(pParse, pOrderBy, p, regResult);
+      assert( nResultCol==1 );
+      if( pSort ){
+        pushOntoSorter(pParse, pSort, p, regResult);
       }else{
         sqlite3ExprCodeMove(pParse, regResult, iParm, 1);
         /* The LIMIT clause will jump out of the loop for us */
@@ -96829,28 +102285,73 @@ static void selectInnerLoop(
     }
 #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.
-    */
-    case SRT_Coroutine:
-    case SRT_Output: {
+    case SRT_Coroutine:       /* Send data to a co-routine */
+    case SRT_Output: {        /* Return the results */
       testcase( eDest==SRT_Coroutine );
       testcase( eDest==SRT_Output );
-      if( pOrderBy ){
+      if( pSort ){
         int r1 = sqlite3GetTempReg(pParse);
-        sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
-        pushOntoSorter(pParse, pOrderBy, p, r1);
+        sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
+        pushOntoSorter(pParse, pSort, p, r1);
         sqlite3ReleaseTempReg(pParse, r1);
       }else if( eDest==SRT_Coroutine ){
         sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
       }else{
-        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
-        sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn);
+        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol);
+        sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
       }
       break;
     }
 
+#ifndef SQLITE_OMIT_CTE
+    /* Write the results into a priority queue that is order according to
+    ** pDest->pOrderBy (in pSO).  pDest->iSDParm (in iParm) is the cursor for an
+    ** index with pSO->nExpr+2 columns.  Build a key using pSO for the first
+    ** pSO->nExpr columns, then make sure all keys are unique by adding a
+    ** final OP_Sequence column.  The last column is the record as a blob.
+    */
+    case SRT_DistQueue:
+    case SRT_Queue: {
+      int nKey;
+      int r1, r2, r3;
+      int addrTest = 0;
+      ExprList *pSO;
+      pSO = pDest->pOrderBy;
+      assert( pSO );
+      nKey = pSO->nExpr;
+      r1 = sqlite3GetTempReg(pParse);
+      r2 = sqlite3GetTempRange(pParse, nKey+2);
+      r3 = r2+nKey+1;
+      if( eDest==SRT_DistQueue ){
+        /* If the destination is DistQueue, then cursor (iParm+1) is open
+        ** on a second ephemeral index that holds all values every previously
+        ** added to the queue. */
+        addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, 
+                                        regResult, nResultCol);
+        VdbeCoverage(v);
+      }
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3);
+      if( eDest==SRT_DistQueue ){
+        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
+        sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+      }
+      for(i=0; i<nKey; i++){
+        sqlite3VdbeAddOp2(v, OP_SCopy,
+                          regResult + pSO->a[i].u.x.iOrderByCol - 1,
+                          r2+i);
+      }
+      sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey);
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1);
+      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+      if( addrTest ) sqlite3VdbeJumpHere(v, addrTest);
+      sqlite3ReleaseTempReg(pParse, r1);
+      sqlite3ReleaseTempRange(pParse, r2, nKey+2);
+      break;
+    }
+#endif /* SQLITE_OMIT_CTE */
+
+
+
 #if !defined(SQLITE_OMIT_TRIGGER)
     /* Discard the results.  This is used for SELECT statements inside
     ** the body of a TRIGGER.  The purpose of such selects is to call
@@ -96868,11 +102369,63 @@ static void selectInnerLoop(
   ** there is a sorter, in which case the sorter has already limited
   ** the output for us.
   */
-  if( pOrderBy==0 && p->iLimit ){
-    sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1);
+  if( pSort==0 && p->iLimit ){
+    sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
+  }
+}
+
+/*
+** Allocate a KeyInfo object sufficient for an index of N key columns and
+** X extra columns.
+*/
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
+  KeyInfo *p = sqlite3DbMallocZero(0, 
+                   sizeof(KeyInfo) + (N+X)*(sizeof(CollSeq*)+1));
+  if( p ){
+    p->aSortOrder = (u8*)&p->aColl[N+X];
+    p->nField = (u16)N;
+    p->nXField = (u16)X;
+    p->enc = ENC(db);
+    p->db = db;
+    p->nRef = 1;
+  }else{
+    db->mallocFailed = 1;
+  }
+  return p;
+}
+
+/*
+** Deallocate a KeyInfo object
+*/
+SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo *p){
+  if( p ){
+    assert( p->nRef>0 );
+    p->nRef--;
+    if( p->nRef==0 ) sqlite3DbFree(0, p);
+  }
+}
+
+/*
+** Make a new pointer to a KeyInfo object
+*/
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo *p){
+  if( p ){
+    assert( p->nRef>0 );
+    p->nRef++;
   }
+  return p;
 }
 
+#ifdef SQLITE_DEBUG
+/*
+** Return TRUE if a KeyInfo object can be change.  The KeyInfo object
+** can only be changed if this is just a single reference to the object.
+**
+** This routine is used only inside of assert() statements.
+*/
+SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; }
+#endif /* SQLITE_DEBUG */
+
 /*
 ** Given an expression list, generate a KeyInfo structure that records
 ** the collating sequence for each expression in that expression list.
@@ -96885,31 +102438,30 @@ static void selectInnerLoop(
 **
 ** Space to hold the KeyInfo structure is obtain from malloc.  The calling
 ** function is responsible for seeing that this structure is eventually
-** freed.  Add the KeyInfo structure to the P4 field of an opcode using
-** P4_KEYINFO_HANDOFF is the usual way of dealing with this.
+** freed.
 */
-static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
-  sqlite3 *db = pParse->db;
+static KeyInfo *keyInfoFromExprList(
+  Parse *pParse,       /* Parsing context */
+  ExprList *pList,     /* Form the KeyInfo object from this ExprList */
+  int iStart,          /* Begin with this column of pList */
+  int nExtra           /* Add this many extra columns to the end */
+){
   int nExpr;
   KeyInfo *pInfo;
   struct ExprList_item *pItem;
+  sqlite3 *db = pParse->db;
   int i;
 
   nExpr = pList->nExpr;
-  pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );
+  pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra-iStart, 1);
   if( pInfo ){
-    pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];
-    pInfo->nField = (u16)nExpr;
-    pInfo->enc = ENC(db);
-    pInfo->db = db;
-    for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){
+    assert( sqlite3KeyInfoIsWriteable(pInfo) );
+    for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
       CollSeq *pColl;
       pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
-      if( !pColl ){
-        pColl = db->pDfltColl;
-      }
-      pInfo->aColl[i] = pColl;
-      pInfo->aSortOrder[i] = pItem->sortOrder;
+      if( !pColl ) pColl = db->pDfltColl;
+      pInfo->aColl[i-iStart] = pColl;
+      pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
     }
   }
   return pInfo;
@@ -97011,24 +102563,31 @@ static void explainComposite(
 static void generateSortTail(
   Parse *pParse,    /* Parsing context */
   Select *p,        /* The SELECT statement */
-  Vdbe *v,          /* Generate code into this VDBE */
+  SortCtx *pSort,   /* Information on the ORDER BY clause */
   int nColumn,      /* Number of columns of data */
   SelectDest *pDest /* Write the sorted results here */
 ){
+  Vdbe *v = pParse->pVdbe;                     /* The prepared statement */
   int addrBreak = sqlite3VdbeMakeLabel(v);     /* Jump here to exit loop */
   int addrContinue = sqlite3VdbeMakeLabel(v);  /* Jump here for next cycle */
   int addr;
+  int addrOnce = 0;
   int iTab;
   int pseudoTab = 0;
-  ExprList *pOrderBy = p->pOrderBy;
-
+  ExprList *pOrderBy = pSort->pOrderBy;
   int eDest = pDest->eDest;
   int iParm = pDest->iSDParm;
-
   int regRow;
   int regRowid;
+  int nKey;
 
-  iTab = pOrderBy->iECursor;
+  if( pSort->labelBkOut ){
+    sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
+    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBreak);
+    sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
+    addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
+  }
+  iTab = pSort->iECursor;
   regRow = sqlite3GetTempReg(pParse);
   if( eDest==SRT_Output || eDest==SRT_Coroutine ){
     pseudoTab = pParse->nTab++;
@@ -97037,19 +102596,23 @@ static void generateSortTail(
   }else{
     regRowid = sqlite3GetTempReg(pParse);
   }
-  if( p->selFlags & SF_UseSorter ){
+  nKey = pOrderBy->nExpr - pSort->nOBSat;
+  if( pSort->sortFlags & SORTFLAG_UseSorter ){
     int regSortOut = ++pParse->nMem;
     int ptab2 = pParse->nTab++;
-    sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2);
+    sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, nKey+2);
+    if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
     addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
-    codeOffset(v, p, addrContinue);
+    VdbeCoverage(v);
+    codeOffset(v, p->iOffset, addrContinue);
     sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
-    sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow);
+    sqlite3VdbeAddOp3(v, OP_Column, ptab2, nKey+1, regRow);
     sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
   }else{
-    addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
-    codeOffset(v, p, addrContinue);
-    sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow);
+    if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
+    addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
+    codeOffset(v, p->iOffset, addrContinue);
+    sqlite3VdbeAddOp3(v, OP_Column, iTab, nKey+1, regRow);
   }
   switch( eDest ){
     case SRT_Table:
@@ -97104,21 +102667,22 @@ static void generateSortTail(
   /* The bottom of the loop
   */
   sqlite3VdbeResolveLabel(v, addrContinue);
-  if( p->selFlags & SF_UseSorter ){
-    sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr);
+  if( pSort->sortFlags & SORTFLAG_UseSorter ){
+    sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v);
   }else{
-    sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
+    sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v);
   }
+  if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn);
   sqlite3VdbeResolveLabel(v, addrBreak);
-  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
-    sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
-  }
 }
 
 /*
 ** Return a pointer to a string containing the 'declaration type' of the
 ** expression pExpr. The string may be treated as static by the caller.
 **
+** Also try to estimate the size of the returned value and return that
+** result in *pEstWidth.
+**
 ** The declaration type is the exact datatype definition extracted from the
 ** original CREATE TABLE statement if the expression is a column. The
 ** declaration type for a ROWID field is INTEGER. Exactly when an expression
@@ -97132,21 +102696,36 @@ static void generateSortTail(
 **   SELECT abc FROM (SELECT col AS abc FROM tbl);
 ** 
 ** The declaration type for any expression other than a column is NULL.
+**
+** This routine has either 3 or 6 parameters depending on whether or not
+** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
 */
-static const char *columnType(
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
+static const char *columnTypeImpl(
+  NameContext *pNC, 
+  Expr *pExpr,
+  const char **pzOrigDb,
+  const char **pzOrigTab,
+  const char **pzOrigCol,
+  u8 *pEstWidth
+){
+  char const *zOrigDb = 0;
+  char const *zOrigTab = 0;
+  char const *zOrigCol = 0;
+#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
+static const char *columnTypeImpl(
   NameContext *pNC, 
   Expr *pExpr,
-  const char **pzOriginDb,
-  const char **pzOriginTab,
-  const char **pzOriginCol
+  u8 *pEstWidth
 ){
+#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
   char const *zType = 0;
-  char const *zOriginDb = 0;
-  char const *zOriginTab = 0;
-  char const *zOriginCol = 0;
   int j;
-  if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
+  u8 estWidth = 1;
 
+  if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
   switch( pExpr->op ){
     case TK_AGG_COLUMN:
     case TK_COLUMN: {
@@ -97207,25 +102786,35 @@ static const char *columnType(
           sNC.pSrcList = pS->pSrc;
           sNC.pNext = pNC;
           sNC.pParse = pNC->pParse;
-          zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); 
+          zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth); 
         }
-      }else if( ALWAYS(pTab->pSchema) ){
+      }else if( pTab->pSchema ){
         /* A real table */
         assert( !pS );
         if( iCol<0 ) iCol = pTab->iPKey;
         assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
         if( iCol<0 ){
           zType = "INTEGER";
-          zOriginCol = "rowid";
+          zOrigCol = "rowid";
         }else{
           zType = pTab->aCol[iCol].zType;
-          zOriginCol = pTab->aCol[iCol].zName;
+          zOrigCol = pTab->aCol[iCol].zName;
+          estWidth = pTab->aCol[iCol].szEst;
         }
-        zOriginTab = pTab->zName;
+        zOrigTab = pTab->zName;
         if( pNC->pParse ){
           int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
-          zOriginDb = pNC->pParse->db->aDb[iDb].zName;
+          zOrigDb = pNC->pParse->db->aDb[iDb].zName;
         }
+#else
+        if( iCol<0 ){
+          zType = "INTEGER";
+        }else{
+          zType = pTab->aCol[iCol].zType;
+          estWidth = pTab->aCol[iCol].szEst;
+        }
+#endif
       }
       break;
     }
@@ -97242,18 +102831,21 @@ static const char *columnType(
       sNC.pSrcList = pS->pSrc;
       sNC.pNext = pNC;
       sNC.pParse = pNC->pParse;
-      zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); 
+      zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth); 
       break;
     }
 #endif
   }
-  
-  if( pzOriginDb ){
-    assert( pzOriginTab && pzOriginCol );
-    *pzOriginDb = zOriginDb;
-    *pzOriginTab = zOriginTab;
-    *pzOriginCol = zOriginCol;
+
+#ifdef SQLITE_ENABLE_COLUMN_METADATA  
+  if( pzOrigDb ){
+    assert( pzOrigTab && pzOrigCol );
+    *pzOrigDb = zOrigDb;
+    *pzOrigTab = zOrigTab;
+    *pzOrigCol = zOrigCol;
   }
+#endif
+  if( pEstWidth ) *pEstWidth = estWidth;
   return zType;
 }
 
@@ -97279,7 +102871,7 @@ static void generateColumnTypes(
     const char *zOrigDb = 0;
     const char *zOrigTab = 0;
     const char *zOrigCol = 0;
-    zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
+    zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0);
 
     /* The vdbe must make its own copy of the column-type and other 
     ** column specific strings, in case the schema is reset before this
@@ -97289,11 +102881,11 @@ static void generateColumnTypes(
     sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
     sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
 #else
-    zType = columnType(&sNC, p, 0, 0, 0);
+    zType = columnType(&sNC, p, 0, 0, 0, 0);
 #endif
     sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
   }
-#endif /* SQLITE_OMIT_DECLTYPE */
+#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
 }
 
 /*
@@ -97357,8 +102949,9 @@ static void generateColumnNames(
         sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
       }
     }else{
-      sqlite3VdbeSetColName(v, i, COLNAME_NAME, 
-          sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
+      const char *z = pEList->a[i].zSpan;
+      z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z);
+      sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC);
     }
   }
   generateColumnTypes(pParse, pTabList, pEList);
@@ -97446,7 +103039,7 @@ static int selectColumnsFromExprList(
         char *zNewName;
         int k;
         for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
-        if( zName[k]==':' ) nName = k;
+        if( k>=0 && zName[k]==':' ) nName = k;
         zName[nName] = 0;
         zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
         sqlite3DbFree(db, zName);
@@ -97482,8 +103075,7 @@ static int selectColumnsFromExprList(
 */
 static void selectAddColumnTypeAndCollation(
   Parse *pParse,        /* Parsing contexts */
-  int nCol,             /* Number of columns */
-  Column *aCol,         /* List of columns */
+  Table *pTab,          /* Add column type information to this table */
   Select *pSelect       /* SELECT used to determine types and collations */
 ){
   sqlite3 *db = pParse->db;
@@ -97493,17 +103085,19 @@ static void selectAddColumnTypeAndCollation(
   int i;
   Expr *p;
   struct ExprList_item *a;
+  u64 szAll = 0;
 
   assert( pSelect!=0 );
   assert( (pSelect->selFlags & SF_Resolved)!=0 );
-  assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
+  assert( pTab->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++){
+  for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
     p = a[i].pExpr;
-    pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
+    pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
+    szAll += pCol->szEst;
     pCol->affinity = sqlite3ExprAffinity(p);
     if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
     pColl = sqlite3ExprCollSeq(pParse, p);
@@ -97511,6 +103105,7 @@ static void selectAddColumnTypeAndCollation(
       pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
     }
   }
+  pTab->szTabRow = sqlite3LogEst(szAll*4);
 }
 
 /*
@@ -97538,9 +103133,9 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
   assert( db->lookaside.bEnabled==0 );
   pTab->nRef = 1;
   pTab->zName = 0;
-  pTab->nRowEst = 1000000;
+  pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
   selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
-  selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
+  selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
   pTab->iPKey = -1;
   if( db->mallocFailed ){
     sqlite3DeleteTable(db, pTab);
@@ -97556,12 +103151,14 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
 SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){
   Vdbe *v = pParse->pVdbe;
   if( v==0 ){
-    v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db);
-#ifndef SQLITE_OMIT_TRACE
-    if( v ){
-      sqlite3VdbeAddOp0(v, OP_Trace);
+    v = pParse->pVdbe = sqlite3VdbeCreate(pParse);
+    if( v ) sqlite3VdbeAddOp0(v, OP_Init);
+    if( pParse->pToplevel==0
+     && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
+    ){
+      pParse->okConstFactor = 1;
     }
-#endif
+
   }
   return v;
 }
@@ -97578,8 +103175,13 @@ SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){
 **
 ** This routine changes the values of iLimit and iOffset only if
 ** a limit or offset is defined by pLimit and pOffset.  iLimit and
-** iOffset should have been preset to appropriate default values
-** (usually but not always -1) prior to calling this routine.
+** iOffset should have been preset to appropriate default values (zero)
+** prior to calling this routine.
+**
+** The iOffset register (if it exists) is initialized to the value
+** of the OFFSET.  The iLimit register is initialized to LIMIT.  Register
+** iOffset+1 is initialized to LIMIT+OFFSET.
+**
 ** Only if pLimit!=0 or pOffset!=0 do the limit registers get
 ** redefined.  The UNION ALL operator uses this property to force
 ** the reuse of the same limit and offset registers across multiple
@@ -97594,7 +103196,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
 
   /* 
   ** "LIMIT -1" always shows all rows.  There is some
-  ** contraversy about what the correct behavior should be.
+  ** controversy about what the correct behavior should be.
   ** The current implementation interprets "LIMIT 0" to mean
   ** no rows.
   */
@@ -97603,33 +103205,33 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
   if( p->pLimit ){
     p->iLimit = iLimit = ++pParse->nMem;
     v = sqlite3GetVdbe(pParse);
-    if( NEVER(v==0) ) return;  /* VDBE should have already been allocated */
+    assert( v!=0 );
     if( sqlite3ExprIsInteger(p->pLimit, &n) ){
       sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
       VdbeComment((v, "LIMIT counter"));
       if( n==0 ){
         sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
-      }else{
-        if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n;
+      }else if( n>=0 && p->nSelectRow>(u64)n ){
+        p->nSelectRow = n;
       }
     }else{
       sqlite3ExprCode(pParse, p->pLimit, iLimit);
-      sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit);
+      sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
       VdbeComment((v, "LIMIT counter"));
-      sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);
+      sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v);
     }
     if( p->pOffset ){
       p->iOffset = iOffset = ++pParse->nMem;
       pParse->nMem++;   /* Allocate an extra register for limit+offset */
       sqlite3ExprCode(pParse, p->pOffset, iOffset);
-      sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset);
+      sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
       VdbeComment((v, "OFFSET counter"));
-      addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset);
+      addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); VdbeCoverage(v);
       sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);
       sqlite3VdbeJumpHere(v, addr1);
       sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
       VdbeComment((v, "LIMIT+OFFSET"));
-      addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit);
+      addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); VdbeCoverage(v);
       sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1);
       sqlite3VdbeJumpHere(v, addr1);
     }
@@ -97658,9 +103260,210 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
   }
   return pRet;
 }
-#endif /* SQLITE_OMIT_COMPOUND_SELECT */
 
-/* Forward reference */
+/*
+** The select statement passed as the second parameter is a compound SELECT
+** with an ORDER BY clause. This function allocates and returns a KeyInfo
+** structure suitable for implementing the ORDER BY.
+**
+** Space to hold the KeyInfo structure is obtained from malloc. The calling
+** function is responsible for ensuring that this structure is eventually
+** freed.
+*/
+static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
+  ExprList *pOrderBy = p->pOrderBy;
+  int nOrderBy = p->pOrderBy->nExpr;
+  sqlite3 *db = pParse->db;
+  KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
+  if( pRet ){
+    int i;
+    for(i=0; i<nOrderBy; i++){
+      struct ExprList_item *pItem = &pOrderBy->a[i];
+      Expr *pTerm = pItem->pExpr;
+      CollSeq *pColl;
+
+      if( pTerm->flags & EP_Collate ){
+        pColl = sqlite3ExprCollSeq(pParse, pTerm);
+      }else{
+        pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1);
+        if( pColl==0 ) pColl = db->pDfltColl;
+        pOrderBy->a[i].pExpr =
+          sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
+      }
+      assert( sqlite3KeyInfoIsWriteable(pRet) );
+      pRet->aColl[i] = pColl;
+      pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
+    }
+  }
+
+  return pRet;
+}
+
+#ifndef SQLITE_OMIT_CTE
+/*
+** This routine generates VDBE code to compute the content of a WITH RECURSIVE
+** query of the form:
+**
+**   <recursive-table> AS (<setup-query> UNION [ALL] <recursive-query>)
+**                         \___________/             \_______________/
+**                           p->pPrior                      p
+**
+**
+** There is exactly one reference to the recursive-table in the FROM clause
+** of recursive-query, marked with the SrcList->a[].isRecursive flag.
+**
+** The setup-query runs once to generate an initial set of rows that go
+** into a Queue table.  Rows are extracted from the Queue table one by
+** one.  Each row extracted from Queue is output to pDest.  Then the single
+** extracted row (now in the iCurrent table) becomes the content of the
+** recursive-table for a recursive-query run.  The output of the recursive-query
+** is added back into the Queue table.  Then another row is extracted from Queue
+** and the iteration continues until the Queue table is empty.
+**
+** If the compound query operator is UNION then no duplicate rows are ever
+** inserted into the Queue table.  The iDistinct table keeps a copy of all rows
+** that have ever been inserted into Queue and causes duplicates to be
+** discarded.  If the operator is UNION ALL, then duplicates are allowed.
+** 
+** If the query has an ORDER BY, then entries in the Queue table are kept in
+** ORDER BY order and the first entry is extracted for each cycle.  Without
+** an ORDER BY, the Queue table is just a FIFO.
+**
+** If a LIMIT clause is provided, then the iteration stops after LIMIT rows
+** have been output to pDest.  A LIMIT of zero means to output no rows and a
+** negative LIMIT means to output all rows.  If there is also an OFFSET clause
+** with a positive value, then the first OFFSET outputs are discarded rather
+** than being sent to pDest.  The LIMIT count does not begin until after OFFSET
+** rows have been skipped.
+*/
+static void generateWithRecursiveQuery(
+  Parse *pParse,        /* Parsing context */
+  Select *p,            /* The recursive SELECT to be coded */
+  SelectDest *pDest     /* What to do with query results */
+){
+  SrcList *pSrc = p->pSrc;      /* The FROM clause of the recursive query */
+  int nCol = p->pEList->nExpr;  /* Number of columns in the recursive table */
+  Vdbe *v = pParse->pVdbe;      /* The prepared statement under construction */
+  Select *pSetup = p->pPrior;   /* The setup query */
+  int addrTop;                  /* Top of the loop */
+  int addrCont, addrBreak;      /* CONTINUE and BREAK addresses */
+  int iCurrent = 0;             /* The Current table */
+  int regCurrent;               /* Register holding Current table */
+  int iQueue;                   /* The Queue table */
+  int iDistinct = 0;            /* To ensure unique results if UNION */
+  int eDest = SRT_Fifo;         /* How to write to Queue */
+  SelectDest destQueue;         /* SelectDest targetting the Queue table */
+  int i;                        /* Loop counter */
+  int rc;                       /* Result code */
+  ExprList *pOrderBy;           /* The ORDER BY clause */
+  Expr *pLimit, *pOffset;       /* Saved LIMIT and OFFSET */
+  int regLimit, regOffset;      /* Registers used by LIMIT and OFFSET */
+
+  /* Obtain authorization to do a recursive query */
+  if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;
+
+  /* Process the LIMIT and OFFSET clauses, if they exist */
+  addrBreak = sqlite3VdbeMakeLabel(v);
+  computeLimitRegisters(pParse, p, addrBreak);
+  pLimit = p->pLimit;
+  pOffset = p->pOffset;
+  regLimit = p->iLimit;
+  regOffset = p->iOffset;
+  p->pLimit = p->pOffset = 0;
+  p->iLimit = p->iOffset = 0;
+  pOrderBy = p->pOrderBy;
+
+  /* Locate the cursor number of the Current table */
+  for(i=0; ALWAYS(i<pSrc->nSrc); i++){
+    if( pSrc->a[i].isRecursive ){
+      iCurrent = pSrc->a[i].iCursor;
+      break;
+    }
+  }
+
+  /* Allocate cursors numbers for Queue and Distinct.  The cursor number for
+  ** the Distinct table must be exactly one greater than Queue in order
+  ** for the SRT_DistFifo and SRT_DistQueue destinations to work. */
+  iQueue = pParse->nTab++;
+  if( p->op==TK_UNION ){
+    eDest = pOrderBy ? SRT_DistQueue : SRT_DistFifo;
+    iDistinct = pParse->nTab++;
+  }else{
+    eDest = pOrderBy ? SRT_Queue : SRT_Fifo;
+  }
+  sqlite3SelectDestInit(&destQueue, eDest, iQueue);
+
+  /* Allocate cursors for Current, Queue, and Distinct. */
+  regCurrent = ++pParse->nMem;
+  sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
+  if( pOrderBy ){
+    KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
+    sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
+                      (char*)pKeyInfo, P4_KEYINFO);
+    destQueue.pOrderBy = pOrderBy;
+  }else{
+    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
+  }
+  VdbeComment((v, "Queue table"));
+  if( iDistinct ){
+    p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
+    p->selFlags |= SF_UsesEphemeral;
+  }
+
+  /* Detach the ORDER BY clause from the compound SELECT */
+  p->pOrderBy = 0;
+
+  /* Store the results of the setup-query in Queue. */
+  pSetup->pNext = 0;
+  rc = sqlite3Select(pParse, pSetup, &destQueue);
+  pSetup->pNext = p;
+  if( rc ) goto end_of_recursive_query;
+
+  /* Find the next row in the Queue and output that row */
+  addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); VdbeCoverage(v);
+
+  /* Transfer the next row in Queue over to Current */
+  sqlite3VdbeAddOp1(v, OP_NullRow, iCurrent); /* To reset column cache */
+  if( pOrderBy ){
+    sqlite3VdbeAddOp3(v, OP_Column, iQueue, pOrderBy->nExpr+1, regCurrent);
+  }else{
+    sqlite3VdbeAddOp2(v, OP_RowData, iQueue, regCurrent);
+  }
+  sqlite3VdbeAddOp1(v, OP_Delete, iQueue);
+
+  /* Output the single row in Current */
+  addrCont = sqlite3VdbeMakeLabel(v);
+  codeOffset(v, regOffset, addrCont);
+  selectInnerLoop(pParse, p, p->pEList, iCurrent,
+      0, 0, pDest, addrCont, addrBreak);
+  if( regLimit ){
+    sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1);
+    VdbeCoverage(v);
+  }
+  sqlite3VdbeResolveLabel(v, addrCont);
+
+  /* Execute the recursive SELECT taking the single row in Current as
+  ** the value for the recursive-table. Store the results in the Queue.
+  */
+  p->pPrior = 0;
+  sqlite3Select(pParse, p, &destQueue);
+  assert( p->pPrior==0 );
+  p->pPrior = pSetup;
+
+  /* Keep running the loop until the Queue is empty */
+  sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
+  sqlite3VdbeResolveLabel(v, addrBreak);
+
+end_of_recursive_query:
+  sqlite3ExprListDelete(pParse->db, p->pOrderBy);
+  p->pOrderBy = pOrderBy;
+  p->pLimit = pLimit;
+  p->pOffset = pOffset;
+  return;
+}
+#endif /* SQLITE_OMIT_CTE */
+
+/* Forward references */
 static int multiSelectOrderBy(
   Parse *pParse,        /* Parsing context */
   Select *p,            /* The right-most of SELECTs to be coded */
@@ -97668,7 +103471,6 @@ static int multiSelectOrderBy(
 );
 
 
-#ifndef SQLITE_OMIT_COMPOUND_SELECT
 /*
 ** This routine is called to process a compound query form from
 ** two or more separate queries using UNION, UNION ALL, EXCEPT, or
@@ -97712,18 +103514,17 @@ static int multiSelect(
   Select *pDelete = 0;  /* Chain of simple selects to delete */
   sqlite3 *db;          /* Database connection */
 #ifndef SQLITE_OMIT_EXPLAIN
-  int iSub1;            /* EQP id of left-hand query */
-  int iSub2;            /* EQP id of right-hand query */
+  int iSub1 = 0;        /* EQP id of left-hand query */
+  int iSub2 = 0;        /* EQP id of right-hand query */
 #endif
 
   /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
   ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
   */
   assert( p && p->pPrior );  /* Calling function guarantees this much */
+  assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION );
   db = pParse->db;
   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",
@@ -97765,11 +103566,17 @@ static int multiSelect(
     goto multi_select_end;
   }
 
+#ifndef SQLITE_OMIT_CTE
+  if( p->selFlags & SF_Recursive ){
+    generateWithRecursiveQuery(pParse, p, &dest);
+  }else
+#endif
+
   /* Compound SELECTs that have an ORDER BY clause are handled separately.
   */
   if( p->pOrderBy ){
     return multiSelectOrderBy(pParse, p, pDest);
-  }
+  }else
 
   /* Generate code for the left and right SELECT statements.
   */
@@ -97793,7 +103600,7 @@ static int multiSelect(
       p->iLimit = pPrior->iLimit;
       p->iOffset = pPrior->iOffset;
       if( p->iLimit ){
-        addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit);
+        addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v);
         VdbeComment((v, "Jump ahead if LIMIT reached"));
       }
       explainSetInteger(iSub2, pParse->iNextSelectId);
@@ -97804,9 +103611,9 @@ static int multiSelect(
       p->nSelectRow += pPrior->nSelectRow;
       if( pPrior->pLimit
        && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
-       && p->nSelectRow > (double)nLimit 
+       && nLimit>0 && p->nSelectRow > (u64)nLimit 
       ){
-        p->nSelectRow = (double)nLimit;
+        p->nSelectRow = nLimit;
       }
       if( addr ){
         sqlite3VdbeJumpHere(v, addr);
@@ -97825,12 +103632,10 @@ static int multiSelect(
       testcase( p->op==TK_EXCEPT );
       testcase( p->op==TK_UNION );
       priorOp = SRT_Union;
-      if( dest.eDest==priorOp && ALWAYS(!p->pLimit &&!p->pOffset) ){
+      if( dest.eDest==priorOp ){
         /* We can reuse a temporary table generated by a SELECT to our
         ** right.
         */
-        assert( p->pRightmost!=p );  /* Can only happen for leftward elements
-                                     ** of a 3-way or more compound */
         assert( p->pLimit==0 );      /* Not allowed on leftward elements */
         assert( p->pOffset==0 );     /* Not allowed on leftward elements */
         unionTab = dest.iSDParm;
@@ -97843,7 +103648,7 @@ static int multiSelect(
         addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
         assert( p->addrOpenEphm[0] == -1 );
         p->addrOpenEphm[0] = addr;
-        p->pRightmost->selFlags |= SF_UsesEphemeral;
+        findRightmost(p)->selFlags |= SF_UsesEphemeral;
         assert( p->pEList );
       }
 
@@ -97902,12 +103707,12 @@ static int multiSelect(
         iBreak = sqlite3VdbeMakeLabel(v);
         iCont = sqlite3VdbeMakeLabel(v);
         computeLimitRegisters(pParse, p, iBreak);
-        sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak);
+        sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
         iStart = sqlite3VdbeCurrentAddr(v);
-        selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
+        selectInnerLoop(pParse, p, p->pEList, unionTab,
                         0, 0, &dest, iCont, iBreak);
         sqlite3VdbeResolveLabel(v, iCont);
-        sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart);
+        sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
         sqlite3VdbeResolveLabel(v, iBreak);
         sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
       }
@@ -97932,7 +103737,7 @@ static int multiSelect(
       addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
       assert( p->addrOpenEphm[0] == -1 );
       p->addrOpenEphm[0] = addr;
-      p->pRightmost->selFlags |= SF_UsesEphemeral;
+      findRightmost(p)->selFlags |= SF_UsesEphemeral;
       assert( p->pEList );
 
       /* Code the SELECTs to our left into temporary table "tab1".
@@ -97977,15 +103782,15 @@ static int multiSelect(
       iBreak = sqlite3VdbeMakeLabel(v);
       iCont = sqlite3VdbeMakeLabel(v);
       computeLimitRegisters(pParse, p, iBreak);
-      sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak);
+      sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
       r1 = sqlite3GetTempReg(pParse);
       iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1);
-      sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
+      sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v);
       sqlite3ReleaseTempReg(pParse, r1);
-      selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
+      selectInnerLoop(pParse, p, p->pEList, tab1,
                       0, 0, &dest, iCont, iBreak);
       sqlite3VdbeResolveLabel(v, iCont);
-      sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart);
+      sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v);
       sqlite3VdbeResolveLabel(v, iBreak);
       sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
       sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
@@ -98011,25 +103816,19 @@ static int multiSelect(
     CollSeq **apColl;             /* For looping through pKeyInfo->aColl[] */
     int nCol;                     /* Number of columns in result set */
 
-    assert( p->pRightmost==p );
+    assert( p->pNext==0 );
     nCol = p->pEList->nExpr;
-    pKeyInfo = sqlite3DbMallocZero(db,
-                       sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1));
+    pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
     if( !pKeyInfo ){
       rc = SQLITE_NOMEM;
       goto multi_select_end;
     }
-
-    pKeyInfo->enc = ENC(db);
-    pKeyInfo->nField = (u16)nCol;
-
     for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
       *apColl = multiSelectCollSeq(pParse, p, i);
       if( 0==*apColl ){
         *apColl = db->pDfltColl;
       }
     }
-    pKeyInfo->aSortOrder = (u8*)apColl;
 
     for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
       for(i=0; i<2; i++){
@@ -98041,11 +103840,12 @@ static int multiSelect(
           break;
         }
         sqlite3VdbeChangeP2(v, addr, nCol);
-        sqlite3VdbeChangeP4(v, addr, (char*)pKeyInfo, P4_KEYINFO);
+        sqlite3VdbeChangeP4(v, addr, (char*)sqlite3KeyInfoRef(pKeyInfo),
+                            P4_KEYINFO);
         pLoop->addrOpenEphm[i] = -1;
       }
     }
-    sqlite3DbFree(db, pKeyInfo);
+    sqlite3KeyInfoUnref(pKeyInfo);
   }
 
 multi_select_end:
@@ -98084,7 +103884,6 @@ static int generateOutputSubroutine(
   int regReturn,          /* The return address register */
   int regPrev,            /* Previous result register.  No uniqueness if 0 */
   KeyInfo *pKeyInfo,      /* For comparing with previous entry */
-  int p4type,             /* The p4 type for pKeyInfo */
   int iBreak              /* Jump here if we hit the LIMIT */
 ){
   Vdbe *v = pParse->pVdbe;
@@ -98098,10 +103897,10 @@ static int generateOutputSubroutine(
   */
   if( regPrev ){
     int j1, j2;
-    j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev);
+    j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v);
     j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst,
-                              (char*)pKeyInfo, p4type);
-    sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
+                              (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
+    sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); VdbeCoverage(v);
     sqlite3VdbeJumpHere(v, j1);
     sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1);
     sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
@@ -98110,7 +103909,7 @@ static int generateOutputSubroutine(
 
   /* Suppress the first OFFSET entries if there is an OFFSET clause
   */
-  codeOffset(v, p, iContinue);
+  codeOffset(v, p->iOffset, iContinue);
 
   switch( pDest->eDest ){
     /* Store the result as data using a unique key.
@@ -98202,7 +104001,7 @@ static int generateOutputSubroutine(
   /* Jump to the end of the loop if the LIMIT is reached.
   */
   if( p->iLimit ){
-    sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1);
+    sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
   }
 
   /* Generate the subroutine return
@@ -98310,9 +104109,7 @@ static int multiSelectOrderBy(
   SelectDest destA;     /* Destination for coroutine A */
   SelectDest destB;     /* Destination for coroutine B */
   int regAddrA;         /* Address register for select-A coroutine */
-  int regEofA;          /* Flag to indicate when select-A is complete */
   int regAddrB;         /* Address register for select-B coroutine */
-  int regEofB;          /* Flag to indicate when select-B is complete */
   int addrSelectA;      /* Address of the select-A coroutine */
   int addrSelectB;      /* Address of the select-B coroutine */
   int regOutA;          /* Address register for the output-A subroutine */
@@ -98320,6 +104117,7 @@ static int multiSelectOrderBy(
   int addrOutA;         /* Address of the output-A subroutine */
   int addrOutB = 0;     /* Address of the output-B subroutine */
   int addrEofA;         /* Address of the select-A-exhausted subroutine */
+  int addrEofA_noB;     /* Alternate addrEofA if B is uninitialized */
   int addrEofB;         /* Address of the select-B-exhausted subroutine */
   int addrAltB;         /* Address of the A<B subroutine */
   int addrAeqB;         /* Address of the A==B subroutine */
@@ -98370,8 +104168,8 @@ static int multiSelectOrderBy(
     for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
       struct ExprList_item *pItem;
       for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
-        assert( pItem->iOrderByCol>0 );
-        if( pItem->iOrderByCol==i ) break;
+        assert( pItem->u.x.iOrderByCol>0 );
+        if( pItem->u.x.iOrderByCol==i ) break;
       }
       if( j==nOrderBy ){
         Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
@@ -98379,7 +104177,7 @@ static int multiSelectOrderBy(
         pNew->flags |= EP_IntValue;
         pNew->u.iValue = i;
         pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
-        if( pOrderBy ) pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i;
+        if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i;
       }
     }
   }
@@ -98395,30 +104193,11 @@ static int multiSelectOrderBy(
   if( aPermute ){
     struct ExprList_item *pItem;
     for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
-      assert( pItem->iOrderByCol>0  && pItem->iOrderByCol<=p->pEList->nExpr );
-      aPermute[i] = pItem->iOrderByCol - 1;
-    }
-    pKeyMerge =
-      sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
-    if( pKeyMerge ){
-      pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy];
-      pKeyMerge->nField = (u16)nOrderBy;
-      pKeyMerge->enc = ENC(db);
-      for(i=0; i<nOrderBy; i++){
-        CollSeq *pColl;
-        Expr *pTerm = pOrderBy->a[i].pExpr;
-        if( pTerm->flags & EP_Collate ){
-          pColl = sqlite3ExprCollSeq(pParse, pTerm);
-        }else{
-          pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
-          if( pColl==0 ) pColl = db->pDfltColl;
-          pOrderBy->a[i].pExpr =
-             sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
-        }
-        pKeyMerge->aColl[i] = pColl;
-        pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
-      }
+      assert( pItem->u.x.iOrderByCol>0
+          && pItem->u.x.iOrderByCol<=p->pEList->nExpr );
+      aPermute[i] = pItem->u.x.iOrderByCol - 1;
     }
+    pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
   }else{
     pKeyMerge = 0;
   }
@@ -98440,12 +104219,9 @@ static int multiSelectOrderBy(
     regPrev = pParse->nMem+1;
     pParse->nMem += nExpr+1;
     sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
-    pKeyDup = sqlite3DbMallocZero(db,
-                  sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
+    pKeyDup = sqlite3KeyInfoAlloc(db, nExpr, 1);
     if( pKeyDup ){
-      pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr];
-      pKeyDup->nField = (u16)nExpr;
-      pKeyDup->enc = ENC(db);
+      assert( sqlite3KeyInfoIsWriteable(pKeyDup) );
       for(i=0; i<nExpr; i++){
         pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
         pKeyDup->aSortOrder[i] = 0;
@@ -98456,6 +104232,7 @@ static int multiSelectOrderBy(
   /* Separate the left and the right query from one another
   */
   p->pPrior = 0;
+  pPrior->pNext = 0;
   sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
   if( pPrior->pPrior==0 ){
     sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
@@ -98478,37 +104255,30 @@ static int multiSelectOrderBy(
   p->pOffset = 0;
 
   regAddrA = ++pParse->nMem;
-  regEofA = ++pParse->nMem;
   regAddrB = ++pParse->nMem;
-  regEofB = ++pParse->nMem;
   regOutA = ++pParse->nMem;
   regOutB = ++pParse->nMem;
   sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
   sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
 
-  /* Jump past the various subroutines and coroutines to the main
-  ** merge loop
-  */
-  j1 = sqlite3VdbeAddOp0(v, OP_Goto);
-  addrSelectA = sqlite3VdbeCurrentAddr(v);
-
-
   /* Generate a coroutine to evaluate the SELECT statement to the
   ** left of the compound operator - the "A" select.
   */
-  VdbeNoopComment((v, "Begin coroutine for left SELECT"));
+  addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
+  j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
+  VdbeComment((v, "left SELECT"));
   pPrior->iLimit = regLimitA;
   explainSetInteger(iSub1, pParse->iNextSelectId);
   sqlite3Select(pParse, pPrior, &destA);
-  sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA);
-  sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
-  VdbeNoopComment((v, "End coroutine for left SELECT"));
+  sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA);
+  sqlite3VdbeJumpHere(v, j1);
 
   /* Generate a coroutine to evaluate the SELECT statement on 
   ** the right - the "B" select
   */
-  addrSelectB = sqlite3VdbeCurrentAddr(v);
-  VdbeNoopComment((v, "Begin coroutine for right SELECT"));
+  addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
+  j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
+  VdbeComment((v, "right SELECT"));
   savedLimit = p->iLimit;
   savedOffset = p->iOffset;
   p->iLimit = regLimitB;
@@ -98517,9 +104287,7 @@ static int multiSelectOrderBy(
   sqlite3Select(pParse, p, &destB);
   p->iLimit = savedLimit;
   p->iOffset = savedOffset;
-  sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB);
-  sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
-  VdbeNoopComment((v, "End coroutine for right SELECT"));
+  sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrB);
 
   /* Generate a subroutine that outputs the current row of the A
   ** select as the next output row of the compound select.
@@ -98527,7 +104295,7 @@ static int multiSelectOrderBy(
   VdbeNoopComment((v, "Output routine for A"));
   addrOutA = generateOutputSubroutine(pParse,
                  p, &destA, pDest, regOutA,
-                 regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd);
+                 regPrev, pKeyDup, labelEnd);
   
   /* Generate a subroutine that outputs the current row of the B
   ** select as the next output row of the compound select.
@@ -98536,19 +104304,20 @@ static int multiSelectOrderBy(
     VdbeNoopComment((v, "Output routine for B"));
     addrOutB = generateOutputSubroutine(pParse,
                  p, &destB, pDest, regOutB,
-                 regPrev, pKeyDup, P4_KEYINFO_STATIC, labelEnd);
+                 regPrev, pKeyDup, labelEnd);
   }
+  sqlite3KeyInfoUnref(pKeyDup);
 
   /* Generate a subroutine to run when the results from select A
   ** are exhausted and only data in select B remains.
   */
-  VdbeNoopComment((v, "eof-A subroutine"));
   if( op==TK_EXCEPT || op==TK_INTERSECT ){
-    addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd);
+    addrEofA_noB = addrEofA = labelEnd;
   }else{  
-    addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd);
-    sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
-    sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
+    VdbeNoopComment((v, "eof-A subroutine"));
+    addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
+    addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
+                                     VdbeCoverage(v);
     sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
     p->nSelectRow += pPrior->nSelectRow;
   }
@@ -98561,9 +104330,8 @@ static int multiSelectOrderBy(
     if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
   }else{  
     VdbeNoopComment((v, "eof-B subroutine"));
-    addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
-    sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
-    sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
+    addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
+    sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v);
     sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB);
   }
 
@@ -98571,8 +104339,7 @@ static int multiSelectOrderBy(
   */
   VdbeNoopComment((v, "A-lt-B subroutine"));
   addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
-  sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
-  sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
+  sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
   sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
 
   /* Generate code to handle the case of A==B
@@ -98585,8 +104352,7 @@ static int multiSelectOrderBy(
   }else{
     VdbeNoopComment((v, "A-eq-B subroutine"));
     addrAeqB =
-    sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
-    sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
+    sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
     sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
   }
 
@@ -98597,28 +104363,23 @@ static int multiSelectOrderBy(
   if( op==TK_ALL || op==TK_UNION ){
     sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
   }
-  sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
-  sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB);
+  sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
   sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
 
   /* This code runs once to initialize everything.
   */
   sqlite3VdbeJumpHere(v, j1);
-  sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofA);
-  sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofB);
-  sqlite3VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA);
-  sqlite3VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB);
-  sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
-  sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB);
+  sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v);
+  sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
 
   /* Implement the main merge loop
   */
   sqlite3VdbeResolveLabel(v, labelCmpr);
   sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
   sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
-                         (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
+                         (char*)pKeyMerge, P4_KEYINFO);
   sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
-  sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
+  sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v);
 
   /* Jump to the this point in order to terminate the query.
   */
@@ -98638,6 +104399,7 @@ static int multiSelectOrderBy(
     sqlite3SelectDelete(db, p->pPrior);
   }
   p->pPrior = pPrior;
+  pPrior->pNext = p;
 
   /*** TBD:  Insert subroutine calls to close cursors on incomplete
   **** subqueries ****/
@@ -98843,6 +104605,14 @@ static void substSelect(
 **  (21)  The subquery does not use LIMIT or the outer query is not
 **        DISTINCT.  (See ticket [752e1646fc]).
 **
+**  (22)  The subquery is not a recursive CTE.
+**
+**  (23)  The parent is not a recursive CTE, or the sub-query is not a
+**        compound query. This restriction is because transforming the
+**        parent to a compound query confuses the code that handles
+**        recursive queries in multiSelect().
+**
+**
 ** 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.
@@ -98895,7 +104665,7 @@ static int flattenSubquery(
   ** and (14). */
   if( pSub->pLimit && p->pLimit ) return 0;              /* Restriction (13) */
   if( pSub->pOffset ) return 0;                          /* Restriction (14) */
-  if( p->pRightmost && pSub->pLimit ){
+  if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
     return 0;                                            /* Restriction (15) */
   }
   if( pSubSrc->nSrc==0 ) return 0;                       /* Restriction (7)  */
@@ -98914,6 +104684,8 @@ static int flattenSubquery(
   if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
      return 0;         /* Restriction (21) */
   }
+  if( pSub->selFlags & SF_Recursive ) return 0;          /* Restriction (22)  */
+  if( (p->selFlags & SF_Recursive) && pSub->pPrior ) return 0;       /* (23)  */
 
   /* OBSOLETE COMMENT 1:
   ** Restriction 3:  If the subquery is a join, make sure the subquery is 
@@ -98981,7 +104753,7 @@ static int flattenSubquery(
     if( p->pOrderBy ){
       int ii;
       for(ii=0; ii<p->pOrderBy->nExpr; ii++){
-        if( p->pOrderBy->a[ii].iOrderByCol==0 ) return 0;
+        if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
       }
     }
   }
@@ -99044,14 +104816,14 @@ static int flattenSubquery(
     p->pOrderBy = pOrderBy;
     p->pSrc = pSrc;
     p->op = TK_ALL;
-    p->pRightmost = 0;
     if( pNew==0 ){
-      pNew = pPrior;
+      p->pPrior = pPrior;
     }else{
       pNew->pPrior = pPrior;
-      pNew->pRightmost = 0;
+      if( pPrior ) pPrior->pNext = pNew;
+      pNew->pNext = p;
+      p->pPrior = pNew;
     }
-    p->pPrior = pNew;
     if( db->mallocFailed ) return 1;
   }
 
@@ -99300,7 +105072,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
   if( IsVirtual(pTab) ) return 0;
   if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
   if( NEVER(pAggInfo->nFunc==0) ) return 0;
-  if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0;
+  if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
   if( pExpr->flags&EP_Distinct ) return 0;
 
   return pTab;
@@ -99390,11 +105162,207 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
   pNew->pHaving = 0;
   pNew->pOrderBy = 0;
   p->pPrior = 0;
+  p->pNext = 0;
+  p->selFlags &= ~SF_Compound;
+  assert( pNew->pPrior!=0 );
+  pNew->pPrior->pNext = pNew;
   pNew->pLimit = 0;
   pNew->pOffset = 0;
   return WRC_Continue;
 }
 
+#ifndef SQLITE_OMIT_CTE
+/*
+** Argument pWith (which may be NULL) points to a linked list of nested 
+** WITH contexts, from inner to outermost. If the table identified by 
+** FROM clause element pItem is really a common-table-expression (CTE) 
+** then return a pointer to the CTE definition for that table. Otherwise
+** return NULL.
+**
+** If a non-NULL value is returned, set *ppContext to point to the With
+** object that the returned CTE belongs to.
+*/
+static struct Cte *searchWith(
+  With *pWith,                    /* Current outermost WITH clause */
+  struct SrcList_item *pItem,     /* FROM clause element to resolve */
+  With **ppContext                /* OUT: WITH clause return value belongs to */
+){
+  const char *zName;
+  if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){
+    With *p;
+    for(p=pWith; p; p=p->pOuter){
+      int i;
+      for(i=0; i<p->nCte; i++){
+        if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
+          *ppContext = p;
+          return &p->a[i];
+        }
+      }
+    }
+  }
+  return 0;
+}
+
+/* The code generator maintains a stack of active WITH clauses
+** with the inner-most WITH clause being at the top of the stack.
+**
+** This routine pushes the WITH clause passed as the second argument
+** onto the top of the stack. If argument bFree is true, then this
+** WITH clause will never be popped from the stack. In this case it
+** should be freed along with the Parse object. In other cases, when
+** bFree==0, the With object will be freed along with the SELECT 
+** statement with which it is associated.
+*/
+SQLITE_PRIVATE void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
+  assert( bFree==0 || pParse->pWith==0 );
+  if( pWith ){
+    pWith->pOuter = pParse->pWith;
+    pParse->pWith = pWith;
+    pParse->bFreeWith = bFree;
+  }
+}
+
+/*
+** This function checks if argument pFrom refers to a CTE declared by 
+** a WITH clause on the stack currently maintained by the parser. And,
+** if currently processing a CTE expression, if it is a recursive
+** reference to the current CTE.
+**
+** If pFrom falls into either of the two categories above, pFrom->pTab
+** and other fields are populated accordingly. The caller should check
+** (pFrom->pTab!=0) to determine whether or not a successful match
+** was found.
+**
+** Whether or not a match is found, SQLITE_OK is returned if no error
+** occurs. If an error does occur, an error message is stored in the
+** parser and some error code other than SQLITE_OK returned.
+*/
+static int withExpand(
+  Walker *pWalker, 
+  struct SrcList_item *pFrom
+){
+  Parse *pParse = pWalker->pParse;
+  sqlite3 *db = pParse->db;
+  struct Cte *pCte;               /* Matched CTE (or NULL if no match) */
+  With *pWith;                    /* WITH clause that pCte belongs to */
+
+  assert( pFrom->pTab==0 );
+
+  pCte = searchWith(pParse->pWith, pFrom, &pWith);
+  if( pCte ){
+    Table *pTab;
+    ExprList *pEList;
+    Select *pSel;
+    Select *pLeft;                /* Left-most SELECT statement */
+    int bMayRecursive;            /* True if compound joined by UNION [ALL] */
+    With *pSavedWith;             /* Initial value of pParse->pWith */
+
+    /* If pCte->zErr is non-NULL at this point, then this is an illegal
+    ** recursive reference to CTE pCte. Leave an error in pParse and return
+    ** early. If pCte->zErr is NULL, then this is not a recursive reference.
+    ** In this case, proceed.  */
+    if( pCte->zErr ){
+      sqlite3ErrorMsg(pParse, pCte->zErr, pCte->zName);
+      return SQLITE_ERROR;
+    }
+
+    assert( pFrom->pTab==0 );
+    pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
+    if( pTab==0 ) return WRC_Abort;
+    pTab->nRef = 1;
+    pTab->zName = sqlite3DbStrDup(db, pCte->zName);
+    pTab->iPKey = -1;
+    pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
+    pTab->tabFlags |= TF_Ephemeral;
+    pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
+    if( db->mallocFailed ) return SQLITE_NOMEM;
+    assert( pFrom->pSelect );
+
+    /* Check if this is a recursive CTE. */
+    pSel = pFrom->pSelect;
+    bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
+    if( bMayRecursive ){
+      int i;
+      SrcList *pSrc = pFrom->pSelect->pSrc;
+      for(i=0; i<pSrc->nSrc; i++){
+        struct SrcList_item *pItem = &pSrc->a[i];
+        if( pItem->zDatabase==0 
+         && pItem->zName!=0 
+         && 0==sqlite3StrICmp(pItem->zName, pCte->zName)
+          ){
+          pItem->pTab = pTab;
+          pItem->isRecursive = 1;
+          pTab->nRef++;
+          pSel->selFlags |= SF_Recursive;
+        }
+      }
+    }
+
+    /* Only one recursive reference is permitted. */ 
+    if( pTab->nRef>2 ){
+      sqlite3ErrorMsg(
+          pParse, "multiple references to recursive table: %s", pCte->zName
+      );
+      return SQLITE_ERROR;
+    }
+    assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 ));
+
+    pCte->zErr = "circular reference: %s";
+    pSavedWith = pParse->pWith;
+    pParse->pWith = pWith;
+    sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
+
+    for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
+    pEList = pLeft->pEList;
+    if( pCte->pCols ){
+      if( pEList->nExpr!=pCte->pCols->nExpr ){
+        sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns",
+            pCte->zName, pEList->nExpr, pCte->pCols->nExpr
+        );
+        pParse->pWith = pSavedWith;
+        return SQLITE_ERROR;
+      }
+      pEList = pCte->pCols;
+    }
+
+    selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol);
+    if( bMayRecursive ){
+      if( pSel->selFlags & SF_Recursive ){
+        pCte->zErr = "multiple recursive references: %s";
+      }else{
+        pCte->zErr = "recursive reference in a subquery: %s";
+      }
+      sqlite3WalkSelect(pWalker, pSel);
+    }
+    pCte->zErr = 0;
+    pParse->pWith = pSavedWith;
+  }
+
+  return SQLITE_OK;
+}
+#endif
+
+#ifndef SQLITE_OMIT_CTE
+/*
+** If the SELECT passed as the second argument has an associated WITH 
+** clause, pop it from the stack stored as part of the Parse object.
+**
+** This function is used as the xSelectCallback2() callback by
+** sqlite3SelectExpand() when walking a SELECT tree to resolve table
+** names and other FROM clause elements. 
+*/
+static void selectPopWith(Walker *pWalker, Select *p){
+  Parse *pParse = pWalker->pParse;
+  With *pWith = findRightmost(p)->pWith;
+  if( pWith!=0 ){
+    assert( pParse->pWith==pWith );
+    pParse->pWith = pWith->pOuter;
+  }
+}
+#else
+#define selectPopWith 0
+#endif
+
 /*
 ** This routine is a Walker callback for "expanding" a SELECT statement.
 ** "Expanding" means to do the following:
@@ -99438,6 +105406,7 @@ static int selectExpander(Walker *pWalker, Select *p){
   }
   pTabList = p->pSrc;
   pEList = p->pEList;
+  sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
 
   /* Make sure cursor numbers have been assigned to all entries in
   ** the FROM clause of the SELECT statement.
@@ -99450,12 +105419,21 @@ static int selectExpander(Walker *pWalker, Select *p){
   */
   for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
     Table *pTab;
+    assert( pFrom->isRecursive==0 || pFrom->pTab );
+    if( pFrom->isRecursive ) continue;
     if( pFrom->pTab!=0 ){
       /* This statement has already been prepared.  There is no need
       ** to go further. */
       assert( i==0 );
+#ifndef SQLITE_OMIT_CTE
+      selectPopWith(pWalker, p);
+#endif
       return WRC_Prune;
     }
+#ifndef SQLITE_OMIT_CTE
+    if( withExpand(pWalker, pFrom) ) return WRC_Abort;
+    if( pFrom->pTab ) {} else
+#endif
     if( pFrom->zName==0 ){
 #ifndef SQLITE_OMIT_SUBQUERY
       Select *pSel = pFrom->pSelect;
@@ -99466,11 +105444,11 @@ static int selectExpander(Walker *pWalker, Select *p){
       pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
       if( pTab==0 ) return WRC_Abort;
       pTab->nRef = 1;
-      pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
+      pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
       while( pSel->pPrior ){ pSel = pSel->pPrior; }
       selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
       pTab->iPKey = -1;
-      pTab->nRowEst = 1000000;
+      pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
       pTab->tabFlags |= TF_Ephemeral;
 #endif
     }else{
@@ -99711,11 +105689,14 @@ static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
 static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
   Walker w;
   memset(&w, 0, sizeof(w));
-  w.xSelectCallback = convertCompoundSelectToSubquery;
   w.xExprCallback = exprWalkNoop;
   w.pParse = pParse;
-  sqlite3WalkSelect(&w, pSelect);
+  if( pParse->hasCompound ){
+    w.xSelectCallback = convertCompoundSelectToSubquery;
+    sqlite3WalkSelect(&w, pSelect);
+  }
   w.xSelectCallback = selectExpander;
+  w.xSelectCallback2 = selectPopWith;
   sqlite3WalkSelect(&w, pSelect);
 }
 
@@ -99734,7 +105715,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
 ** at that point because identifiers had not yet been resolved.  This
 ** routine is called after identifier resolution.
 */
-static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
+static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
   Parse *pParse;
   int i;
   SrcList *pTabList;
@@ -99750,13 +105731,13 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
       if( ALWAYS(pTab!=0) && (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);
+        if( pSel ){
+          while( pSel->pPrior ) pSel = pSel->pPrior;
+          selectAddColumnTypeAndCollation(pParse, pTab, pSel);
+        }
       }
     }
   }
-  return WRC_Continue;
 }
 #endif
 
@@ -99772,10 +105753,9 @@ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
 #ifndef SQLITE_OMIT_SUBQUERY
   Walker w;
   memset(&w, 0, sizeof(w));
-  w.xSelectCallback = selectAddSubqueryTypeInfo;
+  w.xSelectCallback2 = selectAddSubqueryTypeInfo;
   w.xExprCallback = exprWalkNoop;
   w.pParse = pParse;
-  w.bSelectDepthFirst = 1;
   sqlite3WalkSelect(&w, pSelect);
 #endif
 }
@@ -99822,14 +105802,23 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
   Vdbe *v = pParse->pVdbe;
   int i;
   struct AggInfo_func *pFunc;
-  if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){
-    return;
-  }
+  int nReg = pAggInfo->nFunc + pAggInfo->nColumn;
+  if( nReg==0 ) return;
+#ifdef SQLITE_DEBUG
+  /* Verify that all AggInfo registers are within the range specified by
+  ** AggInfo.mnReg..AggInfo.mxReg */
+  assert( nReg==pAggInfo->mxReg-pAggInfo->mnReg+1 );
   for(i=0; i<pAggInfo->nColumn; i++){
-    sqlite3VdbeAddOp2(v, OP_Null, 0, pAggInfo->aCol[i].iMem);
+    assert( pAggInfo->aCol[i].iMem>=pAggInfo->mnReg
+         && pAggInfo->aCol[i].iMem<=pAggInfo->mxReg );
   }
+  for(i=0; i<pAggInfo->nFunc; i++){
+    assert( pAggInfo->aFunc[i].iMem>=pAggInfo->mnReg
+         && pAggInfo->aFunc[i].iMem<=pAggInfo->mxReg );
+  }
+#endif
+  sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg);
   for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
-    sqlite3VdbeAddOp2(v, OP_Null, 0, pFunc->iMem);
     if( pFunc->iDistinct>=0 ){
       Expr *pE = pFunc->pExpr;
       assert( !ExprHasProperty(pE, EP_xIsSelect) );
@@ -99838,9 +105827,9 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
            "argument");
         pFunc->iDistinct = -1;
       }else{
-        KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList);
+        KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0, 0);
         sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
-                          (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+                          (char*)pKeyInfo, P4_KEYINFO);
       }
     }
   }
@@ -99875,7 +105864,6 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
   struct AggInfo_col *pC;
 
   pAggInfo->directMode = 1;
-  sqlite3ExprCacheClear(pParse);
   for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
     int nArg;
     int addrNext = 0;
@@ -99885,7 +105873,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
     if( pList ){
       nArg = pList->nExpr;
       regAgg = sqlite3GetTempRange(pParse, nArg);
-      sqlite3ExprCodeExprList(pParse, pList, regAgg, 1);
+      sqlite3ExprCodeExprList(pParse, pList, regAgg, SQLITE_ECEL_DUP);
     }else{
       nArg = 0;
       regAgg = 0;
@@ -99895,7 +105883,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
       assert( nArg==1 );
       codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
     }
-    if( pF->pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+    if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
       CollSeq *pColl = 0;
       struct ExprList_item *pItem;
       int j;
@@ -99931,7 +105919,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
   ** values to an OP_Copy.
   */
   if( regHit ){
-    addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit);
+    addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
   }
   sqlite3ExprCacheClear(pParse);
   for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
@@ -99955,11 +105943,11 @@ static void explainSimpleCount(
   Index *pIdx                     /* Index used to optimize scan, or NULL */
 ){
   if( pParse->explain==2 ){
-    char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s %s%s(~%d rows)",
-        pTab->zName, 
-        pIdx ? "USING COVERING INDEX " : "",
-        pIdx ? pIdx->zName : "",
-        pTab->nRowEst
+    int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
+    char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
+        pTab->zName,
+        bCover ? " USING COVERING INDEX " : "",
+        bCover ? pIdx->zName : ""
     );
     sqlite3VdbeAddOp4(
         pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
@@ -99973,50 +105961,8 @@ static void explainSimpleCount(
 /*
 ** 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
-** as follows:
-**
-**     pDest->eDest    Result
-**     ------------    -------------------------------------------
-**     SRT_Output      Generate a row of output (using the OP_ResultRow
-**                     opcode) for each row in the result set.
-**
-**     SRT_Mem         Only valid if the result is a single column.
-**                     Store the first column of the first result row
-**                     in register pDest->iSDParm 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->iSDParm. 
-**                     Apply the affinity pDest->affSdst before storing
-**                     results.  Used to implement "IN (SELECT ...)".
-**
-**     SRT_Union       Store results as a key in a temporary table 
-**                     identified by pDest->iSDParm.
-**
-**     SRT_Except      Remove results from the temporary table pDest->iSDParm.
-**
-**     SRT_Table       Store results in temporary table pDest->iSDParm.
-**                     This is like SRT_EphemTab except that the table
-**                     is assumed to already be open.
-**
-**     SRT_EphemTab    Create an temporary table pDest->iSDParm and store
-**                     the result there. The cursor is left open after
-**                     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->iSDParm.
-**
-**     SRT_Exists      Store a 1 in memory cell pDest->iSDParm if the result
-**                     set is not empty.
-**
-**     SRT_Discard     Throw the results away.  This is used by SELECT
-**                     statements within triggers whose only purpose is
-**                     the side-effects of functions.
+** The results are returned according to the SelectDest structure.
+** See comments in sqliteInt.h for further information.
 **
 ** This routine returns the number of errors.  If any errors are
 ** encountered, then an appropriate error message is left in
@@ -100037,12 +105983,11 @@ SQLITE_PRIVATE int sqlite3Select(
   ExprList *pEList;      /* List of columns to extract. */
   SrcList *pTabList;     /* List of tables to select from */
   Expr *pWhere;          /* The WHERE clause.  May be NULL */
-  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
   ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
   Expr *pHaving;         /* The HAVING clause.  May be NULL */
   int rc = 1;            /* Value to return from this function */
-  int addrSortIndex;     /* Address of an OP_OpenEphemeral instruction */
   DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
+  SortCtx sSort;         /* Info on how to code the ORDER BY clause */
   AggInfo sAggInfo;      /* Information used by aggregate queries */
   int iEnd;              /* Address of the end of the query */
   sqlite3 *db;           /* The database connection */
@@ -100059,9 +106004,15 @@ SQLITE_PRIVATE int sqlite3Select(
   if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
   memset(&sAggInfo, 0, sizeof(sAggInfo));
 
+  assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
+  assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
+  assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
+  assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
   if( IgnorableOrderby(pDest) ){
     assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || 
-           pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
+           pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
+           pDest->eDest==SRT_Queue  || pDest->eDest==SRT_DistFifo ||
+           pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo);
     /* If ORDER BY makes no difference in the output then neither does
     ** DISTINCT so it can be removed too. */
     sqlite3ExprListDelete(db, p->pOrderBy);
@@ -100069,7 +106020,8 @@ SQLITE_PRIVATE int sqlite3Select(
     p->selFlags &= ~SF_Distinct;
   }
   sqlite3SelectPrep(pParse, p, 0);
-  pOrderBy = p->pOrderBy;
+  memset(&sSort, 0, sizeof(sSort));
+  sSort.pOrderBy = p->pOrderBy;
   pTabList = p->pSrc;
   pEList = p->pEList;
   if( pParse->nErr || db->mallocFailed ){
@@ -100117,7 +106069,7 @@ SQLITE_PRIVATE int sqlite3Select(
     }
 
     /* Increment Parse.nHeight by the height of the largest expression
-    ** tree refered to by this, the parent select. The child select
+    ** tree referred to by this, the parent select. The child select
     ** may contain expression trees of at most
     ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
     ** more conservative than necessary, but much easier than enforcing
@@ -100133,42 +106085,24 @@ SQLITE_PRIVATE int sqlite3Select(
         p->selFlags |= SF_Aggregate;
       }
       i = -1;
-    }else if( pTabList->nSrc==1 && (p->selFlags & SF_Materialize)==0
-      && OptimizationEnabled(db, SQLITE_SubqCoroutine)
+    }else if( pTabList->nSrc==1
+           && OptimizationEnabled(db, SQLITE_SubqCoroutine)
     ){
       /* Implement a co-routine that will return a single row of the result
       ** set on each invocation.
       */
-      int addrTop;
-      int addrEof;
+      int addrTop = sqlite3VdbeCurrentAddr(v)+1;
       pItem->regReturn = ++pParse->nMem;
-      addrEof = ++pParse->nMem;
-      /* Before coding the OP_Goto to jump to the start of the main routine,
-      ** ensure that the jump to the verify-schema routine has already
-      ** been coded. Otherwise, the verify-schema would likely be coded as 
-      ** part of the co-routine. If the main routine then accessed the 
-      ** database before invoking the co-routine for the first time (for 
-      ** example to initialize a LIMIT register from a sub-select), it would 
-      ** be doing so without having verified the schema version and obtained 
-      ** the required db locks. See ticket d6b36be38.  */
-      sqlite3CodeVerifySchema(pParse, -1);
-      sqlite3VdbeAddOp0(v, OP_Goto);
-      addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor);
-      sqlite3VdbeChangeP5(v, 1);
-      VdbeComment((v, "coroutine for %s", pItem->pTab->zName));
+      sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
+      VdbeComment((v, "%s", pItem->pTab->zName));
       pItem->addrFillSub = addrTop;
-      sqlite3VdbeAddOp2(v, OP_Integer, 0, addrEof);
-      sqlite3VdbeChangeP5(v, 1);
       sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
       explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
       sqlite3Select(pParse, pSub, &dest);
-      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
+      pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
       pItem->viaCoroutine = 1;
-      sqlite3VdbeChangeP2(v, addrTop, dest.iSdst);
-      sqlite3VdbeChangeP3(v, addrTop, dest.nSdst);
-      sqlite3VdbeAddOp2(v, OP_Integer, 1, addrEof);
-      sqlite3VdbeAddOp1(v, OP_Yield, pItem->regReturn);
-      VdbeComment((v, "end %s", pItem->pTab->zName));
+      pItem->regResult = dest.iSdst;
+      sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
       sqlite3VdbeJumpHere(v, addrTop-1);
       sqlite3ClearTempRegCache(pParse);
     }else{
@@ -100184,17 +106118,19 @@ SQLITE_PRIVATE int sqlite3Select(
       pItem->regReturn = ++pParse->nMem;
       topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
       pItem->addrFillSub = topAddr+1;
-      VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
       if( pItem->isCorrelated==0 ){
         /* If the subquery is not correlated and if we are not inside of
         ** a trigger, then we only need to compute the value of the subquery
         ** once. */
-        onceAddr = sqlite3CodeOnce(pParse);
+        onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
+        VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
+      }else{
+        VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
       }
       sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
       explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
       sqlite3Select(pParse, pSub, &dest);
-      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
+      pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
       if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
       retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
       VdbeComment((v, "end %s", pItem->pTab->zName));
@@ -100207,7 +106143,7 @@ SQLITE_PRIVATE int sqlite3Select(
     pParse->nHeight -= sqlite3SelectExprHeight(p);
     pTabList = p->pSrc;
     if( !IgnorableOrderby(pDest) ){
-      pOrderBy = p->pOrderBy;
+      sSort.pOrderBy = p->pOrderBy;
     }
   }
   pEList = p->pEList;
@@ -100221,39 +106157,12 @@ SQLITE_PRIVATE int sqlite3Select(
   /* If there is are a sequence of queries, do the earlier ones first.
   */
   if( p->pPrior ){
-    if( p->pRightmost==0 ){
-      Select *pLoop, *pRight = 0;
-      int cnt = 0;
-      int mxSelect;
-      for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){
-        pLoop->pRightmost = p;
-        pLoop->pNext = pRight;
-        pRight = pLoop;
-      }
-      mxSelect = db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
-      if( mxSelect && cnt>mxSelect ){
-        sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
-        goto select_end;
-      }
-    }
     rc = multiSelect(pParse, p, pDest);
     explainSetInteger(pParse->iSelectId, iRestoreSelectId);
     return rc;
   }
 #endif
 
-  /* If there is both a GROUP BY and an ORDER BY clause and they are
-  ** identical, then disable the ORDER BY clause since the GROUP BY
-  ** will cause elements to come out in the correct order.  This is
-  ** an optimization - the correct answer should result regardless.
-  ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
-  ** to disable this optimization for testing purposes.
-  */
-  if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
-         && OptimizationEnabled(db, SQLITE_GroupByOrder) ){
-    pOrderBy = 0;
-  }
-
   /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and 
   ** if the select-list is the same as the ORDER BY list, then this query
   ** can be rewritten as a GROUP BY. In other words, this:
@@ -100270,12 +106179,12 @@ SQLITE_PRIVATE int sqlite3Select(
   ** BY and DISTINCT, and an index or separate temp-table for the other.
   */
   if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct 
-   && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
+   && sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0
   ){
     p->selFlags &= ~SF_Distinct;
     p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
     pGroupBy = p->pGroupBy;
-    pOrderBy = 0;
+    sSort.pOrderBy = 0;
     /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
     ** the sDistinct.isTnct is still set.  Hence, isTnct represents the
     ** original setting of the SF_Distinct flag, not the current setting */
@@ -100289,16 +106198,16 @@ SQLITE_PRIVATE int sqlite3Select(
   ** we figure out that the sorting index is not needed.  The addrSortIndex
   ** variable is used to facilitate that change.
   */
-  if( pOrderBy ){
+  if( sSort.pOrderBy ){
     KeyInfo *pKeyInfo;
-    pKeyInfo = keyInfoFromExprList(pParse, pOrderBy);
-    pOrderBy->iECursor = pParse->nTab++;
-    p->addrOpenEphm[2] = addrSortIndex =
+    pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, 0);
+    sSort.iECursor = pParse->nTab++;
+    sSort.addrSortIndex =
       sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
-                           pOrderBy->iECursor, pOrderBy->nExpr+2, 0,
-                           (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+                           sSort.iECursor, sSort.pOrderBy->nExpr+2, 0,
+                           (char*)pKeyInfo, P4_KEYINFO);
   }else{
-    addrSortIndex = -1;
+    sSort.addrSortIndex = -1;
   }
 
   /* If the output is destined for a temporary table, open that table.
@@ -100310,11 +106219,11 @@ SQLITE_PRIVATE int sqlite3Select(
   /* Set the limiter.
   */
   iEnd = sqlite3VdbeMakeLabel(v);
-  p->nSelectRow = (double)LARGEST_INT64;
+  p->nSelectRow = LARGEST_INT64;
   computeLimitRegisters(pParse, p, iEnd);
-  if( p->iLimit==0 && addrSortIndex>=0 ){
-    sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
-    p->selFlags |= SF_UseSorter;
+  if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
+    sqlite3VdbeGetOp(v, sSort.addrSortIndex)->opcode = OP_SorterOpen;
+    sSort.sortFlags |= SORTFLAG_UseSorter;
   }
 
   /* Open a virtual index to use for the distinct set.
@@ -100323,8 +106232,8 @@ SQLITE_PRIVATE int sqlite3Select(
     sDistinct.tabTnct = pParse->nTab++;
     sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
                                 sDistinct.tabTnct, 0, 0,
-                                (char*)keyInfoFromExprList(pParse, p->pEList),
-                                P4_KEYINFO_HANDOFF);
+                                (char*)keyInfoFromExprList(pParse, p->pEList,0,0),
+                                P4_KEYINFO);
     sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
     sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
   }else{
@@ -100333,27 +106242,37 @@ SQLITE_PRIVATE int sqlite3Select(
 
   if( !isAgg && pGroupBy==0 ){
     /* No aggregate functions and no GROUP BY clause */
-    ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0);
+    u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
 
     /* Begin the database scan. */
-    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0);
+    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
+                               p->pEList, wctrlFlags, 0);
     if( pWInfo==0 ) goto select_end;
-    if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
-    if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct;
-    if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0;
+    if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
+      p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
+    }
+    if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
+      sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
+    }
+    if( sSort.pOrderBy ){
+      sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo);
+      if( sSort.nOBSat==sSort.pOrderBy->nExpr ){
+        sSort.pOrderBy = 0;
+      }
+    }
 
     /* If sorting index that was created by a prior OP_OpenEphemeral 
     ** instruction ended up not being needed, then change the OP_OpenEphemeral
     ** into an OP_Noop.
     */
-    if( addrSortIndex>=0 && pOrderBy==0 ){
-      sqlite3VdbeChangeToNoop(v, addrSortIndex);
-      p->addrOpenEphm[2] = -1;
+    if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){
+      sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
     }
 
     /* Use the standard inner loop. */
-    selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, &sDistinct, pDest,
-                    pWInfo->iContinue, pWInfo->iBreak);
+    selectInnerLoop(pParse, p, pEList, -1, &sSort, &sDistinct, pDest,
+                    sqlite3WhereContinueLabel(pWInfo),
+                    sqlite3WhereBreakLabel(pWInfo));
 
     /* End the database scan loop.
     */
@@ -100372,6 +106291,7 @@ SQLITE_PRIVATE int sqlite3Select(
     int addrEnd;        /* End of processing for this SELECT */
     int sortPTab = 0;   /* Pseudotable used to decode sorting results */
     int sortOut = 0;    /* Output register from the sorter */
+    int orderByGrp = 0; /* True if the GROUP BY and ORDER BY are the same */
 
     /* Remove any and all aliases between the result set and the
     ** GROUP BY clause.
@@ -100381,16 +106301,28 @@ SQLITE_PRIVATE int sqlite3Select(
       struct ExprList_item *pItem;  /* For looping over expression in a list */
 
       for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){
-        pItem->iAlias = 0;
+        pItem->u.x.iAlias = 0;
       }
       for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
-        pItem->iAlias = 0;
+        pItem->u.x.iAlias = 0;
       }
-      if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100;
+      if( p->nSelectRow>100 ) p->nSelectRow = 100;
     }else{
-      p->nSelectRow = (double)1;
+      p->nSelectRow = 1;
     }
 
+
+    /* If there is both a GROUP BY and an ORDER BY clause and they are
+    ** identical, then it may be possible to disable the ORDER BY clause 
+    ** on the grounds that the GROUP BY will cause elements to come out 
+    ** in the correct order. It also may not - the GROUP BY may use a
+    ** database index that causes rows to be grouped together as required
+    ** but not actually sorted. Either way, record the fact that the
+    ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
+    ** variable.  */
+    if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
+      orderByGrp = 1;
+    }
  
     /* Create a label to jump to when we want to abort the query */
     addrEnd = sqlite3VdbeMakeLabel(v);
@@ -100403,10 +106335,11 @@ SQLITE_PRIVATE int sqlite3Select(
     sNC.pParse = pParse;
     sNC.pSrcList = pTabList;
     sNC.pAggInfo = &sAggInfo;
+    sAggInfo.mnReg = pParse->nMem+1;
     sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0;
     sAggInfo.pGroupBy = pGroupBy;
     sqlite3ExprAnalyzeAggList(&sNC, pEList);
-    sqlite3ExprAnalyzeAggList(&sNC, pOrderBy);
+    sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
     if( pHaving ){
       sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
     }
@@ -100417,6 +106350,7 @@ SQLITE_PRIVATE int sqlite3Select(
       sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
       sNC.ncFlags &= ~NC_InAggFunc;
     }
+    sAggInfo.mxReg = pParse->nMem;
     if( db->mallocFailed ) goto select_end;
 
     /* Processing for aggregates with GROUP BY is very different and
@@ -100439,10 +106373,10 @@ SQLITE_PRIVATE int sqlite3Select(
       ** will be converted into a Noop.  
       */
       sAggInfo.sortingIdx = pParse->nTab++;
-      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
+      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, 0);
       addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, 
           sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 
-          0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+          0, (char*)pKeyInfo, P4_KEYINFO);
 
       /* Initialize memory locations used by GROUP BY aggregate processing
       */
@@ -100468,9 +106402,11 @@ SQLITE_PRIVATE int sqlite3Select(
       ** in the right order to begin with.
       */
       sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
-      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0);
+      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
+          WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
+      );
       if( pWInfo==0 ) goto select_end;
-      if( pWInfo->nOBSat==pGroupBy->nExpr ){
+      if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
         /* The optimizer is able to deliver rows in group by order so
         ** we do not have to sort.  The OP_OpenEphemeral table will be
         ** cancelled later because we still need to use the pKeyInfo
@@ -100530,9 +106466,24 @@ SQLITE_PRIVATE int sqlite3Select(
         sortOut = sqlite3GetTempReg(pParse);
         sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol);
         sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
-        VdbeComment((v, "GROUP BY sort"));
+        VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
         sAggInfo.useSortingIdx = 1;
         sqlite3ExprCacheClear(pParse);
+
+      }
+
+      /* If the index or temporary table used by the GROUP BY sort
+      ** will naturally deliver rows in the order required by the ORDER BY
+      ** clause, cancel the ephemeral table open coded earlier.
+      **
+      ** This is an optimization - the correct answer should result regardless.
+      ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to 
+      ** disable this optimization for testing purposes.  */
+      if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder) 
+       && (groupBySort || sqlite3WhereIsSorted(pWInfo))
+      ){
+        sSort.pOrderBy = 0;
+        sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
       }
 
       /* Evaluate the current GROUP BY terms and store in b0, b1, b2...
@@ -100555,9 +106506,9 @@ SQLITE_PRIVATE int sqlite3Select(
         }
       }
       sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
-                          (char*)pKeyInfo, P4_KEYINFO);
+                          (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
       j1 = sqlite3VdbeCurrentAddr(v);
-      sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1);
+      sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); VdbeCoverage(v);
 
       /* Generate code that runs whenever the GROUP BY changes.
       ** Changes in the GROUP BY are detected by the previous code
@@ -100571,7 +106522,7 @@ SQLITE_PRIVATE int sqlite3Select(
       sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
       sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
       VdbeComment((v, "output one row"));
-      sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd);
+      sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
       VdbeComment((v, "check abort flag"));
       sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
       VdbeComment((v, "reset accumulator"));
@@ -100588,6 +106539,7 @@ SQLITE_PRIVATE int sqlite3Select(
       */
       if( groupBySort ){
         sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
+        VdbeCoverage(v);
       }else{
         sqlite3WhereEnd(pWInfo);
         sqlite3VdbeChangeToNoop(v, addrSortingIdx);
@@ -100615,12 +106567,12 @@ SQLITE_PRIVATE int sqlite3Select(
       sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
       sqlite3VdbeResolveLabel(v, addrOutputRow);
       addrOutputRow = sqlite3VdbeCurrentAddr(v);
-      sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
+      sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v);
       VdbeComment((v, "Groupby result generator entry point"));
       sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
       finalizeAggFunctions(pParse, &sAggInfo);
       sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
-      selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
+      selectInnerLoop(pParse, p, p->pEList, -1, &sSort,
                       &sDistinct, pDest,
                       addrOutputRow+1, addrSetAbort);
       sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
@@ -100661,33 +106613,34 @@ SQLITE_PRIVATE int sqlite3Select(
         sqlite3CodeVerifySchema(pParse, iDb);
         sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
 
-        /* Search for the index that has the least amount of columns. If
-        ** there is such an index, and it has less columns than the table
-        ** does, then we can assume that it consumes less space on disk and
-        ** will therefore be cheaper to scan to determine the query result.
-        ** In this case set iRoot to the root page number of the index b-tree
-        ** and pKeyInfo to the KeyInfo structure required to navigate the
-        ** index.
+        /* Search for the index that has the lowest scan cost.
         **
         ** (2011-04-15) Do not do a full scan of an unordered index.
         **
+        ** (2013-10-03) Do not count the entries in a partial index.
+        **
         ** In practice the KeyInfo structure will not be used. It is only 
         ** passed to keep OP_OpenRead happy.
         */
+        if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab);
         for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
-          if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
+          if( pIdx->bUnordered==0
+           && pIdx->szIdxRow<pTab->szTabRow
+           && pIdx->pPartIdxWhere==0
+           && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
+          ){
             pBest = pIdx;
           }
         }
-        if( pBest && pBest->nColumn<pTab->nCol ){
+        if( pBest ){
           iRoot = pBest->tnum;
-          pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
+          pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest);
         }
 
         /* Open a read-only cursor, execute the OP_Count, close the cursor. */
-        sqlite3VdbeAddOp3(v, OP_OpenRead, iCsr, iRoot, iDb);
+        sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1);
         if( pKeyInfo ){
-          sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF);
+          sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
         }
         sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
         sqlite3VdbeAddOp1(v, OP_Close, iCsr);
@@ -100751,8 +106704,8 @@ SQLITE_PRIVATE int sqlite3Select(
         }
         updateAccumulator(pParse, &sAggInfo);
         assert( pMinMax==0 || pMinMax->nExpr==1 );
-        if( pWInfo->nOBSat>0 ){
-          sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
+        if( sqlite3WhereIsOrdered(pWInfo)>0 ){
+          sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3WhereBreakLabel(pWInfo));
           VdbeComment((v, "%s() by index",
                 (flag==WHERE_ORDERBY_MIN?"min":"max")));
         }
@@ -100760,9 +106713,9 @@ SQLITE_PRIVATE int sqlite3Select(
         finalizeAggFunctions(pParse, &sAggInfo);
       }
 
-      pOrderBy = 0;
+      sSort.pOrderBy = 0;
       sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
-      selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, 0, 
+      selectInnerLoop(pParse, p, p->pEList, -1, 0, 0, 
                       pDest, addrEnd, addrEnd);
       sqlite3ExprListDelete(db, pDel);
     }
@@ -100777,9 +106730,9 @@ SQLITE_PRIVATE int sqlite3Select(
   /* If there is an ORDER BY clause, then we need to sort the results
   ** and send them to the callback one by one.
   */
-  if( pOrderBy ){
-    explainTempTable(pParse, "ORDER BY");
-    generateSortTail(pParse, p, v, pEList->nExpr, pDest);
+  if( sSort.pOrderBy ){
+    explainTempTable(pParse, sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
+    generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest);
   }
 
   /* Jump here to skip this query
@@ -100887,10 +106840,6 @@ SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
     sqlite3ExplainPrintf(pVdbe, "(null-select)");
     return;
   }
-  while( p->pPrior ){
-    p->pPrior->pNext = p;
-    p = p->pPrior;
-  }
   sqlite3ExplainPush(pVdbe);
   while( p ){
     explainOneSelect(pVdbe, p);
@@ -101257,8 +107206,8 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
   /* Ensure the table name matches database name and that the table exists */
   if( db->mallocFailed ) goto trigger_cleanup;
   assert( pTableName->nSrc==1 );
-  if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && 
-      sqlite3FixSrcList(&sFix, pTableName) ){
+  sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName);
+  if( sqlite3FixSrcList(&sFix, pTableName) ){
     goto trigger_cleanup;
   }
   pTab = sqlite3SrcListLookup(pParse, pTableName);
@@ -101400,8 +107349,10 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
   }
   nameToken.z = pTrig->zName;
   nameToken.n = sqlite3Strlen30(nameToken.z);
-  if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken) 
-          && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
+  sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
+  if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) 
+   || sqlite3FixExpr(&sFix, pTrig->pWhen) 
+  ){
     goto triggerfinish_cleanup;
   }
 
@@ -101504,25 +107455,21 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(
   sqlite3 *db,        /* The database connection */
   Token *pTableName,  /* Name of the table into which we insert */
   IdList *pColumn,    /* List of columns in pTableName to insert into */
-  ExprList *pEList,   /* The VALUE clause: a list of values to be inserted */
   Select *pSelect,    /* A SELECT statement that supplies values */
   u8 orconf           /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
 ){
   TriggerStep *pTriggerStep;
 
-  assert(pEList == 0 || pSelect == 0);
-  assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
+  assert(pSelect != 0 || db->mallocFailed);
 
   pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName);
   if( pTriggerStep ){
     pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
     pTriggerStep->pIdList = pColumn;
-    pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
     pTriggerStep->orconf = orconf;
   }else{
     sqlite3IdListDelete(db, pColumn);
   }
-  sqlite3ExprListDelete(db, pEList);
   sqlite3SelectDelete(db, pSelect);
 
   return pTriggerStep;
@@ -101677,6 +107624,7 @@ SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
   assert( pTable!=0 );
   if( (v = sqlite3GetVdbe(pParse))!=0 ){
     int base;
+    static const int iLn = VDBE_OFFSET_LINENO(2);
     static const VdbeOpList dropTrigger[] = {
       { OP_Rewind,     0, ADDR(9),  0},
       { OP_String8,    0, 1,        0}, /* 1 */
@@ -101691,7 +107639,7 @@ SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
 
     sqlite3BeginWriteOperation(pParse, 0, iDb);
     sqlite3OpenMasterTable(pParse, iDb);
-    base = sqlite3VdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger);
+    base = sqlite3VdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger, iLn);
     sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT);
     sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC);
     sqlite3ChangeCookie(pParse, iDb);
@@ -101837,15 +107785,7 @@ static int codeTriggerProgram(
     **   INSERT OR IGNORE INTO t1 ... ;  -- insert into t2 uses IGNORE policy
     */
     pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
-
-    /* Clear the cookieGoto flag. When coding triggers, the cookieGoto 
-    ** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
-    ** that it is not safe to refactor constants (this happens after the
-    ** start of the first loop in the SQL statement is coded - at that 
-    ** point code may be conditionally executed, so it is no longer safe to 
-    ** initialize constant register values).  */
-    assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
-    pParse->cookieGoto = 0;
+    assert( pParse->okConstFactor==0 );
 
     switch( pStep->op ){
       case TK_UPDATE: {
@@ -101860,7 +107800,6 @@ static int codeTriggerProgram(
       case TK_INSERT: {
         sqlite3Insert(pParse, 
           targetSrcList(pParse, pStep),
-          sqlite3ExprListDup(db, pStep->pExprList, 0), 
           sqlite3SelectDup(db, pStep->pSelect, 0), 
           sqlite3IdListDup(db, pStep->pIdList), 
           pParse->eOrconf
@@ -101891,7 +107830,7 @@ static int codeTriggerProgram(
   return 0;
 }
 
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
 /*
 ** This function is used to add VdbeComment() annotations to a VDBE
 ** program. It is not used in production code, only for debugging.
@@ -102031,6 +107970,7 @@ static TriggerPrg *codeRowTrigger(
 
   assert( !pSubParse->pAinc       && !pSubParse->pZombieTab );
   assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
+  sqlite3ParserReset(pSubParse);
   sqlite3StackFree(db, pSubParse);
 
   return pPrg;
@@ -102111,7 +108051,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(
 /*
 ** This is called to code the required FOR EACH ROW triggers for an operation
 ** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE)
-** is given by the op paramater. The tr_tm parameter determines whether the
+** is given by the op parameter. The tr_tm parameter determines whether the
 ** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then
 ** parameter pChanges is passed the list of columns being modified.
 **
@@ -102305,7 +108245,7 @@ static void updateVirtualTable(
 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
   assert( pTab!=0 );
   if( !pTab->pSelect ){
-    sqlite3_value *pValue;
+    sqlite3_value *pValue = 0;
     u8 enc = ENC(sqlite3VdbeDb(v));
     Column *pCol = &pTab->aCol[i];
     VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
@@ -102316,7 +108256,7 @@ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
       sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM);
     }
 #ifndef SQLITE_OMIT_FLOATING_POINT
-    if( iReg>=0 && pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
+    if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
       sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
     }
 #endif
@@ -102339,25 +108279,32 @@ SQLITE_PRIVATE void sqlite3Update(
 ){
   int i, j;              /* Loop counters */
   Table *pTab;           /* The table to be updated */
-  int addr = 0;          /* VDBE instruction address of the start of the loop */
+  int addrTop = 0;       /* VDBE instruction address of the start of the loop */
   WhereInfo *pWInfo;     /* Information about the WHERE clause */
   Vdbe *v;               /* The virtual database engine */
   Index *pIdx;           /* For looping over indices */
+  Index *pPk;            /* The PRIMARY KEY index for WITHOUT ROWID tables */
   int nIdx;              /* Number of indices that need updating */
-  int iCur;              /* VDBE Cursor number of pTab */
+  int iBaseCur;          /* Base cursor number */
+  int iDataCur;          /* Cursor for the canonical data btree */
+  int iIdxCur;           /* Cursor for the first index */
   sqlite3 *db;           /* The database structure */
   int *aRegIdx = 0;      /* One register assigned to each index to be updated */
   int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
                          ** an expression for the i-th column of the table.
                          ** aXRef[i]==-1 if the i-th column is not changed. */
-  int chngRowid;         /* True if the record number is being changed */
+  u8 *aToOpen;           /* 1 for tables and indices to be opened */
+  u8 chngPk;             /* PRIMARY KEY changed in a WITHOUT ROWID table */
+  u8 chngRowid;          /* Rowid changed in a normal table */
+  u8 chngKey;            /* Either chngPk or chngRowid */
   Expr *pRowidExpr = 0;  /* Expression defining the new record number */
-  int openAll = 0;       /* True if all indices need to be opened */
   AuthContext sContext;  /* The authorization context */
   NameContext sNC;       /* The name-context to resolve expressions in */
   int iDb;               /* Database containing the table being updated */
   int okOnePass;         /* True for one-pass algorithm without the FIFO */
   int hasFK;             /* True if foreign key processing is required */
+  int labelBreak;        /* Jump here to break out of UPDATE loop */
+  int labelContinue;     /* Jump here to continue next step of UPDATE loop */
 
 #ifndef SQLITE_OMIT_TRIGGER
   int isView;            /* True when updating a view (INSTEAD OF trigger) */
@@ -102365,6 +108312,9 @@ SQLITE_PRIVATE void sqlite3Update(
   int tmask;             /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
 #endif
   int newmask;           /* Mask of NEW.* columns accessed by BEFORE triggers */
+  int iEph = 0;          /* Ephemeral table holding all primary key values */
+  int nKey = 0;          /* Number of elements in regKey for WITHOUT ROWID */
+  int aiCurOnePass[2];   /* The write cursors opened by WHERE_ONEPASS */
 
   /* Register Allocations */
   int regRowCount = 0;   /* A count of rows changed */
@@ -102373,6 +108323,7 @@ SQLITE_PRIVATE void sqlite3Update(
   int regNew;            /* Content of the NEW.* table in triggers */
   int regOld = 0;        /* Content of OLD.* table in triggers */
   int regRowSet = 0;     /* Rowset of rows to be updated */
+  int regKey = 0;        /* composite PRIMARY KEY value */
 
   memset(&sContext, 0, sizeof(sContext));
   db = pParse->db;
@@ -102410,20 +108361,34 @@ SQLITE_PRIVATE void sqlite3Update(
   if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
     goto update_cleanup;
   }
-  aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol );
-  if( aXRef==0 ) goto update_cleanup;
-  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
 
   /* Allocate a cursors for the main database table and for all indices.
   ** The index cursors might not be used, but if they are used they
   ** need to occur right after the database cursor.  So go ahead and
   ** allocate enough space, just in case.
   */
-  pTabList->a[0].iCursor = iCur = pParse->nTab++;
-  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+  pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++;
+  iIdxCur = iDataCur+1;
+  pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
+  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
+    if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){
+      iDataCur = pParse->nTab;
+      pTabList->a[0].iCursor = iDataCur;
+    }
     pParse->nTab++;
   }
 
+  /* Allocate space for aXRef[], aRegIdx[], and aToOpen[].  
+  ** Initialize aXRef[] and aToOpen[] to their default values.
+  */
+  aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 );
+  if( aXRef==0 ) goto update_cleanup;
+  aRegIdx = aXRef+pTab->nCol;
+  aToOpen = (u8*)(aRegIdx+nIdx);
+  memset(aToOpen, 1, nIdx+1);
+  aToOpen[nIdx+1] = 0;
+  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
+
   /* Initialize the name-context */
   memset(&sNC, 0, sizeof(sNC));
   sNC.pParse = pParse;
@@ -102435,7 +108400,7 @@ SQLITE_PRIVATE void sqlite3Update(
   ** column to be updated, make sure we have authorization to change
   ** that column.
   */
-  chngRowid = 0;
+  chngRowid = chngPk = 0;
   for(i=0; i<pChanges->nExpr; i++){
     if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
       goto update_cleanup;
@@ -102445,13 +108410,15 @@ SQLITE_PRIVATE void sqlite3Update(
         if( j==pTab->iPKey ){
           chngRowid = 1;
           pRowidExpr = pChanges->a[i].pExpr;
+        }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
+          chngPk = 1;
         }
         aXRef[j] = i;
         break;
       }
     }
     if( j>=pTab->nCol ){
-      if( sqlite3IsRowid(pChanges->a[i].zName) ){
+      if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){
         j = -1;
         chngRowid = 1;
         pRowidExpr = pChanges->a[i].pExpr;
@@ -102475,32 +108442,36 @@ SQLITE_PRIVATE void sqlite3Update(
     }
 #endif
   }
+  assert( (chngRowid & chngPk)==0 );
+  assert( chngRowid==0 || chngRowid==1 );
+  assert( chngPk==0 || chngPk==1 );
+  chngKey = chngRowid + chngPk;
+
+  /* The SET expressions are not actually used inside the WHERE loop.
+  ** So reset the colUsed mask
+  */
+  pTabList->a[0].colUsed = 0;
 
-  hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngRowid);
+  hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);
 
-  /* Allocate memory for the array aRegIdx[].  There is one entry in the
-  ** array for each index associated with table being updated.  Fill in
-  ** the value with a register number for indices that are to be used
-  ** and with zero for unused indices.
+  /* There is one entry in the aRegIdx[] array for each index on the table
+  ** being updated.  Fill in aRegIdx[] with a register number that will hold
+  ** the key for accessing each index.  
   */
-  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
-  if( nIdx>0 ){
-    aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
-    if( aRegIdx==0 ) goto update_cleanup;
-  }
   for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
     int reg;
-    if( hasFK || chngRowid ){
+    if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){
       reg = ++pParse->nMem;
     }else{
       reg = 0;
-      for(i=0; i<pIdx->nColumn; i++){
+      for(i=0; i<pIdx->nKeyCol; i++){
         if( aXRef[pIdx->aiColumn[i]]>=0 ){
           reg = ++pParse->nMem;
           break;
         }
       }
     }
+    if( reg==0 ) aToOpen[j+1] = 0;
     aRegIdx[j] = reg;
   }
 
@@ -102524,11 +108495,11 @@ SQLITE_PRIVATE void sqlite3Update(
   /* Allocate required registers. */
   regRowSet = ++pParse->nMem;
   regOldRowid = regNewRowid = ++pParse->nMem;
-  if( pTrigger || hasFK ){
+  if( chngPk || pTrigger || hasFK ){
     regOld = pParse->nMem + 1;
     pParse->nMem += pTab->nCol;
   }
-  if( chngRowid || pTrigger || hasFK ){
+  if( chngKey || pTrigger || hasFK ){
     regNewRowid = ++pParse->nMem;
   }
   regNew = pParse->nMem + 1;
@@ -102544,7 +108515,7 @@ SQLITE_PRIVATE void sqlite3Update(
   */
 #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
   if( isView ){
-    sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
+    sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur);
   }
 #endif
 
@@ -102557,24 +108528,58 @@ SQLITE_PRIVATE void sqlite3Update(
 
   /* Begin the database scan
   */
-  sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
-  pWInfo = sqlite3WhereBegin(
-      pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, 0
-  );
-  if( pWInfo==0 ) goto update_cleanup;
-  okOnePass = pWInfo->okOnePass;
+  if( HasRowid(pTab) ){
+    sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
+    pWInfo = sqlite3WhereBegin(
+        pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur
+    );
+    if( pWInfo==0 ) goto update_cleanup;
+    okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+  
+    /* Remember the rowid of every item to be updated.
+    */
+    sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
+    if( !okOnePass ){
+      sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
+    }
+  
+    /* End the database scan loop.
+    */
+    sqlite3WhereEnd(pWInfo);
+  }else{
+    int iPk;         /* First of nPk memory cells holding PRIMARY KEY value */
+    i16 nPk;         /* Number of components of the PRIMARY KEY */
+    int addrOpen;    /* Address of the OpenEphemeral instruction */
 
-  /* Remember the rowid of every item to be updated.
-  */
-  sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
-  if( !okOnePass ){
-    sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
+    assert( pPk!=0 );
+    nPk = pPk->nKeyCol;
+    iPk = pParse->nMem+1;
+    pParse->nMem += nPk;
+    regKey = ++pParse->nMem;
+    iEph = pParse->nTab++;
+    sqlite3VdbeAddOp2(v, OP_Null, 0, iPk);
+    addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
+    sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 
+                               WHERE_ONEPASS_DESIRED, iIdxCur);
+    if( pWInfo==0 ) goto update_cleanup;
+    okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+    for(i=0; i<nPk; i++){
+      sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i],
+                                      iPk+i);
+    }
+    if( okOnePass ){
+      sqlite3VdbeChangeToNoop(v, addrOpen);
+      nKey = nPk;
+      regKey = iPk;
+    }else{
+      sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
+                        sqlite3IndexAffinityStr(v, pPk), nPk);
+      sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey);
+    }
+    sqlite3WhereEnd(pWInfo);
   }
 
-  /* End the database scan loop.
-  */
-  sqlite3WhereEnd(pWInfo);
-
   /* Initialize the count of updated rows
   */
   if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){
@@ -102582,6 +108587,7 @@ SQLITE_PRIVATE void sqlite3Update(
     sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
   }
 
+  labelBreak = sqlite3VdbeMakeLabel(v);
   if( !isView ){
     /* 
     ** Open every index that needs updating.  Note that if any
@@ -102589,68 +108595,78 @@ SQLITE_PRIVATE void sqlite3Update(
     ** action, then we need to open all indices because we might need
     ** to be deleting some records.
     */
-    if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); 
     if( onError==OE_Replace ){
-      openAll = 1;
+      memset(aToOpen, 1, nIdx+1);
     }else{
-      openAll = 0;
       for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
         if( pIdx->onError==OE_Replace ){
-          openAll = 1;
+          memset(aToOpen, 1, nIdx+1);
           break;
         }
       }
     }
-    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
-      assert( aRegIdx );
-      if( openAll || aRegIdx[i]>0 ){
-        KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
-        sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb,
-                       (char*)pKey, P4_KEYINFO_HANDOFF);
-        assert( pParse->nTab>iCur+i+1 );
-      }
+    if( okOnePass ){
+      if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
+      if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
     }
+    sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iBaseCur, aToOpen,
+                               0, 0);
   }
 
   /* Top of the update loop */
   if( okOnePass ){
-    int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
-    addr = sqlite3VdbeAddOp0(v, OP_Goto);
-    sqlite3VdbeJumpHere(v, a1);
-  }else{
-    addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid);
+    if( aToOpen[iDataCur-iBaseCur] ){
+      assert( pPk!=0 );
+      sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
+      VdbeCoverageNeverTaken(v);
+    }
+    labelContinue = labelBreak;
+    sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
+    VdbeCoverageIf(v, pPk==0);
+    VdbeCoverageIf(v, pPk!=0);
+  }else if( pPk ){
+    labelContinue = sqlite3VdbeMakeLabel(v);
+    sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
+    addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
+    sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
+    VdbeCoverage(v);
+  }else{
+    labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak,
+                             regOldRowid);
+    VdbeCoverage(v);
+    sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
+    VdbeCoverage(v);
   }
 
-  /* Make cursor iCur point to the record that is being updated. If
-  ** this record does not exist for some reason (deleted by a trigger,
-  ** for example, then jump to the next iteration of the RowSet loop.  */
-  sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);
-
   /* If the record number will change, set register regNewRowid to
   ** contain the new value. If the record number is not being modified,
   ** then regNewRowid is the same register as regOldRowid, which is
   ** already populated.  */
-  assert( chngRowid || pTrigger || hasFK || regOldRowid==regNewRowid );
+  assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid );
   if( chngRowid ){
     sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
-    sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid);
+    sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v);
   }
 
-  /* If there are triggers on this table, populate an array of registers 
-  ** with the required old.* column data.  */
-  if( hasFK || pTrigger ){
+  /* Compute the old pre-UPDATE content of the row being changed, if that
+  ** information is needed */
+  if( chngPk || hasFK || pTrigger ){
     u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
     oldmask |= sqlite3TriggerColmask(pParse, 
         pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
     );
     for(i=0; i<pTab->nCol; i++){
-      if( aXRef[i]<0 || oldmask==0xffffffff || (i<32 && (oldmask & (1<<i))) ){
-        sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOld+i);
+      if( oldmask==0xffffffff
+       || (i<32 && (oldmask & MASKBIT32(i))!=0)
+       || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
+      ){
+        testcase(  oldmask!=0xffffffff && i==31 );
+        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
       }else{
         sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
       }
     }
-    if( chngRowid==0 ){
+    if( chngRowid==0 && pPk==0 ){
       sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
     }
   }
@@ -102671,15 +108687,15 @@ SQLITE_PRIVATE void sqlite3Update(
   newmask = sqlite3TriggerColmask(
       pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
   );
-  sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);
+  /*sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);*/
   for(i=0; i<pTab->nCol; i++){
     if( i==pTab->iPKey ){
-      /*sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);*/
+      sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
     }else{
       j = aXRef[i];
       if( j>=0 ){
         sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
-      }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
+      }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
         /* This branch loads the value of a column that will not be changed 
         ** into a register. This is done if there are no BEFORE triggers, or
         ** if there are one or more BEFORE triggers that use this value via
@@ -102687,8 +108703,9 @@ SQLITE_PRIVATE void sqlite3Update(
         */
         testcase( i==31 );
         testcase( i==32 );
-        sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i);
-        sqlite3ColumnDefault(v, pTab, i, regNew+i);
+        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
+      }else{
+        sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
       }
     }
   }
@@ -102697,10 +108714,9 @@ SQLITE_PRIVATE void sqlite3Update(
   ** verified. One could argue that this is wrong.
   */
   if( tmask&TRIGGER_BEFORE ){
-    sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol);
-    sqlite3TableAffinityStr(v, pTab);
+    sqlite3TableAffinity(v, pTab, regNew);
     sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
-        TRIGGER_BEFORE, pTab, regOldRowid, onError, addr);
+        TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue);
 
     /* The row-trigger may have deleted the row being updated. In this
     ** case, jump to the next row. No updates or AFTER triggers are 
@@ -102708,7 +108724,13 @@ SQLITE_PRIVATE void sqlite3Update(
     ** is deleted or renamed by a BEFORE trigger - is left undefined in the
     ** documentation.
     */
-    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);
+    if( pPk ){
+      sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey);
+      VdbeCoverage(v);
+    }else{
+      sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
+      VdbeCoverage(v);
+    }
 
     /* If it did not delete it, the row-trigger may still have modified 
     ** some of the columns of the row being updated. Load the values for 
@@ -102717,46 +108739,57 @@ SQLITE_PRIVATE void sqlite3Update(
     */
     for(i=0; i<pTab->nCol; i++){
       if( aXRef[i]<0 && i!=pTab->iPKey ){
-        sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i);
-        sqlite3ColumnDefault(v, pTab, i, regNew+i);
+        sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
       }
     }
   }
 
   if( !isView ){
-    int j1;                       /* Address of jump instruction */
+    int j1 = 0;           /* Address of jump instruction */
+    int bReplace = 0;     /* True if REPLACE conflict resolution might happen */
 
     /* Do constraint checks. */
-    sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid,
-        aRegIdx, (chngRowid?regOldRowid:0), 1, onError, addr, 0);
+    assert( regOldRowid>0 );
+    sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
+        regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace);
 
     /* Do FK constraint checks. */
     if( hasFK ){
-      sqlite3FkCheck(pParse, pTab, regOldRowid, 0);
+      sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
     }
 
     /* Delete the index entries associated with the current record.  */
-    j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid);
-    sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);
+    if( bReplace || chngKey ){
+      if( pPk ){
+        j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
+      }else{
+        j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
+      }
+      VdbeCoverageNeverTaken(v);
+    }
+    sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx);
   
     /* If changing the record number, delete the old record.  */
-    if( hasFK || chngRowid ){
-      sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
+    if( hasFK || chngKey || pPk!=0 ){
+      sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
+    }
+    if( bReplace || chngKey ){
+      sqlite3VdbeJumpHere(v, j1);
     }
-    sqlite3VdbeJumpHere(v, j1);
 
     if( hasFK ){
-      sqlite3FkCheck(pParse, pTab, 0, regNewRowid);
+      sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey);
     }
   
     /* Insert the new index entries and the new record. */
-    sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, 1, 0, 0);
+    sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
+                             regNewRowid, aRegIdx, 1, 0, 0);
 
     /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
     ** handle rows (possibly in other tables) that refer via a foreign key
     ** to the row just updated. */ 
     if( hasFK ){
-      sqlite3FkActions(pParse, pTab, pChanges, regOldRowid);
+      sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey);
     }
   }
 
@@ -102767,22 +108800,29 @@ SQLITE_PRIVATE void sqlite3Update(
   }
 
   sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
-      TRIGGER_AFTER, pTab, regOldRowid, onError, addr);
+      TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue);
 
   /* Repeat the above with the next record to be updated, until
   ** all record selected by the WHERE clause have been updated.
   */
-  sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
-  sqlite3VdbeJumpHere(v, addr);
+  if( okOnePass ){
+    /* Nothing to do at end-of-loop for a single-pass */
+  }else if( pPk ){
+    sqlite3VdbeResolveLabel(v, labelContinue);
+    sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
+  }else{
+    sqlite3VdbeAddOp2(v, OP_Goto, 0, labelContinue);
+  }
+  sqlite3VdbeResolveLabel(v, labelBreak);
 
   /* Close all tables */
   for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
     assert( aRegIdx );
-    if( openAll || aRegIdx[i]>0 ){
-      sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0);
+    if( aToOpen[i+1] ){
+      sqlite3VdbeAddOp2(v, OP_Close, iIdxCur+i, 0);
     }
   }
-  sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
+  if( iDataCur<iIdxCur ) sqlite3VdbeAddOp2(v, OP_Close, iDataCur, 0);
 
   /* Update the sqlite_sequence table by storing the content of the
   ** maximum rowid counter values recorded while inserting into
@@ -102805,8 +108845,7 @@ SQLITE_PRIVATE void sqlite3Update(
 
 update_cleanup:
   sqlite3AuthContextPop(&sContext);
-  sqlite3DbFree(db, aRegIdx);
-  sqlite3DbFree(db, aXRef);
+  sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */
   sqlite3SrcListDelete(db, pTabList);
   sqlite3ExprListDelete(db, pChanges);
   sqlite3ExprDelete(db, pWhere);
@@ -102899,7 +108938,7 @@ static void updateVirtualTable(
   /* Generate code to scan the ephemeral table and call VUpdate. */
   iReg = ++pParse->nMem;
   pParse->nMem += pTab->nCol+1;
-  addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0);
+  addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v);
   sqlite3VdbeAddOp3(v, OP_Column,  ephemTab, 0, iReg);
   sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1);
   for(i=0; i<pTab->nCol; i++){
@@ -102909,7 +108948,7 @@ static void updateVirtualTable(
   sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
   sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
   sqlite3MayAbort(pParse);
-  sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1);
+  sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v);
   sqlite3VdbeJumpHere(v, addr);
   sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
 
@@ -102992,14 +109031,34 @@ static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
 }
 
 /*
-** The non-standard VACUUM command is used to clean up the database,
+** The VACUUM command is used to clean up the database,
 ** collapse free space, etc.  It is modelled after the VACUUM command
-** in PostgreSQL.
-**
-** In version 1.0.x of SQLite, the VACUUM command would call
-** gdbm_reorganize() on all the database tables.  But beginning
-** with 2.0.0, SQLite no longer uses GDBM so this command has
-** become a no-op.
+** in PostgreSQL.  The VACUUM command works as follows:
+**
+**   (1)  Create a new transient database file
+**   (2)  Copy all content from the database being vacuumed into
+**        the new transient database file
+**   (3)  Copy content from the transient database back into the
+**        original database.
+**
+** The transient database requires temporary disk space approximately
+** equal to the size of the original database.  The copy operation of
+** step (3) requires additional temporary disk space approximately equal
+** to the size of the original database for the rollback journal.
+** Hence, temporary disk space that is approximately 2x the size of the
+** orginal database is required.  Every page of the database is written
+** approximately 3 times:  Once for step (2) and twice for step (3).
+** Two writes per page are required in step (3) because the original
+** database content must be written into the rollback journal prior to
+** overwriting the database with the vacuumed content.
+**
+** Only 1x temporary space and only 1x writes would be required if
+** the copy of step (3) were replace by deleting the original database
+** and renaming the transient database as the original.  But that will
+** not work if other processes are attached to the original database.
+** And a power loss in between deleting the original and renaming the
+** transient would cause the database file to appear to be deleted
+** following reboot.
 */
 SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
   Vdbe *v = sqlite3GetVdbe(pParse);
@@ -103031,7 +109090,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
     sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
     return SQLITE_ERROR;
   }
-  if( db->activeVdbeCnt>1 ){
+  if( db->nVdbeActive>1 ){
     sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress");
     return SQLITE_ERROR;
   }
@@ -103134,7 +109193,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
   rc = execExecSql(db, pzErrMsg,
       "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
       "  FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
-      "   AND rootpage>0"
+      "   AND coalesce(rootpage,1)>0"
   );
   if( rc!=SQLITE_OK ) goto end_of_vacuum;
   rc = execExecSql(db, pzErrMsg,
@@ -103155,7 +109214,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
       "|| ' SELECT * FROM main.' || quote(name) || ';'"
       "FROM main.sqlite_master "
       "WHERE type = 'table' AND name!='sqlite_sequence' "
-      "  AND rootpage>0"
+      "  AND coalesce(rootpage,1)>0"
   );
   if( rc!=SQLITE_OK ) goto end_of_vacuum;
 
@@ -104009,6 +110068,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
       sqlite3VdbeFinalize(pParse->pVdbe);
     }
     sqlite3DeleteTable(db, pParse->pNewTable);
+    sqlite3ParserReset(pParse);
     sqlite3StackFree(db, pParse);
   }
 
@@ -104081,10 +110141,9 @@ static void callFinaliser(sqlite3 *db, int offset){
 ** array. Return the error code for the first error that occurs, or
 ** SQLITE_OK if all xSync operations are successful.
 **
-** Set *pzErrmsg to point to a buffer that should be released using 
-** sqlite3DbFree() containing an error message, if one is available.
+** If an error message is available, leave it in p->zErrMsg.
 */
-SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
+SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe *p){
   int i;
   int rc = SQLITE_OK;
   VTable **aVTrans = db->aVTrans;
@@ -104095,9 +110154,7 @@ SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
     sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
     if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
       rc = x(pVtab);
-      sqlite3DbFree(db, *pzErrmsg);
-      *pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
-      sqlite3_free(pVtab->zErrMsg);
+      sqlite3VtabImportErrmsg(p, pVtab);
     }
   }
   db->aVTrans = aVTrans;
@@ -104287,7 +110344,7 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
   memcpy(pNew->zName, pDef->zName, sqlite3Strlen30(pDef->zName)+1);
   pNew->xFunc = xFunc;
   pNew->pUserData = pArg;
-  pNew->flags |= SQLITE_FUNC_EPHEM;
+  pNew->funcFlags |= SQLITE_FUNC_EPHEM;
   return pNew;
 }
 
@@ -104389,7 +110446,24 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 */
-
+/************** Include whereInt.h in the middle of where.c ******************/
+/************** Begin file whereInt.h ****************************************/
+/*
+** 2013-11-12
+**
+** 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 structure and macro definitions for the query
+** planner logic in "where.c".  These definitions are broken out into
+** a separate source file for easier editing.
+*/
 
 /*
 ** Trace output macros
@@ -104399,18 +110473,170 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
 #endif
 #if defined(SQLITE_DEBUG) \
     && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
-# define WHERETRACE(X)  if(sqlite3WhereTrace) sqlite3DebugPrintf X
+# define WHERETRACE(K,X)  if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
+# define WHERETRACE_ENABLED 1
 #else
-# define WHERETRACE(X)
+# define WHERETRACE(K,X)
 #endif
 
-/* Forward reference
+/* Forward references
 */
 typedef struct WhereClause WhereClause;
 typedef struct WhereMaskSet WhereMaskSet;
 typedef struct WhereOrInfo WhereOrInfo;
 typedef struct WhereAndInfo WhereAndInfo;
-typedef struct WhereCost WhereCost;
+typedef struct WhereLevel WhereLevel;
+typedef struct WhereLoop WhereLoop;
+typedef struct WherePath WherePath;
+typedef struct WhereTerm WhereTerm;
+typedef struct WhereLoopBuilder WhereLoopBuilder;
+typedef struct WhereScan WhereScan;
+typedef struct WhereOrCost WhereOrCost;
+typedef struct WhereOrSet WhereOrSet;
+
+/*
+** This object contains information needed to implement a single nested
+** loop in WHERE clause.
+**
+** Contrast this object with WhereLoop.  This object describes the
+** implementation of the loop.  WhereLoop describes the algorithm.
+** This object contains a pointer to the WhereLoop algorithm as one of
+** its elements.
+**
+** The WhereInfo object contains a single instance of this object for
+** each term in the FROM clause (which is to say, for each of the
+** nested loops as implemented).  The order of WhereLevel objects determines
+** the loop nested order, with WhereInfo.a[0] being the outer loop and
+** WhereInfo.a[WhereInfo.nLevel-1] being the inner loop.
+*/
+struct WhereLevel {
+  int iLeftJoin;        /* Memory cell used to implement LEFT OUTER JOIN */
+  int iTabCur;          /* The VDBE cursor used to access the table */
+  int iIdxCur;          /* The VDBE cursor used to access pIdx */
+  int addrBrk;          /* Jump here to break out of the loop */
+  int addrNxt;          /* Jump here to start the next IN combination */
+  int addrSkip;         /* Jump here for next iteration of skip-scan */
+  int addrCont;         /* Jump here to continue with the next loop cycle */
+  int addrFirst;        /* First instruction of interior of the loop */
+  int addrBody;         /* Beginning of the body of this loop */
+  u8 iFrom;             /* Which entry in the FROM clause */
+  u8 op, p3, p5;        /* Opcode, P3 & P5 of the opcode that ends the loop */
+  int p1, p2;           /* Operands of the opcode used to ends the loop */
+  union {               /* Information that depends on pWLoop->wsFlags */
+    struct {
+      int nIn;              /* Number of entries in aInLoop[] */
+      struct InLoop {
+        int iCur;              /* The VDBE cursor used by this IN operator */
+        int addrInTop;         /* Top of the IN loop */
+        u8 eEndLoopOp;         /* IN Loop terminator. OP_Next or OP_Prev */
+      } *aInLoop;           /* Information about each nested IN operator */
+    } in;                 /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
+    Index *pCovidx;       /* Possible covering index for WHERE_MULTI_OR */
+  } u;
+  struct WhereLoop *pWLoop;  /* The selected WhereLoop object */
+  Bitmask notReady;          /* FROM entries not usable at this level */
+};
+
+/*
+** Each instance of this object represents an algorithm for evaluating one
+** term of a join.  Every term of the FROM clause will have at least
+** one corresponding WhereLoop object (unless INDEXED BY constraints
+** prevent a query solution - which is an error) and many terms of the
+** FROM clause will have multiple WhereLoop objects, each describing a
+** potential way of implementing that FROM-clause term, together with
+** dependencies and cost estimates for using the chosen algorithm.
+**
+** Query planning consists of building up a collection of these WhereLoop
+** objects, then computing a particular sequence of WhereLoop objects, with
+** one WhereLoop object per FROM clause term, that satisfy all dependencies
+** and that minimize the overall cost.
+*/
+struct WhereLoop {
+  Bitmask prereq;       /* Bitmask of other loops that must run first */
+  Bitmask maskSelf;     /* Bitmask identifying table iTab */
+#ifdef SQLITE_DEBUG
+  char cId;             /* Symbolic ID of this loop for debugging use */
+#endif
+  u8 iTab;              /* Position in FROM clause of table for this loop */
+  u8 iSortIdx;          /* Sorting index number.  0==None */
+  LogEst rSetup;        /* One-time setup cost (ex: create transient index) */
+  LogEst rRun;          /* Cost of running each loop */
+  LogEst nOut;          /* Estimated number of output rows */
+  union {
+    struct {               /* Information for internal btree tables */
+      u16 nEq;               /* Number of equality constraints */
+      u16 nSkip;             /* Number of initial index columns to skip */
+      Index *pIndex;         /* Index used, or NULL */
+    } btree;
+    struct {               /* Information for virtual tables */
+      int idxNum;            /* Index number */
+      u8 needFree;           /* True if sqlite3_free(idxStr) is needed */
+      i8 isOrdered;          /* True if satisfies ORDER BY */
+      u16 omitMask;          /* Terms that may be omitted */
+      char *idxStr;          /* Index identifier string */
+    } vtab;
+  } u;
+  u32 wsFlags;          /* WHERE_* flags describing the plan */
+  u16 nLTerm;           /* Number of entries in aLTerm[] */
+  /**** whereLoopXfer() copies fields above ***********************/
+# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
+  u16 nLSlot;           /* Number of slots allocated for aLTerm[] */
+  WhereTerm **aLTerm;   /* WhereTerms used */
+  WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
+  WhereTerm *aLTermSpace[4];  /* Initial aLTerm[] space */
+};
+
+/* This object holds the prerequisites and the cost of running a
+** subquery on one operand of an OR operator in the WHERE clause.
+** See WhereOrSet for additional information 
+*/
+struct WhereOrCost {
+  Bitmask prereq;     /* Prerequisites */
+  LogEst rRun;        /* Cost of running this subquery */
+  LogEst nOut;        /* Number of outputs for this subquery */
+};
+
+/* The WhereOrSet object holds a set of possible WhereOrCosts that
+** correspond to the subquery(s) of OR-clause processing.  Only the
+** best N_OR_COST elements are retained.
+*/
+#define N_OR_COST 3
+struct WhereOrSet {
+  u16 n;                      /* Number of valid a[] entries */
+  WhereOrCost a[N_OR_COST];   /* Set of best costs */
+};
+
+
+/* Forward declaration of methods */
+static int whereLoopResize(sqlite3*, WhereLoop*, int);
+
+/*
+** Each instance of this object holds a sequence of WhereLoop objects
+** that implement some or all of a query plan.
+**
+** Think of each WhereLoop object as a node in a graph with arcs
+** showing dependencies and costs for travelling between nodes.  (That is
+** not a completely accurate description because WhereLoop costs are a
+** vector, not a scalar, and because dependencies are many-to-one, not
+** one-to-one as are graph nodes.  But it is a useful visualization aid.)
+** Then a WherePath object is a path through the graph that visits some
+** or all of the WhereLoop objects once.
+**
+** The "solver" works by creating the N best WherePath objects of length
+** 1.  Then using those as a basis to compute the N best WherePath objects
+** of length 2.  And so forth until the length of WherePaths equals the
+** number of nodes in the FROM clause.  The best (lowest cost) WherePath
+** at the end is the choosen query plan.
+*/
+struct WherePath {
+  Bitmask maskLoop;     /* Bitmask of all WhereLoop objects in this path */
+  Bitmask revLoop;      /* aLoop[]s that should be reversed for ORDER BY */
+  LogEst nRow;          /* Estimated number of rows generated by this path */
+  LogEst rCost;         /* Total cost of this path */
+  LogEst rUnsorted;     /* Total cost of this path ignoring sorting costs */
+  i8 isOrdered;         /* No. of ORDER BY terms satisfied. -1 for unknown */
+  WhereLoop **aLoop;    /* Array of WhereLoop objects implementing this path */
+};
 
 /*
 ** The query generator uses an array of instances of this structure to
@@ -104438,9 +110664,9 @@ typedef struct WhereCost WhereCost;
 **
 **         (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR ....
 **
-** In this second case, wtFlag as the TERM_ORINFO set and eOperator==WO_OR
+** In this second case, wtFlag has the TERM_ORINFO bit set and eOperator==WO_OR
 ** and the WhereTerm.u.pOrInfo field points to auxiliary information that
-** is collected about the
+** is collected about the OR clause.
 **
 ** If a term in the WHERE clause does not match either of the two previous
 ** categories, then eOperator==0.  The WhereTerm.pExpr field is still set
@@ -104463,7 +110689,6 @@ typedef struct WhereCost WhereCost;
 ** in prereqRight and prereqAll.  The default is 64 bits, hence SQLite
 ** is only able to process joins with 64 or fewer tables.
 */
-typedef struct WhereTerm WhereTerm;
 struct WhereTerm {
   Expr *pExpr;            /* Pointer to the subexpression that is this term */
   int iParent;            /* Disable pWC->a[iParent] when this term disabled */
@@ -104473,6 +110698,7 @@ struct WhereTerm {
     WhereOrInfo *pOrInfo;   /* Extra information if (eOperator & WO_OR)!=0 */
     WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
   } u;
+  LogEst truthProb;       /* Probability of truth for this expression */
   u16 eOperator;          /* A WO_xx value describing <op> */
   u8 wtFlags;             /* TERM_xxx bit flags.  See below */
   u8 nChild;              /* Number of children that must disable us */
@@ -104491,13 +110717,29 @@ struct WhereTerm {
 #define TERM_ORINFO     0x10   /* Need to free the WhereTerm.u.pOrInfo object */
 #define TERM_ANDINFO    0x20   /* Need to free the WhereTerm.u.pAndInfo obj */
 #define TERM_OR_OK      0x40   /* Used during OR-clause processing */
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
 #  define TERM_VNULL    0x80   /* Manufactured x>NULL or x<=NULL term */
 #else
 #  define TERM_VNULL    0x00   /* Disabled if not using stat3 */
 #endif
 
 /*
+** An instance of the WhereScan object is used as an iterator for locating
+** terms in the WHERE clause that are useful to the query planner.
+*/
+struct WhereScan {
+  WhereClause *pOrigWC;      /* Original, innermost WhereClause */
+  WhereClause *pWC;          /* WhereClause currently being scanned */
+  char *zCollName;           /* Required collating sequence, if not NULL */
+  char idxaff;               /* Must match this affinity, if zCollName!=NULL */
+  unsigned char nEquiv;      /* Number of entries in aEquiv[] */
+  unsigned char iEquiv;      /* Next unused slot in aEquiv[] */
+  u32 opMask;                /* Acceptable operators */
+  int k;                     /* Resume scanning at this->pWC->a[this->k] */
+  int aEquiv[22];            /* Cursor,Column pairs for equivalence classes */
+};
+
+/*
 ** An instance of the following structure holds all information about a
 ** WHERE clause.  Mostly this is a container for one or more WhereTerms.
 **
@@ -104510,11 +110752,9 @@ struct WhereTerm {
 ** subclauses points to the WhereClause object for the whole clause.
 */
 struct WhereClause {
-  Parse *pParse;           /* The parser context */
-  WhereMaskSet *pMaskSet;  /* Mapping of table cursor numbers to bitmasks */
+  WhereInfo *pWInfo;       /* WHERE clause processing context */
   WhereClause *pOuter;     /* Outer conjunction */
   u8 op;                   /* Split operator.  TK_AND or TK_OR */
-  u16 wctrlFlags;          /* Might include WHERE_AND_ONLY */
   int nTerm;               /* Number of terms */
   int nSlot;               /* Number of entries in a[] */
   WhereTerm *a;            /* Each a[] describes a term of the WHERE cluase */
@@ -104574,19 +110814,61 @@ struct WhereMaskSet {
 };
 
 /*
-** A WhereCost object records a lookup strategy and the estimated
-** cost of pursuing that strategy.
+** This object is a convenience wrapper holding all information needed
+** to construct WhereLoop objects for a particular query.
 */
-struct WhereCost {
-  WherePlan plan;    /* The lookup strategy */
-  double rCost;      /* Overall cost of pursuing this search strategy */
-  Bitmask used;      /* Bitmask of cursors used by this plan */
+struct WhereLoopBuilder {
+  WhereInfo *pWInfo;        /* Information about this WHERE */
+  WhereClause *pWC;         /* WHERE clause terms */
+  ExprList *pOrderBy;       /* ORDER BY clause */
+  WhereLoop *pNew;          /* Template WhereLoop */
+  WhereOrSet *pOrSet;       /* Record best loops here, if not NULL */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  UnpackedRecord *pRec;     /* Probe for stat4 (if required) */
+  int nRecValid;            /* Number of valid fields currently in pRec */
+#endif
 };
 
 /*
-** Bitmasks for the operators that indices are able to exploit.  An
+** The WHERE clause processing routine has two halves.  The
+** first part does the start of the WHERE loop and the second
+** half does the tail of the WHERE loop.  An instance of
+** this structure is returned by the first half and passed
+** into the second half to give some continuity.
+**
+** An instance of this object holds the complete state of the query
+** planner.
+*/
+struct WhereInfo {
+  Parse *pParse;            /* Parsing and code generating context */
+  SrcList *pTabList;        /* List of tables in the join */
+  ExprList *pOrderBy;       /* The ORDER BY clause or NULL */
+  ExprList *pResultSet;     /* Result set. DISTINCT operates on these */
+  WhereLoop *pLoops;        /* List of all WhereLoop objects */
+  Bitmask revMask;          /* Mask of ORDER BY terms that need reversing */
+  LogEst nRowOut;           /* Estimated number of output rows */
+  u16 wctrlFlags;           /* Flags originally passed to sqlite3WhereBegin() */
+  i8 nOBSat;                /* Number of ORDER BY terms satisfied by indices */
+  u8 sorted;                /* True if really sorted (not just grouped) */
+  u8 okOnePass;             /* Ok to use one-pass algorithm for UPDATE/DELETE */
+  u8 untestedTerms;         /* Not all WHERE terms resolved by outer loop */
+  u8 eDistinct;             /* One of the WHERE_DISTINCT_* values below */
+  u8 nLevel;                /* Number of nested loop */
+  int iTop;                 /* The very beginning of the WHERE loop */
+  int iContinue;            /* Jump here to continue with next record */
+  int iBreak;               /* Jump here to break out of the loop */
+  int savedNQueryLoop;      /* pParse->nQueryLoop outside the WHERE loop */
+  int aiCurOnePass[2];      /* OP_OpenWrite cursors for the ONEPASS opt */
+  WhereMaskSet sMaskSet;    /* Map cursor numbers to bitmasks */
+  WhereClause sWC;          /* Decomposition of the WHERE clause */
+  WhereLevel a[1];          /* Information about each nest loop in WHERE */
+};
+
+/*
+** Bitmasks for the operators on WhereTerm objects.  These are all
+** operators that are of interest to the query planner.  An
 ** OR-ed combination of these values can be used when searching for
-** terms in the where clause.
+** particular WhereTerms within a WhereClause.
 */
 #define WO_IN     0x001
 #define WO_EQ     0x002
@@ -104605,74 +110887,138 @@ struct WhereCost {
 #define WO_SINGLE 0x0ff       /* Mask of all non-compound WO_* values */
 
 /*
-** Value for wsFlags returned by bestIndex() and stored in
-** WhereLevel.wsFlags.  These flags determine which search
-** strategies are appropriate.
-**
-** The least significant 12 bits is reserved as a mask for WO_ values above.
-** The WhereLevel.wsFlags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
-** But if the table is the right table of a left join, WhereLevel.wsFlags
-** is set to WO_IN|WO_EQ.  The WhereLevel.wsFlags field can then be used as
-** the "op" parameter to findTerm when we are resolving equality constraints.
-** ISNULL constraints will then not be used on the right table of a left
-** join.  Tickets #2177 and #2189.
-*/
-#define WHERE_ROWID_EQ     0x00001000  /* rowid=EXPR or rowid IN (...) */
-#define WHERE_ROWID_RANGE  0x00002000  /* rowid<EXPR and/or rowid>EXPR */
-#define WHERE_COLUMN_EQ    0x00010000  /* x=EXPR or x IN (...) or x IS NULL */
-#define WHERE_COLUMN_RANGE 0x00020000  /* x<EXPR and/or x>EXPR */
-#define WHERE_COLUMN_IN    0x00040000  /* x IN (...) */
-#define WHERE_COLUMN_NULL  0x00080000  /* x IS NULL */
-#define WHERE_INDEXED      0x000f0000  /* Anything that uses an index */
-#define WHERE_NOT_FULLSCAN 0x100f3000  /* Does not do a full table scan */
-#define WHERE_IN_ABLE      0x080f1000  /* Able to support an IN operator */
-#define WHERE_TOP_LIMIT    0x00100000  /* x<EXPR or x<=EXPR constraint */
-#define WHERE_BTM_LIMIT    0x00200000  /* x>EXPR or x>=EXPR constraint */
-#define WHERE_BOTH_LIMIT   0x00300000  /* Both x>EXPR and x<EXPR */
-#define WHERE_IDX_ONLY     0x00400000  /* Use index only - omit table */
-#define WHERE_ORDERED      0x00800000  /* Output will appear in correct order */
-#define WHERE_REVERSE      0x01000000  /* Scan in reverse order */
-#define WHERE_UNIQUE       0x02000000  /* Selects no more than one row */
-#define WHERE_ALL_UNIQUE   0x04000000  /* This and all prior have one row */
-#define WHERE_OB_UNIQUE    0x00004000  /* Values in ORDER BY columns are 
-                                       ** different for every output row */
-#define WHERE_VIRTUALTABLE 0x08000000  /* Use virtual-table processing */
-#define WHERE_MULTI_OR     0x10000000  /* OR using multiple indices */
-#define WHERE_TEMP_INDEX   0x20000000  /* Uses an ephemeral index */
-#define WHERE_DISTINCT     0x40000000  /* Correct order for DISTINCT */
-#define WHERE_COVER_SCAN   0x80000000  /* Full scan of a covering index */
-
-/*
-** This module contains many separate subroutines that work together to
-** find the best indices to use for accessing a particular table in a query.
-** An instance of the following structure holds context information about the
-** index search so that it can be more easily passed between the various
-** routines.
+** These are definitions of bits in the WhereLoop.wsFlags field.
+** The particular combination of bits in each WhereLoop help to
+** determine the algorithm that WhereLoop represents.
 */
-typedef struct WhereBestIdx WhereBestIdx;
-struct WhereBestIdx {
-  Parse *pParse;                  /* Parser context */
-  WhereClause *pWC;               /* The WHERE clause */
-  struct SrcList_item *pSrc;      /* The FROM clause term to search */
-  Bitmask notReady;               /* Mask of cursors not available */
-  Bitmask notValid;               /* Cursors not available for any purpose */
-  ExprList *pOrderBy;             /* The ORDER BY clause */
-  ExprList *pDistinct;            /* The select-list if query is DISTINCT */
-  sqlite3_index_info **ppIdxInfo; /* Index information passed to xBestIndex */
-  int i, n;                       /* Which loop is being coded; # of loops */
-  WhereLevel *aLevel;             /* Info about outer loops */
-  WhereCost cost;                 /* Lowest cost query plan */
-};
+#define WHERE_COLUMN_EQ    0x00000001  /* x=EXPR */
+#define WHERE_COLUMN_RANGE 0x00000002  /* x<EXPR and/or x>EXPR */
+#define WHERE_COLUMN_IN    0x00000004  /* x IN (...) */
+#define WHERE_COLUMN_NULL  0x00000008  /* x IS NULL */
+#define WHERE_CONSTRAINT   0x0000000f  /* Any of the WHERE_COLUMN_xxx values */
+#define WHERE_TOP_LIMIT    0x00000010  /* x<EXPR or x<=EXPR constraint */
+#define WHERE_BTM_LIMIT    0x00000020  /* x>EXPR or x>=EXPR constraint */
+#define WHERE_BOTH_LIMIT   0x00000030  /* Both x>EXPR and x<EXPR */
+#define WHERE_IDX_ONLY     0x00000040  /* Use index only - omit table */
+#define WHERE_IPK          0x00000100  /* x is the INTEGER PRIMARY KEY */
+#define WHERE_INDEXED      0x00000200  /* WhereLoop.u.btree.pIndex is valid */
+#define WHERE_VIRTUALTABLE 0x00000400  /* WhereLoop.u.vtab is valid */
+#define WHERE_IN_ABLE      0x00000800  /* Able to support an IN operator */
+#define WHERE_ONEROW       0x00001000  /* Selects no more than one row */
+#define WHERE_MULTI_OR     0x00002000  /* OR using multiple indices */
+#define WHERE_AUTO_INDEX   0x00004000  /* Uses an ephemeral index */
+#define WHERE_SKIPSCAN     0x00008000  /* Uses the skip-scan algorithm */
+#define WHERE_UNQ_WANTED   0x00010000  /* WHERE_ONEROW would have been helpful*/
+
+/************** End of whereInt.h ********************************************/
+/************** Continuing where we left off in where.c **********************/
 
 /*
-** Return TRUE if the probe cost is less than the baseline cost
+** Return the estimated number of output rows from a WHERE clause
 */
-static int compareCost(const WhereCost *pProbe, const WhereCost *pBaseline){
-  if( pProbe->rCost<pBaseline->rCost ) return 1;
-  if( pProbe->rCost>pBaseline->rCost ) return 0;
-  if( pProbe->plan.nOBSat>pBaseline->plan.nOBSat ) return 1;
-  if( pProbe->plan.nRow<pBaseline->plan.nRow ) return 1;
-  return 0;
+SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
+  return sqlite3LogEstToInt(pWInfo->nRowOut);
+}
+
+/*
+** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
+** WHERE clause returns outputs for DISTINCT processing.
+*/
+SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo *pWInfo){
+  return pWInfo->eDistinct;
+}
+
+/*
+** Return TRUE if the WHERE clause returns rows in ORDER BY order.
+** Return FALSE if the output needs to be sorted.
+*/
+SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
+  return pWInfo->nOBSat;
+}
+
+/*
+** Return the VDBE address or label to jump to in order to continue
+** immediately with the next row of a WHERE clause.
+*/
+SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo *pWInfo){
+  assert( pWInfo->iContinue!=0 );
+  return pWInfo->iContinue;
+}
+
+/*
+** Return the VDBE address or label to jump to in order to break
+** out of a WHERE loop.
+*/
+SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
+  return pWInfo->iBreak;
+}
+
+/*
+** Return TRUE if an UPDATE or DELETE statement can operate directly on
+** the rowids returned by a WHERE clause.  Return FALSE if doing an
+** UPDATE or DELETE might change subsequent WHERE clause results.
+**
+** If the ONEPASS optimization is used (if this routine returns true)
+** then also write the indices of open cursors used by ONEPASS
+** into aiCur[0] and aiCur[1].  iaCur[0] gets the cursor of the data
+** table and iaCur[1] gets the cursor used by an auxiliary index.
+** Either value may be -1, indicating that cursor is not used.
+** Any cursors returned will have been opened for writing.
+**
+** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is
+** unable to use the ONEPASS optimization.
+*/
+SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){
+  memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2);
+  return pWInfo->okOnePass;
+}
+
+/*
+** Move the content of pSrc into pDest
+*/
+static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
+  pDest->n = pSrc->n;
+  memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0]));
+}
+
+/*
+** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet.
+**
+** The new entry might overwrite an existing entry, or it might be
+** appended, or it might be discarded.  Do whatever is the right thing
+** so that pSet keeps the N_OR_COST best entries seen so far.
+*/
+static int whereOrInsert(
+  WhereOrSet *pSet,      /* The WhereOrSet to be updated */
+  Bitmask prereq,        /* Prerequisites of the new entry */
+  LogEst rRun,           /* Run-cost of the new entry */
+  LogEst nOut            /* Number of outputs for the new entry */
+){
+  u16 i;
+  WhereOrCost *p;
+  for(i=pSet->n, p=pSet->a; i>0; i--, p++){
+    if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
+      goto whereOrInsert_done;
+    }
+    if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){
+      return 0;
+    }
+  }
+  if( pSet->n<N_OR_COST ){
+    p = &pSet->a[pSet->n++];
+    p->nOut = nOut;
+  }else{
+    p = pSet->a;
+    for(i=1; i<pSet->n; i++){
+      if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i;
+    }
+    if( p->rRun<=rRun ) return 0;
+  }
+whereOrInsert_done:
+  p->prereq = prereq;
+  p->rRun = rRun;
+  if( p->nOut>nOut ) p->nOut = nOut;
+  return 1;
 }
 
 /*
@@ -104680,17 +111026,13 @@ static int compareCost(const WhereCost *pProbe, const WhereCost *pBaseline){
 */
 static void whereClauseInit(
   WhereClause *pWC,        /* The WhereClause to be initialized */
-  Parse *pParse,           /* The parsing context */
-  WhereMaskSet *pMaskSet,  /* Mapping from table cursor numbers to bitmasks */
-  u16 wctrlFlags           /* Might include WHERE_AND_ONLY */
+  WhereInfo *pWInfo        /* The WHERE processing context */
 ){
-  pWC->pParse = pParse;
-  pWC->pMaskSet = pMaskSet;
+  pWC->pWInfo = pWInfo;
   pWC->pOuter = 0;
   pWC->nTerm = 0;
   pWC->nSlot = ArraySize(pWC->aStatic);
   pWC->a = pWC->aStatic;
-  pWC->wctrlFlags = wctrlFlags;
 }
 
 /* Forward reference */
@@ -104719,7 +111061,7 @@ static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){
 static void whereClauseClear(WhereClause *pWC){
   int i;
   WhereTerm *a;
-  sqlite3 *db = pWC->pParse->db;
+  sqlite3 *db = pWC->pWInfo->pParse->db;
   for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
     if( a->wtFlags & TERM_DYNAMIC ){
       sqlite3ExprDelete(db, a->pExpr);
@@ -104757,10 +111099,10 @@ static void whereClauseClear(WhereClause *pWC){
 static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
   WhereTerm *pTerm;
   int idx;
-  testcase( wtFlags & TERM_VIRTUAL );  /* EV: R-00211-15100 */
+  testcase( wtFlags & TERM_VIRTUAL );
   if( pWC->nTerm>=pWC->nSlot ){
     WhereTerm *pOld = pWC->a;
-    sqlite3 *db = pWC->pParse->db;
+    sqlite3 *db = pWC->pWInfo->pParse->db;
     pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
     if( pWC->a==0 ){
       if( wtFlags & TERM_DYNAMIC ){
@@ -104776,6 +111118,11 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
     pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
   }
   pTerm = &pWC->a[idx = pWC->nTerm++];
+  if( p && ExprHasProperty(p, EP_Unlikely) ){
+    pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
+  }else{
+    pTerm->truthProb = 1;
+  }
   pTerm->pExpr = sqlite3ExprSkipCollate(p);
   pTerm->wtFlags = wtFlags;
   pTerm->pWC = pWC;
@@ -104800,8 +111147,8 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
 ** the WhereClause.a[] array.  The slot[] array grows as needed to contain
 ** all terms of the WHERE clause.
 */
-static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
-  pWC->op = (u8)op;
+static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
+  pWC->op = op;
   if( pExpr==0 ) return;
   if( pExpr->op!=op ){
     whereClauseInsert(pWC, pExpr, 0);
@@ -104812,9 +111159,9 @@ static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
 }
 
 /*
-** Initialize an expression mask set (a WhereMaskSet object)
+** Initialize a WhereMaskSet object
 */
-#define initMaskSet(P)  memset(P, 0, sizeof(*P))
+#define initMaskSet(P)  (P)->n=0
 
 /*
 ** Return the bitmask for the given cursor number.  Return 0 if
@@ -104825,7 +111172,7 @@ static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){
   assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
   for(i=0; i<pMaskSet->n; i++){
     if( pMaskSet->ix[i]==iCursor ){
-      return ((Bitmask)1)<<i;
+      return MASKBIT(i);
     }
   }
   return 0;
@@ -104845,18 +111192,9 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
 }
 
 /*
-** This routine walks (recursively) an expression tree and generates
+** These routines walk (recursively) an expression tree and generate
 ** a bitmask indicating which tables are used in that expression
 ** tree.
-**
-** In order for this routine to work, the calling function must have
-** previously invoked sqlite3ResolveExprNames() on the expression.  See
-** the header comment on that routine for additional information.
-** 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
-** the bitmasks together.
 */
 static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*);
 static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*);
@@ -104910,14 +111248,7 @@ static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
 /*
 ** Return TRUE if the given operator is one of the operators that is
 ** allowed for an indexable WHERE clause term.  The allowed operators are
-** "=", "<", ">", "<=", ">=", and "IN".
-**
-** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be
-** of one of the following forms: column = expression column > expression
-** column >= expression column < expression column <= expression
-** expression = column expression > column expression >= column
-** expression < column expression <= column column IN
-** (expression-list) column IN (subquery) column IS NULL
+** "=", "<", ">", "<=", ">=", "IN", and "IS NULL"
 */
 static int allowedOp(int op){
   assert( TK_GT>TK_EQ && TK_GT<TK_GE );
@@ -104937,10 +111268,9 @@ static int allowedOp(int op){
 ** are converted into "Y op X".
 **
 ** If left/right precedence rules come into play when determining the
-** collating
-** side of the comparison, it remains associated with the same side after
-** the commutation. So "Y collate NOCASE op X" becomes 
-** "X op Y". This is because any collation sequence on
+** collating sequence, then COLLATE operators are adjusted to ensure
+** that the collating sequence does not change.  For example:
+** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on
 ** the left hand side of a comparison overrides any collation sequence 
 ** attached to the right. For the same reason the EP_Collate flag
 ** is not commuted.
@@ -104998,6 +111328,133 @@ static u16 operatorMask(int op){
 }
 
 /*
+** Advance to the next WhereTerm that matches according to the criteria
+** established when the pScan object was initialized by whereScanInit().
+** Return NULL if there are no more matching WhereTerms.
+*/
+static WhereTerm *whereScanNext(WhereScan *pScan){
+  int iCur;            /* The cursor on the LHS of the term */
+  int iColumn;         /* The column on the LHS of the term.  -1 for IPK */
+  Expr *pX;            /* An expression being tested */
+  WhereClause *pWC;    /* Shorthand for pScan->pWC */
+  WhereTerm *pTerm;    /* The term being tested */
+  int k = pScan->k;    /* Where to start scanning */
+
+  while( pScan->iEquiv<=pScan->nEquiv ){
+    iCur = pScan->aEquiv[pScan->iEquiv-2];
+    iColumn = pScan->aEquiv[pScan->iEquiv-1];
+    while( (pWC = pScan->pWC)!=0 ){
+      for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
+        if( pTerm->leftCursor==iCur
+         && pTerm->u.leftColumn==iColumn
+         && (pScan->iEquiv<=2 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
+        ){
+          if( (pTerm->eOperator & WO_EQUIV)!=0
+           && pScan->nEquiv<ArraySize(pScan->aEquiv)
+          ){
+            int j;
+            pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
+            assert( pX->op==TK_COLUMN );
+            for(j=0; j<pScan->nEquiv; j+=2){
+              if( pScan->aEquiv[j]==pX->iTable
+               && pScan->aEquiv[j+1]==pX->iColumn ){
+                  break;
+              }
+            }
+            if( j==pScan->nEquiv ){
+              pScan->aEquiv[j] = pX->iTable;
+              pScan->aEquiv[j+1] = pX->iColumn;
+              pScan->nEquiv += 2;
+            }
+          }
+          if( (pTerm->eOperator & pScan->opMask)!=0 ){
+            /* Verify the affinity and collating sequence match */
+            if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
+              CollSeq *pColl;
+              Parse *pParse = pWC->pWInfo->pParse;
+              pX = pTerm->pExpr;
+              if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
+                continue;
+              }
+              assert(pX->pLeft);
+              pColl = sqlite3BinaryCompareCollSeq(pParse,
+                                                  pX->pLeft, pX->pRight);
+              if( pColl==0 ) pColl = pParse->db->pDfltColl;
+              if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
+                continue;
+              }
+            }
+            if( (pTerm->eOperator & WO_EQ)!=0
+             && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
+             && pX->iTable==pScan->aEquiv[0]
+             && pX->iColumn==pScan->aEquiv[1]
+            ){
+              continue;
+            }
+            pScan->k = k+1;
+            return pTerm;
+          }
+        }
+      }
+      pScan->pWC = pScan->pWC->pOuter;
+      k = 0;
+    }
+    pScan->pWC = pScan->pOrigWC;
+    k = 0;
+    pScan->iEquiv += 2;
+  }
+  return 0;
+}
+
+/*
+** Initialize a WHERE clause scanner object.  Return a pointer to the
+** first match.  Return NULL if there are no matches.
+**
+** The scanner will be searching the WHERE clause pWC.  It will look
+** for terms of the form "X <op> <expr>" where X is column iColumn of table
+** iCur.  The <op> must be one of the operators described by opMask.
+**
+** If the search is for X and the WHERE clause contains terms of the
+** form X=Y then this routine might also return terms of the form
+** "Y <op> <expr>".  The number of levels of transitivity is limited,
+** but is enough to handle most commonly occurring SQL statements.
+**
+** If X is not the INTEGER PRIMARY KEY then X must be compatible with
+** index pIdx.
+*/
+static WhereTerm *whereScanInit(
+  WhereScan *pScan,       /* The WhereScan object being initialized */
+  WhereClause *pWC,       /* The WHERE clause to be scanned */
+  int iCur,               /* Cursor to scan for */
+  int iColumn,            /* Column to scan for */
+  u32 opMask,             /* Operator(s) to scan for */
+  Index *pIdx             /* Must be compatible with this index */
+){
+  int j;
+
+  /* memset(pScan, 0, sizeof(*pScan)); */
+  pScan->pOrigWC = pWC;
+  pScan->pWC = pWC;
+  if( pIdx && iColumn>=0 ){
+    pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
+    for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
+      if( NEVER(j>pIdx->nColumn) ) return 0;
+    }
+    pScan->zCollName = pIdx->azColl[j];
+  }else{
+    pScan->idxaff = 0;
+    pScan->zCollName = 0;
+  }
+  pScan->opMask = opMask;
+  pScan->k = 0;
+  pScan->aEquiv[0] = iCur;
+  pScan->aEquiv[1] = iColumn;
+  pScan->nEquiv = 2;
+  pScan->iEquiv = 2;
+  return whereScanNext(pScan);
+}
+
+/*
 ** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
 ** where X is a reference to the iColumn of table iCur and <op> is one of
 ** the WO_xx operator codes specified by the op parameter.
@@ -105028,84 +111485,20 @@ static WhereTerm *findTerm(
   u32 op,               /* Mask of WO_xx values describing operator */
   Index *pIdx           /* Must be compatible with this index, if not NULL */
 ){
-  WhereTerm *pTerm;            /* Term being examined as possible result */
-  WhereTerm *pResult = 0;      /* The answer to return */
-  WhereClause *pWCOrig = pWC;  /* Original pWC value */
-  int j, k;                    /* Loop counters */
-  Expr *pX;                /* Pointer to an expression */
-  Parse *pParse;           /* Parsing context */
-  int iOrigCol = iColumn;  /* Original value of iColumn */
-  int nEquiv = 2;          /* Number of entires in aEquiv[] */
-  int iEquiv = 2;          /* Number of entries of aEquiv[] processed so far */
-  int aEquiv[22];          /* iCur,iColumn and up to 10 other equivalents */
-
-  assert( iCur>=0 );
-  aEquiv[0] = iCur;
-  aEquiv[1] = iColumn;
-  for(;;){
-    for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){
-      for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
-        if( pTerm->leftCursor==iCur
-          && pTerm->u.leftColumn==iColumn
-        ){
-          if( (pTerm->prereqRight & notReady)==0
-           && (pTerm->eOperator & op & WO_ALL)!=0
-          ){
-            if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
-              CollSeq *pColl;
-              char idxaff;
-      
-              pX = pTerm->pExpr;
-              pParse = pWC->pParse;
-              idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
-              if( !sqlite3IndexAffinityOk(pX, idxaff) ){
-                continue;
-              }
-      
-              /* Figure out the collation sequence required from an index for
-              ** it to be useful for optimising expression pX. Store this
-              ** value in variable pColl.
-              */
-              assert(pX->pLeft);
-              pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
-              if( pColl==0 ) pColl = pParse->db->pDfltColl;
-      
-              for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
-                if( NEVER(j>=pIdx->nColumn) ) return 0;
-              }
-              if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){
-                continue;
-              }
-            }
-            if( pTerm->prereqRight==0 && (pTerm->eOperator&WO_EQ)!=0 ){
-              pResult = pTerm;
-              goto findTerm_success;
-            }else if( pResult==0 ){
-              pResult = pTerm;
-            }
-          }
-          if( (pTerm->eOperator & WO_EQUIV)!=0
-           && nEquiv<ArraySize(aEquiv)
-          ){
-            pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
-            assert( pX->op==TK_COLUMN );
-            for(j=0; j<nEquiv; j+=2){
-              if( aEquiv[j]==pX->iTable && aEquiv[j+1]==pX->iColumn ) break;
-            }
-            if( j==nEquiv ){
-              aEquiv[j] = pX->iTable;
-              aEquiv[j+1] = pX->iColumn;
-              nEquiv += 2;
-            }
-          }
-        }
+  WhereTerm *pResult = 0;
+  WhereTerm *p;
+  WhereScan scan;
+
+  p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx);
+  while( p ){
+    if( (p->prereqRight & notReady)==0 ){
+      if( p->prereqRight==0 && (p->eOperator&WO_EQ)!=0 ){
+        return p;
       }
+      if( pResult==0 ) pResult = p;
     }
-    if( iEquiv>=nEquiv ) break;
-    iCur = aEquiv[iEquiv++];
-    iColumn = aEquiv[iEquiv++];
+    p = whereScanNext(&scan);
   }
-findTerm_success:
   return pResult;
 }
 
@@ -105114,8 +111507,6 @@ static void exprAnalyze(SrcList*, WhereClause*, int);
 
 /*
 ** Call exprAnalyze on all terms in a WHERE clause.  
-**
-**
 */
 static void exprAnalyzeAll(
   SrcList *pTabList,       /* the FROM clause */
@@ -105171,15 +111562,12 @@ static int isLikeOrGlob(
   }
   assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
 
-  pRight = pList->a[0].pExpr;
+  pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr);
   op = pRight->op;
-  if( op==TK_REGISTER ){
-    op = pRight->op2;
-  }
   if( op==TK_VARIABLE ){
     Vdbe *pReprepare = pParse->pReprepare;
     int iCol = pRight->iColumn;
-    pVal = sqlite3VdbeGetValue(pReprepare, iCol, SQLITE_AFF_NONE);
+    pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_NONE);
     if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
       z = (char *)sqlite3_value_text(pVal);
     }
@@ -105261,8 +111649,10 @@ static int isMatchOfColumn(
 ** a join, then transfer the appropriate markings over to derived.
 */
 static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
-  pDerived->flags |= pBase->flags & EP_FromJoin;
-  pDerived->iRightJoinTable = pBase->iRightJoinTable;
+  if( pDerived ){
+    pDerived->flags |= pBase->flags & EP_FromJoin;
+    pDerived->iRightJoinTable = pBase->iRightJoinTable;
+  }
 }
 
 #if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
@@ -105321,10 +111711,10 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
 ** From another point of view, "indexable" means that the subterm could
 ** potentially be used with an index if an appropriate index exists.
 ** This analysis does not consider whether or not the index exists; that
-** is something the bestIndex() routine will determine.  This analysis
-** only looks at whether subterms appropriate for indexing exist.
+** is decided elsewhere.  This analysis only looks at whether subterms
+** appropriate for indexing exist.
 **
-** All examples A through E above all satisfy case 2.  But if a term
+** All examples A through E above satisfy case 2.  But if a term
 ** also statisfies case 1 (such as B) we know that the optimizer will
 ** always prefer case 1, so in that case we pretend that case 2 is not
 ** satisfied.
@@ -105347,11 +111737,11 @@ static void exprAnalyzeOrTerm(
   WhereClause *pWC,         /* the complete WHERE clause */
   int idxTerm               /* Index of the OR-term to be analyzed */
 ){
-  Parse *pParse = pWC->pParse;            /* Parser context */
+  WhereInfo *pWInfo = pWC->pWInfo;        /* WHERE clause processing context */
+  Parse *pParse = pWInfo->pParse;         /* Parser context */
   sqlite3 *db = pParse->db;               /* Database connection */
   WhereTerm *pTerm = &pWC->a[idxTerm];    /* The term to be analyzed */
   Expr *pExpr = pTerm->pExpr;             /* The expression of the term */
-  WhereMaskSet *pMaskSet = pWC->pMaskSet; /* Table use masks */
   int i;                                  /* Loop counters */
   WhereClause *pOrWc;       /* Breakup of pTerm into subterms */
   WhereTerm *pOrTerm;       /* A Sub-term within the pOrWc */
@@ -105370,7 +111760,7 @@ static void exprAnalyzeOrTerm(
   if( pOrInfo==0 ) return;
   pTerm->wtFlags |= TERM_ORINFO;
   pOrWc = &pOrInfo->wc;
-  whereClauseInit(pOrWc, pWC->pParse, pMaskSet, pWC->wctrlFlags);
+  whereClauseInit(pOrWc, pWInfo);
   whereSplit(pOrWc, pExpr, TK_OR);
   exprAnalyzeAll(pSrc, pOrWc);
   if( db->mallocFailed ) return;
@@ -105396,7 +111786,7 @@ static void exprAnalyzeOrTerm(
         pOrTerm->wtFlags |= TERM_ANDINFO;
         pOrTerm->eOperator = WO_AND;
         pAndWC = &pAndInfo->wc;
-        whereClauseInit(pAndWC, pWC->pParse, pMaskSet, pWC->wctrlFlags);
+        whereClauseInit(pAndWC, pWC->pWInfo);
         whereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
         exprAnalyzeAll(pSrc, pAndWC);
         pAndWC->pOuter = pWC;
@@ -105405,7 +111795,7 @@ static void exprAnalyzeOrTerm(
           for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
             assert( pAndTerm->pExpr );
             if( allowedOp(pAndTerm->pExpr->op) ){
-              b |= getMask(pMaskSet, pAndTerm->leftCursor);
+              b |= getMask(&pWInfo->sMaskSet, pAndTerm->leftCursor);
             }
           }
         }
@@ -105416,10 +111806,10 @@ static void exprAnalyzeOrTerm(
       ** corresponding TERM_VIRTUAL term */
     }else{
       Bitmask b;
-      b = getMask(pMaskSet, pOrTerm->leftCursor);
+      b = getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor);
       if( pOrTerm->wtFlags & TERM_VIRTUAL ){
         WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
-        b |= getMask(pMaskSet, pOther->leftCursor);
+        b |= getMask(&pWInfo->sMaskSet, pOther->leftCursor);
       }
       indexable &= b;
       if( (pOrTerm->eOperator & WO_EQ)==0 ){
@@ -105481,7 +111871,7 @@ static void exprAnalyzeOrTerm(
           assert( j==1 );
           continue;
         }
-        if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){
+        if( (chngToIN & getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor))==0 ){
           /* This term must be of the form t1.a==t2.b where t2 is in the
           ** chngToIN set but t1 is not.  This term will be either preceeded
           ** or follwed by an inverted copy (t2.b==t1.a).  Skip this term 
@@ -105500,7 +111890,7 @@ static void exprAnalyzeOrTerm(
         ** on the second iteration */
         assert( j==1 );
         assert( IsPowerOfTwo(chngToIN) );
-        assert( chngToIN==getMask(pMaskSet, iCursor) );
+        assert( chngToIN==getMask(&pWInfo->sMaskSet, iCursor) );
         break;
       }
       testcase( j==1 );
@@ -105534,8 +111924,6 @@ static void exprAnalyzeOrTerm(
     /* At this point, okToChngToIN is true if original pTerm satisfies
     ** case 1.  In that case, construct a new virtual term that is 
     ** pTerm converted into an IN operator.
-    **
-    ** EV: R-00211-15100
     */
     if( okToChngToIN ){
       Expr *pDup;            /* A transient duplicate expression */
@@ -105549,7 +111937,7 @@ static void exprAnalyzeOrTerm(
         assert( pOrTerm->leftCursor==iCursor );
         assert( pOrTerm->u.leftColumn==iColumn );
         pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
-        pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
+        pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
         pLeft = pOrTerm->pExpr->pLeft;
       }
       assert( pLeft!=0 );
@@ -105598,6 +111986,7 @@ static void exprAnalyze(
   WhereClause *pWC,         /* the WHERE clause */
   int idxTerm               /* Index of the term to be analyzed */
 ){
+  WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
   WhereTerm *pTerm;                /* The term to be analyzed */
   WhereMaskSet *pMaskSet;          /* Set of table index masks */
   Expr *pExpr;                     /* The expression to be analyzed */
@@ -105608,14 +111997,14 @@ static void exprAnalyze(
   int isComplete = 0;              /* RHS of LIKE/GLOB ends with wildcard */
   int noCase = 0;                  /* LIKE/GLOB distinguishes case */
   int op;                          /* Top-level operator.  pExpr->op */
-  Parse *pParse = pWC->pParse;     /* Parsing context */
+  Parse *pParse = pWInfo->pParse;  /* Parsing context */
   sqlite3 *db = pParse->db;        /* Database connection */
 
   if( db->mallocFailed ){
     return;
   }
   pTerm = &pWC->a[idxTerm];
-  pMaskSet = pWC->pMaskSet;
+  pMaskSet = &pWInfo->sMaskSet;
   pExpr = pTerm->pExpr;
   assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
   prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
@@ -105720,6 +112109,7 @@ static void exprAnalyze(
       pNewExpr = sqlite3PExpr(pParse, ops[i], 
                              sqlite3ExprDup(db, pExpr->pLeft, 0),
                              sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
+      transferJoinMarkings(pNewExpr, pExpr);
       idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
       testcase( idxNew==0 );
       exprAnalyze(pSrc, pWC, idxNew);
@@ -105776,9 +112166,7 @@ static void exprAnalyze(
         ** inequality.  To avoid this, make sure to also run the full
         ** LIKE on all candidate expressions by clearing the isComplete flag
         */
-        if( c=='A'-1 ) isComplete = 0;   /* EV: R-64339-08207 */
-
-
+        if( c=='A'-1 ) isComplete = 0;
         c = sqlite3UpperToLower[c];
       }
       *pC = c + 1;
@@ -105789,6 +112177,7 @@ static void exprAnalyze(
     pNewExpr1 = sqlite3PExpr(pParse, TK_GE, 
            sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
            pStr1, 0);
+    transferJoinMarkings(pNewExpr1, pExpr);
     idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
     testcase( idxNew1==0 );
     exprAnalyze(pSrc, pWC, idxNew1);
@@ -105796,6 +112185,7 @@ static void exprAnalyze(
     pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
            sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
            pStr2, 0);
+    transferJoinMarkings(pNewExpr2, pExpr);
     idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
     testcase( idxNew2==0 );
     exprAnalyze(pSrc, pWC, idxNew2);
@@ -105845,7 +112235,7 @@ static void exprAnalyze(
   }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
   /* When sqlite_stat3 histogram data is available an operator of the
   ** form "x IS NOT NULL" can sometimes be evaluated more efficiently
   ** as "x>NULL" if x is not an INTEGER PRIMARY KEY.  So construct a
@@ -105859,6 +112249,7 @@ static void exprAnalyze(
   if( pExpr->op==TK_NOTNULL
    && pExpr->pLeft->op==TK_COLUMN
    && pExpr->pLeft->iColumn>=0
+   && OptimizationEnabled(db, SQLITE_Stat3)
   ){
     Expr *pNewExpr;
     Expr *pLeft = pExpr->pLeft;
@@ -105884,7 +112275,7 @@ static void exprAnalyze(
       pNewTerm->prereqAll = pTerm->prereqAll;
     }
   }
-#endif /* SQLITE_ENABLE_STAT */
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
 
   /* Prevent ON clause terms of a LEFT JOIN from being used to drive
   ** an index for tables to the left of the join.
@@ -105893,11 +112284,8 @@ static void exprAnalyze(
 }
 
 /*
-** This function searches the expression list passed as the second argument
-** for an expression of type TK_COLUMN that refers to the same column and
-** uses the same collation sequence as the iCol'th column of index pIdx.
-** Argument iBase is the cursor number used for the table that pIdx refers
-** to.
+** This function searches pList for a entry that matches the iCol-th column
+** of index pIdx.
 **
 ** If such an expression is found, its index in pList->a[] is returned. If
 ** no expression is found, -1 is returned.
@@ -105929,76 +112317,17 @@ static int findIndexCol(
 }
 
 /*
-** This routine determines if pIdx can be used to assist in processing a
-** DISTINCT qualifier. In other words, it tests whether or not using this
-** index for the outer loop guarantees that rows with equal values for
-** all expressions in the pDistinct list are delivered grouped together.
-**
-** For example, the query 
-**
-**   SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
-**
-** can benefit from any index on columns "b" and "c".
-*/
-static int isDistinctIndex(
-  Parse *pParse,                  /* Parsing context */
-  WhereClause *pWC,               /* The WHERE clause */
-  Index *pIdx,                    /* The index being considered */
-  int base,                       /* Cursor number for the table pIdx is on */
-  ExprList *pDistinct,            /* The DISTINCT expressions */
-  int nEqCol                      /* Number of index columns with == */
-){
-  Bitmask mask = 0;               /* Mask of unaccounted for pDistinct exprs */
-  int i;                          /* Iterator variable */
-
-  assert( pDistinct!=0 );
-  if( pIdx->zName==0 || pDistinct->nExpr>=BMS ) return 0;
-  testcase( pDistinct->nExpr==BMS-1 );
-
-  /* Loop through all the expressions in the distinct list. If any of them
-  ** are not simple column references, return early. Otherwise, test if the
-  ** WHERE clause contains a "col=X" clause. If it does, the expression
-  ** can be ignored. If it does not, and the column does not belong to the
-  ** same table as index pIdx, return early. Finally, if there is no
-  ** matching "col=X" expression and the column is on the same table as pIdx,
-  ** set the corresponding bit in variable mask.
-  */
-  for(i=0; i<pDistinct->nExpr; i++){
-    WhereTerm *pTerm;
-    Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
-    if( p->op!=TK_COLUMN ) return 0;
-    pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
-    if( pTerm ){
-      Expr *pX = pTerm->pExpr;
-      CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
-      CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
-      if( p1==p2 ) continue;
-    }
-    if( p->iTable!=base ) return 0;
-    mask |= (((Bitmask)1) << i);
-  }
-
-  for(i=nEqCol; mask && i<pIdx->nColumn; i++){
-    int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
-    if( iExpr<0 ) break;
-    mask &= ~(((Bitmask)1) << iExpr);
-  }
-
-  return (mask==0);
-}
-
-
-/*
 ** Return true if the DISTINCT expression-list passed as the third argument
-** is redundant. A DISTINCT list is redundant if the database contains a
-** UNIQUE index that guarantees that the result of the query will be distinct
-** anyway.
+** is redundant.
+**
+** A DISTINCT list is redundant if the database contains some subset of
+** columns that are unique and non-null.
 */
 static int isDistinctRedundant(
-  Parse *pParse,
-  SrcList *pTabList,
-  WhereClause *pWC,
-  ExprList *pDistinct
+  Parse *pParse,            /* Parsing context */
+  SrcList *pTabList,        /* The FROM clause */
+  WhereClause *pWC,         /* The WHERE clause */
+  ExprList *pDistinct       /* The result set that needs to be DISTINCT */
 ){
   Table *pTab;
   Index *pIdx;
@@ -106035,17 +112364,17 @@ static int isDistinctRedundant(
   **      contain a "col=X" term are subject to a NOT NULL constraint.
   */
   for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
-    if( pIdx->onError==OE_None ) continue;
-    for(i=0; i<pIdx->nColumn; i++){
-      int iCol = pIdx->aiColumn[i];
+    if( !IsUniqueIndex(pIdx) ) continue;
+    for(i=0; i<pIdx->nKeyCol; i++){
+      i16 iCol = pIdx->aiColumn[i];
       if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){
         int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i);
-        if( iIdxCol<0 || pTab->aCol[pIdx->aiColumn[i]].notNull==0 ){
+        if( iIdxCol<0 || pTab->aCol[iCol].notNull==0 ){
           break;
         }
       }
     }
-    if( i==pIdx->nColumn ){
+    if( i==pIdx->nKeyCol ){
       /* This index implies that the DISTINCT qualifier is redundant. */
       return 1;
     }
@@ -106054,21 +112383,12 @@ static int isDistinctRedundant(
   return 0;
 }
 
+
 /*
-** Prepare a crude estimate of the logarithm of the input value.
-** The results need not be exact.  This is only used for estimating
-** the total cost of performing operations with O(logN) or O(NlogN)
-** complexity.  Because N is just a guess, it is no great tragedy if
-** logN is a little off.
+** Estimate the logarithm of the input value to base 2.
 */
-static double estLog(double N){
-  double logN = 1;
-  double x = 10;
-  while( N>x ){
-    logN += 1;
-    x *= 10;
-  }
-  return logN;
+static LogEst estLog(LogEst N){
+  return N<=10 ? 0 : sqlite3LogEst(N) - 33;
 }
 
 /*
@@ -106077,7 +112397,7 @@ static double estLog(double N){
 ** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
 ** are no-ops.
 */
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_DEBUG)
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
 static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
   int i;
   if( !sqlite3WhereTrace ) return;
@@ -106109,113 +112429,13 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
   sqlite3DebugPrintf("  idxStr=%s\n", p->idxStr);
   sqlite3DebugPrintf("  orderByConsumed=%d\n", p->orderByConsumed);
   sqlite3DebugPrintf("  estimatedCost=%g\n", p->estimatedCost);
+  sqlite3DebugPrintf("  estimatedRows=%lld\n", p->estimatedRows);
 }
 #else
 #define TRACE_IDX_INPUTS(A)
 #define TRACE_IDX_OUTPUTS(A)
 #endif
 
-/* 
-** Required because bestIndex() is called by bestOrClauseIndex() 
-*/
-static void bestIndex(WhereBestIdx*);
-
-/*
-** This routine attempts to find an scanning strategy that can be used 
-** to optimize an 'OR' expression that is part of a WHERE clause. 
-**
-** The table associated with FROM clause term pSrc may be either a
-** regular B-Tree table or a virtual table.
-*/
-static void bestOrClauseIndex(WhereBestIdx *p){
-#ifndef SQLITE_OMIT_OR_OPTIMIZATION
-  WhereClause *pWC = p->pWC;           /* The WHERE clause */
-  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
-  const int iCur = pSrc->iCursor;      /* The cursor of the table  */
-  const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur);  /* Bitmask for pSrc */
-  WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm];        /* End of pWC->a[] */
-  WhereTerm *pTerm;                    /* A single term of the WHERE clause */
-
-  /* The OR-clause optimization is disallowed if the INDEXED BY or
-  ** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */
-  if( pSrc->notIndexed || pSrc->pIndex!=0 ){
-    return;
-  }
-  if( pWC->wctrlFlags & WHERE_AND_ONLY ){
-    return;
-  }
-
-  /* Search the WHERE clause terms for a usable WO_OR term. */
-  for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
-    if( (pTerm->eOperator & WO_OR)!=0
-     && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
-     && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 
-    ){
-      WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
-      WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
-      WhereTerm *pOrTerm;
-      int flags = WHERE_MULTI_OR;
-      double rTotal = 0;
-      double nRow = 0;
-      Bitmask used = 0;
-      WhereBestIdx sBOI;
-
-      sBOI = *p;
-      sBOI.pOrderBy = 0;
-      sBOI.pDistinct = 0;
-      sBOI.ppIdxInfo = 0;
-      for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
-        WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", 
-          (pOrTerm - pOrWC->a), (pTerm - pWC->a)
-        ));
-        if( (pOrTerm->eOperator& WO_AND)!=0 ){
-          sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
-          bestIndex(&sBOI);
-        }else if( pOrTerm->leftCursor==iCur ){
-          WhereClause tempWC;
-          tempWC.pParse = pWC->pParse;
-          tempWC.pMaskSet = pWC->pMaskSet;
-          tempWC.pOuter = pWC;
-          tempWC.op = TK_AND;
-          tempWC.a = pOrTerm;
-          tempWC.wctrlFlags = 0;
-          tempWC.nTerm = 1;
-          sBOI.pWC = &tempWC;
-          bestIndex(&sBOI);
-        }else{
-          continue;
-        }
-        rTotal += sBOI.cost.rCost;
-        nRow += sBOI.cost.plan.nRow;
-        used |= sBOI.cost.used;
-        if( rTotal>=p->cost.rCost ) break;
-      }
-
-      /* If there is an ORDER BY clause, increase the scan cost to account 
-      ** for the cost of the sort. */
-      if( p->pOrderBy!=0 ){
-        WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
-                    rTotal, rTotal+nRow*estLog(nRow)));
-        rTotal += nRow*estLog(nRow);
-      }
-
-      /* If the cost of scanning using this OR term for optimization is
-      ** less than the current cost stored in pCost, replace the contents
-      ** of pCost. */
-      WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow));
-      if( rTotal<p->cost.rCost ){
-        p->cost.rCost = rTotal;
-        p->cost.used = used;
-        p->cost.plan.nRow = nRow;
-        p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
-        p->cost.plan.wsFlags = flags;
-        p->cost.plan.u.pTerm = pTerm;
-      }
-    }
-  }
-#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
-}
-
 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
 /*
 ** Return TRUE if the WHERE clause term pTerm is of a form where it
@@ -106231,88 +112451,13 @@ static int termCanDriveIndex(
   if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
   if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
   if( (pTerm->prereqRight & notReady)!=0 ) return 0;
+  if( pTerm->u.leftColumn<0 ) return 0;
   aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
   if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
   return 1;
 }
 #endif
 
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
-/*
-** If the query plan for pSrc specified in pCost is a full table scan
-** and indexing is allows (if there is no NOT INDEXED clause) and it
-** possible to construct a transient index that would perform better
-** than a full table scan even when the cost of constructing the index
-** is taken into account, then alter the query plan to use the
-** transient index.
-*/
-static void bestAutomaticIndex(WhereBestIdx *p){
-  Parse *pParse = p->pParse;            /* The parsing context */
-  WhereClause *pWC = p->pWC;            /* The WHERE clause */
-  struct SrcList_item *pSrc = p->pSrc;  /* The FROM clause term to search */
-  double nTableRow;                     /* Rows in the input table */
-  double logN;                          /* log(nTableRow) */
-  double costTempIdx;         /* per-query cost of the transient index */
-  WhereTerm *pTerm;           /* A single term of the WHERE clause */
-  WhereTerm *pWCEnd;          /* End of pWC->a[] */
-  Table *pTable;              /* Table tht might be indexed */
-
-  if( pParse->nQueryLoop<=(double)1 ){
-    /* There is no point in building an automatic index for a single scan */
-    return;
-  }
-  if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
-    /* Automatic indices are disabled at run-time */
-    return;
-  }
-  if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0
-   && (p->cost.plan.wsFlags & WHERE_COVER_SCAN)==0
-  ){
-    /* We already have some kind of index in use for this query. */
-    return;
-  }
-  if( pSrc->viaCoroutine ){
-    /* Cannot index a co-routine */
-    return;
-  }
-  if( pSrc->notIndexed ){
-    /* The NOT INDEXED clause appears in the SQL. */
-    return;
-  }
-  if( pSrc->isCorrelated ){
-    /* The source is a correlated sub-query. No point in indexing it. */
-    return;
-  }
-
-  assert( pParse->nQueryLoop >= (double)1 );
-  pTable = pSrc->pTab;
-  nTableRow = pTable->nRowEst;
-  logN = estLog(nTableRow);
-  costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
-  if( costTempIdx>=p->cost.rCost ){
-    /* The cost of creating the transient table would be greater than
-    ** doing the full table scan */
-    return;
-  }
-
-  /* Search for any equality comparison term */
-  pWCEnd = &pWC->a[pWC->nTerm];
-  for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
-    if( termCanDriveIndex(pTerm, pSrc, p->notReady) ){
-      WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n",
-                    p->cost.rCost, costTempIdx));
-      p->cost.rCost = costTempIdx;
-      p->cost.plan.nRow = logN + 1;
-      p->cost.plan.wsFlags = WHERE_TEMP_INDEX;
-      p->cost.used = pTerm->prereqRight;
-      break;
-    }
-  }
-}
-#else
-# define bestAutomaticIndex(A)  /* no-op */
-#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
-
 
 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
 /*
@@ -106327,50 +112472,61 @@ static void constructAutomaticIndex(
   Bitmask notReady,           /* Mask of cursors that are not available */
   WhereLevel *pLevel          /* Write new index here */
 ){
-  int nColumn;                /* Number of columns in the constructed index */
+  int nKeyCol;                /* Number of columns in the constructed index */
   WhereTerm *pTerm;           /* A single term of the WHERE clause */
   WhereTerm *pWCEnd;          /* End of pWC->a[] */
-  int nByte;                  /* Byte of memory needed for pIdx */
   Index *pIdx;                /* Object describing the transient index */
   Vdbe *v;                    /* Prepared statement under construction */
   int addrInit;               /* Address of the initialization bypass jump */
   Table *pTable;              /* The table being indexed */
-  KeyInfo *pKeyinfo;          /* Key information for the index */   
   int addrTop;                /* Top of the index fill loop */
   int regRecord;              /* Register holding an index record */
   int n;                      /* Column counter */
   int i;                      /* Loop counter */
   int mxBitCol;               /* Maximum column in pSrc->colUsed */
   CollSeq *pColl;             /* Collating sequence to on a column */
+  WhereLoop *pLoop;           /* The Loop object */
+  char *zNotUsed;             /* Extra space on the end of pIdx */
   Bitmask idxCols;            /* Bitmap of columns used for indexing */
   Bitmask extraCols;          /* Bitmap of additional columns */
+  u8 sentWarning = 0;         /* True if a warnning has been issued */
 
   /* Generate code to skip over the creation and initialization of the
   ** transient index on 2nd and subsequent iterations of the loop. */
   v = pParse->pVdbe;
   assert( v!=0 );
-  addrInit = sqlite3CodeOnce(pParse);
+  addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v);
 
   /* Count the number of columns that will be added to the index
   ** and used to match WHERE clause constraints */
-  nColumn = 0;
+  nKeyCol = 0;
   pTable = pSrc->pTab;
   pWCEnd = &pWC->a[pWC->nTerm];
+  pLoop = pLevel->pWLoop;
   idxCols = 0;
   for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
     if( termCanDriveIndex(pTerm, pSrc, notReady) ){
       int iCol = pTerm->u.leftColumn;
-      Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<<iCol;
+      Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
       testcase( iCol==BMS );
       testcase( iCol==BMS-1 );
+      if( !sentWarning ){
+        sqlite3_log(SQLITE_WARNING_AUTOINDEX,
+            "automatic index on %s(%s)", pTable->zName,
+            pTable->aCol[iCol].zName);
+        sentWarning = 1;
+      }
       if( (idxCols & cMask)==0 ){
-        nColumn++;
+        if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ) return;
+        pLoop->aLTerm[nKeyCol++] = pTerm;
         idxCols |= cMask;
       }
     }
   }
-  assert( nColumn>0 );
-  pLevel->plan.nEq = nColumn;
+  assert( nKeyCol>0 );
+  pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol;
+  pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
+                     | WHERE_AUTO_INDEX;
 
   /* Count the number of additional columns needed to create a
   ** covering index.  A "covering index" is an index that contains all
@@ -106380,38 +112536,32 @@ static void constructAutomaticIndex(
   ** original table changes and the index and table cannot both be used
   ** if they go out of sync.
   */
-  extraCols = pSrc->colUsed & (~idxCols | (((Bitmask)1)<<(BMS-1)));
+  extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
   mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol;
   testcase( pTable->nCol==BMS-1 );
   testcase( pTable->nCol==BMS-2 );
   for(i=0; i<mxBitCol; i++){
-    if( extraCols & (((Bitmask)1)<<i) ) nColumn++;
+    if( extraCols & MASKBIT(i) ) nKeyCol++;
   }
-  if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
-    nColumn += pTable->nCol - BMS + 1;
+  if( pSrc->colUsed & MASKBIT(BMS-1) ){
+    nKeyCol += pTable->nCol - BMS + 1;
   }
-  pLevel->plan.wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WO_EQ;
+  pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY;
 
   /* Construct the Index object to describe this index */
-  nByte = sizeof(Index);
-  nByte += nColumn*sizeof(int);     /* Index.aiColumn */
-  nByte += nColumn*sizeof(char*);   /* Index.azColl */
-  nByte += nColumn;                 /* Index.aSortOrder */
-  pIdx = sqlite3DbMallocZero(pParse->db, nByte);
+  pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed);
   if( pIdx==0 ) return;
-  pLevel->plan.u.pIdx = pIdx;
-  pIdx->azColl = (char**)&pIdx[1];
-  pIdx->aiColumn = (int*)&pIdx->azColl[nColumn];
-  pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn];
+  pLoop->u.btree.pIndex = pIdx;
   pIdx->zName = "auto-index";
-  pIdx->nColumn = nColumn;
   pIdx->pTable = pTable;
   n = 0;
   idxCols = 0;
   for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
     if( termCanDriveIndex(pTerm, pSrc, notReady) ){
       int iCol = pTerm->u.leftColumn;
-      Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<<iCol;
+      Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
+      testcase( iCol==BMS-1 );
+      testcase( iCol==BMS );
       if( (idxCols & cMask)==0 ){
         Expr *pX = pTerm->pExpr;
         idxCols |= cMask;
@@ -106422,40 +112572,42 @@ static void constructAutomaticIndex(
       }
     }
   }
-  assert( (u32)n==pLevel->plan.nEq );
+  assert( (u32)n==pLoop->u.btree.nEq );
 
   /* Add additional columns needed to make the automatic index into
   ** a covering index */
   for(i=0; i<mxBitCol; i++){
-    if( extraCols & (((Bitmask)1)<<i) ){
+    if( extraCols & MASKBIT(i) ){
       pIdx->aiColumn[n] = i;
       pIdx->azColl[n] = "BINARY";
       n++;
     }
   }
-  if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
+  if( pSrc->colUsed & MASKBIT(BMS-1) ){
     for(i=BMS-1; i<pTable->nCol; i++){
       pIdx->aiColumn[n] = i;
       pIdx->azColl[n] = "BINARY";
       n++;
     }
   }
-  assert( n==nColumn );
+  assert( n==nKeyCol );
+  pIdx->aiColumn[n] = -1;
+  pIdx->azColl[n] = "BINARY";
 
   /* Create the automatic index */
-  pKeyinfo = sqlite3IndexKeyinfo(pParse, pIdx);
   assert( pLevel->iIdxCur>=0 );
-  sqlite3VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0,
-                    (char*)pKeyinfo, P4_KEYINFO_HANDOFF);
+  pLevel->iIdxCur = pParse->nTab++;
+  sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
+  sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
   VdbeComment((v, "for %s", pTable->zName));
 
   /* Fill the automatic index with content */
-  addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur);
+  addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
   regRecord = sqlite3GetTempReg(pParse);
-  sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 1);
+  sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0);
   sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
   sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
-  sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
+  sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
   sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
   sqlite3VdbeJumpHere(v, addrTop);
   sqlite3ReleaseTempReg(pParse, regRecord);
@@ -106471,11 +112623,12 @@ static void constructAutomaticIndex(
 ** responsibility of the caller to eventually release the structure
 ** by passing the pointer returned by this function to sqlite3_free().
 */
-static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
-  Parse *pParse = p->pParse; 
-  WhereClause *pWC = p->pWC;
-  struct SrcList_item *pSrc = p->pSrc;
-  ExprList *pOrderBy = p->pOrderBy;
+static sqlite3_index_info *allocateIndexInfo(
+  Parse *pParse,
+  WhereClause *pWC,
+  struct SrcList_item *pSrc,
+  ExprList *pOrderBy
+){
   int i, j;
   int nTerm;
   struct sqlite3_index_constraint *pIdxCons;
@@ -106485,8 +112638,6 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
   int nOrderBy;
   sqlite3_index_info *pIdxInfo;
 
-  WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName));
-
   /* Count the number of possible WHERE clause constraints referring
   ** to this virtual table */
   for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
@@ -106494,7 +112645,8 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
     assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
     testcase( pTerm->eOperator & WO_IN );
     testcase( pTerm->eOperator & WO_ISNULL );
-    if( pTerm->eOperator & (WO_ISNULL) ) continue;
+    testcase( pTerm->eOperator & WO_ALL );
+    if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV))==0 ) continue;
     if( pTerm->wtFlags & TERM_VNULL ) continue;
     nTerm++;
   }
@@ -106522,7 +112674,6 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
                            + sizeof(*pIdxOrderBy)*nOrderBy );
   if( pIdxInfo==0 ){
     sqlite3ErrorMsg(pParse, "out of memory");
-    /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
     return 0;
   }
 
@@ -106547,7 +112698,8 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
     assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
     testcase( pTerm->eOperator & WO_IN );
     testcase( pTerm->eOperator & WO_ISNULL );
-    if( pTerm->eOperator & (WO_ISNULL) ) continue;
+    testcase( pTerm->eOperator & WO_ALL );
+    if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV))==0 ) continue;
     if( pTerm->wtFlags & TERM_VNULL ) continue;
     pIdxCons[j].iColumn = pTerm->u.leftColumn;
     pIdxCons[j].iTermOffset = i;
@@ -106578,8 +112730,8 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
 /*
 ** The table object reference passed as the second argument to this function
 ** must represent a virtual table. This function invokes the xBestIndex()
-** method of the virtual table with the sqlite3_index_info pointer passed
-** as the argument.
+** method of the virtual table with the sqlite3_index_info object that
+** comes in as the 3rd argument to this function.
 **
 ** If an error occurs, pParse is populated with an error message and a
 ** non-zero value is returned. Otherwise, 0 is returned and the output
@@ -106594,7 +112746,6 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
   int i;
   int rc;
 
-  WHERETRACE(("xBestIndex for %s\n", pTab->zName));
   TRACE_IDX_INPUTS(p);
   rc = pVtab->pModule->xBestIndex(pVtab, p);
   TRACE_IDX_OUTPUTS(p);
@@ -106620,209 +112771,10 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
 
   return pParse->nErr;
 }
+#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
 
 
-/*
-** Compute the best index for a virtual table.
-**
-** The best index is computed by the xBestIndex method of the virtual
-** table module.  This routine is really just a wrapper that sets up
-** the sqlite3_index_info structure that is used to communicate with
-** xBestIndex.
-**
-** In a join, this routine might be called multiple times for the
-** same virtual table.  The sqlite3_index_info structure is created
-** and initialized on the first invocation and reused on all subsequent
-** invocations.  The sqlite3_index_info structure is also used when
-** code is generated to access the virtual table.  The whereInfoDelete() 
-** routine takes care of freeing the sqlite3_index_info structure after
-** everybody has finished with it.
-*/
-static void bestVirtualIndex(WhereBestIdx *p){
-  Parse *pParse = p->pParse;      /* The parsing context */
-  WhereClause *pWC = p->pWC;      /* The WHERE clause */
-  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
-  Table *pTab = pSrc->pTab;
-  sqlite3_index_info *pIdxInfo;
-  struct sqlite3_index_constraint *pIdxCons;
-  struct sqlite3_index_constraint_usage *pUsage;
-  WhereTerm *pTerm;
-  int i, j;
-  int nOrderBy;
-  int bAllowIN;                   /* Allow IN optimizations */
-  double rCost;
-
-  /* Make sure wsFlags is initialized to some sane value. Otherwise, if the 
-  ** malloc in allocateIndexInfo() fails and this function returns leaving
-  ** wsFlags in an uninitialized state, the caller may behave unpredictably.
-  */
-  memset(&p->cost, 0, sizeof(p->cost));
-  p->cost.plan.wsFlags = WHERE_VIRTUALTABLE;
-
-  /* If the sqlite3_index_info structure has not been previously
-  ** allocated and initialized, then allocate and initialize it now.
-  */
-  pIdxInfo = *p->ppIdxInfo;
-  if( pIdxInfo==0 ){
-    *p->ppIdxInfo = pIdxInfo = allocateIndexInfo(p);
-  }
-  if( pIdxInfo==0 ){
-    return;
-  }
-
-  /* At this point, the sqlite3_index_info structure that pIdxInfo points
-  ** to will have been initialized, either during the current invocation or
-  ** during some prior invocation.  Now we just have to customize the
-  ** details of pIdxInfo for the current invocation and pass it to
-  ** xBestIndex.
-  */
-
-  /* The module name must be defined. Also, by this point there must
-  ** be a pointer to an sqlite3_vtab structure. Otherwise
-  ** sqlite3ViewGetColumnNames() would have picked up the error. 
-  */
-  assert( pTab->azModuleArg && pTab->azModuleArg[0] );
-  assert( sqlite3GetVTable(pParse->db, pTab) );
-
-  /* Try once or twice.  On the first attempt, allow IN optimizations.
-  ** If an IN optimization is accepted by the virtual table xBestIndex
-  ** method, but the  pInfo->aConstrainUsage.omit flag is not set, then
-  ** the query will not work because it might allow duplicate rows in
-  ** output.  In that case, run the xBestIndex method a second time
-  ** without the IN constraints.  Usually this loop only runs once.
-  ** The loop will exit using a "break" statement.
-  */
-  for(bAllowIN=1; 1; bAllowIN--){
-    assert( bAllowIN==0 || bAllowIN==1 );
-
-    /* Set the aConstraint[].usable fields and initialize all 
-    ** output variables to zero.
-    **
-    ** aConstraint[].usable is true for constraints where the right-hand
-    ** side contains only references to tables to the left of the current
-    ** table.  In other words, if the constraint is of the form:
-    **
-    **           column = expr
-    **
-    ** and we are evaluating a join, then the constraint on column is 
-    ** only valid if all tables referenced in expr occur to the left
-    ** of the table containing column.
-    **
-    ** The aConstraints[] array contains entries for all constraints
-    ** on the current table.  That way we only have to compute it once
-    ** even though we might try to pick the best index multiple times.
-    ** For each attempt at picking an index, the order of tables in the
-    ** join might be different so we have to recompute the usable flag
-    ** each time.
-    */
-    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
-    pUsage = pIdxInfo->aConstraintUsage;
-    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
-      j = pIdxCons->iTermOffset;
-      pTerm = &pWC->a[j];
-      if( (pTerm->prereqRight&p->notReady)==0
-       && (bAllowIN || (pTerm->eOperator & WO_IN)==0)
-      ){
-        pIdxCons->usable = 1;
-      }else{
-        pIdxCons->usable = 0;
-      }
-    }
-    memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
-    if( pIdxInfo->needToFreeIdxStr ){
-      sqlite3_free(pIdxInfo->idxStr);
-    }
-    pIdxInfo->idxStr = 0;
-    pIdxInfo->idxNum = 0;
-    pIdxInfo->needToFreeIdxStr = 0;
-    pIdxInfo->orderByConsumed = 0;
-    /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
-    pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
-    nOrderBy = pIdxInfo->nOrderBy;
-    if( !p->pOrderBy ){
-      pIdxInfo->nOrderBy = 0;
-    }
-  
-    if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
-      return;
-    }
-  
-    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
-    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
-      if( pUsage[i].argvIndex>0 ){
-        j = pIdxCons->iTermOffset;
-        pTerm = &pWC->a[j];
-        p->cost.used |= pTerm->prereqRight;
-        if( (pTerm->eOperator & WO_IN)!=0 ){
-          if( pUsage[i].omit==0 ){
-            /* Do not attempt to use an IN constraint if the virtual table
-            ** says that the equivalent EQ constraint cannot be safely omitted.
-            ** If we do attempt to use such a constraint, some rows might be
-            ** repeated in the output. */
-            break;
-          }
-          /* A virtual table that is constrained by an IN clause may not
-          ** consume the ORDER BY clause because (1) the order of IN terms
-          ** is not necessarily related to the order of output terms and
-          ** (2) Multiple outputs from a single IN value will not merge
-          ** together.  */
-          pIdxInfo->orderByConsumed = 0;
-        }
-      }
-    }
-    if( i>=pIdxInfo->nConstraint ) break;
-  }
-
-  /* The orderByConsumed signal is only valid if all outer loops collectively
-  ** generate just a single row of output.
-  */
-  if( pIdxInfo->orderByConsumed ){
-    for(i=0; i<p->i; i++){
-      if( (p->aLevel[i].plan.wsFlags & WHERE_UNIQUE)==0 ){
-        pIdxInfo->orderByConsumed = 0;
-      }
-    }
-  }
-  
-  /* If there is an ORDER BY clause, and the selected virtual table index
-  ** does not satisfy it, increase the cost of the scan accordingly. This
-  ** matches the processing for non-virtual tables in bestBtreeIndex().
-  */
-  rCost = pIdxInfo->estimatedCost;
-  if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){
-    rCost += estLog(rCost)*rCost;
-  }
-
-  /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the
-  ** inital value of lowestCost in this loop. If it is, then the
-  ** (cost<lowestCost) test below will never be true.
-  ** 
-  ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT 
-  ** is defined.
-  */
-  if( (SQLITE_BIG_DBL/((double)2))<rCost ){
-    p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
-  }else{
-    p->cost.rCost = rCost;
-  }
-  p->cost.plan.u.pVtabIdx = pIdxInfo;
-  if( pIdxInfo->orderByConsumed ){
-    p->cost.plan.wsFlags |= WHERE_ORDERED;
-    p->cost.plan.nOBSat = nOrderBy;
-  }else{
-    p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
-  }
-  p->cost.plan.nEq = 0;
-  pIdxInfo->nOrderBy = nOrderBy;
-
-  /* Try to find a more efficient access pattern by using multiple indexes
-  ** to optimize an OR expression within the WHERE clause. 
-  */
-  bestOrClauseIndex(p);
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
 /*
 ** Estimate the location of a particular key among all keys in an
 ** index.  Store the results in aStat as follows:
@@ -106832,140 +112784,76 @@ static void bestVirtualIndex(WhereBestIdx *p){
 **
 ** Return SQLITE_OK on success.
 */
-static int whereKeyStats(
+static void whereKeyStats(
   Parse *pParse,              /* Database connection */
   Index *pIdx,                /* Index to consider domain of */
-  sqlite3_value *pVal,        /* Value to consider */
+  UnpackedRecord *pRec,       /* Vector of values to consider */
   int roundUp,                /* Round up if true.  Round down if false */
   tRowcnt *aStat              /* OUT: stats written here */
 ){
-  tRowcnt n;
-  IndexSample *aSample;
-  int i, eType;
-  int isEq = 0;
-  i64 v;
-  double r, rS;
+  IndexSample *aSample = pIdx->aSample;
+  int iCol;                   /* Index of required stats in anEq[] etc. */
+  int iMin = 0;               /* Smallest sample not yet tested */
+  int i = pIdx->nSample;      /* Smallest sample larger than or equal to pRec */
+  int iTest;                  /* Next sample to test */
+  int res;                    /* Result of comparison operation */
 
-  assert( roundUp==0 || roundUp==1 );
+#ifndef SQLITE_DEBUG
+  UNUSED_PARAMETER( pParse );
+#endif
+  assert( pRec!=0 );
+  iCol = pRec->nField - 1;
   assert( pIdx->nSample>0 );
-  if( pVal==0 ) return SQLITE_ERROR;
-  n = pIdx->aiRowEst[0];
-  aSample = pIdx->aSample;
-  eType = sqlite3_value_type(pVal);
-
-  if( eType==SQLITE_INTEGER ){
-    v = sqlite3_value_int64(pVal);
-    r = (i64)v;
-    for(i=0; i<pIdx->nSample; i++){
-      if( aSample[i].eType==SQLITE_NULL ) continue;
-      if( aSample[i].eType>=SQLITE_TEXT ) break;
-      if( aSample[i].eType==SQLITE_INTEGER ){
-        if( aSample[i].u.i>=v ){
-          isEq = aSample[i].u.i==v;
-          break;
-        }
-      }else{
-        assert( aSample[i].eType==SQLITE_FLOAT );
-        if( aSample[i].u.r>=r ){
-          isEq = aSample[i].u.r==r;
-          break;
-        }
-      }
-    }
-  }else if( eType==SQLITE_FLOAT ){
-    r = sqlite3_value_double(pVal);
-    for(i=0; i<pIdx->nSample; i++){
-      if( aSample[i].eType==SQLITE_NULL ) continue;
-      if( aSample[i].eType>=SQLITE_TEXT ) break;
-      if( aSample[i].eType==SQLITE_FLOAT ){
-        rS = aSample[i].u.r;
-      }else{
-        rS = aSample[i].u.i;
-      }
-      if( rS>=r ){
-        isEq = rS==r;
-        break;
-      }
+  assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
+  do{
+    iTest = (iMin+i)/2;
+    res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec, 0);
+    if( res<0 ){
+      iMin = iTest+1;
+    }else{
+      i = iTest;
     }
-  }else if( eType==SQLITE_NULL ){
-    i = 0;
-    if( aSample[0].eType==SQLITE_NULL ) isEq = 1;
+  }while( res && iMin<i );
+
+#ifdef SQLITE_DEBUG
+  /* The following assert statements check that the binary search code
+  ** above found the right answer. This block serves no purpose other
+  ** than to invoke the asserts.  */
+  if( res==0 ){
+    /* If (res==0) is true, then sample $i must be equal to pRec */
+    assert( i<pIdx->nSample );
+    assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)
+         || pParse->db->mallocFailed );
   }else{
-    assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
-    for(i=0; i<pIdx->nSample; i++){
-      if( aSample[i].eType==SQLITE_TEXT || aSample[i].eType==SQLITE_BLOB ){
-        break;
-      }
-    }
-    if( i<pIdx->nSample ){      
-      sqlite3 *db = pParse->db;
-      CollSeq *pColl;
-      const u8 *z;
-      if( eType==SQLITE_BLOB ){
-        z = (const u8 *)sqlite3_value_blob(pVal);
-        pColl = db->pDfltColl;
-        assert( pColl->enc==SQLITE_UTF8 );
-      }else{
-        pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl);
-        if( pColl==0 ){
-          return SQLITE_ERROR;
-        }
-        z = (const u8 *)sqlite3ValueText(pVal, pColl->enc);
-        if( !z ){
-          return SQLITE_NOMEM;
-        }
-        assert( z && pColl && pColl->xCmp );
-      }
-      n = sqlite3ValueBytes(pVal, pColl->enc);
-  
-      for(; i<pIdx->nSample; i++){
-        int c;
-        int eSampletype = aSample[i].eType;
-        if( eSampletype<eType ) continue;
-        if( eSampletype!=eType ) break;
-#ifndef SQLITE_OMIT_UTF16
-        if( pColl->enc!=SQLITE_UTF8 ){
-          int nSample;
-          char *zSample = sqlite3Utf8to16(
-              db, pColl->enc, aSample[i].u.z, aSample[i].nByte, &nSample
-          );
-          if( !zSample ){
-            assert( db->mallocFailed );
-            return SQLITE_NOMEM;
-          }
-          c = pColl->xCmp(pColl->pUser, nSample, zSample, n, z);
-          sqlite3DbFree(db, zSample);
-        }else
-#endif
-        {
-          c = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z);
-        }
-        if( c>=0 ){
-          if( c==0 ) isEq = 1;
-          break;
-        }
-      }
-    }
+    /* Otherwise, pRec must be smaller than sample $i and larger than
+    ** sample ($i-1).  */
+    assert( i==pIdx->nSample 
+         || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)>0
+         || pParse->db->mallocFailed );
+    assert( i==0
+         || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec, 0)<0
+         || pParse->db->mallocFailed );
   }
+#endif /* ifdef SQLITE_DEBUG */
 
   /* At this point, aSample[i] is the first sample that is greater than
   ** or equal to pVal.  Or if i==pIdx->nSample, then all samples are less
-  ** than pVal.  If aSample[i]==pVal, then isEq==1.
+  ** than pVal.  If aSample[i]==pVal, then res==0.
   */
-  if( isEq ){
-    assert( i<pIdx->nSample );
-    aStat[0] = aSample[i].nLt;
-    aStat[1] = aSample[i].nEq;
+  if( res==0 ){
+    aStat[0] = aSample[i].anLt[iCol];
+    aStat[1] = aSample[i].anEq[iCol];
   }else{
     tRowcnt iLower, iUpper, iGap;
     if( i==0 ){
       iLower = 0;
-      iUpper = aSample[0].nLt;
+      iUpper = aSample[0].anLt[iCol];
     }else{
-      iUpper = i>=pIdx->nSample ? n : aSample[i].nLt;
-      iLower = aSample[i-1].nEq + aSample[i-1].nLt;
+      i64 nRow0 = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]);
+      iUpper = i>=pIdx->nSample ? nRow0 : aSample[i].anLt[iCol];
+      iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol];
     }
-    aStat[1] = pIdx->avgEq;
+    aStat[1] = pIdx->aAvgEq[iCol];
     if( iLower>=iUpper ){
       iGap = 0;
     }else{
@@ -106978,44 +112866,140 @@ static int whereKeyStats(
     }
     aStat[0] = iLower + iGap;
   }
-  return SQLITE_OK;
 }
-#endif /* SQLITE_ENABLE_STAT3 */
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
 
 /*
-** If expression pExpr represents a literal value, set *pp to point to
-** an sqlite3_value structure containing the same value, with affinity
-** aff applied to it, before returning. It is the responsibility of the 
-** caller to eventually release this structure by passing it to 
-** sqlite3ValueFree().
+** If it is not NULL, pTerm is a term that provides an upper or lower
+** bound on a range scan. Without considering pTerm, it is estimated 
+** that the scan will visit nNew rows. This function returns the number
+** estimated to be visited after taking pTerm into account.
+**
+** If the user explicitly specified a likelihood() value for this term,
+** then the return value is the likelihood multiplied by the number of
+** input rows. Otherwise, this function assumes that an "IS NOT NULL" term
+** has a likelihood of 0.50, and any other term a likelihood of 0.25.
+*/
+static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){
+  LogEst nRet = nNew;
+  if( pTerm ){
+    if( pTerm->truthProb<=0 ){
+      nRet += pTerm->truthProb;
+    }else if( (pTerm->wtFlags & TERM_VNULL)==0 ){
+      nRet -= 20;        assert( 20==sqlite3LogEst(4) );
+    }
+  }
+  return nRet;
+}
+
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+/* 
+** This function is called to estimate the number of rows visited by a
+** range-scan on a skip-scan index. For example:
+**
+**   CREATE INDEX i1 ON t1(a, b, c);
+**   SELECT * FROM t1 WHERE a=? AND c BETWEEN ? AND ?;
+**
+** Value pLoop->nOut is currently set to the estimated number of rows 
+** visited for scanning (a=? AND b=?). This function reduces that estimate 
+** by some factor to account for the (c BETWEEN ? AND ?) expression based
+** on the stat4 data for the index. this scan will be peformed multiple 
+** times (once for each (a,b) combination that matches a=?) is dealt with 
+** by the caller.
+**
+** It does this by scanning through all stat4 samples, comparing values
+** extracted from pLower and pUpper with the corresponding column in each
+** sample. If L and U are the number of samples found to be less than or
+** equal to the values extracted from pLower and pUpper respectively, and
+** N is the total number of samples, the pLoop->nOut value is adjusted
+** as follows:
+**
+**   nOut = nOut * ( min(U - L, 1) / N )
 **
-** If the current parse is a recompile (sqlite3Reprepare()) and pExpr
-** is an SQL variable that currently has a non-NULL value bound to it,
-** create an sqlite3_value structure containing this value, again with
-** affinity aff applied to it, instead.
+** If pLower is NULL, or a value cannot be extracted from the term, L is
+** set to zero. If pUpper is NULL, or a value cannot be extracted from it,
+** U is set to N.
 **
-** If neither of the above apply, set *pp to NULL.
+** Normally, this function sets *pbDone to 1 before returning. However,
+** if no value can be extracted from either pLower or pUpper (and so the
+** estimate of the number of rows delivered remains unchanged), *pbDone
+** is left as is.
 **
-** If an error occurs, return an error code. Otherwise, SQLITE_OK.
+** If an error occurs, an SQLite error code is returned. Otherwise, 
+** SQLITE_OK.
 */
-#ifdef SQLITE_ENABLE_STAT3
-static int valueFromExpr(
-  Parse *pParse, 
-  Expr *pExpr, 
-  u8 aff, 
-  sqlite3_value **pp
+static int whereRangeSkipScanEst(
+  Parse *pParse,       /* Parsing & code generating context */
+  WhereTerm *pLower,   /* Lower bound on the range. ex: "x>123" Might be NULL */
+  WhereTerm *pUpper,   /* Upper bound on the range. ex: "x<455" Might be NULL */
+  WhereLoop *pLoop,    /* Update the .nOut value of this loop */
+  int *pbDone          /* Set to true if at least one expr. value extracted */
 ){
-  if( pExpr->op==TK_VARIABLE
-   || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
-  ){
-    int iVar = pExpr->iColumn;
-    sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
-    *pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff);
-    return SQLITE_OK;
+  Index *p = pLoop->u.btree.pIndex;
+  int nEq = pLoop->u.btree.nEq;
+  sqlite3 *db = pParse->db;
+  int nLower = -1;
+  int nUpper = p->nSample+1;
+  int rc = SQLITE_OK;
+  int iCol = p->aiColumn[nEq];
+  u8 aff = iCol>=0 ? p->pTable->aCol[iCol].affinity : SQLITE_AFF_INTEGER;
+  CollSeq *pColl;
+  
+  sqlite3_value *p1 = 0;          /* Value extracted from pLower */
+  sqlite3_value *p2 = 0;          /* Value extracted from pUpper */
+  sqlite3_value *pVal = 0;        /* Value extracted from record */
+
+  pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]);
+  if( pLower ){
+    rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->pRight, aff, &p1);
+    nLower = 0;
   }
-  return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp);
+  if( pUpper && rc==SQLITE_OK ){
+    rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->pRight, aff, &p2);
+    nUpper = p2 ? 0 : p->nSample;
+  }
+
+  if( p1 || p2 ){
+    int i;
+    int nDiff;
+    for(i=0; rc==SQLITE_OK && i<p->nSample; i++){
+      rc = sqlite3Stat4Column(db, p->aSample[i].p, p->aSample[i].n, nEq, &pVal);
+      if( rc==SQLITE_OK && p1 ){
+        int res = sqlite3MemCompare(p1, pVal, pColl);
+        if( res>=0 ) nLower++;
+      }
+      if( rc==SQLITE_OK && p2 ){
+        int res = sqlite3MemCompare(p2, pVal, pColl);
+        if( res>=0 ) nUpper++;
+      }
+    }
+    nDiff = (nUpper - nLower);
+    if( nDiff<=0 ) nDiff = 1;
+
+    /* If there is both an upper and lower bound specified, and the 
+    ** comparisons indicate that they are close together, use the fallback
+    ** method (assume that the scan visits 1/64 of the rows) for estimating
+    ** the number of rows visited. Otherwise, estimate the number of rows
+    ** using the method described in the header comment for this function. */
+    if( nDiff!=1 || pUpper==0 || pLower==0 ){
+      int nAdjust = (sqlite3LogEst(p->nSample) - sqlite3LogEst(nDiff));
+      pLoop->nOut -= nAdjust;
+      *pbDone = 1;
+      WHERETRACE(0x10, ("range skip-scan regions: %u..%u  adjust=%d est=%d\n",
+                           nLower, nUpper, nAdjust*-1, pLoop->nOut));
+    }
+
+  }else{
+    assert( *pbDone==0 );
+  }
+
+  sqlite3ValueFree(p1);
+  sqlite3ValueFree(p2);
+  sqlite3ValueFree(pVal);
+
+  return rc;
 }
-#endif
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
 
 /*
 ** This function is used to estimate the number of rows that will be visited
@@ -107032,97 +113016,167 @@ static int valueFromExpr(
 ** If either of the upper or lower bound is not present, then NULL is passed in
 ** place of the corresponding WhereTerm.
 **
-** The nEq parameter is passed the index of the index column subject to the
-** range constraint. Or, equivalently, the number of equality constraints
-** optimized by the proposed index scan. For example, assuming index p is
-** on t1(a, b), and the SQL query is:
+** The value in (pBuilder->pNew->u.btree.nEq) is the index of the index
+** column subject to the range constraint. Or, equivalently, the number of
+** equality constraints optimized by the proposed index scan. For example,
+** assuming index p is on t1(a, b), and the SQL query is:
 **
 **   ... FROM t1 WHERE a = ? AND b > ? AND b < ? ...
 **
-** then nEq should be passed the value 1 (as the range restricted column,
-** b, is the second left-most column of the index). Or, if the query is:
+** then nEq is set to 1 (as the range restricted column, b, is the second 
+** left-most column of the index). Or, if the query is:
 **
 **   ... FROM t1 WHERE a > ? AND a < ? ...
 **
-** then nEq should be passed 0.
+** then nEq is set to 0.
 **
-** The returned value is an integer divisor to reduce the estimated
-** search space.  A return value of 1 means that range constraints are
-** no help at all.  A return value of 2 means range constraints are
-** expected to reduce the search space by half.  And so forth...
-**
-** In the absence of sqlite_stat3 ANALYZE data, each range inequality
-** reduces the search space by a factor of 4.  Hence a single constraint (x>?)
-** results in a return of 4 and a range constraint (x>? AND x<?) results
-** in a return of 16.
+** When this function is called, *pnOut is set to the sqlite3LogEst() of the
+** number of rows that the index scan is expected to visit without 
+** considering the range constraints. If nEq is 0, this is the number of 
+** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
+** to account for the range contraints pLower and pUpper.
+** 
+** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be
+** used, a single range inequality reduces the search space by a factor of 4. 
+** and a pair of constraints (x>? AND x<?) reduces the expected number of
+** rows visited by a factor of 64.
 */
 static int whereRangeScanEst(
   Parse *pParse,       /* Parsing & code generating context */
-  Index *p,            /* The index containing the range-compared column; "x" */
-  int nEq,             /* index into p->aCol[] of the range-compared column */
+  WhereLoopBuilder *pBuilder,
   WhereTerm *pLower,   /* Lower bound on the range. ex: "x>123" Might be NULL */
   WhereTerm *pUpper,   /* Upper bound on the range. ex: "x<455" Might be NULL */
-  double *pRangeDiv   /* OUT: Reduce search space by this divisor */
+  WhereLoop *pLoop     /* Modify the .nOut and maybe .rRun fields */
 ){
   int rc = SQLITE_OK;
+  int nOut = pLoop->nOut;
+  LogEst nNew;
 
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+  Index *p = pLoop->u.btree.pIndex;
+  int nEq = pLoop->u.btree.nEq;
 
-  if( nEq==0 && p->nSample ){
-    sqlite3_value *pRangeVal;
-    tRowcnt iLower = 0;
-    tRowcnt iUpper = p->aiRowEst[0];
-    tRowcnt a[2];
-    u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
-
-    if( pLower ){
-      Expr *pExpr = pLower->pExpr->pRight;
-      rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
-      assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
-      if( rc==SQLITE_OK
-       && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
-      ){
+  if( p->nSample>0
+   && nEq<p->nSampleCol
+   && OptimizationEnabled(pParse->db, SQLITE_Stat3) 
+  ){
+    if( nEq==pBuilder->nRecValid ){
+      UnpackedRecord *pRec = pBuilder->pRec;
+      tRowcnt a[2];
+      u8 aff;
+
+      /* Variable iLower will be set to the estimate of the number of rows in 
+      ** the index that are less than the lower bound of the range query. The
+      ** lower bound being the concatenation of $P and $L, where $P is the
+      ** key-prefix formed by the nEq values matched against the nEq left-most
+      ** columns of the index, and $L is the value in pLower.
+      **
+      ** Or, if pLower is NULL or $L cannot be extracted from it (because it
+      ** is not a simple variable or literal value), the lower bound of the
+      ** range is $P. Due to a quirk in the way whereKeyStats() works, even
+      ** if $L is available, whereKeyStats() is called for both ($P) and 
+      ** ($P:$L) and the larger of the two returned values used.
+      **
+      ** Similarly, iUpper is to be set to the estimate of the number of rows
+      ** less than the upper bound of the range query. Where the upper bound
+      ** is either ($P) or ($P:$U). Again, even if $U is available, both values
+      ** of iUpper are requested of whereKeyStats() and the smaller used.
+      */
+      tRowcnt iLower;
+      tRowcnt iUpper;
+
+      if( nEq==p->nKeyCol ){
+        aff = SQLITE_AFF_INTEGER;
+      }else{
+        aff = p->pTable->aCol[p->aiColumn[nEq]].affinity;
+      }
+      /* Determine iLower and iUpper using ($P) only. */
+      if( nEq==0 ){
+        iLower = 0;
+        iUpper = sqlite3LogEstToInt(p->aiRowLogEst[0]);
+      }else{
+        /* Note: this call could be optimized away - since the same values must 
+        ** have been requested when testing key $P in whereEqualScanEst().  */
+        whereKeyStats(pParse, p, pRec, 0, a);
         iLower = a[0];
-        if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
+        iUpper = a[0] + a[1];
       }
-      sqlite3ValueFree(pRangeVal);
-    }
-    if( rc==SQLITE_OK && pUpper ){
-      Expr *pExpr = pUpper->pExpr->pRight;
-      rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
-      assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
-      if( rc==SQLITE_OK
-       && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
-      ){
-        iUpper = a[0];
-        if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
+
+      /* If possible, improve on the iLower estimate using ($P:$L). */
+      if( pLower ){
+        int bOk;                    /* True if value is extracted from pExpr */
+        Expr *pExpr = pLower->pExpr->pRight;
+        assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
+        rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
+        if( rc==SQLITE_OK && bOk ){
+          tRowcnt iNew;
+          whereKeyStats(pParse, p, pRec, 0, a);
+          iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0);
+          if( iNew>iLower ) iLower = iNew;
+          nOut--;
+        }
       }
-      sqlite3ValueFree(pRangeVal);
-    }
-    if( rc==SQLITE_OK ){
-      if( iUpper<=iLower ){
-        *pRangeDiv = (double)p->aiRowEst[0];
-      }else{
-        *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower);
+
+      /* If possible, improve on the iUpper estimate using ($P:$U). */
+      if( pUpper ){
+        int bOk;                    /* True if value is extracted from pExpr */
+        Expr *pExpr = pUpper->pExpr->pRight;
+        assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
+        rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
+        if( rc==SQLITE_OK && bOk ){
+          tRowcnt iNew;
+          whereKeyStats(pParse, p, pRec, 1, a);
+          iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0);
+          if( iNew<iUpper ) iUpper = iNew;
+          nOut--;
+        }
       }
-      WHERETRACE(("range scan regions: %u..%u  div=%g\n",
-                  (u32)iLower, (u32)iUpper, *pRangeDiv));
-      return SQLITE_OK;
+
+      pBuilder->pRec = pRec;
+      if( rc==SQLITE_OK ){
+        if( iUpper>iLower ){
+          nNew = sqlite3LogEst(iUpper - iLower);
+        }else{
+          nNew = 10;        assert( 10==sqlite3LogEst(2) );
+        }
+        if( nNew<nOut ){
+          nOut = nNew;
+        }
+        pLoop->nOut = (LogEst)nOut;
+        WHERETRACE(0x10, ("range scan regions: %u..%u  est=%d\n",
+                           (u32)iLower, (u32)iUpper, nOut));
+        return SQLITE_OK;
+      }
+    }else{
+      int bDone = 0;
+      rc = whereRangeSkipScanEst(pParse, pLower, pUpper, pLoop, &bDone);
+      if( bDone ) return rc;
     }
   }
 #else
   UNUSED_PARAMETER(pParse);
-  UNUSED_PARAMETER(p);
-  UNUSED_PARAMETER(nEq);
+  UNUSED_PARAMETER(pBuilder);
 #endif
   assert( pLower || pUpper );
-  *pRangeDiv = (double)1;
-  if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= (double)4;
-  if( pUpper ) *pRangeDiv *= (double)4;
+  assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 );
+  nNew = whereRangeAdjust(pLower, nOut);
+  nNew = whereRangeAdjust(pUpper, nNew);
+
+  /* TUNING: If there is both an upper and lower limit, assume the range is
+  ** reduced by an additional 75%. This means that, by default, an open-ended
+  ** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the
+  ** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to
+  ** match 1/64 of the index. */ 
+  if( pLower && pUpper ) nNew -= 20;
+
+  nOut -= (pLower!=0) + (pUpper!=0);
+  if( nNew<10 ) nNew = 10;
+  if( nNew<nOut ) nOut = nNew;
+  pLoop->nOut = (LogEst)nOut;
   return rc;
 }
 
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
 /*
 ** Estimate the number of rows that will be returned based on
 ** an equality constraint x=VALUE and where that VALUE occurs in
@@ -107142,37 +113196,53 @@ static int whereRangeScanEst(
 */
 static int whereEqualScanEst(
   Parse *pParse,       /* Parsing & code generating context */
-  Index *p,            /* The index whose left-most column is pTerm */
+  WhereLoopBuilder *pBuilder,
   Expr *pExpr,         /* Expression for VALUE in the x=VALUE constraint */
-  double *pnRow        /* Write the revised row estimate here */
+  tRowcnt *pnRow       /* Write the revised row estimate here */
 ){
-  sqlite3_value *pRhs = 0;  /* VALUE on right-hand side of pTerm */
+  Index *p = pBuilder->pNew->u.btree.pIndex;
+  int nEq = pBuilder->pNew->u.btree.nEq;
+  UnpackedRecord *pRec = pBuilder->pRec;
   u8 aff;                   /* Column affinity */
   int rc;                   /* Subfunction return code */
   tRowcnt a[2];             /* Statistics */
+  int bOk;
 
+  assert( nEq>=1 );
+  assert( nEq<=p->nColumn );
   assert( p->aSample!=0 );
   assert( p->nSample>0 );
-  aff = p->pTable->aCol[p->aiColumn[0]].affinity;
-  if( pExpr ){
-    rc = valueFromExpr(pParse, pExpr, aff, &pRhs);
-    if( rc ) goto whereEqualScanEst_cancel;
-  }else{
-    pRhs = sqlite3ValueNew(pParse->db);
+  assert( pBuilder->nRecValid<nEq );
+
+  /* If values are not available for all fields of the index to the left
+  ** of this one, no estimate can be made. Return SQLITE_NOTFOUND. */
+  if( pBuilder->nRecValid<(nEq-1) ){
+    return SQLITE_NOTFOUND;
   }
-  if( pRhs==0 ) return SQLITE_NOTFOUND;
-  rc = whereKeyStats(pParse, p, pRhs, 0, a);
-  if( rc==SQLITE_OK ){
-    WHERETRACE(("equality scan regions: %d\n", (int)a[1]));
-    *pnRow = a[1];
+
+  /* This is an optimization only. The call to sqlite3Stat4ProbeSetValue()
+  ** below would return the same value.  */
+  if( nEq>=p->nColumn ){
+    *pnRow = 1;
+    return SQLITE_OK;
   }
-whereEqualScanEst_cancel:
-  sqlite3ValueFree(pRhs);
+
+  aff = p->pTable->aCol[p->aiColumn[nEq-1]].affinity;
+  rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk);
+  pBuilder->pRec = pRec;
+  if( rc!=SQLITE_OK ) return rc;
+  if( bOk==0 ) return SQLITE_NOTFOUND;
+  pBuilder->nRecValid = nEq;
+
+  whereKeyStats(pParse, p, pRec, 0, a);
+  WHERETRACE(0x10,("equality scan regions: %d\n", (int)a[1]));
+  *pnRow = a[1];
+  
   return rc;
 }
-#endif /* defined(SQLITE_ENABLE_STAT3) */
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
 
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
 /*
 ** Estimate the number of rows that will be returned based on
 ** an IN constraint where the right-hand side of the IN operator
@@ -107191,902 +113261,35 @@ whereEqualScanEst_cancel:
 */
 static int whereInScanEst(
   Parse *pParse,       /* Parsing & code generating context */
-  Index *p,            /* The index whose left-most column is pTerm */
+  WhereLoopBuilder *pBuilder,
   ExprList *pList,     /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
-  double *pnRow        /* Write the revised row estimate here */
-){
-  int rc = SQLITE_OK;         /* Subfunction return code */
-  double nEst;                /* Number of rows for a single term */
-  double nRowEst = (double)0; /* New estimate of the number of rows */
-  int i;                      /* Loop counter */
+  tRowcnt *pnRow       /* Write the revised row estimate here */
+){
+  Index *p = pBuilder->pNew->u.btree.pIndex;
+  i64 nRow0 = sqlite3LogEstToInt(p->aiRowLogEst[0]);
+  int nRecValid = pBuilder->nRecValid;
+  int rc = SQLITE_OK;     /* Subfunction return code */
+  tRowcnt nEst;           /* Number of rows for a single term */
+  tRowcnt nRowEst = 0;    /* New estimate of the number of rows */
+  int i;                  /* Loop counter */
 
   assert( p->aSample!=0 );
   for(i=0; rc==SQLITE_OK && i<pList->nExpr; i++){
-    nEst = p->aiRowEst[0];
-    rc = whereEqualScanEst(pParse, p, pList->a[i].pExpr, &nEst);
+    nEst = nRow0;
+    rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst);
     nRowEst += nEst;
+    pBuilder->nRecValid = nRecValid;
   }
+
   if( rc==SQLITE_OK ){
-    if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
+    if( nRowEst > nRow0 ) nRowEst = nRow0;
     *pnRow = nRowEst;
-    WHERETRACE(("IN row estimate: est=%g\n", nRowEst));
+    WHERETRACE(0x10,("IN row estimate: est=%g\n", nRowEst));
   }
+  assert( pBuilder->nRecValid==nRecValid );
   return rc;
 }
-#endif /* defined(SQLITE_ENABLE_STAT3) */
-
-/*
-** Check to see if column iCol of the table with cursor iTab will appear
-** in sorted order according to the current query plan.
-**
-** Return values:
-**
-**    0   iCol is not ordered
-**    1   iCol has only a single value
-**    2   iCol is in ASC order
-**    3   iCol is in DESC order
-*/
-static int isOrderedColumn(
-  WhereBestIdx *p,
-  int iTab,
-  int iCol
-){
-  int i, j;
-  WhereLevel *pLevel = &p->aLevel[p->i-1];
-  Index *pIdx;
-  u8 sortOrder;
-  for(i=p->i-1; i>=0; i--, pLevel--){
-    if( pLevel->iTabCur!=iTab ) continue;
-    if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
-      return 1;
-    }
-    assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 );
-    if( (pIdx = pLevel->plan.u.pIdx)!=0 ){
-      if( iCol<0 ){
-        sortOrder = 0;
-        testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
-      }else{
-        int n = pIdx->nColumn;
-        for(j=0; j<n; j++){
-          if( iCol==pIdx->aiColumn[j] ) break;
-        }
-        if( j>=n ) return 0;
-        sortOrder = pIdx->aSortOrder[j];
-        testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
-      }
-    }else{
-      if( iCol!=(-1) ) return 0;
-      sortOrder = 0;
-      testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
-    }
-    if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){
-      assert( sortOrder==0 || sortOrder==1 );
-      testcase( sortOrder==1 );
-      sortOrder = 1 - sortOrder;
-    }
-    return sortOrder+2;
-  }
-  return 0;
-}
-
-/*
-** This routine decides if pIdx can be used to satisfy the ORDER BY
-** clause, either in whole or in part.  The return value is the 
-** cumulative number of terms in the ORDER BY clause that are satisfied
-** by the index pIdx and other indices in outer loops.
-**
-** The table being queried has a cursor number of "base".  pIdx is the
-** index that is postulated for use to access the table.
-**
-** The *pbRev value is set to 0 order 1 depending on whether or not
-** pIdx should be run in the forward order or in reverse order.
-*/
-static int isSortingIndex(
-  WhereBestIdx *p,    /* Best index search context */
-  Index *pIdx,        /* The index we are testing */
-  int base,           /* Cursor number for the table to be sorted */
-  int *pbRev,         /* Set to 1 for reverse-order scan of pIdx */
-  int *pbObUnique     /* ORDER BY column values will different in every row */
-){
-  int i;                        /* Number of pIdx terms used */
-  int j;                        /* Number of ORDER BY terms satisfied */
-  int sortOrder = 2;            /* 0: forward.  1: backward.  2: unknown */
-  int nTerm;                    /* Number of ORDER BY terms */
-  struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */
-  Table *pTab = pIdx->pTable;   /* Table that owns index pIdx */
-  ExprList *pOrderBy;           /* The ORDER BY clause */
-  Parse *pParse = p->pParse;    /* Parser context */
-  sqlite3 *db = pParse->db;     /* Database connection */
-  int nPriorSat;                /* ORDER BY terms satisfied by outer loops */
-  int seenRowid = 0;            /* True if an ORDER BY rowid term is seen */
-  int uniqueNotNull;            /* pIdx is UNIQUE with all terms are NOT NULL */
-  int outerObUnique;            /* Outer loops generate different values in
-                                ** every row for the ORDER BY columns */
-
-  if( p->i==0 ){
-    nPriorSat = 0;
-    outerObUnique = 1;
-  }else{
-    u32 wsFlags = p->aLevel[p->i-1].plan.wsFlags;
-    nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
-    if( (wsFlags & WHERE_ORDERED)==0 ){
-      /* This loop cannot be ordered unless the next outer loop is
-      ** also ordered */
-      return nPriorSat;
-    }
-    if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){
-      /* Only look at the outer-most loop if the OrderByIdxJoin
-      ** optimization is disabled */
-      return nPriorSat;
-    }
-    testcase( wsFlags & WHERE_OB_UNIQUE );
-    testcase( wsFlags & WHERE_ALL_UNIQUE );
-    outerObUnique = (wsFlags & (WHERE_OB_UNIQUE|WHERE_ALL_UNIQUE))!=0;
-  }
-  pOrderBy = p->pOrderBy;
-  assert( pOrderBy!=0 );
-  if( pIdx->bUnordered ){
-    /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot
-    ** be used for sorting */
-    return nPriorSat;
-  }
-  nTerm = pOrderBy->nExpr;
-  uniqueNotNull = pIdx->onError!=OE_None;
-  assert( nTerm>0 );
-
-  /* Argument pIdx must either point to a 'real' named index structure, 
-  ** or an index structure allocated on the stack by bestBtreeIndex() to
-  ** represent the rowid index that is part of every table.  */
-  assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
-
-  /* Match terms of the ORDER BY clause against columns of
-  ** the index.
-  **
-  ** Note that indices have pIdx->nColumn regular columns plus
-  ** one additional column containing the rowid.  The rowid column
-  ** of the index is also allowed to match against the ORDER BY
-  ** clause.
-  */
-  j = nPriorSat;
-  for(i=0,pOBItem=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){
-    Expr *pOBExpr;          /* The expression of the ORDER BY pOBItem */
-    CollSeq *pColl;         /* The collating sequence of pOBExpr */
-    int termSortOrder;      /* Sort order for this term */
-    int iColumn;            /* The i-th column of the index.  -1 for rowid */
-    int iSortOrder;         /* 1 for DESC, 0 for ASC on the i-th index term */
-    int isEq;               /* Subject to an == or IS NULL constraint */
-    int isMatch;            /* ORDER BY term matches the index term */
-    const char *zColl;      /* Name of collating sequence for i-th index term */
-    WhereTerm *pConstraint; /* A constraint in the WHERE clause */
-
-    /* If the next term of the ORDER BY clause refers to anything other than
-    ** a column in the "base" table, then this index will not be of any
-    ** further use in handling the ORDER BY. */
-    pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
-    if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
-      break;
-    }
-
-    /* Find column number and collating sequence for the next entry
-    ** in the index */
-    if( pIdx->zName && i<pIdx->nColumn ){
-      iColumn = pIdx->aiColumn[i];
-      if( iColumn==pIdx->pTable->iPKey ){
-        iColumn = -1;
-      }
-      iSortOrder = pIdx->aSortOrder[i];
-      zColl = pIdx->azColl[i];
-      assert( zColl!=0 );
-    }else{
-      iColumn = -1;
-      iSortOrder = 0;
-      zColl = 0;
-    }
-
-    /* Check to see if the column number and collating sequence of the
-    ** index match the column number and collating sequence of the ORDER BY
-    ** clause entry.  Set isMatch to 1 if they both match. */
-    if( pOBExpr->iColumn==iColumn ){
-      if( zColl ){
-        pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
-        if( !pColl ) pColl = db->pDfltColl;
-        isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
-      }else{
-        isMatch = 1;
-      }
-    }else{
-      isMatch = 0;
-    }
-
-    /* termSortOrder is 0 or 1 for whether or not the access loop should
-    ** run forward or backwards (respectively) in order to satisfy this 
-    ** term of the ORDER BY clause. */
-    assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
-    assert( iSortOrder==0 || iSortOrder==1 );
-    termSortOrder = iSortOrder ^ pOBItem->sortOrder;
-
-    /* If X is the column in the index and ORDER BY clause, check to see
-    ** if there are any X= or X IS NULL constraints in the WHERE clause. */
-    pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
-                           WO_EQ|WO_ISNULL|WO_IN, pIdx);
-    if( pConstraint==0 ){
-      isEq = 0;
-    }else if( (pConstraint->eOperator & WO_IN)!=0 ){
-      isEq = 0;
-    }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
-      uniqueNotNull = 0;
-      isEq = 1;  /* "X IS NULL" means X has only a single value */
-    }else if( pConstraint->prereqRight==0 ){
-      isEq = 1;  /* Constraint "X=constant" means X has only a single value */
-    }else{
-      Expr *pRight = pConstraint->pExpr->pRight;
-      if( pRight->op==TK_COLUMN ){
-        WHERETRACE(("       .. isOrderedColumn(tab=%d,col=%d)",
-                    pRight->iTable, pRight->iColumn));
-        isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
-        WHERETRACE((" -> isEq=%d\n", isEq));
-
-        /* If the constraint is of the form X=Y where Y is an ordered value
-        ** in an outer loop, then make sure the sort order of Y matches the
-        ** sort order required for X. */
-        if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){
-          testcase( isEq==2 );
-          testcase( isEq==3 );
-          break;
-        }
-      }else{
-        isEq = 0;  /* "X=expr" places no ordering constraints on X */
-      }
-    }
-    if( !isMatch ){
-      if( isEq==0 ){
-        break;
-      }else{
-        continue;
-      }
-    }else if( isEq!=1 ){
-      if( sortOrder==2 ){
-        sortOrder = termSortOrder;
-      }else if( termSortOrder!=sortOrder ){
-        break;
-      }
-    }
-    j++;
-    pOBItem++;
-    if( iColumn<0 ){
-      seenRowid = 1;
-      break;
-    }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){
-      testcase( isEq==0 );
-      testcase( isEq==2 );
-      testcase( isEq==3 );
-      uniqueNotNull = 0;
-    }
-  }
-  if( seenRowid ){
-    uniqueNotNull = 1;
-  }else if( uniqueNotNull==0 || i<pIdx->nColumn ){
-    uniqueNotNull = 0;
-  }
-
-  /* If we have not found at least one ORDER BY term that matches the
-  ** index, then show no progress. */
-  if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
-
-  /* Either the outer queries must generate rows where there are no two
-  ** rows with the same values in all ORDER BY columns, or else this
-  ** loop must generate just a single row of output.  Example:  Suppose
-  ** the outer loops generate A=1 and A=1, and this loop generates B=3
-  ** and B=4.  Then without the following test, ORDER BY A,B would 
-  ** generate the wrong order output: 1,3 1,4 1,3 1,4
-  */
-  if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat;
-  *pbObUnique = uniqueNotNull;
-
-  /* Return the necessary scan order back to the caller */
-  *pbRev = sortOrder & 1;
-
-  /* If there was an "ORDER BY rowid" term that matched, or it is only
-  ** possible for a single row from this table to match, then skip over
-  ** any additional ORDER BY terms dealing with this table.
-  */
-  if( uniqueNotNull ){
-    /* Advance j over additional ORDER BY terms associated with base */
-    WhereMaskSet *pMS = p->pWC->pMaskSet;
-    Bitmask m = ~getMask(pMS, base);
-    while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){
-      j++;
-    }
-  }
-  return j;
-}
-
-/*
-** Find the best query plan for accessing a particular table.  Write the
-** best query plan and its cost into the p->cost.
-**
-** The lowest cost plan wins.  The cost is an estimate of the amount of
-** CPU and disk I/O needed to process the requested result.
-** Factors that influence cost include:
-**
-**    *  The estimated number of rows that will be retrieved.  (The
-**       fewer the better.)
-**
-**    *  Whether or not sorting must occur.
-**
-**    *  Whether or not there must be separate lookups in the
-**       index and in the main table.
-**
-** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in
-** the SQL statement, then this function only considers plans using the 
-** named index. If no such plan is found, then the returned cost is
-** SQLITE_BIG_DBL. If a plan is found that uses the named index, 
-** then the cost is calculated in the usual way.
-**
-** If a NOT INDEXED clause was attached to the table 
-** in the SELECT statement, then no indexes are considered. However, the 
-** selected plan may still take advantage of the built-in rowid primary key
-** index.
-*/
-static void bestBtreeIndex(WhereBestIdx *p){
-  Parse *pParse = p->pParse;  /* The parsing context */
-  WhereClause *pWC = p->pWC;  /* The WHERE clause */
-  struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
-  int iCur = pSrc->iCursor;   /* The cursor of the table to be accessed */
-  Index *pProbe;              /* An index we are evaluating */
-  Index *pIdx;                /* Copy of pProbe, or zero for IPK index */
-  int eqTermMask;             /* Current mask of valid equality operators */
-  int idxEqTermMask;          /* Index mask of valid equality operators */
-  Index sPk;                  /* A fake index object for the primary key */
-  tRowcnt aiRowEstPk[2];      /* The aiRowEst[] value for the sPk index */
-  int aiColumnPk = -1;        /* The aColumn[] value for the sPk index */
-  int wsFlagMask;             /* Allowed flags in p->cost.plan.wsFlag */
-  int nPriorSat;              /* ORDER BY terms satisfied by outer loops */
-  int nOrderBy;               /* Number of ORDER BY terms */
-  char bSortInit;             /* Initializer for bSort in inner loop */
-  char bDistInit;             /* Initializer for bDist in inner loop */
-
-
-  /* Initialize the cost to a worst-case value */
-  memset(&p->cost, 0, sizeof(p->cost));
-  p->cost.rCost = SQLITE_BIG_DBL;
-
-  /* If the pSrc table is the right table of a LEFT JOIN then we may not
-  ** use an index to satisfy IS NULL constraints on that table.  This is
-  ** because columns might end up being NULL if the table does not match -
-  ** a circumstance which the index cannot help us discover.  Ticket #2177.
-  */
-  if( pSrc->jointype & JT_LEFT ){
-    idxEqTermMask = WO_EQ|WO_IN;
-  }else{
-    idxEqTermMask = WO_EQ|WO_IN|WO_ISNULL;
-  }
-
-  if( pSrc->pIndex ){
-    /* An INDEXED BY clause specifies a particular index to use */
-    pIdx = pProbe = pSrc->pIndex;
-    wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE);
-    eqTermMask = idxEqTermMask;
-  }else{
-    /* There is no INDEXED BY clause.  Create a fake Index object in local
-    ** variable sPk to represent the rowid primary key index.  Make this
-    ** fake index the first in a chain of Index objects with all of the real
-    ** indices to follow */
-    Index *pFirst;                  /* First of real indices on the table */
-    memset(&sPk, 0, sizeof(Index));
-    sPk.nColumn = 1;
-    sPk.aiColumn = &aiColumnPk;
-    sPk.aiRowEst = aiRowEstPk;
-    sPk.onError = OE_Replace;
-    sPk.pTable = pSrc->pTab;
-    aiRowEstPk[0] = pSrc->pTab->nRowEst;
-    aiRowEstPk[1] = 1;
-    pFirst = pSrc->pTab->pIndex;
-    if( pSrc->notIndexed==0 ){
-      /* The real indices of the table are only considered if the
-      ** NOT INDEXED qualifier is omitted from the FROM clause */
-      sPk.pNext = pFirst;
-    }
-    pProbe = &sPk;
-    wsFlagMask = ~(
-        WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE
-    );
-    eqTermMask = WO_EQ|WO_IN;
-    pIdx = 0;
-  }
-
-  nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
-  if( p->i ){
-    nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
-    bSortInit = nPriorSat<nOrderBy;
-    bDistInit = 0;
-  }else{
-    nPriorSat = 0;
-    bSortInit = nOrderBy>0;
-    bDistInit = p->pDistinct!=0;
-  }
-
-  /* Loop over all indices looking for the best one to use
-  */
-  for(; pProbe; pIdx=pProbe=pProbe->pNext){
-    const tRowcnt * const aiRowEst = pProbe->aiRowEst;
-    WhereCost pc;               /* Cost of using pProbe */
-    double log10N = (double)1;  /* base-10 logarithm of nRow (inexact) */
-
-    /* The following variables are populated based on the properties of
-    ** index being evaluated. They are then used to determine the expected
-    ** cost and number of rows returned.
-    **
-    **  pc.plan.nEq: 
-    **    Number of equality terms that can be implemented using the index.
-    **    In other words, the number of initial fields in the index that
-    **    are used in == or IN or NOT NULL constraints of the WHERE clause.
-    **
-    **  nInMul:  
-    **    The "in-multiplier". This is an estimate of how many seek operations 
-    **    SQLite must perform on the index in question. For example, if the 
-    **    WHERE clause is:
-    **
-    **      WHERE a IN (1, 2, 3) AND b IN (4, 5, 6)
-    **
-    **    SQLite must perform 9 lookups on an index on (a, b), so nInMul is 
-    **    set to 9. Given the same schema and either of the following WHERE 
-    **    clauses:
-    **
-    **      WHERE a =  1
-    **      WHERE a >= 2
-    **
-    **    nInMul is set to 1.
-    **
-    **    If there exists a WHERE term of the form "x IN (SELECT ...)", then 
-    **    the sub-select is assumed to return 25 rows for the purposes of 
-    **    determining nInMul.
-    **
-    **  bInEst:  
-    **    Set to true if there was at least one "x IN (SELECT ...)" term used 
-    **    in determining the value of nInMul.  Note that the RHS of the
-    **    IN operator must be a SELECT, not a value list, for this variable
-    **    to be true.
-    **
-    **  rangeDiv:
-    **    An estimate of a divisor by which to reduce the search space due
-    **    to inequality constraints.  In the absence of sqlite_stat3 ANALYZE
-    **    data, a single inequality reduces the search space to 1/4rd its
-    **    original size (rangeDiv==4).  Two inequalities reduce the search
-    **    space to 1/16th of its original size (rangeDiv==16).
-    **
-    **  bSort:   
-    **    Boolean. True if there is an ORDER BY clause that will require an 
-    **    external sort (i.e. scanning the index being evaluated will not 
-    **    correctly order records).
-    **
-    **  bDist:
-    **    Boolean. True if there is a DISTINCT clause that will require an 
-    **    external btree.
-    **
-    **  bLookup: 
-    **    Boolean. True if a table lookup is required for each index entry
-    **    visited.  In other words, true if this is not a covering index.
-    **    This is always false for the rowid primary key index of a table.
-    **    For other indexes, it is true unless all the columns of the table
-    **    used by the SELECT statement are present in the index (such an
-    **    index is sometimes described as a covering index).
-    **    For example, given the index on (a, b), the second of the following 
-    **    two queries requires table b-tree lookups in order to find the value
-    **    of column c, but the first does not because columns a and b are
-    **    both available in the index.
-    **
-    **             SELECT a, b    FROM tbl WHERE a = 1;
-    **             SELECT a, b, c FROM tbl WHERE a = 1;
-    */
-    int bInEst = 0;               /* True if "x IN (SELECT...)" seen */
-    int nInMul = 1;               /* Number of distinct equalities to lookup */
-    double rangeDiv = (double)1;  /* Estimated reduction in search space */
-    int nBound = 0;               /* Number of range constraints seen */
-    char bSort = bSortInit;       /* True if external sort required */
-    char bDist = bDistInit;       /* True if index cannot help with DISTINCT */
-    char bLookup = 0;             /* True if not a covering index */
-    WhereTerm *pTerm;             /* A single term of the WHERE clause */
-#ifdef SQLITE_ENABLE_STAT3
-    WhereTerm *pFirstTerm = 0;    /* First term matching the index */
-#endif
-
-    WHERETRACE((
-      "   %s(%s):\n",
-      pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
-    ));
-    memset(&pc, 0, sizeof(pc));
-    pc.plan.nOBSat = nPriorSat;
-
-    /* Determine the values of pc.plan.nEq and nInMul */
-    for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
-      int j = pProbe->aiColumn[pc.plan.nEq];
-      pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
-      if( pTerm==0 ) break;
-      pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
-      testcase( pTerm->pWC!=pWC );
-      if( pTerm->eOperator & WO_IN ){
-        Expr *pExpr = pTerm->pExpr;
-        pc.plan.wsFlags |= WHERE_COLUMN_IN;
-        if( ExprHasProperty(pExpr, EP_xIsSelect) ){
-          /* "x IN (SELECT ...)":  Assume the SELECT returns 25 rows */
-          nInMul *= 25;
-          bInEst = 1;
-        }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
-          /* "x IN (value, value, ...)" */
-          nInMul *= pExpr->x.pList->nExpr;
-        }
-      }else if( pTerm->eOperator & WO_ISNULL ){
-        pc.plan.wsFlags |= WHERE_COLUMN_NULL;
-      }
-#ifdef SQLITE_ENABLE_STAT3
-      if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
-#endif
-      pc.used |= pTerm->prereqRight;
-    }
- 
-    /* If the index being considered is UNIQUE, and there is an equality 
-    ** constraint for all columns in the index, then this search will find
-    ** at most a single row. In this case set the WHERE_UNIQUE flag to 
-    ** indicate this to the caller.
-    **
-    ** Otherwise, if the search may find more than one row, test to see if
-    ** there is a range constraint on indexed column (pc.plan.nEq+1) that
-    ** can be optimized using the index. 
-    */
-    if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
-      testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
-      testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL );
-      if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
-        pc.plan.wsFlags |= WHERE_UNIQUE;
-        if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
-          pc.plan.wsFlags |= WHERE_ALL_UNIQUE;
-        }
-      }
-    }else if( pProbe->bUnordered==0 ){
-      int j;
-      j = (pc.plan.nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[pc.plan.nEq]);
-      if( findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
-        WhereTerm *pTop, *pBtm;
-        pTop = findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE, pIdx);
-        pBtm = findTerm(pWC, iCur, j, p->notReady, WO_GT|WO_GE, pIdx);
-        whereRangeScanEst(pParse, pProbe, pc.plan.nEq, pBtm, pTop, &rangeDiv);
-        if( pTop ){
-          nBound = 1;
-          pc.plan.wsFlags |= WHERE_TOP_LIMIT;
-          pc.used |= pTop->prereqRight;
-          testcase( pTop->pWC!=pWC );
-        }
-        if( pBtm ){
-          nBound++;
-          pc.plan.wsFlags |= WHERE_BTM_LIMIT;
-          pc.used |= pBtm->prereqRight;
-          testcase( pBtm->pWC!=pWC );
-        }
-        pc.plan.wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
-      }
-    }
-
-    /* If there is an ORDER BY clause and the index being considered will
-    ** naturally scan rows in the required order, set the appropriate flags
-    ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
-    ** the index will scan rows in a different order, set the bSort
-    ** variable.  */
-    if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
-      int bRev = 2;
-      int bObUnique = 0;
-      WHERETRACE(("      --> before isSortIndex: nPriorSat=%d\n",nPriorSat));
-      pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique);
-      WHERETRACE(("      --> after  isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
-                  bRev, bObUnique, pc.plan.nOBSat));
-      if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
-        pc.plan.wsFlags |= WHERE_ORDERED;
-        if( bObUnique ) pc.plan.wsFlags |= WHERE_OB_UNIQUE;
-      }
-      if( nOrderBy==pc.plan.nOBSat ){
-        bSort = 0;
-        pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE;
-      }
-      if( bRev & 1 ) pc.plan.wsFlags |= WHERE_REVERSE;
-    }
-
-    /* If there is a DISTINCT qualifier and this index will scan rows in
-    ** order of the DISTINCT expressions, clear bDist and set the appropriate
-    ** flags in pc.plan.wsFlags. */
-    if( bDist
-     && isDistinctIndex(pParse, pWC, pProbe, iCur, p->pDistinct, pc.plan.nEq)
-     && (pc.plan.wsFlags & WHERE_COLUMN_IN)==0
-    ){
-      bDist = 0;
-      pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
-    }
-
-    /* If currently calculating the cost of using an index (not the IPK
-    ** index), determine if all required column data may be obtained without 
-    ** using the main table (i.e. if the index is a covering
-    ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
-    ** pc.plan.wsFlags. Otherwise, set the bLookup variable to true.  */
-    if( pIdx ){
-      Bitmask m = pSrc->colUsed;
-      int j;
-      for(j=0; j<pIdx->nColumn; j++){
-        int x = pIdx->aiColumn[j];
-        if( x<BMS-1 ){
-          m &= ~(((Bitmask)1)<<x);
-        }
-      }
-      if( m==0 ){
-        pc.plan.wsFlags |= WHERE_IDX_ONLY;
-      }else{
-        bLookup = 1;
-      }
-    }
-
-    /*
-    ** Estimate the number of rows of output.  For an "x IN (SELECT...)"
-    ** constraint, do not let the estimate exceed half the rows in the table.
-    */
-    pc.plan.nRow = (double)(aiRowEst[pc.plan.nEq] * nInMul);
-    if( bInEst && pc.plan.nRow*2>aiRowEst[0] ){
-      pc.plan.nRow = aiRowEst[0]/2;
-      nInMul = (int)(pc.plan.nRow / aiRowEst[pc.plan.nEq]);
-    }
-
-#ifdef SQLITE_ENABLE_STAT3
-    /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
-    ** and we do not think that values of x are unique and if histogram
-    ** data is available for column x, then it might be possible
-    ** to get a better estimate on the number of rows based on
-    ** VALUE and how common that value is according to the histogram.
-    */
-    if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
-     && pFirstTerm!=0 && aiRowEst[1]>1 ){
-      assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
-      if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
-        testcase( pFirstTerm->eOperator & WO_EQ );
-        testcase( pFirstTerm->eOperator & WO_EQUIV );
-        testcase( pFirstTerm->eOperator & WO_ISNULL );
-        whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
-                          &pc.plan.nRow);
-      }else if( bInEst==0 ){
-        assert( pFirstTerm->eOperator & WO_IN );
-        whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
-                       &pc.plan.nRow);
-      }
-    }
-#endif /* SQLITE_ENABLE_STAT3 */
-
-    /* Adjust the number of output rows and downward to reflect rows
-    ** that are excluded by range constraints.
-    */
-    pc.plan.nRow = pc.plan.nRow/rangeDiv;
-    if( pc.plan.nRow<1 ) pc.plan.nRow = 1;
-
-    /* Experiments run on real SQLite databases show that the time needed
-    ** to do a binary search to locate a row in a table or index is roughly
-    ** log10(N) times the time to move from one row to the next row within
-    ** a table or index.  The actual times can vary, with the size of
-    ** records being an important factor.  Both moves and searches are
-    ** slower with larger records, presumably because fewer records fit
-    ** on one page and hence more pages have to be fetched.
-    **
-    ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do
-    ** not give us data on the relative sizes of table and index records.
-    ** So this computation assumes table records are about twice as big
-    ** as index records
-    */
-    if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED|WHERE_OB_UNIQUE))
-                                                              ==WHERE_IDX_ONLY
-     && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
-     && sqlite3GlobalConfig.bUseCis
-     && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
-    ){
-      /* This index is not useful for indexing, but it is a covering index.
-      ** A full-scan of the index might be a little faster than a full-scan
-      ** of the table, so give this case a cost slightly less than a table
-      ** scan. */
-      pc.rCost = aiRowEst[0]*3 + pProbe->nColumn;
-      pc.plan.wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE;
-    }else if( (pc.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
-      /* The cost of a full table scan is a number of move operations equal
-      ** to the number of rows in the table.
-      **
-      ** We add an additional 4x penalty to full table scans.  This causes
-      ** the cost function to err on the side of choosing an index over
-      ** choosing a full scan.  This 4x full-scan penalty is an arguable
-      ** decision and one which we expect to revisit in the future.  But
-      ** it seems to be working well enough at the moment.
-      */
-      pc.rCost = aiRowEst[0]*4;
-      pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
-      if( pIdx ){
-        pc.plan.wsFlags &= ~WHERE_ORDERED;
-        pc.plan.nOBSat = nPriorSat;
-      }
-    }else{
-      log10N = estLog(aiRowEst[0]);
-      pc.rCost = pc.plan.nRow;
-      if( pIdx ){
-        if( bLookup ){
-          /* For an index lookup followed by a table lookup:
-          **    nInMul index searches to find the start of each index range
-          **  + nRow steps through the index
-          **  + nRow table searches to lookup the table entry using the rowid
-          */
-          pc.rCost += (nInMul + pc.plan.nRow)*log10N;
-        }else{
-          /* For a covering index:
-          **     nInMul index searches to find the initial entry 
-          **   + nRow steps through the index
-          */
-          pc.rCost += nInMul*log10N;
-        }
-      }else{
-        /* For a rowid primary key lookup:
-        **    nInMult table searches to find the initial entry for each range
-        **  + nRow steps through the table
-        */
-        pc.rCost += nInMul*log10N;
-      }
-    }
-
-    /* Add in the estimated cost of sorting the result.  Actual experimental
-    ** measurements of sorting performance in SQLite show that sorting time
-    ** adds C*N*log10(N) to the cost, where N is the number of rows to be 
-    ** sorted and C is a factor between 1.95 and 4.3.  We will split the
-    ** difference and select C of 3.0.
-    */
-    if( bSort ){
-      double m = estLog(pc.plan.nRow*(nOrderBy - pc.plan.nOBSat)/nOrderBy);
-      m *= (double)(pc.plan.nOBSat ? 2 : 3);
-      pc.rCost += pc.plan.nRow*m;
-    }
-    if( bDist ){
-      pc.rCost += pc.plan.nRow*estLog(pc.plan.nRow)*3;
-    }
-
-    /**** Cost of using this index has now been computed ****/
-
-    /* If there are additional constraints on this table that cannot
-    ** be used with the current index, but which might lower the number
-    ** of output rows, adjust the nRow value accordingly.  This only 
-    ** matters if the current index is the least costly, so do not bother
-    ** with this step if we already know this index will not be chosen.
-    ** Also, never reduce the output row count below 2 using this step.
-    **
-    ** It is critical that the notValid mask be used here instead of
-    ** the notReady mask.  When computing an "optimal" index, the notReady
-    ** mask will only have one bit set - the bit for the current table.
-    ** The notValid mask, on the other hand, always has all bits set for
-    ** tables that are not in outer loops.  If notReady is used here instead
-    ** of notValid, then a optimal index that depends on inner joins loops
-    ** might be selected even when there exists an optimal index that has
-    ** no such dependency.
-    */
-    if( pc.plan.nRow>2 && pc.rCost<=p->cost.rCost ){
-      int k;                       /* Loop counter */
-      int nSkipEq = pc.plan.nEq;   /* Number of == constraints to skip */
-      int nSkipRange = nBound;     /* Number of < constraints to skip */
-      Bitmask thisTab;             /* Bitmap for pSrc */
-
-      thisTab = getMask(pWC->pMaskSet, iCur);
-      for(pTerm=pWC->a, k=pWC->nTerm; pc.plan.nRow>2 && k; k--, pTerm++){
-        if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
-        if( (pTerm->prereqAll & p->notValid)!=thisTab ) continue;
-        if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
-          if( nSkipEq ){
-            /* Ignore the first pc.plan.nEq equality matches since the index
-            ** has already accounted for these */
-            nSkipEq--;
-          }else{
-            /* Assume each additional equality match reduces the result
-            ** set size by a factor of 10 */
-            pc.plan.nRow /= 10;
-          }
-        }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){
-          if( nSkipRange ){
-            /* Ignore the first nSkipRange range constraints since the index
-            ** has already accounted for these */
-            nSkipRange--;
-          }else{
-            /* Assume each additional range constraint reduces the result
-            ** set size by a factor of 3.  Indexed range constraints reduce
-            ** the search space by a larger factor: 4.  We make indexed range
-            ** more selective intentionally because of the subjective 
-            ** observation that indexed range constraints really are more
-            ** selective in practice, on average. */
-            pc.plan.nRow /= 3;
-          }
-        }else if( (pTerm->eOperator & WO_NOOP)==0 ){
-          /* Any other expression lowers the output row count by half */
-          pc.plan.nRow /= 2;
-        }
-      }
-      if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
-    }
-
-
-    WHERETRACE((
-      "      nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
-      "      notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
-      "      used=0x%llx nOBSat=%d\n",
-      pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
-      p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
-      pc.plan.nOBSat
-    ));
-
-    /* If this index is the best we have seen so far, then record this
-    ** index and its cost in the p->cost structure.
-    */
-    if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){
-      p->cost = pc;
-      p->cost.plan.wsFlags &= wsFlagMask;
-      p->cost.plan.u.pIdx = pIdx;
-    }
-
-    /* If there was an INDEXED BY clause, then only that one index is
-    ** considered. */
-    if( pSrc->pIndex ) break;
-
-    /* Reset masks for the next index in the loop */
-    wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE);
-    eqTermMask = idxEqTermMask;
-  }
-
-  /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
-  ** is set, then reverse the order that the index will be scanned
-  ** in. This is used for application testing, to help find cases
-  ** where application behavior depends on the (undefined) order that
-  ** SQLite outputs rows in in the absence of an ORDER BY clause.  */
-  if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
-    p->cost.plan.wsFlags |= WHERE_REVERSE;
-  }
-
-  assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
-  assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
-  assert( pSrc->pIndex==0 
-       || p->cost.plan.u.pIdx==0 
-       || p->cost.plan.u.pIdx==pSrc->pIndex 
-  );
-
-  WHERETRACE(("   best index is %s cost=%.1f\n",
-         p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
-         p->cost.rCost));
-  
-  bestOrClauseIndex(p);
-  bestAutomaticIndex(p);
-  p->cost.plan.wsFlags |= eqTermMask;
-}
-
-/*
-** Find the query plan for accessing table pSrc->pTab. Write the
-** best query plan and its cost into the WhereCost object supplied 
-** as the last parameter. This function may calculate the cost of
-** both real and virtual table scans.
-**
-** This function does not take ORDER BY or DISTINCT into account.  Nor
-** does it remember the virtual table query plan.  All it does is compute
-** the cost while determining if an OR optimization is applicable.  The
-** details will be reconsidered later if the optimization is found to be
-** applicable.
-*/
-static void bestIndex(WhereBestIdx *p){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-  if( IsVirtual(p->pSrc->pTab) ){
-    sqlite3_index_info *pIdxInfo = 0;
-    p->ppIdxInfo = &pIdxInfo;
-    bestVirtualIndex(p);
-    assert( pIdxInfo!=0 || p->pParse->db->mallocFailed );
-    if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){
-      sqlite3_free(pIdxInfo->idxStr);
-    }
-    sqlite3DbFree(p->pParse->db, pIdxInfo);
-  }else
-#endif
-  {
-    bestBtreeIndex(p);
-  }
-}
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
 
 /*
 ** Disable a term in the WHERE clause.  Except, do not disable the term
@@ -108103,9 +113306,6 @@ static void bestIndex(WhereBestIdx *p){
 ** in the ON clause.  The term is disabled in (3) because it is not part
 ** of a LEFT OUTER JOIN.  In (1), the term is not disabled.
 **
-** IMPLEMENTATION-OF: R-24597-58655 No tests are done for terms that are
-** completely satisfied by indices.
-**
 ** Disabling a term causes that term to not be tested in the inner loop
 ** of the join.  Disabling is an optimization.  When terms are satisfied
 ** by indices, we disable them to prevent redundant tests in the inner
@@ -108118,6 +113318,7 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
   if( pTerm
       && (pTerm->wtFlags & TERM_CODED)==0
       && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
+      && (pLevel->notReady & pTerm->prereqAll)==0
   ){
     pTerm->wtFlags |= TERM_CODED;
     if( pTerm->iParent>=0 ){
@@ -108185,6 +113386,7 @@ static int codeEqualityTerm(
   WhereTerm *pTerm,   /* The term of the WHERE clause to be coded */
   WhereLevel *pLevel, /* The level of the FROM clause we are working on */
   int iEq,            /* Index of the equality term within this level */
+  int bRev,           /* True for reverse-order IN operations */
   int iTarget         /* Attempt to leave results in this register */
 ){
   Expr *pX = pTerm->pExpr;
@@ -108202,27 +113404,29 @@ static int codeEqualityTerm(
     int eType;
     int iTab;
     struct InLoop *pIn;
-    u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
+    WhereLoop *pLoop = pLevel->pWLoop;
 
-    if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 
-      && pLevel->plan.u.pIdx->aSortOrder[iEq]
+    if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
+      && pLoop->u.btree.pIndex!=0
+      && pLoop->u.btree.pIndex->aSortOrder[iEq]
     ){
       testcase( iEq==0 );
-      testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 );
-      testcase( iEq>0 && iEq+1<pLevel->plan.u.pIdx->nColumn );
       testcase( bRev );
       bRev = !bRev;
     }
     assert( pX->op==TK_IN );
     iReg = iTarget;
-    eType = sqlite3FindInIndex(pParse, pX, 0);
+    eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0);
     if( eType==IN_INDEX_INDEX_DESC ){
       testcase( bRev );
       bRev = !bRev;
     }
     iTab = pX->iTable;
     sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
-    assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
+    VdbeCoverageIf(v, bRev);
+    VdbeCoverageIf(v, !bRev);
+    assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
+    pLoop->wsFlags |= WHERE_IN_ABLE;
     if( pLevel->u.in.nIn==0 ){
       pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
     }
@@ -108239,8 +113443,8 @@ static int codeEqualityTerm(
       }else{
         pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
       }
-      pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
-      sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
+      pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen;
+      sqlite3VdbeAddOp1(v, OP_IsNull, iReg); VdbeCoverage(v);
     }else{
       pLevel->u.in.nIn = 0;
     }
@@ -108252,7 +113456,7 @@ static int codeEqualityTerm(
 
 /*
 ** Generate code that will evaluate all == and IN constraints for an
-** index.
+** index scan.
 **
 ** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
 ** Suppose the WHERE clause is this:  a==5 AND b IN (1,2,3) AND c>5 AND c<10
@@ -108267,9 +113471,15 @@ static int codeEqualityTerm(
 ** The only thing it does is allocate the pLevel->iMem memory cell and
 ** compute the affinity string.
 **
-** This routine always allocates at least one memory cell and returns
-** the index of that memory cell. The code that
-** calls this routine will use that memory cell to store the termination
+** The nExtraReg parameter is 0 or 1.  It is 0 if all WHERE clause constraints
+** are == or IN and are covered by the nEq.  nExtraReg is 1 if there is
+** an inequality constraint (such as the "c>=5 AND c<10" in the example) that
+** occurs after the nEq quality constraints.
+**
+** This routine allocates a range of nEq+nExtraReg memory cells and returns
+** the index of the first memory cell in that range. The code that
+** calls this routine will use that memory range to store keys for
+** start and termination conditions of the loop.
 ** key value of the loop.  If one or more IN operators appear, then
 ** this routine allocates an additional nEq memory cells for internal
 ** use.
@@ -108292,29 +113502,33 @@ static int codeEqualityTerm(
 static int codeAllEqualityTerms(
   Parse *pParse,        /* Parsing context */
   WhereLevel *pLevel,   /* Which nested loop of the FROM we are coding */
-  WhereClause *pWC,     /* The WHERE clause */
-  Bitmask notReady,     /* Which parts of FROM have not yet been coded */
+  int bRev,             /* Reverse the order of IN operators */
   int nExtraReg,        /* Number of extra registers to allocate */
   char **pzAff          /* OUT: Set to point to affinity string */
 ){
-  int nEq = pLevel->plan.nEq;   /* The number of == or IN constraints to code */
+  u16 nEq;                      /* The number of == or IN constraints to code */
+  u16 nSkip;                    /* Number of left-most columns to skip */
   Vdbe *v = pParse->pVdbe;      /* The vm under construction */
   Index *pIdx;                  /* The index being used for this loop */
-  int iCur = pLevel->iTabCur;   /* The cursor of the table */
   WhereTerm *pTerm;             /* A single constraint term */
+  WhereLoop *pLoop;             /* The WhereLoop object */
   int j;                        /* Loop counter */
   int regBase;                  /* Base register */
   int nReg;                     /* Number of registers to allocate */
   char *zAff;                   /* Affinity string to return */
 
   /* This module is only called on query plans that use an index. */
-  assert( pLevel->plan.wsFlags & WHERE_INDEXED );
-  pIdx = pLevel->plan.u.pIdx;
+  pLoop = pLevel->pWLoop;
+  assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
+  nEq = pLoop->u.btree.nEq;
+  nSkip = pLoop->u.btree.nSkip;
+  pIdx = pLoop->u.btree.pIndex;
+  assert( pIdx!=0 );
 
   /* Figure out how many memory cells we will need then allocate them.
   */
   regBase = pParse->nMem + 1;
-  nReg = pLevel->plan.nEq + nExtraReg;
+  nReg = pLoop->u.btree.nEq + nExtraReg;
   pParse->nMem += nReg;
 
   zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx));
@@ -108322,19 +113536,37 @@ static int codeAllEqualityTerms(
     pParse->db->mallocFailed = 1;
   }
 
+  if( nSkip ){
+    int iIdxCur = pLevel->iIdxCur;
+    sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
+    VdbeCoverageIf(v, bRev==0);
+    VdbeCoverageIf(v, bRev!=0);
+    VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
+    j = sqlite3VdbeAddOp0(v, OP_Goto);
+    pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
+                            iIdxCur, 0, regBase, nSkip);
+    VdbeCoverageIf(v, bRev==0);
+    VdbeCoverageIf(v, bRev!=0);
+    sqlite3VdbeJumpHere(v, j);
+    for(j=0; j<nSkip; j++){
+      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
+      assert( pIdx->aiColumn[j]>=0 );
+      VdbeComment((v, "%s", pIdx->pTable->aCol[pIdx->aiColumn[j]].zName));
+    }
+  }    
+
   /* Evaluate the equality constraints
   */
-  assert( pIdx->nColumn>=nEq );
-  for(j=0; j<nEq; j++){
+  assert( zAff==0 || (int)strlen(zAff)>=nEq );
+  for(j=nSkip; j<nEq; j++){
     int r1;
-    int k = pIdx->aiColumn[j];
-    pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx);
-    if( pTerm==0 ) break;
-    /* The following true for indices with redundant columns. 
+    pTerm = pLoop->aLTerm[j];
+    assert( pTerm!=0 );
+    /* The following testcase is true for indices with redundant columns. 
     ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
     testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
-    testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
-    r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, regBase+j);
+    testcase( pTerm->wtFlags & TERM_VIRTUAL );
+    r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
     if( r1!=regBase+j ){
       if( nReg==1 ){
         sqlite3ReleaseTempReg(pParse, regBase);
@@ -108347,7 +113579,10 @@ static int codeAllEqualityTerms(
     testcase( pTerm->eOperator & WO_IN );
     if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
       Expr *pRight = pTerm->pExpr->pRight;
-      sqlite3ExprCodeIsNullJump(v, pRight, regBase+j, pLevel->addrBrk);
+      if( sqlite3ExprCanBeNull(pRight) ){
+        sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
+        VdbeCoverage(v);
+      }
       if( zAff ){
         if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){
           zAff[j] = SQLITE_AFF_NONE;
@@ -108378,7 +113613,7 @@ static void explainAppendTerm(
   const char *zOp             /* Name of the operator */
 ){
   if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5);
-  sqlite3StrAccumAppend(pStr, zColumn, -1);
+  sqlite3StrAccumAppendAll(pStr, zColumn);
   sqlite3StrAccumAppend(pStr, zOp, 1);
   sqlite3StrAccumAppend(pStr, "?", 1);
 }
@@ -108402,32 +113637,40 @@ static void explainAppendTerm(
 ** It is the responsibility of the caller to free the buffer when it is
 ** no longer required.
 */
-static char *explainIndexRange(sqlite3 *db, WhereLevel *pLevel, Table *pTab){
-  WherePlan *pPlan = &pLevel->plan;
-  Index *pIndex = pPlan->u.pIdx;
-  int nEq = pPlan->nEq;
+static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
+  Index *pIndex = pLoop->u.btree.pIndex;
+  u16 nEq = pLoop->u.btree.nEq;
+  u16 nSkip = pLoop->u.btree.nSkip;
   int i, j;
   Column *aCol = pTab->aCol;
-  int *aiColumn = pIndex->aiColumn;
+  i16 *aiColumn = pIndex->aiColumn;
   StrAccum txt;
 
-  if( nEq==0 && (pPlan->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
+  if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
     return 0;
   }
   sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH);
   txt.db = db;
   sqlite3StrAccumAppend(&txt, " (", 2);
   for(i=0; i<nEq; i++){
-    explainAppendTerm(&txt, i, aCol[aiColumn[i]].zName, "=");
+    char *z = aiColumn[i] < 0 ? "rowid" : aCol[aiColumn[i]].zName;
+    if( i>=nSkip ){
+      explainAppendTerm(&txt, i, z, "=");
+    }else{
+      if( i ) sqlite3StrAccumAppend(&txt, " AND ", 5);
+      sqlite3StrAccumAppend(&txt, "ANY(", 4);
+      sqlite3StrAccumAppendAll(&txt, z);
+      sqlite3StrAccumAppend(&txt, ")", 1);
+    }
   }
 
   j = i;
-  if( pPlan->wsFlags&WHERE_BTM_LIMIT ){
-    char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
+  if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
+    char *z = aiColumn[j] < 0 ? "rowid" : aCol[aiColumn[j]].zName;
     explainAppendTerm(&txt, i++, z, ">");
   }
-  if( pPlan->wsFlags&WHERE_TOP_LIMIT ){
-    char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
+  if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
+    char *z = aiColumn[j] < 0 ? "rowid" : aCol[aiColumn[j]].zName;
     explainAppendTerm(&txt, i, z, "<");
   }
   sqlite3StrAccumAppend(&txt, ")", 1);
@@ -108448,21 +113691,26 @@ static void explainOneScan(
   int iFrom,                      /* Value for "from" column of output */
   u16 wctrlFlags                  /* Flags passed to sqlite3WhereBegin() */
 ){
-  if( pParse->explain==2 ){
-    u32 flags = pLevel->plan.wsFlags;
+#ifndef SQLITE_DEBUG
+  if( pParse->explain==2 )
+#endif
+  {
     struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
     Vdbe *v = pParse->pVdbe;      /* VM being constructed */
     sqlite3 *db = pParse->db;     /* Database handle */
     char *zMsg;                   /* Text to add to EQP output */
-    sqlite3_int64 nRow;           /* Expected number of rows visited by scan */
     int iId = pParse->iSelectId;  /* Select id (left-most output column) */
     int isSearch;                 /* True for a SEARCH. False for SCAN. */
+    WhereLoop *pLoop;             /* The controlling WhereLoop object */
+    u32 flags;                    /* Flags that describe this loop */
 
+    pLoop = pLevel->pWLoop;
+    flags = pLoop->wsFlags;
     if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;
 
-    isSearch = (pLevel->plan.nEq>0)
-             || (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
-             || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
+    isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
+            || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
+            || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
 
     zMsg = sqlite3MPrintf(db, "%s", isSearch?"SEARCH":"SCAN");
     if( pItem->pSelect ){
@@ -108474,43 +113722,44 @@ static void explainOneScan(
     if( pItem->zAlias ){
       zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
     }
-    if( (flags & WHERE_INDEXED)!=0 ){
-      char *zWhere = explainIndexRange(db, pLevel, pItem->pTab);
-      zMsg = sqlite3MAppendf(db, zMsg, "%s USING %s%sINDEX%s%s%s", zMsg, 
-          ((flags & WHERE_TEMP_INDEX)?"AUTOMATIC ":""),
-          ((flags & WHERE_IDX_ONLY)?"COVERING ":""),
-          ((flags & WHERE_TEMP_INDEX)?"":" "),
-          ((flags & WHERE_TEMP_INDEX)?"": pLevel->plan.u.pIdx->zName),
-          zWhere
-      );
+    if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0
+     && ALWAYS(pLoop->u.btree.pIndex!=0)
+    ){
+      const char *zFmt;
+      Index *pIdx = pLoop->u.btree.pIndex;
+      char *zWhere = explainIndexRange(db, pLoop, pItem->pTab);
+      assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
+      if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
+        zFmt = zWhere ? "%s USING PRIMARY KEY%.0s%s" : "%s%.0s%s";
+      }else if( flags & WHERE_AUTO_INDEX ){
+        zFmt = "%s USING AUTOMATIC COVERING INDEX%.0s%s";
+      }else if( flags & WHERE_IDX_ONLY ){
+        zFmt = "%s USING COVERING INDEX %s%s";
+      }else{
+        zFmt = "%s USING INDEX %s%s";
+      }
+      zMsg = sqlite3MAppendf(db, zMsg, zFmt, zMsg, pIdx->zName, zWhere);
       sqlite3DbFree(db, zWhere);
-    }else if( flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+    }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
       zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
 
-      if( flags&WHERE_ROWID_EQ ){
+      if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
         zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg);
       }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
         zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>? AND rowid<?)", zMsg);
       }else if( flags&WHERE_BTM_LIMIT ){
         zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>?)", zMsg);
-      }else if( flags&WHERE_TOP_LIMIT ){
+      }else if( ALWAYS(flags&WHERE_TOP_LIMIT) ){
         zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid<?)", zMsg);
       }
     }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
     else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
-      sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
       zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
-                  pVtabIdx->idxNum, pVtabIdx->idxStr);
+                  pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
     }
 #endif
-    if( wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ){
-      testcase( wctrlFlags & WHERE_ORDERBY_MIN );
-      nRow = 1;
-    }else{
-      nRow = (sqlite3_int64)pLevel->plan.nRow;
-    }
-    zMsg = sqlite3MAppendf(db, zMsg, "%s (~%lld rows)", zMsg, nRow);
+    zMsg = sqlite3MAppendf(db, zMsg, "%s", zMsg);
     sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
   }
 }
@@ -108526,7 +113775,6 @@ static void explainOneScan(
 static Bitmask codeOneLoopStart(
   WhereInfo *pWInfo,   /* Complete information about the WHERE clause */
   int iLevel,          /* Which level of pWInfo->a[] should be coded */
-  u16 wctrlFlags,      /* One of the WHERE_* flags defined in sqliteInt.h */
   Bitmask notReady     /* Which tables are currently available */
 ){
   int j, k;            /* Loop counters */
@@ -108535,27 +113783,31 @@ static Bitmask codeOneLoopStart(
   int omitTable;       /* True if we use the index only */
   int bRev;            /* True if we need to scan in reverse order */
   WhereLevel *pLevel;  /* The where level to be coded */
+  WhereLoop *pLoop;    /* The WhereLoop object being coded */
   WhereClause *pWC;    /* Decomposition of the entire WHERE clause */
   WhereTerm *pTerm;               /* A WHERE clause term */
   Parse *pParse;                  /* Parsing context */
+  sqlite3 *db;                    /* Database connection */
   Vdbe *v;                        /* The prepared stmt under constructions */
   struct SrcList_item *pTabItem;  /* FROM clause term being coded */
   int addrBrk;                    /* Jump here to break out of the loop */
   int addrCont;                   /* Jump here to continue with next cycle */
   int iRowidReg = 0;        /* Rowid is stored in this register, if not zero */
   int iReleaseReg = 0;      /* Temp register to free before returning */
-  Bitmask newNotReady;      /* Return value */
 
   pParse = pWInfo->pParse;
   v = pParse->pVdbe;
-  pWC = pWInfo->pWC;
+  pWC = &pWInfo->sWC;
+  db = pParse->db;
   pLevel = &pWInfo->a[iLevel];
+  pLoop = pLevel->pWLoop;
   pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
   iCur = pTabItem->iCursor;
-  bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
-  omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0 
-           && (wctrlFlags & WHERE_FORCE_TABLE)==0;
-  VdbeNoopComment((v, "Begin Join Loop %d", iLevel));
+  pLevel->notReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur);
+  bRev = (pWInfo->revMask>>iLevel)&1;
+  omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 
+           && (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0;
+  VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
 
   /* Create labels for the "break" and "continue" instructions
   ** for the current loop.  Jump to addrBrk to break out of a loop.
@@ -108583,87 +113835,85 @@ static Bitmask codeOneLoopStart(
   /* Special case of a FROM clause subquery implemented as a co-routine */
   if( pTabItem->viaCoroutine ){
     int regYield = pTabItem->regReturn;
-    sqlite3VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield);
-    pLevel->p2 =  sqlite3VdbeAddOp1(v, OP_Yield, regYield);
-    VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName));
-    sqlite3VdbeAddOp2(v, OP_If, regYield+1, addrBrk);
+    sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
+    pLevel->p2 =  sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
+    VdbeCoverage(v);
+    VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName));
     pLevel->op = OP_Goto;
   }else
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  if(  (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
-    /* Case 0:  The table is a virtual-table.  Use the VFilter and VNext
+  if(  (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
+    /* Case 1:  The table is a virtual-table.  Use the VFilter and VNext
     **          to access the data.
     */
     int iReg;   /* P3 Value for OP_VFilter */
     int addrNotFound;
-    sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
-    int nConstraint = pVtabIdx->nConstraint;
-    struct sqlite3_index_constraint_usage *aUsage =
-                                                pVtabIdx->aConstraintUsage;
-    const struct sqlite3_index_constraint *aConstraint =
-                                                pVtabIdx->aConstraint;
+    int nConstraint = pLoop->nLTerm;
 
     sqlite3ExprCachePush(pParse);
     iReg = sqlite3GetTempRange(pParse, nConstraint+2);
     addrNotFound = pLevel->addrBrk;
-    for(j=1; j<=nConstraint; j++){
-      for(k=0; k<nConstraint; k++){
-        if( aUsage[k].argvIndex==j ){
-          int iTarget = iReg+j+1;
-          pTerm = &pWC->a[aConstraint[k].iTermOffset];
-          if( pTerm->eOperator & WO_IN ){
-            codeEqualityTerm(pParse, pTerm, pLevel, k, iTarget);
-            addrNotFound = pLevel->addrNxt;
-          }else{
-            sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
-          }
-          break;
-        }
+    for(j=0; j<nConstraint; j++){
+      int iTarget = iReg+j+2;
+      pTerm = pLoop->aLTerm[j];
+      if( pTerm==0 ) continue;
+      if( pTerm->eOperator & WO_IN ){
+        codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
+        addrNotFound = pLevel->addrNxt;
+      }else{
+        sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
       }
-      if( k==nConstraint ) break;
     }
-    sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
-    sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
-    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
-                      pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
-    pVtabIdx->needToFreeIdxStr = 0;
-    for(j=0; j<nConstraint; j++){
-      if( aUsage[j].omit ){
-        int iTerm = aConstraint[j].iTermOffset;
-        disableTerm(pLevel, &pWC->a[iTerm]);
+    sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
+    sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1);
+    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
+                      pLoop->u.vtab.idxStr,
+                      pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC);
+    VdbeCoverage(v);
+    pLoop->u.vtab.needFree = 0;
+    for(j=0; j<nConstraint && j<16; j++){
+      if( (pLoop->u.vtab.omitMask>>j)&1 ){
+        disableTerm(pLevel, pLoop->aLTerm[j]);
       }
     }
     pLevel->op = OP_VNext;
     pLevel->p1 = iCur;
     pLevel->p2 = sqlite3VdbeCurrentAddr(v);
     sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
-    sqlite3ExprCachePop(pParse, 1);
+    sqlite3ExprCachePop(pParse);
   }else
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
-  if( pLevel->plan.wsFlags & WHERE_ROWID_EQ ){
-    /* Case 1:  We can directly reference a single row using an
+  if( (pLoop->wsFlags & WHERE_IPK)!=0
+   && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0
+  ){
+    /* Case 2:  We can directly reference a single row using an
     **          equality comparison against the ROWID field.  Or
     **          we reference multiple rows using a "rowid IN (...)"
     **          construct.
     */
-    iReleaseReg = sqlite3GetTempReg(pParse);
-    pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
+    assert( pLoop->u.btree.nEq==1 );
+    pTerm = pLoop->aLTerm[0];
     assert( pTerm!=0 );
     assert( pTerm->pExpr!=0 );
     assert( omitTable==0 );
-    testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
-    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, iReleaseReg);
+    testcase( pTerm->wtFlags & TERM_VIRTUAL );
+    iReleaseReg = ++pParse->nMem;
+    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
+    if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
     addrNxt = pLevel->addrNxt;
-    sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
+    sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); VdbeCoverage(v);
     sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
+    VdbeCoverage(v);
     sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1);
     sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
     VdbeComment((v, "pk"));
     pLevel->op = OP_Noop;
-  }else if( pLevel->plan.wsFlags & WHERE_ROWID_RANGE ){
-    /* Case 2:  We have an inequality comparison against the ROWID field.
+  }else if( (pLoop->wsFlags & WHERE_IPK)!=0
+         && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
+  ){
+    /* Case 3:  We have an inequality comparison against the ROWID field.
     */
     int testOp = OP_Noop;
     int start;
@@ -108671,8 +113921,11 @@ static Bitmask codeOneLoopStart(
     WhereTerm *pStart, *pEnd;
 
     assert( omitTable==0 );
-    pStart = findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0);
-    pEnd = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0);
+    j = 0;
+    pStart = pEnd = 0;
+    if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++];
+    if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++];
+    assert( pStart!=0 || pEnd!=0 );
     if( bRev ){
       pTerm = pStart;
       pStart = pEnd;
@@ -108686,34 +113939,42 @@ static Bitmask codeOneLoopStart(
       ** seek opcodes.  It depends on a particular ordering of TK_xx
       */
       const u8 aMoveOp[] = {
-           /* TK_GT */  OP_SeekGt,
-           /* TK_LE */  OP_SeekLe,
-           /* TK_LT */  OP_SeekLt,
-           /* TK_GE */  OP_SeekGe
+           /* TK_GT */  OP_SeekGT,
+           /* TK_LE */  OP_SeekLE,
+           /* TK_LT */  OP_SeekLT,
+           /* TK_GE */  OP_SeekGE
       };
       assert( TK_LE==TK_GT+1 );      /* Make sure the ordering.. */
       assert( TK_LT==TK_GT+2 );      /*  ... of the TK_xx values... */
       assert( TK_GE==TK_GT+3 );      /*  ... is correcct. */
 
-      testcase( pStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+      assert( (pStart->wtFlags & TERM_VNULL)==0 );
+      testcase( pStart->wtFlags & TERM_VIRTUAL );
       pX = pStart->pExpr;
       assert( pX!=0 );
-      assert( pStart->leftCursor==iCur );
+      testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
       r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
       sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1);
       VdbeComment((v, "pk"));
+      VdbeCoverageIf(v, pX->op==TK_GT);
+      VdbeCoverageIf(v, pX->op==TK_LE);
+      VdbeCoverageIf(v, pX->op==TK_LT);
+      VdbeCoverageIf(v, pX->op==TK_GE);
       sqlite3ExprCacheAffinityChange(pParse, r1, 1);
       sqlite3ReleaseTempReg(pParse, rTemp);
       disableTerm(pLevel, pStart);
     }else{
       sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk);
+      VdbeCoverageIf(v, bRev==0);
+      VdbeCoverageIf(v, bRev!=0);
     }
     if( pEnd ){
       Expr *pX;
       pX = pEnd->pExpr;
       assert( pX!=0 );
-      assert( pEnd->leftCursor==iCur );
-      testcase( pEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+      assert( (pEnd->wtFlags & TERM_VNULL)==0 );
+      testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */
+      testcase( pEnd->wtFlags & TERM_VIRTUAL );
       memEndValue = ++pParse->nMem;
       sqlite3ExprCode(pParse, pX->pRight, memEndValue);
       if( pX->op==TK_LT || pX->op==TK_GT ){
@@ -108727,20 +113988,20 @@ static Bitmask codeOneLoopStart(
     pLevel->op = bRev ? OP_Prev : OP_Next;
     pLevel->p1 = iCur;
     pLevel->p2 = start;
-    if( pStart==0 && pEnd==0 ){
-      pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
-    }else{
-      assert( pLevel->p5==0 );
-    }
+    assert( pLevel->p5==0 );
     if( testOp!=OP_Noop ){
-      iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
+      iRowidReg = ++pParse->nMem;
       sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
       sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
       sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
+      VdbeCoverageIf(v, testOp==OP_Le);
+      VdbeCoverageIf(v, testOp==OP_Lt);
+      VdbeCoverageIf(v, testOp==OP_Ge);
+      VdbeCoverageIf(v, testOp==OP_Gt);
       sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
     }
-  }else if( pLevel->plan.wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
-    /* Case 3: A scan using an index.
+  }else if( pLoop->wsFlags & WHERE_INDEXED ){
+    /* Case 4: A scan using an index.
     **
     **         The WHERE clause may contain zero or more equality 
     **         terms ("==" or "IN" operators) that refer to the N
@@ -108776,20 +114037,19 @@ static Bitmask codeOneLoopStart(
       0,
       OP_Rewind,           /* 2: (!start_constraints && startEq &&  !bRev) */
       OP_Last,             /* 3: (!start_constraints && startEq &&   bRev) */
-      OP_SeekGt,           /* 4: (start_constraints  && !startEq && !bRev) */
-      OP_SeekLt,           /* 5: (start_constraints  && !startEq &&  bRev) */
-      OP_SeekGe,           /* 6: (start_constraints  &&  startEq && !bRev) */
-      OP_SeekLe            /* 7: (start_constraints  &&  startEq &&  bRev) */
+      OP_SeekGT,           /* 4: (start_constraints  && !startEq && !bRev) */
+      OP_SeekLT,           /* 5: (start_constraints  && !startEq &&  bRev) */
+      OP_SeekGE,           /* 6: (start_constraints  &&  startEq && !bRev) */
+      OP_SeekLE            /* 7: (start_constraints  &&  startEq &&  bRev) */
     };
     static const u8 aEndOp[] = {
-      OP_Noop,             /* 0: (!end_constraints) */
-      OP_IdxGE,            /* 1: (end_constraints && !bRev) */
-      OP_IdxLT             /* 2: (end_constraints && bRev) */
+      OP_IdxGE,            /* 0: (end_constraints && !bRev && !endEq) */
+      OP_IdxGT,            /* 1: (end_constraints && !bRev &&  endEq) */
+      OP_IdxLE,            /* 2: (end_constraints &&  bRev && !endEq) */
+      OP_IdxLT,            /* 3: (end_constraints &&  bRev &&  endEq) */
     };
-    int nEq = pLevel->plan.nEq;  /* Number of == or IN terms */
-    int isMinQuery = 0;          /* If this is an optimized SELECT min(x).. */
+    u16 nEq = pLoop->u.btree.nEq;     /* Number of == or IN terms */
     int regBase;                 /* Base register holding constraint values */
-    int r1;                      /* Temp register */
     WhereTerm *pRangeStart = 0;  /* Inequality constraint at range start */
     WhereTerm *pRangeEnd = 0;    /* Inequality constraint at range end */
     int startEq;                 /* True if range start uses ==, >= or <= */
@@ -108801,11 +114061,13 @@ static Bitmask codeOneLoopStart(
     int nExtraReg = 0;           /* Number of extra registers needed */
     int op;                      /* Instruction opcode */
     char *zStartAff;             /* Affinity for start of range constraint */
-    char *zEndAff;               /* Affinity for end of range constraint */
+    char cEndAff = 0;            /* Affinity for end of range constraint */
+    u8 bSeekPastNull = 0;        /* True to seek past initial nulls */
+    u8 bStopAtNull = 0;          /* Add condition to terminate at NULLs */
 
-    pIdx = pLevel->plan.u.pIdx;
+    pIdx = pLoop->u.btree.pIndex;
     iIdxCur = pLevel->iIdxCur;
-    k = (nEq==pIdx->nColumn ? -1 : pIdx->aiColumn[nEq]);
+    assert( nEq>=pLoop->u.btree.nSkip );
 
     /* If this loop satisfies a sort order (pOrderBy) request that 
     ** was passed to this function to implement a "SELECT min(x) ..." 
@@ -108815,52 +114077,62 @@ static Bitmask codeOneLoopStart(
     ** the first one after the nEq equality constraints in the index,
     ** this requires some special handling.
     */
-    if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0
-     && (pLevel->plan.wsFlags&WHERE_ORDERED)
-     && (pIdx->nColumn>nEq)
+    assert( pWInfo->pOrderBy==0
+         || pWInfo->pOrderBy->nExpr==1
+         || (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 );
+    if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
+     && pWInfo->nOBSat>0
+     && (pIdx->nKeyCol>nEq)
     ){
-      /* assert( pOrderBy->nExpr==1 ); */
-      /* assert( pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq] ); */
-      isMinQuery = 1;
+      assert( pLoop->u.btree.nSkip==0 );
+      bSeekPastNull = 1;
       nExtraReg = 1;
     }
 
     /* Find any inequality constraint terms for the start and end 
     ** of the range. 
     */
-    if( pLevel->plan.wsFlags & WHERE_TOP_LIMIT ){
-      pRangeEnd = findTerm(pWC, iCur, k, notReady, (WO_LT|WO_LE), pIdx);
+    j = nEq;
+    if( pLoop->wsFlags & WHERE_BTM_LIMIT ){
+      pRangeStart = pLoop->aLTerm[j++];
       nExtraReg = 1;
     }
-    if( pLevel->plan.wsFlags & WHERE_BTM_LIMIT ){
-      pRangeStart = findTerm(pWC, iCur, k, notReady, (WO_GT|WO_GE), pIdx);
+    if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
+      pRangeEnd = pLoop->aLTerm[j++];
       nExtraReg = 1;
+      if( pRangeStart==0
+       && (j = pIdx->aiColumn[nEq])>=0 
+       && pIdx->pTable->aCol[j].notNull==0
+      ){
+        bSeekPastNull = 1;
+      }
     }
+    assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
 
     /* Generate code to evaluate all constraint terms using == or IN
     ** and store the values of those terms in an array of registers
     ** starting at regBase.
     */
-    regBase = codeAllEqualityTerms(
-        pParse, pLevel, pWC, notReady, nExtraReg, &zStartAff
-    );
-    zEndAff = sqlite3DbStrDup(pParse->db, zStartAff);
+    regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
+    assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
+    if( zStartAff ) cEndAff = zStartAff[nEq];
     addrNxt = pLevel->addrNxt;
 
     /* If we are doing a reverse order scan on an ascending index, or
     ** a forward order scan on a descending index, interchange the 
     ** start and end terms (pRangeStart and pRangeEnd).
     */
-    if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
-     || (bRev && pIdx->nColumn==nEq)
+    if( (nEq<pIdx->nKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
+     || (bRev && pIdx->nKeyCol==nEq)
     ){
       SWAP(WhereTerm *, pRangeEnd, pRangeStart);
+      SWAP(u8, bSeekPastNull, bStopAtNull);
     }
 
-    testcase( pRangeStart && pRangeStart->eOperator & WO_LE );
-    testcase( pRangeStart && pRangeStart->eOperator & WO_GE );
-    testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE );
-    testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE );
+    testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
+    testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 );
+    testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 );
+    testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 );
     startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE);
     endEq =   !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE);
     start_constraints = pRangeStart || nEq>0;
@@ -108870,8 +114142,11 @@ static Bitmask codeOneLoopStart(
     if( pRangeStart ){
       Expr *pRight = pRangeStart->pExpr->pRight;
       sqlite3ExprCode(pParse, pRight, regBase+nEq);
-      if( (pRangeStart->wtFlags & TERM_VNULL)==0 ){
-        sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
+      if( (pRangeStart->wtFlags & TERM_VNULL)==0
+       && sqlite3ExprCanBeNull(pRight)
+      ){
+        sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
+        VdbeCoverage(v);
       }
       if( zStartAff ){
         if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){
@@ -108883,456 +114158,2608 @@ static Bitmask codeOneLoopStart(
         if( sqlite3ExprNeedsNoAffinityChange(pRight, zStartAff[nEq]) ){
           zStartAff[nEq] = SQLITE_AFF_NONE;
         }
-      }  
-      nConstraint++;
-      testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
-    }else if( isMinQuery ){
-      sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
-      nConstraint++;
-      startEq = 0;
-      start_constraints = 1;
+      }  
+      nConstraint++;
+      testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
+    }else if( bSeekPastNull ){
+      sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
+      nConstraint++;
+      startEq = 0;
+      start_constraints = 1;
+    }
+    codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff);
+    op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
+    assert( op!=0 );
+    sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
+    VdbeCoverage(v);
+    VdbeCoverageIf(v, op==OP_Rewind);  testcase( op==OP_Rewind );
+    VdbeCoverageIf(v, op==OP_Last);    testcase( op==OP_Last );
+    VdbeCoverageIf(v, op==OP_SeekGT);  testcase( op==OP_SeekGT );
+    VdbeCoverageIf(v, op==OP_SeekGE);  testcase( op==OP_SeekGE );
+    VdbeCoverageIf(v, op==OP_SeekLE);  testcase( op==OP_SeekLE );
+    VdbeCoverageIf(v, op==OP_SeekLT);  testcase( op==OP_SeekLT );
+
+    /* Load the value for the inequality constraint at the end of the
+    ** range (if any).
+    */
+    nConstraint = nEq;
+    if( pRangeEnd ){
+      Expr *pRight = pRangeEnd->pExpr->pRight;
+      sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
+      sqlite3ExprCode(pParse, pRight, regBase+nEq);
+      if( (pRangeEnd->wtFlags & TERM_VNULL)==0
+       && sqlite3ExprCanBeNull(pRight)
+      ){
+        sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
+        VdbeCoverage(v);
+      }
+      if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE
+       && !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff)
+      ){
+        codeApplyAffinity(pParse, regBase+nEq, 1, &cEndAff);
+      }
+      nConstraint++;
+      testcase( pRangeEnd->wtFlags & TERM_VIRTUAL );
+    }else if( bStopAtNull ){
+      sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
+      endEq = 0;
+      nConstraint++;
+    }
+    sqlite3DbFree(db, zStartAff);
+
+    /* Top of the loop body */
+    pLevel->p2 = sqlite3VdbeCurrentAddr(v);
+
+    /* Check if the index cursor is past the end of the range. */
+    if( nConstraint ){
+      op = aEndOp[bRev*2 + endEq];
+      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
+      testcase( op==OP_IdxGT );  VdbeCoverageIf(v, op==OP_IdxGT );
+      testcase( op==OP_IdxGE );  VdbeCoverageIf(v, op==OP_IdxGE );
+      testcase( op==OP_IdxLT );  VdbeCoverageIf(v, op==OP_IdxLT );
+      testcase( op==OP_IdxLE );  VdbeCoverageIf(v, op==OP_IdxLE );
+    }
+
+    /* Seek the table cursor, if required */
+    disableTerm(pLevel, pRangeStart);
+    disableTerm(pLevel, pRangeEnd);
+    if( omitTable ){
+      /* pIdx is a covering index.  No need to access the main table. */
+    }else if( HasRowid(pIdx->pTable) ){
+      iRowidReg = ++pParse->nMem;
+      sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
+      sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
+      sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg);  /* Deferred seek */
+    }else if( iCur!=iIdxCur ){
+      Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
+      iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
+      for(j=0; j<pPk->nKeyCol; j++){
+        k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
+        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
+      }
+      sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
+                           iRowidReg, pPk->nKeyCol); VdbeCoverage(v);
+    }
+
+    /* Record the instruction used to terminate the loop. Disable 
+    ** WHERE clause terms made redundant by the index range scan.
+    */
+    if( pLoop->wsFlags & WHERE_ONEROW ){
+      pLevel->op = OP_Noop;
+    }else if( bRev ){
+      pLevel->op = OP_Prev;
+    }else{
+      pLevel->op = OP_Next;
+    }
+    pLevel->p1 = iIdxCur;
+    pLevel->p3 = (pLoop->wsFlags&WHERE_UNQ_WANTED)!=0 ? 1:0;
+    if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){
+      pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
+    }else{
+      assert( pLevel->p5==0 );
+    }
+  }else
+
+#ifndef SQLITE_OMIT_OR_OPTIMIZATION
+  if( pLoop->wsFlags & WHERE_MULTI_OR ){
+    /* Case 5:  Two or more separately indexed terms connected by OR
+    **
+    ** Example:
+    **
+    **   CREATE TABLE t1(a,b,c,d);
+    **   CREATE INDEX i1 ON t1(a);
+    **   CREATE INDEX i2 ON t1(b);
+    **   CREATE INDEX i3 ON t1(c);
+    **
+    **   SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13)
+    **
+    ** In the example, there are three indexed terms connected by OR.
+    ** The top of the loop looks like this:
+    **
+    **          Null       1                # Zero the rowset in reg 1
+    **
+    ** Then, for each indexed term, the following. The arguments to
+    ** RowSetTest are such that the rowid of the current row is inserted
+    ** into the RowSet. If it is already present, control skips the
+    ** Gosub opcode and jumps straight to the code generated by WhereEnd().
+    **
+    **        sqlite3WhereBegin(<term>)
+    **          RowSetTest                  # Insert rowid into rowset
+    **          Gosub      2 A
+    **        sqlite3WhereEnd()
+    **
+    ** Following the above, code to terminate the loop. Label A, the target
+    ** of the Gosub above, jumps to the instruction right after the Goto.
+    **
+    **          Null       1                # Zero the rowset in reg 1
+    **          Goto       B                # The loop is finished.
+    **
+    **       A: <loop body>                 # Return data, whatever.
+    **
+    **          Return     2                # Jump back to the Gosub
+    **
+    **       B: <after the loop>
+    **
+    ** Added 2014-05-26: If the table is a WITHOUT ROWID table, then
+    ** use an ephermeral index instead of a RowSet to record the primary
+    ** keys of the rows we have already seen.
+    **
+    */
+    WhereClause *pOrWc;    /* The OR-clause broken out into subterms */
+    SrcList *pOrTab;       /* Shortened table list or OR-clause generation */
+    Index *pCov = 0;             /* Potential covering index (or NULL) */
+    int iCovCur = pParse->nTab++;  /* Cursor used for index scans (if any) */
+
+    int regReturn = ++pParse->nMem;           /* Register used with OP_Gosub */
+    int regRowset = 0;                        /* Register for RowSet object */
+    int regRowid = 0;                         /* Register holding rowid */
+    int iLoopBody = sqlite3VdbeMakeLabel(v);  /* Start of loop body */
+    int iRetInit;                             /* Address of regReturn init */
+    int untestedTerms = 0;             /* Some terms not completely tested */
+    int ii;                            /* Loop counter */
+    u16 wctrlFlags;                    /* Flags for sub-WHERE clause */
+    Expr *pAndExpr = 0;                /* An ".. AND (...)" expression */
+    Table *pTab = pTabItem->pTab;
+   
+    pTerm = pLoop->aLTerm[0];
+    assert( pTerm!=0 );
+    assert( pTerm->eOperator & WO_OR );
+    assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
+    pOrWc = &pTerm->u.pOrInfo->wc;
+    pLevel->op = OP_Return;
+    pLevel->p1 = regReturn;
+
+    /* Set up a new SrcList in pOrTab containing the table being scanned
+    ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
+    ** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
+    */
+    if( pWInfo->nLevel>1 ){
+      int nNotReady;                 /* The number of notReady tables */
+      struct SrcList_item *origSrc;     /* Original list of tables */
+      nNotReady = pWInfo->nLevel - iLevel - 1;
+      pOrTab = sqlite3StackAllocRaw(db,
+                            sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
+      if( pOrTab==0 ) return notReady;
+      pOrTab->nAlloc = (u8)(nNotReady + 1);
+      pOrTab->nSrc = pOrTab->nAlloc;
+      memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
+      origSrc = pWInfo->pTabList->a;
+      for(k=1; k<=nNotReady; k++){
+        memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
+      }
+    }else{
+      pOrTab = pWInfo->pTabList;
+    }
+
+    /* Initialize the rowset register to contain NULL. An SQL NULL is 
+    ** equivalent to an empty rowset.  Or, create an ephermeral index
+    ** capable of holding primary keys in the case of a WITHOUT ROWID.
+    **
+    ** Also initialize regReturn to contain the address of the instruction 
+    ** immediately following the OP_Return at the bottom of the loop. This
+    ** is required in a few obscure LEFT JOIN cases where control jumps
+    ** over the top of the loop into the body of it. In this case the 
+    ** correct response for the end-of-loop code (the OP_Return) is to 
+    ** fall through to the next instruction, just as an OP_Next does if
+    ** called on an uninitialized cursor.
+    */
+    if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+      if( HasRowid(pTab) ){
+        regRowset = ++pParse->nMem;
+        sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
+      }else{
+        Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+        regRowset = pParse->nTab++;
+        sqlite3VdbeAddOp2(v, OP_OpenEphemeral, regRowset, pPk->nKeyCol);
+        sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+      }
+      regRowid = ++pParse->nMem;
+    }
+    iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
+
+    /* If the original WHERE clause is z of the form:  (x1 OR x2 OR ...) AND y
+    ** Then for every term xN, evaluate as the subexpression: xN AND z
+    ** That way, terms in y that are factored into the disjunction will
+    ** be picked up by the recursive calls to sqlite3WhereBegin() below.
+    **
+    ** Actually, each subexpression is converted to "xN AND w" where w is
+    ** the "interesting" terms of z - terms that did not originate in the
+    ** ON or USING clause of a LEFT JOIN, and terms that are usable as 
+    ** indices.
+    **
+    ** This optimization also only applies if the (x1 OR x2 OR ...) term
+    ** is not contained in the ON clause of a LEFT JOIN.
+    ** See ticket http://www.sqlite.org/src/info/f2369304e4
+    */
+    if( pWC->nTerm>1 ){
+      int iTerm;
+      for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
+        Expr *pExpr = pWC->a[iTerm].pExpr;
+        if( &pWC->a[iTerm] == pTerm ) continue;
+        if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
+        testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
+        testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
+        if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue;
+        if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
+        pExpr = sqlite3ExprDup(db, pExpr, 0);
+        pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
+      }
+      if( pAndExpr ){
+        pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
+      }
+    }
+
+    /* Run a separate WHERE clause for each term of the OR clause.  After
+    ** eliminating duplicates from other WHERE clauses, the action for each
+    ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
+    */
+    wctrlFlags =  WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
+                  WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY;
+    for(ii=0; ii<pOrWc->nTerm; ii++){
+      WhereTerm *pOrTerm = &pOrWc->a[ii];
+      if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
+        WhereInfo *pSubWInfo;           /* Info for single OR-term scan */
+        Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
+        int j1 = 0;                     /* Address of jump operation */
+        if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
+          pAndExpr->pLeft = pOrExpr;
+          pOrExpr = pAndExpr;
+        }
+        /* Loop through table entries that match term pOrTerm. */
+        pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
+                                      wctrlFlags, iCovCur);
+        assert( pSubWInfo || pParse->nErr || db->mallocFailed );
+        if( pSubWInfo ){
+          WhereLoop *pSubLoop;
+          explainOneScan(
+              pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
+          );
+          /* This is the sub-WHERE clause body.  First skip over
+          ** duplicate rows from prior sub-WHERE clauses, and record the
+          ** rowid (or PRIMARY KEY) for the current row so that the same
+          ** row will be skipped in subsequent sub-WHERE clauses.
+          */
+          if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+            int r;
+            int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
+            if( HasRowid(pTab) ){
+              r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0);
+              j1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, r,iSet);
+              VdbeCoverage(v);
+            }else{
+              Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+              int nPk = pPk->nKeyCol;
+              int iPk;
+
+              /* Read the PK into an array of temp registers. */
+              r = sqlite3GetTempRange(pParse, nPk);
+              for(iPk=0; iPk<nPk; iPk++){
+                int iCol = pPk->aiColumn[iPk];
+                sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur, r+iPk, 0);
+              }
+
+              /* Check if the temp table already contains this key. If so,
+              ** the row has already been included in the result set and
+              ** can be ignored (by jumping past the Gosub below). Otherwise,
+              ** insert the key into the temp table and proceed with processing
+              ** the row.
+              **
+              ** Use some of the same optimizations as OP_RowSetTest: If iSet
+              ** is zero, assume that the key cannot already be present in
+              ** the temp table. And if iSet is -1, assume that there is no 
+              ** need to insert the key into the temp table, as it will never 
+              ** be tested for.  */ 
+              if( iSet ){
+                j1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk);
+                VdbeCoverage(v);
+              }
+              if( iSet>=0 ){
+                sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid);
+                sqlite3VdbeAddOp3(v, OP_IdxInsert, regRowset, regRowid, 0);
+                if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+              }
+
+              /* Release the array of temp registers */
+              sqlite3ReleaseTempRange(pParse, r, nPk);
+            }
+          }
+
+          /* Invoke the main loop body as a subroutine */
+          sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
+
+          /* Jump here (skipping the main loop body subroutine) if the
+          ** current sub-WHERE row is a duplicate from prior sub-WHEREs. */
+          if( j1 ) sqlite3VdbeJumpHere(v, j1);
+
+          /* The pSubWInfo->untestedTerms flag means that this OR term
+          ** contained one or more AND term from a notReady table.  The
+          ** terms from the notReady table could not be tested and will
+          ** need to be tested later.
+          */
+          if( pSubWInfo->untestedTerms ) untestedTerms = 1;
+
+          /* If all of the OR-connected terms are optimized using the same
+          ** index, and the index is opened using the same cursor number
+          ** by each call to sqlite3WhereBegin() made by this loop, it may
+          ** be possible to use that index as a covering index.
+          **
+          ** If the call to sqlite3WhereBegin() above resulted in a scan that
+          ** uses an index, and this is either the first OR-connected term
+          ** processed or the index is the same as that used by all previous
+          ** terms, set pCov to the candidate covering index. Otherwise, set 
+          ** pCov to NULL to indicate that no candidate covering index will 
+          ** be available.
+          */
+          pSubLoop = pSubWInfo->a[0].pWLoop;
+          assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
+          if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0
+           && (ii==0 || pSubLoop->u.btree.pIndex==pCov)
+           && (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
+          ){
+            assert( pSubWInfo->a[0].iIdxCur==iCovCur );
+            pCov = pSubLoop->u.btree.pIndex;
+            wctrlFlags |= WHERE_REOPEN_IDX;
+          }else{
+            pCov = 0;
+          }
+
+          /* Finish the loop through table entries that match term pOrTerm. */
+          sqlite3WhereEnd(pSubWInfo);
+        }
+      }
+    }
+    pLevel->u.pCovidx = pCov;
+    if( pCov ) pLevel->iIdxCur = iCovCur;
+    if( pAndExpr ){
+      pAndExpr->pLeft = 0;
+      sqlite3ExprDelete(db, pAndExpr);
+    }
+    sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
+    sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
+    sqlite3VdbeResolveLabel(v, iLoopBody);
+
+    if( pWInfo->nLevel>1 ) sqlite3StackFree(db, pOrTab);
+    if( !untestedTerms ) disableTerm(pLevel, pTerm);
+  }else
+#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
+
+  {
+    /* Case 6:  There is no usable index.  We must do a complete
+    **          scan of the entire table.
+    */
+    static const u8 aStep[] = { OP_Next, OP_Prev };
+    static const u8 aStart[] = { OP_Rewind, OP_Last };
+    assert( bRev==0 || bRev==1 );
+    if( pTabItem->isRecursive ){
+      /* Tables marked isRecursive have only a single row that is stored in
+      ** a pseudo-cursor.  No need to Rewind or Next such cursors. */
+      pLevel->op = OP_Noop;
+    }else{
+      pLevel->op = aStep[bRev];
+      pLevel->p1 = iCur;
+      pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
+      VdbeCoverageIf(v, bRev==0);
+      VdbeCoverageIf(v, bRev!=0);
+      pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
+    }
+  }
+
+  /* Insert code to test every subexpression that can be completely
+  ** computed using the current set of tables.
+  */
+  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
+    Expr *pE;
+    testcase( pTerm->wtFlags & TERM_VIRTUAL );
+    testcase( pTerm->wtFlags & TERM_CODED );
+    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+    if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
+      testcase( pWInfo->untestedTerms==0
+               && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
+      pWInfo->untestedTerms = 1;
+      continue;
+    }
+    pE = pTerm->pExpr;
+    assert( pE!=0 );
+    if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
+      continue;
+    }
+    sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
+    pTerm->wtFlags |= TERM_CODED;
+  }
+
+  /* Insert code to test for implied constraints based on transitivity
+  ** of the "==" operator.
+  **
+  ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123"
+  ** and we are coding the t1 loop and the t2 loop has not yet coded,
+  ** then we cannot use the "t1.a=t2.b" constraint, but we can code
+  ** the implied "t1.a=123" constraint.
+  */
+  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
+    Expr *pE, *pEAlt;
+    WhereTerm *pAlt;
+    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+    if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue;
+    if( pTerm->leftCursor!=iCur ) continue;
+    if( pLevel->iLeftJoin ) continue;
+    pE = pTerm->pExpr;
+    assert( !ExprHasProperty(pE, EP_FromJoin) );
+    assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
+    pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0);
+    if( pAlt==0 ) continue;
+    if( pAlt->wtFlags & (TERM_CODED) ) continue;
+    testcase( pAlt->eOperator & WO_EQ );
+    testcase( pAlt->eOperator & WO_IN );
+    VdbeModuleComment((v, "begin transitive constraint"));
+    pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt));
+    if( pEAlt ){
+      *pEAlt = *pAlt->pExpr;
+      pEAlt->pLeft = pE->pLeft;
+      sqlite3ExprIfFalse(pParse, pEAlt, addrCont, SQLITE_JUMPIFNULL);
+      sqlite3StackFree(db, pEAlt);
+    }
+  }
+
+  /* For a LEFT OUTER JOIN, generate code that will record the fact that
+  ** at least one row of the right table has matched the left table.  
+  */
+  if( pLevel->iLeftJoin ){
+    pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
+    sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
+    VdbeComment((v, "record LEFT JOIN hit"));
+    sqlite3ExprCacheClear(pParse);
+    for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
+      testcase( pTerm->wtFlags & TERM_VIRTUAL );
+      testcase( pTerm->wtFlags & TERM_CODED );
+      if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+      if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
+        assert( pWInfo->untestedTerms );
+        continue;
+      }
+      assert( pTerm->pExpr );
+      sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
+      pTerm->wtFlags |= TERM_CODED;
+    }
+  }
+
+  return pLevel->notReady;
+}
+
+#if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN)
+/*
+** Generate "Explanation" text for a WhereTerm.
+*/
+static void whereExplainTerm(Vdbe *v, WhereTerm *pTerm){
+  char zType[4];
+  memcpy(zType, "...", 4);
+  if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
+  if( pTerm->eOperator & WO_EQUIV  ) zType[1] = 'E';
+  if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
+  sqlite3ExplainPrintf(v, "%s ", zType);
+  sqlite3ExplainExpr(v, pTerm->pExpr);
+}
+#endif /* WHERETRACE_ENABLED && SQLITE_ENABLE_TREE_EXPLAIN */
+
+
+#ifdef WHERETRACE_ENABLED
+/*
+** Print a WhereLoop object for debugging purposes
+*/
+static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
+  WhereInfo *pWInfo = pWC->pWInfo;
+  int nb = 1+(pWInfo->pTabList->nSrc+7)/8;
+  struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
+  Table *pTab = pItem->pTab;
+  sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
+                     p->iTab, nb, p->maskSelf, nb, p->prereq);
+  sqlite3DebugPrintf(" %12s",
+                     pItem->zAlias ? pItem->zAlias : pTab->zName);
+  if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+     const char *zName;
+     if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){
+      if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){
+        int i = sqlite3Strlen30(zName) - 1;
+        while( zName[i]!='_' ) i--;
+        zName += i;
+      }
+      sqlite3DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq);
+    }else{
+      sqlite3DebugPrintf("%20s","");
+    }
+  }else{
+    char *z;
+    if( p->u.vtab.idxStr ){
+      z = sqlite3_mprintf("(%d,\"%s\",%x)",
+                p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask);
+    }else{
+      z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
+    }
+    sqlite3DebugPrintf(" %-19s", z);
+    sqlite3_free(z);
+  }
+  sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm);
+  sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
+#ifdef SQLITE_ENABLE_TREE_EXPLAIN
+  /* If the 0x100 bit of wheretracing is set, then show all of the constraint
+  ** expressions in the WhereLoop.aLTerm[] array.
+  */
+  if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){  /* WHERETRACE 0x100 */
+    int i;
+    Vdbe *v = pWInfo->pParse->pVdbe;
+    sqlite3ExplainBegin(v);
+    for(i=0; i<p->nLTerm; i++){
+      WhereTerm *pTerm = p->aLTerm[i];
+      if( pTerm==0 ) continue;
+      sqlite3ExplainPrintf(v, "  (%d) #%-2d ", i+1, (int)(pTerm-pWC->a));
+      sqlite3ExplainPush(v);
+      whereExplainTerm(v, pTerm);
+      sqlite3ExplainPop(v);
+      sqlite3ExplainNL(v);
+    }
+    sqlite3ExplainFinish(v);
+    sqlite3DebugPrintf("%s", sqlite3VdbeExplanation(v));
+  }
+#endif
+}
+#endif
+
+/*
+** Convert bulk memory into a valid WhereLoop that can be passed
+** to whereLoopClear harmlessly.
+*/
+static void whereLoopInit(WhereLoop *p){
+  p->aLTerm = p->aLTermSpace;
+  p->nLTerm = 0;
+  p->nLSlot = ArraySize(p->aLTermSpace);
+  p->wsFlags = 0;
+}
+
+/*
+** Clear the WhereLoop.u union.  Leave WhereLoop.pLTerm intact.
+*/
+static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){
+  if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){
+    if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){
+      sqlite3_free(p->u.vtab.idxStr);
+      p->u.vtab.needFree = 0;
+      p->u.vtab.idxStr = 0;
+    }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
+      sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
+      sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo);
+      sqlite3DbFree(db, p->u.btree.pIndex);
+      p->u.btree.pIndex = 0;
+    }
+  }
+}
+
+/*
+** Deallocate internal memory used by a WhereLoop object
+*/
+static void whereLoopClear(sqlite3 *db, WhereLoop *p){
+  if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
+  whereLoopClearUnion(db, p);
+  whereLoopInit(p);
+}
+
+/*
+** Increase the memory allocation for pLoop->aLTerm[] to be at least n.
+*/
+static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
+  WhereTerm **paNew;
+  if( p->nLSlot>=n ) return SQLITE_OK;
+  n = (n+7)&~7;
+  paNew = sqlite3DbMallocRaw(db, sizeof(p->aLTerm[0])*n);
+  if( paNew==0 ) return SQLITE_NOMEM;
+  memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot);
+  if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
+  p->aLTerm = paNew;
+  p->nLSlot = n;
+  return SQLITE_OK;
+}
+
+/*
+** Transfer content from the second pLoop into the first.
+*/
+static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
+  whereLoopClearUnion(db, pTo);
+  if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
+    memset(&pTo->u, 0, sizeof(pTo->u));
+    return SQLITE_NOMEM;
+  }
+  memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
+  memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0]));
+  if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){
+    pFrom->u.vtab.needFree = 0;
+  }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){
+    pFrom->u.btree.pIndex = 0;
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Delete a WhereLoop object
+*/
+static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
+  whereLoopClear(db, p);
+  sqlite3DbFree(db, p);
+}
+
+/*
+** Free a WhereInfo structure
+*/
+static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
+  if( ALWAYS(pWInfo) ){
+    whereClauseClear(&pWInfo->sWC);
+    while( pWInfo->pLoops ){
+      WhereLoop *p = pWInfo->pLoops;
+      pWInfo->pLoops = p->pNextLoop;
+      whereLoopDelete(db, p);
+    }
+    sqlite3DbFree(db, pWInfo);
+  }
+}
+
+/*
+** Return TRUE if both of the following are true:
+**
+**   (1)  X has the same or lower cost that Y
+**   (2)  X is a proper subset of Y
+**
+** By "proper subset" we mean that X uses fewer WHERE clause terms
+** than Y and that every WHERE clause term used by X is also used
+** by Y.
+**
+** If X is a proper subset of Y then Y is a better choice and ought
+** to have a lower cost.  This routine returns TRUE when that cost 
+** relationship is inverted and needs to be adjusted.
+*/
+static int whereLoopCheaperProperSubset(
+  const WhereLoop *pX,       /* First WhereLoop to compare */
+  const WhereLoop *pY        /* Compare against this WhereLoop */
+){
+  int i, j;
+  if( pX->nLTerm >= pY->nLTerm ) return 0; /* X is not a subset of Y */
+  if( pX->rRun >= pY->rRun ){
+    if( pX->rRun > pY->rRun ) return 0;    /* X costs more than Y */
+    if( pX->nOut > pY->nOut ) return 0;    /* X costs more than Y */
+  }
+  for(i=pX->nLTerm-1; i>=0; i--){
+    for(j=pY->nLTerm-1; j>=0; j--){
+      if( pY->aLTerm[j]==pX->aLTerm[i] ) break;
+    }
+    if( j<0 ) return 0;  /* X not a subset of Y since term X[i] not used by Y */
+  }
+  return 1;  /* All conditions meet */
+}
+
+/*
+** Try to adjust the cost of WhereLoop pTemplate upwards or downwards so
+** that:
+**
+**   (1) pTemplate costs less than any other WhereLoops that are a proper
+**       subset of pTemplate
+**
+**   (2) pTemplate costs more than any other WhereLoops for which pTemplate
+**       is a proper subset.
+**
+** To say "WhereLoop X is a proper subset of Y" means that X uses fewer
+** WHERE clause terms than Y and that every WHERE clause term used by X is
+** also used by Y.
+**
+** This adjustment is omitted for SKIPSCAN loops.  In a SKIPSCAN loop, the
+** WhereLoop.nLTerm field is not an accurate measure of the number of WHERE
+** clause terms covered, since some of the first nLTerm entries in aLTerm[]
+** will be NULL (because they are skipped).  That makes it more difficult
+** to compare the loops.  We could add extra code to do the comparison, and
+** perhaps we will someday.  But SKIPSCAN is sufficiently uncommon, and this
+** adjustment is sufficient minor, that it is very difficult to construct
+** a test case where the extra code would improve the query plan.  Better
+** to avoid the added complexity and just omit cost adjustments to SKIPSCAN
+** loops.
+*/
+static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
+  if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return;
+  if( (pTemplate->wsFlags & WHERE_SKIPSCAN)!=0 ) return;
+  for(; p; p=p->pNextLoop){
+    if( p->iTab!=pTemplate->iTab ) continue;
+    if( (p->wsFlags & WHERE_INDEXED)==0 ) continue;
+    if( (p->wsFlags & WHERE_SKIPSCAN)!=0 ) continue;
+    if( whereLoopCheaperProperSubset(p, pTemplate) ){
+      /* Adjust pTemplate cost downward so that it is cheaper than its 
+      ** subset p */
+      pTemplate->rRun = p->rRun;
+      pTemplate->nOut = p->nOut - 1;
+    }else if( whereLoopCheaperProperSubset(pTemplate, p) ){
+      /* Adjust pTemplate cost upward so that it is costlier than p since
+      ** pTemplate is a proper subset of p */
+      pTemplate->rRun = p->rRun;
+      pTemplate->nOut = p->nOut + 1;
+    }
+  }
+}
+
+/*
+** Search the list of WhereLoops in *ppPrev looking for one that can be
+** supplanted by pTemplate.
+**
+** Return NULL if the WhereLoop list contains an entry that can supplant
+** pTemplate, in other words if pTemplate does not belong on the list.
+**
+** If pX is a WhereLoop that pTemplate can supplant, then return the
+** link that points to pX.
+**
+** If pTemplate cannot supplant any existing element of the list but needs
+** to be added to the list, then return a pointer to the tail of the list.
+*/
+static WhereLoop **whereLoopFindLesser(
+  WhereLoop **ppPrev,
+  const WhereLoop *pTemplate
+){
+  WhereLoop *p;
+  for(p=(*ppPrev); p; ppPrev=&p->pNextLoop, p=*ppPrev){
+    if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){
+      /* If either the iTab or iSortIdx values for two WhereLoop are different
+      ** then those WhereLoops need to be considered separately.  Neither is
+      ** a candidate to replace the other. */
+      continue;
+    }
+    /* In the current implementation, the rSetup value is either zero
+    ** or the cost of building an automatic index (NlogN) and the NlogN
+    ** is the same for compatible WhereLoops. */
+    assert( p->rSetup==0 || pTemplate->rSetup==0 
+                 || p->rSetup==pTemplate->rSetup );
+
+    /* whereLoopAddBtree() always generates and inserts the automatic index
+    ** case first.  Hence compatible candidate WhereLoops never have a larger
+    ** rSetup. Call this SETUP-INVARIANT */
+    assert( p->rSetup>=pTemplate->rSetup );
+
+    /* Any loop using an appliation-defined index (or PRIMARY KEY or
+    ** UNIQUE constraint) with one or more == constraints is better
+    ** than an automatic index. */
+    if( (p->wsFlags & WHERE_AUTO_INDEX)!=0
+     && (pTemplate->wsFlags & WHERE_INDEXED)!=0
+     && (pTemplate->wsFlags & WHERE_COLUMN_EQ)!=0
+     && (p->prereq & pTemplate->prereq)==pTemplate->prereq
+    ){
+      break;
+    }
+
+    /* If existing WhereLoop p is better than pTemplate, pTemplate can be
+    ** discarded.  WhereLoop p is better if:
+    **   (1)  p has no more dependencies than pTemplate, and
+    **   (2)  p has an equal or lower cost than pTemplate
+    */
+    if( (p->prereq & pTemplate->prereq)==p->prereq    /* (1)  */
+     && p->rSetup<=pTemplate->rSetup                  /* (2a) */
+     && p->rRun<=pTemplate->rRun                      /* (2b) */
+     && p->nOut<=pTemplate->nOut                      /* (2c) */
+    ){
+      return 0;  /* Discard pTemplate */
+    }
+
+    /* If pTemplate is always better than p, then cause p to be overwritten
+    ** with pTemplate.  pTemplate is better than p if:
+    **   (1)  pTemplate has no more dependences than p, and
+    **   (2)  pTemplate has an equal or lower cost than p.
+    */
+    if( (p->prereq & pTemplate->prereq)==pTemplate->prereq   /* (1)  */
+     && p->rRun>=pTemplate->rRun                             /* (2a) */
+     && p->nOut>=pTemplate->nOut                             /* (2b) */
+    ){
+      assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */
+      break;   /* Cause p to be overwritten by pTemplate */
+    }
+  }
+  return ppPrev;
+}
+
+/*
+** Insert or replace a WhereLoop entry using the template supplied.
+**
+** An existing WhereLoop entry might be overwritten if the new template
+** is better and has fewer dependencies.  Or the template will be ignored
+** and no insert will occur if an existing WhereLoop is faster and has
+** fewer dependencies than the template.  Otherwise a new WhereLoop is
+** added based on the template.
+**
+** If pBuilder->pOrSet is not NULL then we care about only the
+** prerequisites and rRun and nOut costs of the N best loops.  That
+** information is gathered in the pBuilder->pOrSet object.  This special
+** processing mode is used only for OR clause processing.
+**
+** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
+** still might overwrite similar loops with the new template if the
+** new template is better.  Loops may be overwritten if the following 
+** conditions are met:
+**
+**    (1)  They have the same iTab.
+**    (2)  They have the same iSortIdx.
+**    (3)  The template has same or fewer dependencies than the current loop
+**    (4)  The template has the same or lower cost than the current loop
+*/
+static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
+  WhereLoop **ppPrev, *p;
+  WhereInfo *pWInfo = pBuilder->pWInfo;
+  sqlite3 *db = pWInfo->pParse->db;
+
+  /* If pBuilder->pOrSet is defined, then only keep track of the costs
+  ** and prereqs.
+  */
+  if( pBuilder->pOrSet!=0 ){
+#if WHERETRACE_ENABLED
+    u16 n = pBuilder->pOrSet->n;
+    int x =
+#endif
+    whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
+                                    pTemplate->nOut);
+#if WHERETRACE_ENABLED /* 0x8 */
+    if( sqlite3WhereTrace & 0x8 ){
+      sqlite3DebugPrintf(x?"   or-%d:  ":"   or-X:  ", n);
+      whereLoopPrint(pTemplate, pBuilder->pWC);
+    }
+#endif
+    return SQLITE_OK;
+  }
+
+  /* Look for an existing WhereLoop to replace with pTemplate
+  */
+  whereLoopAdjustCost(pWInfo->pLoops, pTemplate);
+  ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate);
+
+  if( ppPrev==0 ){
+    /* There already exists a WhereLoop on the list that is better
+    ** than pTemplate, so just ignore pTemplate */
+#if WHERETRACE_ENABLED /* 0x8 */
+    if( sqlite3WhereTrace & 0x8 ){
+      sqlite3DebugPrintf("ins-noop: ");
+      whereLoopPrint(pTemplate, pBuilder->pWC);
+    }
+#endif
+    return SQLITE_OK;  
+  }else{
+    p = *ppPrev;
+  }
+
+  /* If we reach this point it means that either p[] should be overwritten
+  ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
+  ** WhereLoop and insert it.
+  */
+#if WHERETRACE_ENABLED /* 0x8 */
+  if( sqlite3WhereTrace & 0x8 ){
+    if( p!=0 ){
+      sqlite3DebugPrintf("ins-del:  ");
+      whereLoopPrint(p, pBuilder->pWC);
+    }
+    sqlite3DebugPrintf("ins-new:  ");
+    whereLoopPrint(pTemplate, pBuilder->pWC);
+  }
+#endif
+  if( p==0 ){
+    /* Allocate a new WhereLoop to add to the end of the list */
+    *ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
+    if( p==0 ) return SQLITE_NOMEM;
+    whereLoopInit(p);
+    p->pNextLoop = 0;
+  }else{
+    /* We will be overwriting WhereLoop p[].  But before we do, first
+    ** go through the rest of the list and delete any other entries besides
+    ** p[] that are also supplated by pTemplate */
+    WhereLoop **ppTail = &p->pNextLoop;
+    WhereLoop *pToDel;
+    while( *ppTail ){
+      ppTail = whereLoopFindLesser(ppTail, pTemplate);
+      if( ppTail==0 ) break;
+      pToDel = *ppTail;
+      if( pToDel==0 ) break;
+      *ppTail = pToDel->pNextLoop;
+#if WHERETRACE_ENABLED /* 0x8 */
+      if( sqlite3WhereTrace & 0x8 ){
+        sqlite3DebugPrintf("ins-del:  ");
+        whereLoopPrint(pToDel, pBuilder->pWC);
+      }
+#endif
+      whereLoopDelete(db, pToDel);
+    }
+  }
+  whereLoopXfer(db, p, pTemplate);
+  if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+    Index *pIndex = p->u.btree.pIndex;
+    if( pIndex && pIndex->tnum==0 ){
+      p->u.btree.pIndex = 0;
+    }
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Adjust the WhereLoop.nOut value downward to account for terms of the
+** WHERE clause that reference the loop but which are not used by an
+** index.
+**
+** In the current implementation, the first extra WHERE clause term reduces
+** the number of output rows by a factor of 10 and each additional term
+** reduces the number of output rows by sqrt(2).
+*/
+static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){
+  WhereTerm *pTerm, *pX;
+  Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
+  int i, j;
+
+  if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){
+    return;
+  }
+  for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
+    if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
+    if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
+    if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
+    for(j=pLoop->nLTerm-1; j>=0; j--){
+      pX = pLoop->aLTerm[j];
+      if( pX==0 ) continue;
+      if( pX==pTerm ) break;
+      if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
+    }
+    if( j<0 ){
+      pLoop->nOut += (pTerm->truthProb<=0 ? pTerm->truthProb : -1);
+    }
+  }
+}
+
+/*
+** Adjust the cost C by the costMult facter T.  This only occurs if
+** compiled with -DSQLITE_ENABLE_COSTMULT
+*/
+#ifdef SQLITE_ENABLE_COSTMULT
+# define ApplyCostMultiplier(C,T)  C += T
+#else
+# define ApplyCostMultiplier(C,T)
+#endif
+
+/*
+** We have so far matched pBuilder->pNew->u.btree.nEq terms of the 
+** index pIndex. Try to match one more.
+**
+** When this function is called, pBuilder->pNew->nOut contains the 
+** number of rows expected to be visited by filtering using the nEq 
+** terms only. If it is modified, this value is restored before this 
+** function returns.
+**
+** If pProbe->tnum==0, that means pIndex is a fake index used for the
+** INTEGER PRIMARY KEY.
+*/
+static int whereLoopAddBtreeIndex(
+  WhereLoopBuilder *pBuilder,     /* The WhereLoop factory */
+  struct SrcList_item *pSrc,      /* FROM clause term being analyzed */
+  Index *pProbe,                  /* An index on pSrc */
+  LogEst nInMul                   /* log(Number of iterations due to IN) */
+){
+  WhereInfo *pWInfo = pBuilder->pWInfo;  /* WHERE analyse context */
+  Parse *pParse = pWInfo->pParse;        /* Parsing context */
+  sqlite3 *db = pParse->db;       /* Database connection malloc context */
+  WhereLoop *pNew;                /* Template WhereLoop under construction */
+  WhereTerm *pTerm;               /* A WhereTerm under consideration */
+  int opMask;                     /* Valid operators for constraints */
+  WhereScan scan;                 /* Iterator for WHERE terms */
+  Bitmask saved_prereq;           /* Original value of pNew->prereq */
+  u16 saved_nLTerm;               /* Original value of pNew->nLTerm */
+  u16 saved_nEq;                  /* Original value of pNew->u.btree.nEq */
+  u16 saved_nSkip;                /* Original value of pNew->u.btree.nSkip */
+  u32 saved_wsFlags;              /* Original value of pNew->wsFlags */
+  LogEst saved_nOut;              /* Original value of pNew->nOut */
+  int iCol;                       /* Index of the column in the table */
+  int rc = SQLITE_OK;             /* Return code */
+  LogEst rLogSize;                /* Logarithm of table size */
+  WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
+
+  pNew = pBuilder->pNew;
+  if( db->mallocFailed ) return SQLITE_NOMEM;
+
+  assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
+  assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
+  if( pNew->wsFlags & WHERE_BTM_LIMIT ){
+    opMask = WO_LT|WO_LE;
+  }else if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){
+    opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE;
+  }else{
+    opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE;
+  }
+  if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
+
+  assert( pNew->u.btree.nEq<pProbe->nColumn );
+  iCol = pProbe->aiColumn[pNew->u.btree.nEq];
+
+  pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol,
+                        opMask, pProbe);
+  saved_nEq = pNew->u.btree.nEq;
+  saved_nSkip = pNew->u.btree.nSkip;
+  saved_nLTerm = pNew->nLTerm;
+  saved_wsFlags = pNew->wsFlags;
+  saved_prereq = pNew->prereq;
+  saved_nOut = pNew->nOut;
+  pNew->rSetup = 0;
+  rLogSize = estLog(pProbe->aiRowLogEst[0]);
+
+  /* Consider using a skip-scan if there are no WHERE clause constraints
+  ** available for the left-most terms of the index, and if the average
+  ** number of repeats in the left-most terms is at least 18. 
+  **
+  ** The magic number 18 is selected on the basis that scanning 17 rows
+  ** is almost always quicker than an index seek (even though if the index
+  ** contains fewer than 2^17 rows we assume otherwise in other parts of
+  ** the code). And, even if it is not, it should not be too much slower. 
+  ** On the other hand, the extra seeks could end up being significantly
+  ** more expensive.  */
+  assert( 42==sqlite3LogEst(18) );
+  if( pTerm==0
+   && saved_nEq==saved_nSkip
+   && saved_nEq+1<pProbe->nKeyCol
+   && pProbe->aiRowLogEst[saved_nEq+1]>=42  /* TUNING: Minimum for skip-scan */
+   && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
+  ){
+    LogEst nIter;
+    pNew->u.btree.nEq++;
+    pNew->u.btree.nSkip++;
+    pNew->aLTerm[pNew->nLTerm++] = 0;
+    pNew->wsFlags |= WHERE_SKIPSCAN;
+    nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1];
+    pNew->nOut -= nIter;
+    whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul);
+    pNew->nOut = saved_nOut;
+  }
+  for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
+    u16 eOp = pTerm->eOperator;   /* Shorthand for pTerm->eOperator */
+    LogEst rCostIdx;
+    LogEst nOutUnadjusted;        /* nOut before IN() and WHERE adjustments */
+    int nIn = 0;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+    int nRecValid = pBuilder->nRecValid;
+#endif
+    if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0)
+     && (iCol<0 || pSrc->pTab->aCol[iCol].notNull)
+    ){
+      continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */
+    }
+    if( pTerm->prereqRight & pNew->maskSelf ) continue;
+
+    pNew->wsFlags = saved_wsFlags;
+    pNew->u.btree.nEq = saved_nEq;
+    pNew->nLTerm = saved_nLTerm;
+    if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
+    pNew->aLTerm[pNew->nLTerm++] = pTerm;
+    pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf;
+
+    assert( nInMul==0
+        || (pNew->wsFlags & WHERE_COLUMN_NULL)!=0 
+        || (pNew->wsFlags & WHERE_COLUMN_IN)!=0 
+        || (pNew->wsFlags & WHERE_SKIPSCAN)!=0 
+    );
+
+    if( eOp & WO_IN ){
+      Expr *pExpr = pTerm->pExpr;
+      pNew->wsFlags |= WHERE_COLUMN_IN;
+      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+        /* "x IN (SELECT ...)":  TUNING: the SELECT returns 25 rows */
+        nIn = 46;  assert( 46==sqlite3LogEst(25) );
+      }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
+        /* "x IN (value, value, ...)" */
+        nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
+      }
+      assert( nIn>0 );  /* RHS always has 2 or more terms...  The parser
+                        ** changes "x IN (?)" into "x=?". */
+
+    }else if( eOp & (WO_EQ) ){
+      pNew->wsFlags |= WHERE_COLUMN_EQ;
+      if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){
+        if( iCol>=0 && !IsUniqueIndex(pProbe) ){
+          pNew->wsFlags |= WHERE_UNQ_WANTED;
+        }else{
+          pNew->wsFlags |= WHERE_ONEROW;
+        }
+      }
+    }else if( eOp & WO_ISNULL ){
+      pNew->wsFlags |= WHERE_COLUMN_NULL;
+    }else if( eOp & (WO_GT|WO_GE) ){
+      testcase( eOp & WO_GT );
+      testcase( eOp & WO_GE );
+      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
+      pBtm = pTerm;
+      pTop = 0;
+    }else{
+      assert( eOp & (WO_LT|WO_LE) );
+      testcase( eOp & WO_LT );
+      testcase( eOp & WO_LE );
+      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
+      pTop = pTerm;
+      pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
+                     pNew->aLTerm[pNew->nLTerm-2] : 0;
+    }
+
+    /* At this point pNew->nOut is set to the number of rows expected to
+    ** be visited by the index scan before considering term pTerm, or the
+    ** values of nIn and nInMul. In other words, assuming that all 
+    ** "x IN(...)" terms are replaced with "x = ?". This block updates
+    ** the value of pNew->nOut to account for pTerm (but not nIn/nInMul).  */
+    assert( pNew->nOut==saved_nOut );
+    if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
+      /* Adjust nOut using stat3/stat4 data. Or, if there is no stat3/stat4
+      ** data, using some other estimate.  */
+      whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
+    }else{
+      int nEq = ++pNew->u.btree.nEq;
+      assert( eOp & (WO_ISNULL|WO_EQ|WO_IN) );
+
+      assert( pNew->nOut==saved_nOut );
+      if( pTerm->truthProb<=0 && iCol>=0 ){
+        assert( (eOp & WO_IN) || nIn==0 );
+        testcase( eOp & WO_IN );
+        pNew->nOut += pTerm->truthProb;
+        pNew->nOut -= nIn;
+      }else{
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+        tRowcnt nOut = 0;
+        if( nInMul==0 
+         && pProbe->nSample 
+         && pNew->u.btree.nEq<=pProbe->nSampleCol
+         && OptimizationEnabled(db, SQLITE_Stat3) 
+         && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
+        ){
+          Expr *pExpr = pTerm->pExpr;
+          if( (eOp & (WO_EQ|WO_ISNULL))!=0 ){
+            testcase( eOp & WO_EQ );
+            testcase( eOp & WO_ISNULL );
+            rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
+          }else{
+            rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
+          }
+          if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
+          if( rc!=SQLITE_OK ) break;          /* Jump out of the pTerm loop */
+          if( nOut ){
+            pNew->nOut = sqlite3LogEst(nOut);
+            if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
+            pNew->nOut -= nIn;
+          }
+        }
+        if( nOut==0 )
+#endif
+        {
+          pNew->nOut += (pProbe->aiRowLogEst[nEq] - pProbe->aiRowLogEst[nEq-1]);
+          if( eOp & WO_ISNULL ){
+            /* TUNING: If there is no likelihood() value, assume that a 
+            ** "col IS NULL" expression matches twice as many rows 
+            ** as (col=?). */
+            pNew->nOut += 10;
+          }
+        }
+      }
+    }
+
+    /* Set rCostIdx to the cost of visiting selected rows in index. Add
+    ** it to pNew->rRun, which is currently set to the cost of the index
+    ** seek only. Then, if this is a non-covering index, add the cost of
+    ** visiting the rows in the main table.  */
+    rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
+    pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
+    if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
+      pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
+    }
+    ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult);
+
+    nOutUnadjusted = pNew->nOut;
+    pNew->rRun += nInMul + nIn;
+    pNew->nOut += nInMul + nIn;
+    whereLoopOutputAdjust(pBuilder->pWC, pNew);
+    rc = whereLoopInsert(pBuilder, pNew);
+
+    if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
+      pNew->nOut = saved_nOut;
+    }else{
+      pNew->nOut = nOutUnadjusted;
+    }
+
+    if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
+     && pNew->u.btree.nEq<pProbe->nColumn
+    ){
+      whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
+    }
+    pNew->nOut = saved_nOut;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+    pBuilder->nRecValid = nRecValid;
+#endif
+  }
+  pNew->prereq = saved_prereq;
+  pNew->u.btree.nEq = saved_nEq;
+  pNew->u.btree.nSkip = saved_nSkip;
+  pNew->wsFlags = saved_wsFlags;
+  pNew->nOut = saved_nOut;
+  pNew->nLTerm = saved_nLTerm;
+  return rc;
+}
+
+/*
+** Return True if it is possible that pIndex might be useful in
+** implementing the ORDER BY clause in pBuilder.
+**
+** Return False if pBuilder does not contain an ORDER BY clause or
+** if there is no way for pIndex to be useful in implementing that
+** ORDER BY clause.
+*/
+static int indexMightHelpWithOrderBy(
+  WhereLoopBuilder *pBuilder,
+  Index *pIndex,
+  int iCursor
+){
+  ExprList *pOB;
+  int ii, jj;
+
+  if( pIndex->bUnordered ) return 0;
+  if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
+  for(ii=0; ii<pOB->nExpr; ii++){
+    Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
+    if( pExpr->op!=TK_COLUMN ) return 0;
+    if( pExpr->iTable==iCursor ){
+      for(jj=0; jj<pIndex->nKeyCol; jj++){
+        if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+/*
+** Return a bitmask where 1s indicate that the corresponding column of
+** the table is used by an index.  Only the first 63 columns are considered.
+*/
+static Bitmask columnsInIndex(Index *pIdx){
+  Bitmask m = 0;
+  int j;
+  for(j=pIdx->nColumn-1; j>=0; j--){
+    int x = pIdx->aiColumn[j];
+    if( x>=0 ){
+      testcase( x==BMS-1 );
+      testcase( x==BMS-2 );
+      if( x<BMS-1 ) m |= MASKBIT(x);
+    }
+  }
+  return m;
+}
+
+/* Check to see if a partial index with pPartIndexWhere can be used
+** in the current query.  Return true if it can be and false if not.
+*/
+static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
+  int i;
+  WhereTerm *pTerm;
+  for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+    if( sqlite3ExprImpliesExpr(pTerm->pExpr, pWhere, iTab) ) return 1;
+  }
+  return 0;
+}
+
+/*
+** Add all WhereLoop objects for a single table of the join where the table
+** is idenfied by pBuilder->pNew->iTab.  That table is guaranteed to be
+** a b-tree table, not a virtual table.
+**
+** The costs (WhereLoop.rRun) of the b-tree loops added by this function
+** are calculated as follows:
+**
+** For a full scan, assuming the table (or index) contains nRow rows:
+**
+**     cost = nRow * 3.0                    // full-table scan
+**     cost = nRow * K                      // scan of covering index
+**     cost = nRow * (K+3.0)                // scan of non-covering index
+**
+** where K is a value between 1.1 and 3.0 set based on the relative 
+** estimated average size of the index and table records.
+**
+** For an index scan, where nVisit is the number of index rows visited
+** by the scan, and nSeek is the number of seek operations required on 
+** the index b-tree:
+**
+**     cost = nSeek * (log(nRow) + K * nVisit)          // covering index
+**     cost = nSeek * (log(nRow) + (K+3.0) * nVisit)    // non-covering index
+**
+** Normally, nSeek is 1. nSeek values greater than 1 come about if the 
+** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when 
+** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans.
+**
+** The estimated values (nRow, nVisit, nSeek) often contain a large amount
+** of uncertainty.  For this reason, scoring is designed to pick plans that
+** "do the least harm" if the estimates are inaccurate.  For example, a
+** log(nRow) factor is omitted from a non-covering index scan in order to
+** bias the scoring in favor of using an index, since the worst-case
+** performance of using an index is far better than the worst-case performance
+** of a full table scan.
+*/
+static int whereLoopAddBtree(
+  WhereLoopBuilder *pBuilder, /* WHERE clause information */
+  Bitmask mExtra              /* Extra prerequesites for using this table */
+){
+  WhereInfo *pWInfo;          /* WHERE analysis context */
+  Index *pProbe;              /* An index we are evaluating */
+  Index sPk;                  /* A fake index object for the primary key */
+  LogEst aiRowEstPk[2];       /* The aiRowLogEst[] value for the sPk index */
+  i16 aiColumnPk = -1;        /* The aColumn[] value for the sPk index */
+  SrcList *pTabList;          /* The FROM clause */
+  struct SrcList_item *pSrc;  /* The FROM clause btree term to add */
+  WhereLoop *pNew;            /* Template WhereLoop object */
+  int rc = SQLITE_OK;         /* Return code */
+  int iSortIdx = 1;           /* Index number */
+  int b;                      /* A boolean value */
+  LogEst rSize;               /* number of rows in the table */
+  LogEst rLogSize;            /* Logarithm of the number of rows in the table */
+  WhereClause *pWC;           /* The parsed WHERE clause */
+  Table *pTab;                /* Table being queried */
+  
+  pNew = pBuilder->pNew;
+  pWInfo = pBuilder->pWInfo;
+  pTabList = pWInfo->pTabList;
+  pSrc = pTabList->a + pNew->iTab;
+  pTab = pSrc->pTab;
+  pWC = pBuilder->pWC;
+  assert( !IsVirtual(pSrc->pTab) );
+
+  if( pSrc->pIndex ){
+    /* An INDEXED BY clause specifies a particular index to use */
+    pProbe = pSrc->pIndex;
+  }else if( !HasRowid(pTab) ){
+    pProbe = pTab->pIndex;
+  }else{
+    /* There is no INDEXED BY clause.  Create a fake Index object in local
+    ** variable sPk to represent the rowid primary key index.  Make this
+    ** fake index the first in a chain of Index objects with all of the real
+    ** indices to follow */
+    Index *pFirst;                  /* First of real indices on the table */
+    memset(&sPk, 0, sizeof(Index));
+    sPk.nKeyCol = 1;
+    sPk.nColumn = 1;
+    sPk.aiColumn = &aiColumnPk;
+    sPk.aiRowLogEst = aiRowEstPk;
+    sPk.onError = OE_Replace;
+    sPk.pTable = pTab;
+    sPk.szIdxRow = pTab->szTabRow;
+    aiRowEstPk[0] = pTab->nRowLogEst;
+    aiRowEstPk[1] = 0;
+    pFirst = pSrc->pTab->pIndex;
+    if( pSrc->notIndexed==0 ){
+      /* The real indices of the table are only considered if the
+      ** NOT INDEXED qualifier is omitted from the FROM clause */
+      sPk.pNext = pFirst;
+    }
+    pProbe = &sPk;
+  }
+  rSize = pTab->nRowLogEst;
+  rLogSize = estLog(rSize);
+
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+  /* Automatic indexes */
+  if( !pBuilder->pOrSet
+   && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
+   && pSrc->pIndex==0
+   && !pSrc->viaCoroutine
+   && !pSrc->notIndexed
+   && HasRowid(pTab)
+   && !pSrc->isCorrelated
+   && !pSrc->isRecursive
+  ){
+    /* Generate auto-index WhereLoops */
+    WhereTerm *pTerm;
+    WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
+    for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
+      if( pTerm->prereqRight & pNew->maskSelf ) continue;
+      if( termCanDriveIndex(pTerm, pSrc, 0) ){
+        pNew->u.btree.nEq = 1;
+        pNew->u.btree.nSkip = 0;
+        pNew->u.btree.pIndex = 0;
+        pNew->nLTerm = 1;
+        pNew->aLTerm[0] = pTerm;
+        /* TUNING: One-time cost for computing the automatic index is
+        ** approximately 7*N*log2(N) where N is the number of rows in
+        ** the table being indexed. */
+        pNew->rSetup = rLogSize + rSize + 28;  assert( 28==sqlite3LogEst(7) );
+        ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
+        /* TUNING: Each index lookup yields 20 rows in the table.  This
+        ** is more than the usual guess of 10 rows, since we have no way
+        ** of knowning how selective the index will ultimately be.  It would
+        ** not be unreasonable to make this value much larger. */
+        pNew->nOut = 43;  assert( 43==sqlite3LogEst(20) );
+        pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
+        pNew->wsFlags = WHERE_AUTO_INDEX;
+        pNew->prereq = mExtra | pTerm->prereqRight;
+        rc = whereLoopInsert(pBuilder, pNew);
+      }
+    }
+  }
+#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
+
+  /* Loop over all indices
+  */
+  for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){
+    if( pProbe->pPartIdxWhere!=0
+     && !whereUsablePartialIndex(pNew->iTab, pWC, pProbe->pPartIdxWhere) ){
+      continue;  /* Partial index inappropriate for this query */
+    }
+    rSize = pProbe->aiRowLogEst[0];
+    pNew->u.btree.nEq = 0;
+    pNew->u.btree.nSkip = 0;
+    pNew->nLTerm = 0;
+    pNew->iSortIdx = 0;
+    pNew->rSetup = 0;
+    pNew->prereq = mExtra;
+    pNew->nOut = rSize;
+    pNew->u.btree.pIndex = pProbe;
+    b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
+    /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
+    assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 );
+    if( pProbe->tnum<=0 ){
+      /* Integer primary key index */
+      pNew->wsFlags = WHERE_IPK;
+
+      /* Full table scan */
+      pNew->iSortIdx = b ? iSortIdx : 0;
+      /* TUNING: Cost of full table scan is (N*3.0). */
+      pNew->rRun = rSize + 16;
+      ApplyCostMultiplier(pNew->rRun, pTab->costMult);
+      whereLoopOutputAdjust(pWC, pNew);
+      rc = whereLoopInsert(pBuilder, pNew);
+      pNew->nOut = rSize;
+      if( rc ) break;
+    }else{
+      Bitmask m;
+      if( pProbe->isCovering ){
+        pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
+        m = 0;
+      }else{
+        m = pSrc->colUsed & ~columnsInIndex(pProbe);
+        pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;
+      }
+
+      /* Full scan via index */
+      if( b
+       || !HasRowid(pTab)
+       || ( m==0
+         && pProbe->bUnordered==0
+         && (pProbe->szIdxRow<pTab->szTabRow)
+         && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
+         && sqlite3GlobalConfig.bUseCis
+         && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
+          )
+      ){
+        pNew->iSortIdx = b ? iSortIdx : 0;
+
+        /* The cost of visiting the index rows is N*K, where K is
+        ** between 1.1 and 3.0, depending on the relative sizes of the
+        ** index and table rows. If this is a non-covering index scan,
+        ** also add the cost of visiting table rows (N*3.0).  */
+        pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
+        if( m!=0 ){
+          pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
+        }
+        ApplyCostMultiplier(pNew->rRun, pTab->costMult);
+        whereLoopOutputAdjust(pWC, pNew);
+        rc = whereLoopInsert(pBuilder, pNew);
+        pNew->nOut = rSize;
+        if( rc ) break;
+      }
+    }
+
+    rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+    sqlite3Stat4ProbeFree(pBuilder->pRec);
+    pBuilder->nRecValid = 0;
+    pBuilder->pRec = 0;
+#endif
+
+    /* If there was an INDEXED BY clause, then only that one index is
+    ** considered. */
+    if( pSrc->pIndex ) break;
+  }
+  return rc;
+}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Add all WhereLoop objects for a table of the join identified by
+** pBuilder->pNew->iTab.  That table is guaranteed to be a virtual table.
+*/
+static int whereLoopAddVirtual(
+  WhereLoopBuilder *pBuilder,  /* WHERE clause information */
+  Bitmask mExtra
+){
+  WhereInfo *pWInfo;           /* WHERE analysis context */
+  Parse *pParse;               /* The parsing context */
+  WhereClause *pWC;            /* The WHERE clause */
+  struct SrcList_item *pSrc;   /* The FROM clause term to search */
+  Table *pTab;
+  sqlite3 *db;
+  sqlite3_index_info *pIdxInfo;
+  struct sqlite3_index_constraint *pIdxCons;
+  struct sqlite3_index_constraint_usage *pUsage;
+  WhereTerm *pTerm;
+  int i, j;
+  int iTerm, mxTerm;
+  int nConstraint;
+  int seenIn = 0;              /* True if an IN operator is seen */
+  int seenVar = 0;             /* True if a non-constant constraint is seen */
+  int iPhase;                  /* 0: const w/o IN, 1: const, 2: no IN,  2: IN */
+  WhereLoop *pNew;
+  int rc = SQLITE_OK;
+
+  pWInfo = pBuilder->pWInfo;
+  pParse = pWInfo->pParse;
+  db = pParse->db;
+  pWC = pBuilder->pWC;
+  pNew = pBuilder->pNew;
+  pSrc = &pWInfo->pTabList->a[pNew->iTab];
+  pTab = pSrc->pTab;
+  assert( IsVirtual(pTab) );
+  pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pBuilder->pOrderBy);
+  if( pIdxInfo==0 ) return SQLITE_NOMEM;
+  pNew->prereq = 0;
+  pNew->rSetup = 0;
+  pNew->wsFlags = WHERE_VIRTUALTABLE;
+  pNew->nLTerm = 0;
+  pNew->u.vtab.needFree = 0;
+  pUsage = pIdxInfo->aConstraintUsage;
+  nConstraint = pIdxInfo->nConstraint;
+  if( whereLoopResize(db, pNew, nConstraint) ){
+    sqlite3DbFree(db, pIdxInfo);
+    return SQLITE_NOMEM;
+  }
+
+  for(iPhase=0; iPhase<=3; iPhase++){
+    if( !seenIn && (iPhase&1)!=0 ){
+      iPhase++;
+      if( iPhase>3 ) break;
+    }
+    if( !seenVar && iPhase>1 ) break;
+    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
+      j = pIdxCons->iTermOffset;
+      pTerm = &pWC->a[j];
+      switch( iPhase ){
+        case 0:    /* Constants without IN operator */
+          pIdxCons->usable = 0;
+          if( (pTerm->eOperator & WO_IN)!=0 ){
+            seenIn = 1;
+          }
+          if( pTerm->prereqRight!=0 ){
+            seenVar = 1;
+          }else if( (pTerm->eOperator & WO_IN)==0 ){
+            pIdxCons->usable = 1;
+          }
+          break;
+        case 1:    /* Constants with IN operators */
+          assert( seenIn );
+          pIdxCons->usable = (pTerm->prereqRight==0);
+          break;
+        case 2:    /* Variables without IN */
+          assert( seenVar );
+          pIdxCons->usable = (pTerm->eOperator & WO_IN)==0;
+          break;
+        default:   /* Variables with IN */
+          assert( seenVar && seenIn );
+          pIdxCons->usable = 1;
+          break;
+      }
+    }
+    memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
+    if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
+    pIdxInfo->idxStr = 0;
+    pIdxInfo->idxNum = 0;
+    pIdxInfo->needToFreeIdxStr = 0;
+    pIdxInfo->orderByConsumed = 0;
+    pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
+    pIdxInfo->estimatedRows = 25;
+    rc = vtabBestIndex(pParse, pTab, pIdxInfo);
+    if( rc ) goto whereLoopAddVtab_exit;
+    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+    pNew->prereq = mExtra;
+    mxTerm = -1;
+    assert( pNew->nLSlot>=nConstraint );
+    for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
+    pNew->u.vtab.omitMask = 0;
+    for(i=0; i<nConstraint; i++, pIdxCons++){
+      if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
+        j = pIdxCons->iTermOffset;
+        if( iTerm>=nConstraint
+         || j<0
+         || j>=pWC->nTerm
+         || pNew->aLTerm[iTerm]!=0
+        ){
+          rc = SQLITE_ERROR;
+          sqlite3ErrorMsg(pParse, "%s.xBestIndex() malfunction", pTab->zName);
+          goto whereLoopAddVtab_exit;
+        }
+        testcase( iTerm==nConstraint-1 );
+        testcase( j==0 );
+        testcase( j==pWC->nTerm-1 );
+        pTerm = &pWC->a[j];
+        pNew->prereq |= pTerm->prereqRight;
+        assert( iTerm<pNew->nLSlot );
+        pNew->aLTerm[iTerm] = pTerm;
+        if( iTerm>mxTerm ) mxTerm = iTerm;
+        testcase( iTerm==15 );
+        testcase( iTerm==16 );
+        if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;
+        if( (pTerm->eOperator & WO_IN)!=0 ){
+          if( pUsage[i].omit==0 ){
+            /* Do not attempt to use an IN constraint if the virtual table
+            ** says that the equivalent EQ constraint cannot be safely omitted.
+            ** If we do attempt to use such a constraint, some rows might be
+            ** repeated in the output. */
+            break;
+          }
+          /* A virtual table that is constrained by an IN clause may not
+          ** consume the ORDER BY clause because (1) the order of IN terms
+          ** is not necessarily related to the order of output terms and
+          ** (2) Multiple outputs from a single IN value will not merge
+          ** together.  */
+          pIdxInfo->orderByConsumed = 0;
+        }
+      }
     }
-    codeApplyAffinity(pParse, regBase, nConstraint, zStartAff);
-    op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
-    assert( op!=0 );
-    testcase( op==OP_Rewind );
-    testcase( op==OP_Last );
-    testcase( op==OP_SeekGt );
-    testcase( op==OP_SeekGe );
-    testcase( op==OP_SeekLe );
-    testcase( op==OP_SeekLt );
-    sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
-
-    /* Load the value for the inequality constraint at the end of the
-    ** range (if any).
-    */
-    nConstraint = nEq;
-    if( pRangeEnd ){
-      Expr *pRight = pRangeEnd->pExpr->pRight;
-      sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
-      sqlite3ExprCode(pParse, pRight, regBase+nEq);
-      if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){
-        sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
+    if( i>=nConstraint ){
+      pNew->nLTerm = mxTerm+1;
+      assert( pNew->nLTerm<=pNew->nLSlot );
+      pNew->u.vtab.idxNum = pIdxInfo->idxNum;
+      pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
+      pIdxInfo->needToFreeIdxStr = 0;
+      pNew->u.vtab.idxStr = pIdxInfo->idxStr;
+      pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ?
+                                      pIdxInfo->nOrderBy : 0);
+      pNew->rSetup = 0;
+      pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
+      pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
+      whereLoopInsert(pBuilder, pNew);
+      if( pNew->u.vtab.needFree ){
+        sqlite3_free(pNew->u.vtab.idxStr);
+        pNew->u.vtab.needFree = 0;
       }
-      if( zEndAff ){
-        if( sqlite3CompareAffinity(pRight, zEndAff[nEq])==SQLITE_AFF_NONE){
-          /* Since the comparison is to be performed with no conversions
-          ** applied to the operands, set the affinity to apply to pRight to 
-          ** SQLITE_AFF_NONE.  */
-          zEndAff[nEq] = SQLITE_AFF_NONE;
-        }
-        if( sqlite3ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){
-          zEndAff[nEq] = SQLITE_AFF_NONE;
-        }
-      }  
-      codeApplyAffinity(pParse, regBase, nEq+1, zEndAff);
-      nConstraint++;
-      testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
     }
-    sqlite3DbFree(pParse->db, zStartAff);
-    sqlite3DbFree(pParse->db, zEndAff);
-
-    /* Top of the loop body */
-    pLevel->p2 = sqlite3VdbeCurrentAddr(v);
+  }  
 
-    /* Check if the index cursor is past the end of the range. */
-    op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)];
-    testcase( op==OP_Noop );
-    testcase( op==OP_IdxGE );
-    testcase( op==OP_IdxLT );
-    if( op!=OP_Noop ){
-      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
-      sqlite3VdbeChangeP5(v, endEq!=bRev ?1:0);
-    }
+whereLoopAddVtab_exit:
+  if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
+  sqlite3DbFree(db, pIdxInfo);
+  return rc;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
 
-    /* If there are inequality constraints, check that the value
-    ** of the table column that the inequality contrains is not NULL.
-    ** If it is, jump to the next iteration of the loop.
-    */
-    r1 = sqlite3GetTempReg(pParse);
-    testcase( pLevel->plan.wsFlags & WHERE_BTM_LIMIT );
-    testcase( pLevel->plan.wsFlags & WHERE_TOP_LIMIT );
-    if( (pLevel->plan.wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){
-      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
-      sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
-    }
-    sqlite3ReleaseTempReg(pParse, r1);
+/*
+** Add WhereLoop entries to handle OR terms.  This works for either
+** btrees or virtual tables.
+*/
+static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
+  WhereInfo *pWInfo = pBuilder->pWInfo;
+  WhereClause *pWC;
+  WhereLoop *pNew;
+  WhereTerm *pTerm, *pWCEnd;
+  int rc = SQLITE_OK;
+  int iCur;
+  WhereClause tempWC;
+  WhereLoopBuilder sSubBuild;
+  WhereOrSet sSum, sCur;
+  struct SrcList_item *pItem;
+  
+  pWC = pBuilder->pWC;
+  if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
+  pWCEnd = pWC->a + pWC->nTerm;
+  pNew = pBuilder->pNew;
+  memset(&sSum, 0, sizeof(sSum));
+  pItem = pWInfo->pTabList->a + pNew->iTab;
+  iCur = pItem->iCursor;
+
+  for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
+    if( (pTerm->eOperator & WO_OR)!=0
+     && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 
+    ){
+      WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
+      WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
+      WhereTerm *pOrTerm;
+      int once = 1;
+      int i, j;
+    
+      sSubBuild = *pBuilder;
+      sSubBuild.pOrderBy = 0;
+      sSubBuild.pOrSet = &sCur;
 
-    /* Seek the table cursor, if required */
-    disableTerm(pLevel, pRangeStart);
-    disableTerm(pLevel, pRangeEnd);
-    if( !omitTable ){
-      iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
-      sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
-      sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
-      sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg);  /* Deferred seek */
+      for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
+        if( (pOrTerm->eOperator & WO_AND)!=0 ){
+          sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
+        }else if( pOrTerm->leftCursor==iCur ){
+          tempWC.pWInfo = pWC->pWInfo;
+          tempWC.pOuter = pWC;
+          tempWC.op = TK_AND;
+          tempWC.nTerm = 1;
+          tempWC.a = pOrTerm;
+          sSubBuild.pWC = &tempWC;
+        }else{
+          continue;
+        }
+        sCur.n = 0;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+        if( IsVirtual(pItem->pTab) ){
+          rc = whereLoopAddVirtual(&sSubBuild, mExtra);
+        }else
+#endif
+        {
+          rc = whereLoopAddBtree(&sSubBuild, mExtra);
+        }
+        assert( rc==SQLITE_OK || sCur.n==0 );
+        if( sCur.n==0 ){
+          sSum.n = 0;
+          break;
+        }else if( once ){
+          whereOrMove(&sSum, &sCur);
+          once = 0;
+        }else{
+          WhereOrSet sPrev;
+          whereOrMove(&sPrev, &sSum);
+          sSum.n = 0;
+          for(i=0; i<sPrev.n; i++){
+            for(j=0; j<sCur.n; j++){
+              whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
+                            sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
+                            sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
+            }
+          }
+        }
+      }
+      pNew->nLTerm = 1;
+      pNew->aLTerm[0] = pTerm;
+      pNew->wsFlags = WHERE_MULTI_OR;
+      pNew->rSetup = 0;
+      pNew->iSortIdx = 0;
+      memset(&pNew->u, 0, sizeof(pNew->u));
+      for(i=0; rc==SQLITE_OK && i<sSum.n; i++){
+        /* TUNING: Currently sSum.a[i].rRun is set to the sum of the costs
+        ** of all sub-scans required by the OR-scan. However, due to rounding
+        ** errors, it may be that the cost of the OR-scan is equal to its
+        ** most expensive sub-scan. Add the smallest possible penalty 
+        ** (equivalent to multiplying the cost by 1.07) to ensure that 
+        ** this does not happen. Otherwise, for WHERE clauses such as the
+        ** following where there is an index on "y":
+        **
+        **     WHERE likelihood(x=?, 0.99) OR y=?
+        **
+        ** the planner may elect to "OR" together a full-table scan and an
+        ** index lookup. And other similarly odd results.  */
+        pNew->rRun = sSum.a[i].rRun + 1;
+        pNew->nOut = sSum.a[i].nOut;
+        pNew->prereq = sSum.a[i].prereq;
+        rc = whereLoopInsert(pBuilder, pNew);
+      }
     }
+  }
+  return rc;
+}
 
-    /* Record the instruction used to terminate the loop. Disable 
-    ** WHERE clause terms made redundant by the index range scan.
-    */
-    if( pLevel->plan.wsFlags & WHERE_UNIQUE ){
-      pLevel->op = OP_Noop;
-    }else if( bRev ){
-      pLevel->op = OP_Prev;
+/*
+** Add all WhereLoop objects for all tables 
+*/
+static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
+  WhereInfo *pWInfo = pBuilder->pWInfo;
+  Bitmask mExtra = 0;
+  Bitmask mPrior = 0;
+  int iTab;
+  SrcList *pTabList = pWInfo->pTabList;
+  struct SrcList_item *pItem;
+  sqlite3 *db = pWInfo->pParse->db;
+  int nTabList = pWInfo->nLevel;
+  int rc = SQLITE_OK;
+  u8 priorJoinType = 0;
+  WhereLoop *pNew;
+
+  /* Loop over the tables in the join, from left to right */
+  pNew = pBuilder->pNew;
+  whereLoopInit(pNew);
+  for(iTab=0, pItem=pTabList->a; iTab<nTabList; iTab++, pItem++){
+    pNew->iTab = iTab;
+    pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor);
+    if( ((pItem->jointype|priorJoinType) & (JT_LEFT|JT_CROSS))!=0 ){
+      mExtra = mPrior;
+    }
+    priorJoinType = pItem->jointype;
+    if( IsVirtual(pItem->pTab) ){
+      rc = whereLoopAddVirtual(pBuilder, mExtra);
     }else{
-      pLevel->op = OP_Next;
+      rc = whereLoopAddBtree(pBuilder, mExtra);
     }
-    pLevel->p1 = iIdxCur;
-    if( pLevel->plan.wsFlags & WHERE_COVER_SCAN ){
-      pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
-    }else{
-      assert( pLevel->p5==0 );
+    if( rc==SQLITE_OK ){
+      rc = whereLoopAddOr(pBuilder, mExtra);
     }
-  }else
+    mPrior |= pNew->maskSelf;
+    if( rc || db->mallocFailed ) break;
+  }
+  whereLoopClear(db, pNew);
+  return rc;
+}
 
-#ifndef SQLITE_OMIT_OR_OPTIMIZATION
-  if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
-    /* Case 4:  Two or more separately indexed terms connected by OR
-    **
-    ** Example:
-    **
-    **   CREATE TABLE t1(a,b,c,d);
-    **   CREATE INDEX i1 ON t1(a);
-    **   CREATE INDEX i2 ON t1(b);
-    **   CREATE INDEX i3 ON t1(c);
-    **
-    **   SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13)
-    **
-    ** In the example, there are three indexed terms connected by OR.
-    ** The top of the loop looks like this:
-    **
-    **          Null       1                # Zero the rowset in reg 1
-    **
-    ** Then, for each indexed term, the following. The arguments to
-    ** RowSetTest are such that the rowid of the current row is inserted
-    ** into the RowSet. If it is already present, control skips the
-    ** Gosub opcode and jumps straight to the code generated by WhereEnd().
-    **
-    **        sqlite3WhereBegin(<term>)
-    **          RowSetTest                  # Insert rowid into rowset
-    **          Gosub      2 A
-    **        sqlite3WhereEnd()
-    **
-    ** Following the above, code to terminate the loop. Label A, the target
-    ** of the Gosub above, jumps to the instruction right after the Goto.
-    **
-    **          Null       1                # Zero the rowset in reg 1
-    **          Goto       B                # The loop is finished.
-    **
-    **       A: <loop body>                 # Return data, whatever.
-    **
-    **          Return     2                # Jump back to the Gosub
-    **
-    **       B: <after the loop>
-    **
-    */
-    WhereClause *pOrWc;    /* The OR-clause broken out into subterms */
-    SrcList *pOrTab;       /* Shortened table list or OR-clause generation */
-    Index *pCov = 0;             /* Potential covering index (or NULL) */
-    int iCovCur = pParse->nTab++;  /* Cursor used for index scans (if any) */
+/*
+** Examine a WherePath (with the addition of the extra WhereLoop of the 5th
+** parameters) to see if it outputs rows in the requested ORDER BY
+** (or GROUP BY) without requiring a separate sort operation.  Return N:
+** 
+**   N>0:   N terms of the ORDER BY clause are satisfied
+**   N==0:  No terms of the ORDER BY clause are satisfied
+**   N<0:   Unknown yet how many terms of ORDER BY might be satisfied.   
+**
+** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as
+** strict.  With GROUP BY and DISTINCT the only requirement is that
+** equivalent rows appear immediately adjacent to one another.  GROUP BY
+** and DISTINCT do not require rows to appear in any particular order as long
+** as equivelent rows are grouped together.  Thus for GROUP BY and DISTINCT
+** the pOrderBy terms can be matched in any order.  With ORDER BY, the 
+** pOrderBy terms must be matched in strict left-to-right order.
+*/
+static i8 wherePathSatisfiesOrderBy(
+  WhereInfo *pWInfo,    /* The WHERE clause */
+  ExprList *pOrderBy,   /* ORDER BY or GROUP BY or DISTINCT clause to check */
+  WherePath *pPath,     /* The WherePath to check */
+  u16 wctrlFlags,       /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */
+  u16 nLoop,            /* Number of entries in pPath->aLoop[] */
+  WhereLoop *pLast,     /* Add this WhereLoop to the end of pPath->aLoop[] */
+  Bitmask *pRevMask     /* OUT: Mask of WhereLoops to run in reverse order */
+){
+  u8 revSet;            /* True if rev is known */
+  u8 rev;               /* Composite sort order */
+  u8 revIdx;            /* Index sort order */
+  u8 isOrderDistinct;   /* All prior WhereLoops are order-distinct */
+  u8 distinctColumns;   /* True if the loop has UNIQUE NOT NULL columns */
+  u8 isMatch;           /* iColumn matches a term of the ORDER BY clause */
+  u16 nKeyCol;          /* Number of key columns in pIndex */
+  u16 nColumn;          /* Total number of ordered columns in the index */
+  u16 nOrderBy;         /* Number terms in the ORDER BY clause */
+  int iLoop;            /* Index of WhereLoop in pPath being processed */
+  int i, j;             /* Loop counters */
+  int iCur;             /* Cursor number for current WhereLoop */
+  int iColumn;          /* A column number within table iCur */
+  WhereLoop *pLoop = 0; /* Current WhereLoop being processed. */
+  WhereTerm *pTerm;     /* A single term of the WHERE clause */
+  Expr *pOBExpr;        /* An expression from the ORDER BY clause */
+  CollSeq *pColl;       /* COLLATE function from an ORDER BY clause term */
+  Index *pIndex;        /* The index associated with pLoop */
+  sqlite3 *db = pWInfo->pParse->db;  /* Database connection */
+  Bitmask obSat = 0;    /* Mask of ORDER BY terms satisfied so far */
+  Bitmask obDone;       /* Mask of all ORDER BY terms */
+  Bitmask orderDistinctMask;  /* Mask of all well-ordered loops */
+  Bitmask ready;              /* Mask of inner loops */
 
-    int regReturn = ++pParse->nMem;           /* Register used with OP_Gosub */
-    int regRowset = 0;                        /* Register for RowSet object */
-    int regRowid = 0;                         /* Register holding rowid */
-    int iLoopBody = sqlite3VdbeMakeLabel(v);  /* Start of loop body */
-    int iRetInit;                             /* Address of regReturn init */
-    int untestedTerms = 0;             /* Some terms not completely tested */
-    int ii;                            /* Loop counter */
-    Expr *pAndExpr = 0;                /* An ".. AND (...)" expression */
-   
-    pTerm = pLevel->plan.u.pTerm;
-    assert( pTerm!=0 );
-    assert( pTerm->eOperator & WO_OR );
-    assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
-    pOrWc = &pTerm->u.pOrInfo->wc;
-    pLevel->op = OP_Return;
-    pLevel->p1 = regReturn;
+  /*
+  ** We say the WhereLoop is "one-row" if it generates no more than one
+  ** row of output.  A WhereLoop is one-row if all of the following are true:
+  **  (a) All index columns match with WHERE_COLUMN_EQ.
+  **  (b) The index is unique
+  ** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row.
+  ** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags.
+  **
+  ** We say the WhereLoop is "order-distinct" if the set of columns from
+  ** that WhereLoop that are in the ORDER BY clause are different for every
+  ** row of the WhereLoop.  Every one-row WhereLoop is automatically
+  ** order-distinct.   A WhereLoop that has no columns in the ORDER BY clause
+  ** is not order-distinct. To be order-distinct is not quite the same as being
+  ** UNIQUE since a UNIQUE column or index can have multiple rows that 
+  ** are NULL and NULL values are equivalent for the purpose of order-distinct.
+  ** To be order-distinct, the columns must be UNIQUE and NOT NULL.
+  **
+  ** The rowid for a table is always UNIQUE and NOT NULL so whenever the
+  ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is
+  ** automatically order-distinct.
+  */
 
-    /* Set up a new SrcList in pOrTab containing the table being scanned
-    ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
-    ** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
-    */
-    if( pWInfo->nLevel>1 ){
-      int nNotReady;                 /* The number of notReady tables */
-      struct SrcList_item *origSrc;     /* Original list of tables */
-      nNotReady = pWInfo->nLevel - iLevel - 1;
-      pOrTab = sqlite3StackAllocRaw(pParse->db,
-                            sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
-      if( pOrTab==0 ) return notReady;
-      pOrTab->nAlloc = (i16)(nNotReady + 1);
-      pOrTab->nSrc = pOrTab->nAlloc;
-      memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
-      origSrc = pWInfo->pTabList->a;
-      for(k=1; k<=nNotReady; k++){
-        memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
-      }
-    }else{
-      pOrTab = pWInfo->pTabList;
-    }
+  assert( pOrderBy!=0 );
+  if( nLoop && OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return 0;
 
-    /* Initialize the rowset register to contain NULL. An SQL NULL is 
-    ** equivalent to an empty rowset.
-    **
-    ** Also initialize regReturn to contain the address of the instruction 
-    ** immediately following the OP_Return at the bottom of the loop. This
-    ** is required in a few obscure LEFT JOIN cases where control jumps
-    ** over the top of the loop into the body of it. In this case the 
-    ** correct response for the end-of-loop code (the OP_Return) is to 
-    ** fall through to the next instruction, just as an OP_Next does if
-    ** called on an uninitialized cursor.
-    */
-    if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
-      regRowset = ++pParse->nMem;
-      regRowid = ++pParse->nMem;
-      sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
+  nOrderBy = pOrderBy->nExpr;
+  testcase( nOrderBy==BMS-1 );
+  if( nOrderBy>BMS-1 ) return 0;  /* Cannot optimize overly large ORDER BYs */
+  isOrderDistinct = 1;
+  obDone = MASKBIT(nOrderBy)-1;
+  orderDistinctMask = 0;
+  ready = 0;
+  for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
+    if( iLoop>0 ) ready |= pLoop->maskSelf;
+    pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast;
+    if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
+      if( pLoop->u.vtab.isOrdered ) obSat = obDone;
+      break;
     }
-    iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
+    iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
 
-    /* If the original WHERE clause is z of the form:  (x1 OR x2 OR ...) AND y
-    ** Then for every term xN, evaluate as the subexpression: xN AND z
-    ** That way, terms in y that are factored into the disjunction will
-    ** be picked up by the recursive calls to sqlite3WhereBegin() below.
-    **
-    ** Actually, each subexpression is converted to "xN AND w" where w is
-    ** the "interesting" terms of z - terms that did not originate in the
-    ** ON or USING clause of a LEFT JOIN, and terms that are usable as 
-    ** indices.
-    **
-    ** This optimization also only applies if the (x1 OR x2 OR ...) term
-    ** is not contained in the ON clause of a LEFT JOIN.
-    ** See ticket http://www.sqlite.org/src/info/f2369304e4
+    /* Mark off any ORDER BY term X that is a column in the table of
+    ** the current loop for which there is term in the WHERE
+    ** clause of the form X IS NULL or X=? that reference only outer
+    ** loops.
     */
-    if( pWC->nTerm>1 ){
-      int iTerm;
-      for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
-        Expr *pExpr = pWC->a[iTerm].pExpr;
-        if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
-        if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue;
-        if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
-        pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
-        pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr);
-      }
-      if( pAndExpr ){
-        pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
+    for(i=0; i<nOrderBy; i++){
+      if( MASKBIT(i) & obSat ) continue;
+      pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
+      if( pOBExpr->op!=TK_COLUMN ) continue;
+      if( pOBExpr->iTable!=iCur ) continue;
+      pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
+                       ~ready, WO_EQ|WO_ISNULL, 0);
+      if( pTerm==0 ) continue;
+      if( (pTerm->eOperator&WO_EQ)!=0 && pOBExpr->iColumn>=0 ){
+        const char *z1, *z2;
+        pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
+        if( !pColl ) pColl = db->pDfltColl;
+        z1 = pColl->zName;
+        pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr);
+        if( !pColl ) pColl = db->pDfltColl;
+        z2 = pColl->zName;
+        if( sqlite3StrICmp(z1, z2)!=0 ) continue;
       }
+      obSat |= MASKBIT(i);
     }
 
-    for(ii=0; ii<pOrWc->nTerm; ii++){
-      WhereTerm *pOrTerm = &pOrWc->a[ii];
-      if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
-        WhereInfo *pSubWInfo;          /* Info for single OR-term scan */
-        Expr *pOrExpr = pOrTerm->pExpr;
-        if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
-          pAndExpr->pLeft = pOrExpr;
-          pOrExpr = pAndExpr;
-        }
-        /* Loop through table entries that match term pOrTerm. */
-        pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
-                        WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
-                        WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
-        assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed );
-        if( pSubWInfo ){
-          WhereLevel *pLvl;
-          explainOneScan(
-              pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
-          );
-          if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
-            int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
-            int r;
-            r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur, 
-                                         regRowid, 0);
-            sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
-                                 sqlite3VdbeCurrentAddr(v)+2, r, iSet);
+    if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
+      if( pLoop->wsFlags & WHERE_IPK ){
+        pIndex = 0;
+        nKeyCol = 0;
+        nColumn = 1;
+      }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
+        return 0;
+      }else{
+        nKeyCol = pIndex->nKeyCol;
+        nColumn = pIndex->nColumn;
+        assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
+        assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable));
+        isOrderDistinct = IsUniqueIndex(pIndex);
+      }
+
+      /* Loop through all columns of the index and deal with the ones
+      ** that are not constrained by == or IN.
+      */
+      rev = revSet = 0;
+      distinctColumns = 0;
+      for(j=0; j<nColumn; j++){
+        u8 bOnce;   /* True to run the ORDER BY search loop */
+
+        /* Skip over == and IS NULL terms */
+        if( j<pLoop->u.btree.nEq
+         && pLoop->u.btree.nSkip==0
+         && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0
+        ){
+          if( i & WO_ISNULL ){
+            testcase( isOrderDistinct );
+            isOrderDistinct = 0;
           }
-          sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
+          continue;  
+        }
 
-          /* The pSubWInfo->untestedTerms flag means that this OR term
-          ** contained one or more AND term from a notReady table.  The
-          ** terms from the notReady table could not be tested and will
-          ** need to be tested later.
-          */
-          if( pSubWInfo->untestedTerms ) untestedTerms = 1;
+        /* Get the column number in the table (iColumn) and sort order
+        ** (revIdx) for the j-th column of the index.
+        */
+        if( pIndex ){
+          iColumn = pIndex->aiColumn[j];
+          revIdx = pIndex->aSortOrder[j];
+          if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
+        }else{
+          iColumn = -1;
+          revIdx = 0;
+        }
 
-          /* If all of the OR-connected terms are optimized using the same
-          ** index, and the index is opened using the same cursor number
-          ** by each call to sqlite3WhereBegin() made by this loop, it may
-          ** be possible to use that index as a covering index.
-          **
-          ** If the call to sqlite3WhereBegin() above resulted in a scan that
-          ** uses an index, and this is either the first OR-connected term
-          ** processed or the index is the same as that used by all previous
-          ** terms, set pCov to the candidate covering index. Otherwise, set 
-          ** pCov to NULL to indicate that no candidate covering index will 
-          ** be available.
-          */
-          pLvl = &pSubWInfo->a[0];
-          if( (pLvl->plan.wsFlags & WHERE_INDEXED)!=0
-           && (pLvl->plan.wsFlags & WHERE_TEMP_INDEX)==0
-           && (ii==0 || pLvl->plan.u.pIdx==pCov)
-          ){
-            assert( pLvl->iIdxCur==iCovCur );
-            pCov = pLvl->plan.u.pIdx;
+        /* An unconstrained column that might be NULL means that this
+        ** WhereLoop is not well-ordered
+        */
+        if( isOrderDistinct
+         && iColumn>=0
+         && j>=pLoop->u.btree.nEq
+         && pIndex->pTable->aCol[iColumn].notNull==0
+        ){
+          isOrderDistinct = 0;
+        }
+
+        /* Find the ORDER BY term that corresponds to the j-th column
+        ** of the index and mark that ORDER BY term off 
+        */
+        bOnce = 1;
+        isMatch = 0;
+        for(i=0; bOnce && i<nOrderBy; i++){
+          if( MASKBIT(i) & obSat ) continue;
+          pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
+          testcase( wctrlFlags & WHERE_GROUPBY );
+          testcase( wctrlFlags & WHERE_DISTINCTBY );
+          if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
+          if( pOBExpr->op!=TK_COLUMN ) continue;
+          if( pOBExpr->iTable!=iCur ) continue;
+          if( pOBExpr->iColumn!=iColumn ) continue;
+          if( iColumn>=0 ){
+            pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
+            if( !pColl ) pColl = db->pDfltColl;
+            if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
+          }
+          isMatch = 1;
+          break;
+        }
+        if( isMatch && (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
+          /* Make sure the sort order is compatible in an ORDER BY clause.
+          ** Sort order is irrelevant for a GROUP BY clause. */
+          if( revSet ){
+            if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0;
           }else{
-            pCov = 0;
+            rev = revIdx ^ pOrderBy->a[i].sortOrder;
+            if( rev ) *pRevMask |= MASKBIT(iLoop);
+            revSet = 1;
+          }
+        }
+        if( isMatch ){
+          if( iColumn<0 ){
+            testcase( distinctColumns==0 );
+            distinctColumns = 1;
+          }
+          obSat |= MASKBIT(i);
+        }else{
+          /* No match found */
+          if( j==0 || j<nKeyCol ){
+            testcase( isOrderDistinct!=0 );
+            isOrderDistinct = 0;
           }
+          break;
+        }
+      } /* end Loop over all index columns */
+      if( distinctColumns ){
+        testcase( isOrderDistinct==0 );
+        isOrderDistinct = 1;
+      }
+    } /* end-if not one-row */
 
-          /* Finish the loop through table entries that match term pOrTerm. */
-          sqlite3WhereEnd(pSubWInfo);
+    /* Mark off any other ORDER BY terms that reference pLoop */
+    if( isOrderDistinct ){
+      orderDistinctMask |= pLoop->maskSelf;
+      for(i=0; i<nOrderBy; i++){
+        Expr *p;
+        Bitmask mTerm;
+        if( MASKBIT(i) & obSat ) continue;
+        p = pOrderBy->a[i].pExpr;
+        mTerm = exprTableUsage(&pWInfo->sMaskSet,p);
+        if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue;
+        if( (mTerm&~orderDistinctMask)==0 ){
+          obSat |= MASKBIT(i);
         }
       }
     }
-    pLevel->u.pCovidx = pCov;
-    if( pCov ) pLevel->iIdxCur = iCovCur;
-    if( pAndExpr ){
-      pAndExpr->pLeft = 0;
-      sqlite3ExprDelete(pParse->db, pAndExpr);
+  } /* End the loop over all WhereLoops from outer-most down to inner-most */
+  if( obSat==obDone ) return (i8)nOrderBy;
+  if( !isOrderDistinct ){
+    for(i=nOrderBy-1; i>0; i--){
+      Bitmask m = MASKBIT(i) - 1;
+      if( (obSat&m)==m ) return i;
     }
-    sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
-    sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
-    sqlite3VdbeResolveLabel(v, iLoopBody);
+    return 0;
+  }
+  return -1;
+}
 
-    if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab);
-    if( !untestedTerms ) disableTerm(pLevel, pTerm);
-  }else
-#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
 
-  {
-    /* Case 5:  There is no usable index.  We must do a complete
-    **          scan of the entire table.
-    */
-    static const u8 aStep[] = { OP_Next, OP_Prev };
-    static const u8 aStart[] = { OP_Rewind, OP_Last };
-    assert( bRev==0 || bRev==1 );
-    assert( omitTable==0 );
-    pLevel->op = aStep[bRev];
-    pLevel->p1 = iCur;
-    pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
-    pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
-  }
-  newNotReady = notReady & ~getMask(pWC->pMaskSet, iCur);
+/*
+** If the WHERE_GROUPBY flag is set in the mask passed to sqlite3WhereBegin(),
+** the planner assumes that the specified pOrderBy list is actually a GROUP
+** BY clause - and so any order that groups rows as required satisfies the
+** request.
+**
+** Normally, in this case it is not possible for the caller to determine
+** whether or not the rows are really being delivered in sorted order, or
+** just in some other order that provides the required grouping. However,
+** if the WHERE_SORTBYGROUP flag is also passed to sqlite3WhereBegin(), then
+** this function may be called on the returned WhereInfo object. It returns
+** true if the rows really will be sorted in the specified order, or false
+** otherwise.
+**
+** For example, assuming:
+**
+**   CREATE INDEX i1 ON t1(x, Y);
+**
+** then
+**
+**   SELECT * FROM t1 GROUP BY x,y ORDER BY x,y;   -- IsSorted()==1
+**   SELECT * FROM t1 GROUP BY y,x ORDER BY y,x;   -- IsSorted()==0
+*/
+SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo *pWInfo){
+  assert( pWInfo->wctrlFlags & WHERE_GROUPBY );
+  assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP );
+  return pWInfo->sorted;
+}
 
-  /* Insert code to test every subexpression that can be completely
-  ** computed using the current set of tables.
-  **
-  ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through
-  ** the use of indices become tests that are evaluated against each row of
-  ** the relevant input tables.
-  */
-  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
-    Expr *pE;
-    testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
-    testcase( pTerm->wtFlags & TERM_CODED );
-    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
-    if( (pTerm->prereqAll & newNotReady)!=0 ){
-      testcase( pWInfo->untestedTerms==0
-               && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
-      pWInfo->untestedTerms = 1;
-      continue;
-    }
-    pE = pTerm->pExpr;
-    assert( pE!=0 );
-    if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
-      continue;
-    }
-    sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
-    pTerm->wtFlags |= TERM_CODED;
-  }
+#ifdef WHERETRACE_ENABLED
+/* For debugging use only: */
+static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
+  static char zName[65];
+  int i;
+  for(i=0; i<nLoop; i++){ zName[i] = pPath->aLoop[i]->cId; }
+  if( pLast ) zName[i++] = pLast->cId;
+  zName[i] = 0;
+  return zName;
+}
+#endif
 
-  /* Insert code to test for implied constraints based on transitivity
-  ** of the "==" operator.
+/*
+** Return the cost of sorting nRow rows, assuming that the keys have 
+** nOrderby columns and that the first nSorted columns are already in
+** order.
+*/
+static LogEst whereSortingCost(
+  WhereInfo *pWInfo,
+  LogEst nRow,
+  int nOrderBy,
+  int nSorted
+){
+  /* TUNING: Estimated cost of a full external sort, where N is 
+  ** the number of rows to sort is:
   **
-  ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123"
-  ** and we are coding the t1 loop and the t2 loop has not yet coded,
-  ** then we cannot use the "t1.a=t2.b" constraint, but we can code
-  ** the implied "t1.a=123" constraint.
-  */
-  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
-    Expr *pE;
-    WhereTerm *pAlt;
-    Expr sEq;
-    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
-    if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue;
-    if( pTerm->leftCursor!=iCur ) continue;
-    pE = pTerm->pExpr;
-    assert( !ExprHasProperty(pE, EP_FromJoin) );
-    assert( (pTerm->prereqRight & newNotReady)!=0 );
-    pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0);
-    if( pAlt==0 ) continue;
-    if( pAlt->wtFlags & (TERM_CODED) ) continue;
-    VdbeNoopComment((v, "begin transitive constraint"));
-    sEq = *pAlt->pExpr;
-    sEq.pLeft = pE->pLeft;
-    sqlite3ExprIfFalse(pParse, &sEq, addrCont, SQLITE_JUMPIFNULL);
-  }
+  **   cost = (3.0 * N * log(N)).
+  ** 
+  ** Or, if the order-by clause has X terms but only the last Y 
+  ** terms are out of order, then block-sorting will reduce the 
+  ** sorting cost to:
+  **
+  **   cost = (3.0 * N * log(N)) * (Y/X)
+  **
+  ** The (Y/X) term is implemented using stack variable rScale
+  ** below.  */
+  LogEst rScale, rSortCost;
+  assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
+  rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
+  rSortCost = nRow + estLog(nRow) + rScale + 16;
 
-  /* For a LEFT OUTER JOIN, generate code that will record the fact that
-  ** at least one row of the right table has matched the left table.  
-  */
-  if( pLevel->iLeftJoin ){
-    pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
-    sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
-    VdbeComment((v, "record LEFT JOIN hit"));
-    sqlite3ExprCacheClear(pParse);
-    for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
-      testcase( pTerm->wtFlags & TERM_VIRTUAL );  /* IMP: R-30575-11662 */
-      testcase( pTerm->wtFlags & TERM_CODED );
-      if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
-      if( (pTerm->prereqAll & newNotReady)!=0 ){
-        assert( pWInfo->untestedTerms );
-        continue;
-      }
-      assert( pTerm->pExpr );
-      sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
-      pTerm->wtFlags |= TERM_CODED;
-    }
+  /* TUNING: The cost of implementing DISTINCT using a B-TREE is
+  ** similar but with a larger constant of proportionality. 
+  ** Multiply by an additional factor of 3.0.  */
+  if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
+    rSortCost += 16;
   }
-  sqlite3ReleaseTempReg(pParse, iReleaseReg);
 
-  return newNotReady;
+  return rSortCost;
 }
 
-#if defined(SQLITE_TEST)
 /*
-** The following variable holds a text description of query plan generated
-** by the most recent call to sqlite3WhereBegin().  Each call to WhereBegin
-** overwrites the previous.  This information is used for testing and
-** analysis only.
+** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
+** attempts to find the lowest cost path that visits each WhereLoop
+** once.  This path is then loaded into the pWInfo->a[].pWLoop fields.
+**
+** Assume that the total number of output rows that will need to be sorted
+** will be nRowEst (in the 10*log2 representation).  Or, ignore sorting
+** costs if nRowEst==0.
+**
+** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
+** error occurs.
 */
-SQLITE_API char sqlite3_query_plan[BMS*2*40];  /* Text of the join */
-static int nQPlan = 0;              /* Next free slow in _query_plan[] */
+static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
+  int mxChoice;             /* Maximum number of simultaneous paths tracked */
+  int nLoop;                /* Number of terms in the join */
+  Parse *pParse;            /* Parsing context */
+  sqlite3 *db;              /* The database connection */
+  int iLoop;                /* Loop counter over the terms of the join */
+  int ii, jj;               /* Loop counters */
+  int mxI = 0;              /* Index of next entry to replace */
+  int nOrderBy;             /* Number of ORDER BY clause terms */
+  LogEst mxCost = 0;        /* Maximum cost of a set of paths */
+  LogEst mxUnsorted = 0;    /* Maximum unsorted cost of a set of path */
+  int nTo, nFrom;           /* Number of valid entries in aTo[] and aFrom[] */
+  WherePath *aFrom;         /* All nFrom paths at the previous level */
+  WherePath *aTo;           /* The nTo best paths at the current level */
+  WherePath *pFrom;         /* An element of aFrom[] that we are working on */
+  WherePath *pTo;           /* An element of aTo[] that we are working on */
+  WhereLoop *pWLoop;        /* One of the WhereLoop objects */
+  WhereLoop **pX;           /* Used to divy up the pSpace memory */
+  LogEst *aSortCost = 0;    /* Sorting and partial sorting costs */
+  char *pSpace;             /* Temporary memory used by this routine */
+  int nSpace;               /* Bytes of space allocated at pSpace */
 
-#endif /* SQLITE_TEST */
+  pParse = pWInfo->pParse;
+  db = pParse->db;
+  nLoop = pWInfo->nLevel;
+  /* TUNING: For simple queries, only the best path is tracked.
+  ** For 2-way joins, the 5 best paths are followed.
+  ** For joins of 3 or more tables, track the 10 best paths */
+  mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
+  assert( nLoop<=pWInfo->pTabList->nSrc );
+  WHERETRACE(0x002, ("---- begin solver.  (nRowEst=%d)\n", nRowEst));
+
+  /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
+  ** case the purpose of this call is to estimate the number of rows returned
+  ** by the overall query. Once this estimate has been obtained, the caller
+  ** will invoke this function a second time, passing the estimate as the
+  ** nRowEst parameter.  */
+  if( pWInfo->pOrderBy==0 || nRowEst==0 ){
+    nOrderBy = 0;
+  }else{
+    nOrderBy = pWInfo->pOrderBy->nExpr;
+  }
+
+  /* Allocate and initialize space for aTo, aFrom and aSortCost[] */
+  nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
+  nSpace += sizeof(LogEst) * nOrderBy;
+  pSpace = sqlite3DbMallocRaw(db, nSpace);
+  if( pSpace==0 ) return SQLITE_NOMEM;
+  aTo = (WherePath*)pSpace;
+  aFrom = aTo+mxChoice;
+  memset(aFrom, 0, sizeof(aFrom[0]));
+  pX = (WhereLoop**)(aFrom+mxChoice);
+  for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
+    pFrom->aLoop = pX;
+  }
+  if( nOrderBy ){
+    /* If there is an ORDER BY clause and it is not being ignored, set up
+    ** space for the aSortCost[] array. Each element of the aSortCost array
+    ** is either zero - meaning it has not yet been initialized - or the
+    ** cost of sorting nRowEst rows of data where the first X terms of
+    ** the ORDER BY clause are already in order, where X is the array 
+    ** index.  */
+    aSortCost = (LogEst*)pX;
+    memset(aSortCost, 0, sizeof(LogEst) * nOrderBy);
+  }
+  assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] );
+  assert( aSortCost!=0 || &pSpace[nSpace]==(char*)pX );
+
+  /* Seed the search with a single WherePath containing zero WhereLoops.
+  **
+  ** TUNING: Do not let the number of iterations go above 25.  If the cost
+  ** of computing an automatic index is not paid back within the first 25
+  ** rows, then do not use the automatic index. */
+  aFrom[0].nRow = MIN(pParse->nQueryLoop, 46);  assert( 46==sqlite3LogEst(25) );
+  nFrom = 1;
+  assert( aFrom[0].isOrdered==0 );
+  if( nOrderBy ){
+    /* If nLoop is zero, then there are no FROM terms in the query. Since
+    ** in this case the query may return a maximum of one row, the results
+    ** are already in the requested order. Set isOrdered to nOrderBy to
+    ** indicate this. Or, if nLoop is greater than zero, set isOrdered to
+    ** -1, indicating that the result set may or may not be ordered, 
+    ** depending on the loops added to the current plan.  */
+    aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy;
+  }
+
+  /* Compute successively longer WherePaths using the previous generation
+  ** of WherePaths as the basis for the next.  Keep track of the mxChoice
+  ** best paths at each generation */
+  for(iLoop=0; iLoop<nLoop; iLoop++){
+    nTo = 0;
+    for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
+      for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+        LogEst nOut;                      /* Rows visited by (pFrom+pWLoop) */
+        LogEst rCost;                     /* Cost of path (pFrom+pWLoop) */
+        LogEst rUnsorted;                 /* Unsorted cost of (pFrom+pWLoop) */
+        i8 isOrdered = pFrom->isOrdered;  /* isOrdered for (pFrom+pWLoop) */
+        Bitmask maskNew;                  /* Mask of src visited by (..) */
+        Bitmask revMask = 0;              /* Mask of rev-order loops for (..) */
+
+        if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
+        if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
+        /* At this point, pWLoop is a candidate to be the next loop. 
+        ** Compute its cost */
+        rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
+        rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
+        nOut = pFrom->nRow + pWLoop->nOut;
+        maskNew = pFrom->maskLoop | pWLoop->maskSelf;
+        if( isOrdered<0 ){
+          isOrdered = wherePathSatisfiesOrderBy(pWInfo,
+                       pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
+                       iLoop, pWLoop, &revMask);
+        }else{
+          revMask = pFrom->revLoop;
+        }
+        if( isOrdered>=0 && isOrdered<nOrderBy ){
+          if( aSortCost[isOrdered]==0 ){
+            aSortCost[isOrdered] = whereSortingCost(
+                pWInfo, nRowEst, nOrderBy, isOrdered
+            );
+          }
+          rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]);
 
+          WHERETRACE(0x002,
+              ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
+               aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy, 
+               rUnsorted, rCost));
+        }else{
+          rCost = rUnsorted;
+        }
 
-/*
-** Free a WhereInfo structure
-*/
-static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
-  if( ALWAYS(pWInfo) ){
-    int i;
-    for(i=0; i<pWInfo->nLevel; i++){
-      sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
-      if( pInfo ){
-        /* assert( pInfo->needToFreeIdxStr==0 || db->mallocFailed ); */
-        if( pInfo->needToFreeIdxStr ){
-          sqlite3_free(pInfo->idxStr);
+        /* Check to see if pWLoop should be added to the set of
+        ** mxChoice best-so-far paths.
+        **
+        ** First look for an existing path among best-so-far paths
+        ** that covers the same set of loops and has the same isOrdered
+        ** setting as the current path candidate.
+        **
+        ** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent
+        ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
+        ** of legal values for isOrdered, -1..64.
+        */
+        for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
+          if( pTo->maskLoop==maskNew
+           && ((pTo->isOrdered^isOrdered)&0x80)==0
+          ){
+            testcase( jj==nTo-1 );
+            break;
+          }
+        }
+        if( jj>=nTo ){
+          /* None of the existing best-so-far paths match the candidate. */
+          if( nTo>=mxChoice
+           && (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted))
+          ){
+            /* The current candidate is no better than any of the mxChoice
+            ** paths currently in the best-so-far buffer.  So discard
+            ** this candidate as not viable. */
+#ifdef WHERETRACE_ENABLED /* 0x4 */
+            if( sqlite3WhereTrace&0x4 ){
+              sqlite3DebugPrintf("Skip   %s cost=%-3d,%3d order=%c\n",
+                  wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+                  isOrdered>=0 ? isOrdered+'0' : '?');
+            }
+#endif
+            continue;
+          }
+          /* If we reach this points it means that the new candidate path
+          ** needs to be added to the set of best-so-far paths. */
+          if( nTo<mxChoice ){
+            /* Increase the size of the aTo set by one */
+            jj = nTo++;
+          }else{
+            /* New path replaces the prior worst to keep count below mxChoice */
+            jj = mxI;
+          }
+          pTo = &aTo[jj];
+#ifdef WHERETRACE_ENABLED /* 0x4 */
+          if( sqlite3WhereTrace&0x4 ){
+            sqlite3DebugPrintf("New    %s cost=%-3d,%3d order=%c\n",
+                wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+                isOrdered>=0 ? isOrdered+'0' : '?');
+          }
+#endif
+        }else{
+          /* Control reaches here if best-so-far path pTo=aTo[jj] covers the
+          ** same set of loops and has the sam isOrdered setting as the
+          ** candidate path.  Check to see if the candidate should replace
+          ** pTo or if the candidate should be skipped */
+          if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){
+#ifdef WHERETRACE_ENABLED /* 0x4 */
+            if( sqlite3WhereTrace&0x4 ){
+              sqlite3DebugPrintf(
+                  "Skip   %s cost=%-3d,%3d order=%c",
+                  wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+                  isOrdered>=0 ? isOrdered+'0' : '?');
+              sqlite3DebugPrintf("   vs %s cost=%-3d,%d order=%c\n",
+                  wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
+                  pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
+            }
+#endif
+            /* Discard the candidate path from further consideration */
+            testcase( pTo->rCost==rCost );
+            continue;
+          }
+          testcase( pTo->rCost==rCost+1 );
+          /* Control reaches here if the candidate path is better than the
+          ** pTo path.  Replace pTo with the candidate. */
+#ifdef WHERETRACE_ENABLED /* 0x4 */
+          if( sqlite3WhereTrace&0x4 ){
+            sqlite3DebugPrintf(
+                "Update %s cost=%-3d,%3d order=%c",
+                wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+                isOrdered>=0 ? isOrdered+'0' : '?');
+            sqlite3DebugPrintf("  was %s cost=%-3d,%3d order=%c\n",
+                wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
+                pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
+          }
+#endif
+        }
+        /* pWLoop is a winner.  Add it to the set of best so far */
+        pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
+        pTo->revLoop = revMask;
+        pTo->nRow = nOut;
+        pTo->rCost = rCost;
+        pTo->rUnsorted = rUnsorted;
+        pTo->isOrdered = isOrdered;
+        memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
+        pTo->aLoop[iLoop] = pWLoop;
+        if( nTo>=mxChoice ){
+          mxI = 0;
+          mxCost = aTo[0].rCost;
+          mxUnsorted = aTo[0].nRow;
+          for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
+            if( pTo->rCost>mxCost 
+             || (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted) 
+            ){
+              mxCost = pTo->rCost;
+              mxUnsorted = pTo->rUnsorted;
+              mxI = jj;
+            }
+          }
         }
-        sqlite3DbFree(db, pInfo);
       }
-      if( pWInfo->a[i].plan.wsFlags & WHERE_TEMP_INDEX ){
-        Index *pIdx = pWInfo->a[i].plan.u.pIdx;
-        if( pIdx ){
-          sqlite3DbFree(db, pIdx->zColAff);
-          sqlite3DbFree(db, pIdx);
+    }
+
+#ifdef WHERETRACE_ENABLED  /* >=2 */
+    if( sqlite3WhereTrace>=2 ){
+      sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
+      for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
+        sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
+           wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
+           pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
+        if( pTo->isOrdered>0 ){
+          sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
+        }else{
+          sqlite3DebugPrintf("\n");
         }
       }
     }
-    whereClauseClear(pWInfo->pWC);
-    sqlite3DbFree(db, pWInfo);
+#endif
+
+    /* Swap the roles of aFrom and aTo for the next generation */
+    pFrom = aTo;
+    aTo = aFrom;
+    aFrom = pFrom;
+    nFrom = nTo;
+  }
+
+  if( nFrom==0 ){
+    sqlite3ErrorMsg(pParse, "no query solution");
+    sqlite3DbFree(db, pSpace);
+    return SQLITE_ERROR;
+  }
+  
+  /* Find the lowest cost path.  pFrom will be left pointing to that path */
+  pFrom = aFrom;
+  for(ii=1; ii<nFrom; ii++){
+    if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii];
+  }
+  assert( pWInfo->nLevel==nLoop );
+  /* Load the lowest cost path into pWInfo */
+  for(iLoop=0; iLoop<nLoop; iLoop++){
+    WhereLevel *pLevel = pWInfo->a + iLoop;
+    pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop];
+    pLevel->iFrom = pWLoop->iTab;
+    pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
+  }
+  if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0
+   && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0
+   && pWInfo->eDistinct==WHERE_DISTINCT_NOOP
+   && nRowEst
+  ){
+    Bitmask notUsed;
+    int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
+                 WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed);
+    if( rc==pWInfo->pResultSet->nExpr ){
+      pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
+    }
+  }
+  if( pWInfo->pOrderBy ){
+    if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){
+      if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){
+        pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
+      }
+    }else{
+      pWInfo->nOBSat = pFrom->isOrdered;
+      if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0;
+      pWInfo->revMask = pFrom->revLoop;
+    }
+    if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
+        && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr
+    ){
+      Bitmask notUsed = 0;
+      int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, 
+          pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed
+      );
+      assert( pWInfo->sorted==0 );
+      pWInfo->sorted = (nOrder==pWInfo->pOrderBy->nExpr);
+    }
   }
+
+
+  pWInfo->nRowOut = pFrom->nRow;
+
+  /* Free temporary memory and return success */
+  sqlite3DbFree(db, pSpace);
+  return SQLITE_OK;
 }
 
+/*
+** Most queries use only a single table (they are not joins) and have
+** simple == constraints against indexed fields.  This routine attempts
+** to plan those simple cases using much less ceremony than the
+** general-purpose query planner, and thereby yield faster sqlite3_prepare()
+** times for the common case.
+**
+** Return non-zero on success, if this query can be handled by this
+** no-frills query planner.  Return zero if this query needs the 
+** general-purpose query planner.
+*/
+static int whereShortCut(WhereLoopBuilder *pBuilder){
+  WhereInfo *pWInfo;
+  struct SrcList_item *pItem;
+  WhereClause *pWC;
+  WhereTerm *pTerm;
+  WhereLoop *pLoop;
+  int iCur;
+  int j;
+  Table *pTab;
+  Index *pIdx;
+  
+  pWInfo = pBuilder->pWInfo;
+  if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0;
+  assert( pWInfo->pTabList->nSrc>=1 );
+  pItem = pWInfo->pTabList->a;
+  pTab = pItem->pTab;
+  if( IsVirtual(pTab) ) return 0;
+  if( pItem->zIndex ) return 0;
+  iCur = pItem->iCursor;
+  pWC = &pWInfo->sWC;
+  pLoop = pBuilder->pNew;
+  pLoop->wsFlags = 0;
+  pLoop->u.btree.nSkip = 0;
+  pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0);
+  if( pTerm ){
+    pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
+    pLoop->aLTerm[0] = pTerm;
+    pLoop->nLTerm = 1;
+    pLoop->u.btree.nEq = 1;
+    /* TUNING: Cost of a rowid lookup is 10 */
+    pLoop->rRun = 33;  /* 33==sqlite3LogEst(10) */
+  }else{
+    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+      assert( pLoop->aLTermSpace==pLoop->aLTerm );
+      assert( ArraySize(pLoop->aLTermSpace)==4 );
+      if( !IsUniqueIndex(pIdx)
+       || pIdx->pPartIdxWhere!=0 
+       || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) 
+      ) continue;
+      for(j=0; j<pIdx->nKeyCol; j++){
+        pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx);
+        if( pTerm==0 ) break;
+        pLoop->aLTerm[j] = pTerm;
+      }
+      if( j!=pIdx->nKeyCol ) continue;
+      pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED;
+      if( pIdx->isCovering || (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){
+        pLoop->wsFlags |= WHERE_IDX_ONLY;
+      }
+      pLoop->nLTerm = j;
+      pLoop->u.btree.nEq = j;
+      pLoop->u.btree.pIndex = pIdx;
+      /* TUNING: Cost of a unique index lookup is 15 */
+      pLoop->rRun = 39;  /* 39==sqlite3LogEst(15) */
+      break;
+    }
+  }
+  if( pLoop->wsFlags ){
+    pLoop->nOut = (LogEst)1;
+    pWInfo->a[0].pWLoop = pLoop;
+    pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
+    pWInfo->a[0].iTabCur = iCur;
+    pWInfo->nRowOut = 1;
+    if( pWInfo->pOrderBy ) pWInfo->nOBSat =  pWInfo->pOrderBy->nExpr;
+    if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
+      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+    }
+#ifdef SQLITE_DEBUG
+    pLoop->cId = '0';
+#endif
+    return 1;
+  }
+  return 0;
+}
 
 /*
 ** Generate the beginning of the loop used for WHERE clause processing.
@@ -109409,25 +116836,25 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
 **
 ** ORDER BY CLAUSE PROCESSING
 **
-** pOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
+** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause
+** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement
 ** if there is one.  If there is no ORDER BY clause or if this routine
 ** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
 **
-** If an index can be used so that the natural output order of the table
-** scan is correct for the ORDER BY clause, then that index is used and
-** the returned WhereInfo.nOBSat field is set to pOrderBy->nExpr.  This
-** is an optimization that prevents an unnecessary sort of the result set
-** if an index appropriate for the ORDER BY clause already exists.
-**
-** If the where clause loops cannot be arranged to provide the correct
-** output order, then WhereInfo.nOBSat is 0.
+** The iIdxCur parameter is the cursor number of an index.  If 
+** WHERE_ONETABLE_ONLY is set, iIdxCur is the cursor number of an index
+** to use for OR clause processing.  The WHERE clause should use this
+** specific cursor.  If WHERE_ONEPASS_DESIRED is set, then iIdxCur is
+** the first cursor in an array of cursors for all indices.  iIdxCur should
+** be used to compute the appropriate cursor depending on which index is
+** used.
 */
 SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   Parse *pParse,        /* The parser context */
-  SrcList *pTabList,    /* A list of all tables to be scanned */
+  SrcList *pTabList,    /* FROM clause: A list of all tables to be scanned */
   Expr *pWhere,         /* The WHERE clause */
-  ExprList *pOrderBy,   /* An ORDER BY clause, or NULL */
-  ExprList *pDistinct,  /* The select-list for DISTINCT queries - or NULL */
+  ExprList *pOrderBy,   /* An ORDER BY (or GROUP BY) clause, or NULL */
+  ExprList *pResultSet, /* Result set of the query */
   u16 wctrlFlags,       /* One of the WHERE_* flags defined in sqliteInt.h */
   int iIdxCur           /* If WHERE_ONETABLE_ONLY is set, index cursor number */
 ){
@@ -109436,18 +116863,29 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   WhereInfo *pWInfo;         /* Will become the return value of this function */
   Vdbe *v = pParse->pVdbe;   /* The virtual database engine */
   Bitmask notReady;          /* Cursors that are not yet positioned */
-  WhereBestIdx sWBI;         /* Best index search context */
+  WhereLoopBuilder sWLB;     /* The WhereLoop builder */
   WhereMaskSet *pMaskSet;    /* The expression mask set */
   WhereLevel *pLevel;        /* A single level in pWInfo->a[] */
-  int iFrom;                 /* First unused FROM clause element */
-  int andFlags;              /* AND-ed combination of all pWC->a[].wtFlags */
+  WhereLoop *pLoop;          /* Pointer to a single WhereLoop object */
   int ii;                    /* Loop counter */
   sqlite3 *db;               /* Database connection */
+  int rc;                    /* Return code */
 
 
   /* Variable initialization */
-  memset(&sWBI, 0, sizeof(sWBI));
-  sWBI.pParse = pParse;
+  db = pParse->db;
+  memset(&sWLB, 0, sizeof(sWLB));
+
+  /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
+  testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
+  if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0;
+  sWLB.pOrderBy = pOrderBy;
+
+  /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
+  ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
+  if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
+    wctrlFlags &= ~WHERE_WANT_DISTINCT;
+  }
 
   /* The number of tables in the FROM clause is limited by the number of
   ** bits in a Bitmask 
@@ -109472,46 +116910,57 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** field (type Bitmask) it must be aligned on an 8-byte boundary on
   ** some architectures. Hence the ROUND8() below.
   */
-  db = pParse->db;
   nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
-  pWInfo = sqlite3DbMallocZero(db, 
-      nByteWInfo + 
-      sizeof(WhereClause) +
-      sizeof(WhereMaskSet)
-  );
+  pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
   if( db->mallocFailed ){
     sqlite3DbFree(db, pWInfo);
     pWInfo = 0;
     goto whereBeginError;
   }
+  pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
   pWInfo->nLevel = nTabList;
   pWInfo->pParse = pParse;
   pWInfo->pTabList = pTabList;
-  pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
-  pWInfo->pWC = sWBI.pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
+  pWInfo->pOrderBy = pOrderBy;
+  pWInfo->pResultSet = pResultSet;
+  pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
   pWInfo->wctrlFlags = wctrlFlags;
   pWInfo->savedNQueryLoop = pParse->nQueryLoop;
-  pMaskSet = (WhereMaskSet*)&sWBI.pWC[1];
-  sWBI.aLevel = pWInfo->a;
-
-  /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
-  ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
-  if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0;
+  pMaskSet = &pWInfo->sMaskSet;
+  sWLB.pWInfo = pWInfo;
+  sWLB.pWC = &pWInfo->sWC;
+  sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
+  assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
+  whereLoopInit(sWLB.pNew);
+#ifdef SQLITE_DEBUG
+  sWLB.pNew->cId = '*';
+#endif
 
   /* Split the WHERE clause into separate subexpressions where each
   ** subexpression is separated by an AND operator.
   */
   initMaskSet(pMaskSet);
-  whereClauseInit(sWBI.pWC, pParse, pMaskSet, wctrlFlags);
-  sqlite3ExprCodeConstants(pParse, pWhere);
-  whereSplit(sWBI.pWC, pWhere, TK_AND);   /* IMP: R-15842-53296 */
+  whereClauseInit(&pWInfo->sWC, pWInfo);
+  whereSplit(&pWInfo->sWC, pWhere, TK_AND);
     
   /* Special case: a WHERE clause that is constant.  Evaluate the
   ** expression and either jump over all of the code or fall thru.
   */
-  if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
-    sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL);
-    pWhere = 0;
+  for(ii=0; ii<sWLB.pWC->nTerm; ii++){
+    if( nTabList==0 || sqlite3ExprIsConstantNotJoin(sWLB.pWC->a[ii].pExpr) ){
+      sqlite3ExprIfFalse(pParse, sWLB.pWC->a[ii].pExpr, pWInfo->iBreak,
+                         SQLITE_JUMPIFNULL);
+      sWLB.pWC->a[ii].wtFlags |= TERM_CODED;
+    }
+  }
+
+  /* Special case: No FROM clause
+  */
+  if( nTabList==0 ){
+    if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr;
+    if( wctrlFlags & WHERE_WANT_DISTINCT ){
+      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+    }
   }
 
   /* Assign a bit from the bitmask to every term in the FROM clause.
@@ -109549,306 +116998,151 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** want to analyze these virtual terms, so start analyzing at the end
   ** and work forward so that the added virtual terms are never processed.
   */
-  exprAnalyzeAll(pTabList, sWBI.pWC);
+  exprAnalyzeAll(pTabList, &pWInfo->sWC);
   if( db->mallocFailed ){
     goto whereBeginError;
   }
 
-  /* Check if the DISTINCT qualifier, if there is one, is redundant. 
-  ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
-  ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
-  */
-  if( pDistinct && isDistinctRedundant(pParse, pTabList, sWBI.pWC, pDistinct) ){
-    pDistinct = 0;
-    pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+  if( wctrlFlags & WHERE_WANT_DISTINCT ){
+    if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
+      /* The DISTINCT marking is pointless.  Ignore it. */
+      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+    }else if( pOrderBy==0 ){
+      /* Try to ORDER BY the result set to make distinct processing easier */
+      pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
+      pWInfo->pOrderBy = pResultSet;
+    }
   }
 
-  /* Chose the best index to use for each table in the FROM clause.
-  **
-  ** This loop fills in the following fields:
-  **
-  **   pWInfo->a[].pIdx      The index to use for this level of the loop.
-  **   pWInfo->a[].wsFlags   WHERE_xxx flags associated with pIdx
-  **   pWInfo->a[].nEq       The number of == and IN constraints
-  **   pWInfo->a[].iFrom     Which term of the FROM clause is being coded
-  **   pWInfo->a[].iTabCur   The VDBE cursor for the database table
-  **   pWInfo->a[].iIdxCur   The VDBE cursor for the index
-  **   pWInfo->a[].pTerm     When wsFlags==WO_OR, the OR-clause term
-  **
-  ** This loop also figures out the nesting order of tables in the FROM
-  ** clause.
-  */
-  sWBI.notValid = ~(Bitmask)0;
-  sWBI.pOrderBy = pOrderBy;
-  sWBI.n = nTabList;
-  sWBI.pDistinct = pDistinct;
-  andFlags = ~0;
-  WHERETRACE(("*** Optimizer Start ***\n"));
-  for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){
-    WhereCost bestPlan;         /* Most efficient plan seen so far */
-    Index *pIdx;                /* Index for FROM table at pTabItem */
-    int j;                      /* For looping over FROM tables */
-    int bestJ = -1;             /* The value of j */
-    Bitmask m;                  /* Bitmask value for j or bestJ */
-    int isOptimal;              /* Iterator for optimal/non-optimal search */
-    int ckOptimal;              /* Do the optimal scan check */
-    int nUnconstrained;         /* Number tables without INDEXED BY */
-    Bitmask notIndexed;         /* Mask of tables that cannot use an index */
-
-    memset(&bestPlan, 0, sizeof(bestPlan));
-    bestPlan.rCost = SQLITE_BIG_DBL;
-    WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i));
-
-    /* Loop through the remaining entries in the FROM clause to find the
-    ** next nested loop. The loop tests all FROM clause entries
-    ** either once or twice. 
-    **
-    ** The first test is always performed if there are two or more entries
-    ** remaining and never performed if there is only one FROM clause entry
-    ** to choose from.  The first test looks for an "optimal" scan.  In
-    ** this context an optimal scan is one that uses the same strategy
-    ** for the given FROM clause entry as would be selected if the entry
-    ** were used as the innermost nested loop.  In other words, a table
-    ** is chosen such that the cost of running that table cannot be reduced
-    ** by waiting for other tables to run first.  This "optimal" test works
-    ** by first assuming that the FROM clause is on the inner loop and finding
-    ** its query plan, then checking to see if that query plan uses any
-    ** other FROM clause terms that are sWBI.notValid.  If no notValid terms
-    ** are used then the "optimal" query plan works.
-    **
-    ** Note that the WhereCost.nRow parameter for an optimal scan might
-    ** not be as small as it would be if the table really were the innermost
-    ** join.  The nRow value can be reduced by WHERE clause constraints
-    ** that do not use indices.  But this nRow reduction only happens if the
-    ** table really is the innermost join.  
-    **
-    ** The second loop iteration is only performed if no optimal scan
-    ** strategies were found by the first iteration. This second iteration
-    ** is used to search for the lowest cost scan overall.
-    **
-    ** Without the optimal scan step (the first iteration) a suboptimal
-    ** plan might be chosen for queries like this:
-    **   
-    **   CREATE TABLE t1(a, b); 
-    **   CREATE TABLE t2(c, d);
-    **   SELECT * FROM t2, t1 WHERE t2.rowid = t1.a;
-    **
-    ** The best strategy is to iterate through table t1 first. However it
-    ** is not possible to determine this with a simple greedy algorithm.
-    ** Since the cost of a linear scan through table t2 is the same 
-    ** as the cost of a linear scan through table t1, a simple greedy 
-    ** algorithm may choose to use t2 for the outer loop, which is a much
-    ** costlier approach.
-    */
-    nUnconstrained = 0;
-    notIndexed = 0;
-
-    /* The optimal scan check only occurs if there are two or more tables
-    ** available to be reordered */
-    if( iFrom==nTabList-1 ){
-      ckOptimal = 0;  /* Common case of just one table in the FROM clause */
-    }else{
-      ckOptimal = -1;
-      for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
-        m = getMask(pMaskSet, sWBI.pSrc->iCursor);
-        if( (m & sWBI.notValid)==0 ){
-          if( j==iFrom ) iFrom++;
-          continue;
-        }
-        if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break;
-        if( ++ckOptimal ) break;
-        if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
-      }
+  /* Construct the WhereLoop objects */
+  WHERETRACE(0xffff,("*** Optimizer Start ***\n"));
+  /* Display all terms of the WHERE clause */
+#if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN)
+  if( sqlite3WhereTrace & 0x100 ){
+    int i;
+    Vdbe *v = pParse->pVdbe;
+    sqlite3ExplainBegin(v);
+    for(i=0; i<sWLB.pWC->nTerm; i++){
+      sqlite3ExplainPrintf(v, "#%-2d ", i);
+      sqlite3ExplainPush(v);
+      whereExplainTerm(v, &sWLB.pWC->a[i]);
+      sqlite3ExplainPop(v);
+      sqlite3ExplainNL(v);
     }
-    assert( ckOptimal==0 || ckOptimal==1 );
-
-    for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){
-      for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
-        if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){
-          /* This break and one like it in the ckOptimal computation loop
-          ** above prevent table reordering across LEFT and CROSS JOINs.
-          ** The LEFT JOIN case is necessary for correctness.  The prohibition
-          ** against reordering across a CROSS JOIN is an SQLite feature that
-          ** allows the developer to control table reordering */
-          break;
-        }
-        m = getMask(pMaskSet, sWBI.pSrc->iCursor);
-        if( (m & sWBI.notValid)==0 ){
-          assert( j>iFrom );
-          continue;
-        }
-        sWBI.notReady = (isOptimal ? m : sWBI.notValid);
-        if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
-  
-        WHERETRACE(("   === trying table %d (%s) with isOptimal=%d ===\n",
-                    j, sWBI.pSrc->pTab->zName, isOptimal));
-        assert( sWBI.pSrc->pTab );
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-        if( IsVirtual(sWBI.pSrc->pTab) ){
-          sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo;
-          bestVirtualIndex(&sWBI);
-        }else 
+    sqlite3ExplainFinish(v);
+    sqlite3DebugPrintf("%s", sqlite3VdbeExplanation(v));
+  }
 #endif
-        {
-          bestBtreeIndex(&sWBI);
-        }
-        assert( isOptimal || (sWBI.cost.used&sWBI.notValid)==0 );
-
-        /* If an INDEXED BY clause is present, then the plan must use that
-        ** index if it uses any index at all */
-        assert( sWBI.pSrc->pIndex==0 
-                  || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
-                  || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
-
-        if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
-          notIndexed |= m;
-        }
-        if( isOptimal ){
-          pWInfo->a[j].rOptCost = sWBI.cost.rCost;
-        }else if( ckOptimal ){
-          /* If two or more tables have nearly the same outer loop cost, but
-          ** very different inner loop (optimal) cost, we want to choose
-          ** for the outer loop that table which benefits the least from
-          ** being in the inner loop.  The following code scales the 
-          ** outer loop cost estimate to accomplish that. */
-          WHERETRACE(("   scaling cost from %.1f to %.1f\n",
-                      sWBI.cost.rCost,
-                      sWBI.cost.rCost/pWInfo->a[j].rOptCost));
-          sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
-        }
-
-        /* Conditions under which this table becomes the best so far:
-        **
-        **   (1) The table must not depend on other tables that have not
-        **       yet run.  (In other words, it must not depend on tables
-        **       in inner loops.)
-        **
-        **   (2) (This rule was removed on 2012-11-09.  The scaling of the
-        **       cost using the optimal scan cost made this rule obsolete.)
-        **
-        **   (3) All tables have an INDEXED BY clause or this table lacks an
-        **       INDEXED BY clause or this table uses the specific
-        **       index specified by its INDEXED BY clause.  This rule ensures
-        **       that a best-so-far is always selected even if an impossible
-        **       combination of INDEXED BY clauses are given.  The error
-        **       will be detected and relayed back to the application later.
-        **       The NEVER() comes about because rule (2) above prevents
-        **       An indexable full-table-scan from reaching rule (3).
-        **
-        **   (4) The plan cost must be lower than prior plans, where "cost"
-        **       is defined by the compareCost() function above. 
-        */
-        if( (sWBI.cost.used&sWBI.notValid)==0                    /* (1) */
-            && (nUnconstrained==0 || sWBI.pSrc->pIndex==0        /* (3) */
-                || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
-            && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan))   /* (4) */
-        ){
-          WHERETRACE(("   === table %d (%s) is best so far\n"
-                      "       cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
-                      j, sWBI.pSrc->pTab->zName,
-                      sWBI.cost.rCost, sWBI.cost.plan.nRow,
-                      sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
-          bestPlan = sWBI.cost;
-          bestJ = j;
-        }
-
-        /* In a join like "w JOIN x LEFT JOIN y JOIN z"  make sure that
-        ** table y (and not table z) is always the next inner loop inside
-        ** of table x. */
-        if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
-      }
-    }
-    assert( bestJ>=0 );
-    assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
-    assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 );
-    testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
-    testcase( bestJ>iFrom && bestJ<nTabList-1
-                          && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 );
-    WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
-                "    cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
-                bestJ, pTabList->a[bestJ].pTab->zName,
-                pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
-                bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
-    if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
-      assert( pWInfo->eDistinct==0 );
-      pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
-    }
-    andFlags &= bestPlan.plan.wsFlags;
-    pLevel->plan = bestPlan.plan;
-    pLevel->iTabCur = pTabList->a[bestJ].iCursor;
-    testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
-    testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
-    if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
-      if( (wctrlFlags & WHERE_ONETABLE_ONLY) 
-       && (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0 
-      ){
-        pLevel->iIdxCur = iIdxCur;
-      }else{
-        pLevel->iIdxCur = pParse->nTab++;
+  if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
+    rc = whereLoopAddAll(&sWLB);
+    if( rc ) goto whereBeginError;
+  
+    /* Display all of the WhereLoop objects if wheretrace is enabled */
+#ifdef WHERETRACE_ENABLED /* !=0 */
+    if( sqlite3WhereTrace ){
+      WhereLoop *p;
+      int i;
+      static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
+                                       "ABCDEFGHIJKLMNOPQRSTUVWYXZ";
+      for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
+        p->cId = zLabel[i%sizeof(zLabel)];
+        whereLoopPrint(p, sWLB.pWC);
       }
-    }else{
-      pLevel->iIdxCur = -1;
     }
-    sWBI.notValid &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
-    pLevel->iFrom = (u8)bestJ;
-    if( bestPlan.plan.nRow>=(double)1 ){
-      pParse->nQueryLoop *= bestPlan.plan.nRow;
-    }
-
-    /* Check that if the table scanned by this loop iteration had an
-    ** INDEXED BY clause attached to it, that the named index is being
-    ** used for the scan. If not, then query compilation has failed.
-    ** Return an error.
-    */
-    pIdx = pTabList->a[bestJ].pIndex;
-    if( pIdx ){
-      if( (bestPlan.plan.wsFlags & WHERE_INDEXED)==0 ){
-        sqlite3ErrorMsg(pParse, "cannot use index: %s", pIdx->zName);
-        goto whereBeginError;
-      }else{
-        /* If an INDEXED BY clause is used, the bestIndex() function is
-        ** guaranteed to find the index specified in the INDEXED BY clause
-        ** if it find an index at all. */
-        assert( bestPlan.plan.u.pIdx==pIdx );
-      }
+#endif
+  
+    wherePathSolver(pWInfo, 0);
+    if( db->mallocFailed ) goto whereBeginError;
+    if( pWInfo->pOrderBy ){
+       wherePathSolver(pWInfo, pWInfo->nRowOut+1);
+       if( db->mallocFailed ) goto whereBeginError;
     }
   }
-  WHERETRACE(("*** Optimizer Finished ***\n"));
-  if( pParse->nErr || db->mallocFailed ){
+  if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
+     pWInfo->revMask = (Bitmask)(-1);
+  }
+  if( pParse->nErr || NEVER(db->mallocFailed) ){
     goto whereBeginError;
   }
-  if( nTabList ){
-    pLevel--;
-    pWInfo->nOBSat = pLevel->plan.nOBSat;
-  }else{
-    pWInfo->nOBSat = 0;
+#ifdef WHERETRACE_ENABLED /* !=0 */
+  if( sqlite3WhereTrace ){
+    int ii;
+    sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
+    if( pWInfo->nOBSat>0 ){
+      sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask);
+    }
+    switch( pWInfo->eDistinct ){
+      case WHERE_DISTINCT_UNIQUE: {
+        sqlite3DebugPrintf("  DISTINCT=unique");
+        break;
+      }
+      case WHERE_DISTINCT_ORDERED: {
+        sqlite3DebugPrintf("  DISTINCT=ordered");
+        break;
+      }
+      case WHERE_DISTINCT_UNORDERED: {
+        sqlite3DebugPrintf("  DISTINCT=unordered");
+        break;
+      }
+    }
+    sqlite3DebugPrintf("\n");
+    for(ii=0; ii<pWInfo->nLevel; ii++){
+      whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
+    }
   }
-
-  /* If the total query only selects a single row, then the ORDER BY
-  ** clause is irrelevant.
-  */
-  if( (andFlags & WHERE_UNIQUE)!=0 && pOrderBy ){
-    assert( nTabList==0 || (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 );
-    pWInfo->nOBSat = pOrderBy->nExpr;
+#endif
+  /* Attempt to omit tables from the join that do not effect the result */
+  if( pWInfo->nLevel>=2
+   && pResultSet!=0
+   && OptimizationEnabled(db, SQLITE_OmitNoopJoin)
+  ){
+    Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet);
+    if( sWLB.pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, sWLB.pOrderBy);
+    while( pWInfo->nLevel>=2 ){
+      WhereTerm *pTerm, *pEnd;
+      pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop;
+      if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break;
+      if( (wctrlFlags & WHERE_WANT_DISTINCT)==0
+       && (pLoop->wsFlags & WHERE_ONEROW)==0
+      ){
+        break;
+      }
+      if( (tabUsed & pLoop->maskSelf)!=0 ) break;
+      pEnd = sWLB.pWC->a + sWLB.pWC->nTerm;
+      for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
+        if( (pTerm->prereqAll & pLoop->maskSelf)!=0
+         && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
+        ){
+          break;
+        }
+      }
+      if( pTerm<pEnd ) break;
+      WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
+      pWInfo->nLevel--;
+      nTabList--;
+    }
   }
+  WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
+  pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
 
   /* If the caller is an UPDATE or DELETE statement that is requesting
   ** to use a one-pass algorithm, determine if this is appropriate.
-  ** The one-pass algorithm only works if the WHERE clause constraints
+  ** The one-pass algorithm only works if the WHERE clause constrains
   ** the statement to update a single row.
   */
   assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
-  if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){
+  if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 
+   && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
     pWInfo->okOnePass = 1;
-    pWInfo->a[0].plan.wsFlags &= ~WHERE_IDX_ONLY;
+    if( HasRowid(pTabList->a[0].pTab) ){
+      pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY;
+    }
   }
 
   /* Open all tables in the pTabList and any indices selected for
   ** searching those tables.
   */
-  sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
   notReady = ~(Bitmask)0;
-  pWInfo->nRowOut = (double)1;
   for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
     Table *pTab;     /* Table to open */
     int iDb;         /* Index of database containing table/index */
@@ -109856,13 +117150,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
 
     pTabItem = &pTabList->a[pLevel->iFrom];
     pTab = pTabItem->pTab;
-    pWInfo->nRowOut *= pLevel->plan.nRow;
     iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+    pLoop = pLevel->pWLoop;
     if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
       /* Do nothing */
     }else
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-    if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
+    if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
       const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
       int iCur = pTabItem->iCursor;
       sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
@@ -109870,13 +117164,18 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
       /* noop */
     }else
 #endif
-    if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
+    if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
          && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){
-      int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
+      int op = OP_OpenRead;
+      if( pWInfo->okOnePass ){
+        op = OP_OpenWrite;
+        pWInfo->aiCurOnePass[0] = pTabItem->iCursor;
+      };
       sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
-      testcase( pTab->nCol==BMS-1 );
-      testcase( pTab->nCol==BMS );
-      if( !pWInfo->okOnePass && pTab->nCol<BMS ){
+      assert( pTabItem->iCursor==pLevel->iTabCur );
+      testcase( !pWInfo->okOnePass && pTab->nCol==BMS-1 );
+      testcase( !pWInfo->okOnePass && pTab->nCol==BMS );
+      if( !pWInfo->okOnePass && pTab->nCol<BMS && HasRowid(pTab) ){
         Bitmask b = pTabItem->colUsed;
         int n = 0;
         for(; b; b=b>>1, n++){}
@@ -109887,23 +117186,46 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     }else{
       sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
     }
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
-    if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
-      constructAutomaticIndex(pParse, sWBI.pWC, pTabItem, notReady, pLevel);
-    }else
-#endif
-    if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
-      Index *pIx = pLevel->plan.u.pIdx;
-      KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
-      int iIndexCur = pLevel->iIdxCur;
+    if( pLoop->wsFlags & WHERE_INDEXED ){
+      Index *pIx = pLoop->u.btree.pIndex;
+      int iIndexCur;
+      int op = OP_OpenRead;
+      /* iIdxCur is always set if to a positive value if ONEPASS is possible */
+      assert( iIdxCur!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 );
+      if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx)
+       && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0
+      ){
+        /* This is one term of an OR-optimization using the PRIMARY KEY of a
+        ** WITHOUT ROWID table.  No need for a separate index */
+        iIndexCur = pLevel->iTabCur;
+        op = 0;
+      }else if( pWInfo->okOnePass ){
+        Index *pJ = pTabItem->pTab->pIndex;
+        iIndexCur = iIdxCur;
+        assert( wctrlFlags & WHERE_ONEPASS_DESIRED );
+        while( ALWAYS(pJ) && pJ!=pIx ){
+          iIndexCur++;
+          pJ = pJ->pNext;
+        }
+        op = OP_OpenWrite;
+        pWInfo->aiCurOnePass[1] = iIndexCur;
+      }else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
+        iIndexCur = iIdxCur;
+        if( wctrlFlags & WHERE_REOPEN_IDX ) op = OP_ReopenIdx;
+      }else{
+        iIndexCur = pParse->nTab++;
+      }
+      pLevel->iIdxCur = iIndexCur;
       assert( pIx->pSchema==pTab->pSchema );
       assert( iIndexCur>=0 );
-      sqlite3VdbeAddOp4(v, OP_OpenRead, iIndexCur, pIx->tnum, iDb,
-                        (char*)pKey, P4_KEYINFO_HANDOFF);
-      VdbeComment((v, "%s", pIx->zName));
+      if( op ){
+        sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
+        sqlite3VdbeSetP4KeyInfo(pParse, pIx);
+        VdbeComment((v, "%s", pIx->zName));
+      }
     }
-    sqlite3CodeVerifySchema(pParse, iDb);
-    notReady &= ~getMask(sWBI.pWC->pMaskSet, pTabItem->iCursor);
+    if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
+    notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor);
   }
   pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
   if( db->mallocFailed ) goto whereBeginError;
@@ -109915,67 +117237,21 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   notReady = ~(Bitmask)0;
   for(ii=0; ii<nTabList; ii++){
     pLevel = &pWInfo->a[ii];
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+    if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
+      constructAutomaticIndex(pParse, &pWInfo->sWC,
+                &pTabList->a[pLevel->iFrom], notReady, pLevel);
+      if( db->mallocFailed ) goto whereBeginError;
+    }
+#endif
     explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
-    notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady);
+    pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
+    notReady = codeOneLoopStart(pWInfo, ii, notReady);
     pWInfo->iContinue = pLevel->addrCont;
   }
 
-#ifdef SQLITE_TEST  /* For testing and debugging use only */
-  /* Record in the query plan information about the current table
-  ** and the index used to access it (if any).  If the table itself
-  ** is not used, its name is just '{}'.  If no index is used
-  ** the index is listed as "{}".  If the primary key is used the
-  ** index name is '*'.
-  */
-  for(ii=0; ii<nTabList; ii++){
-    char *z;
-    int n;
-    int w;
-    struct SrcList_item *pTabItem;
-
-    pLevel = &pWInfo->a[ii];
-    w = pLevel->plan.wsFlags;
-    pTabItem = &pTabList->a[pLevel->iFrom];
-    z = pTabItem->zAlias;
-    if( z==0 ) z = pTabItem->pTab->zName;
-    n = sqlite3Strlen30(z);
-    if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
-      if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){
-        memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
-        nQPlan += 2;
-      }else{
-        memcpy(&sqlite3_query_plan[nQPlan], z, n);
-        nQPlan += n;
-      }
-      sqlite3_query_plan[nQPlan++] = ' ';
-    }
-    testcase( w & WHERE_ROWID_EQ );
-    testcase( w & WHERE_ROWID_RANGE );
-    if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
-      memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
-      nQPlan += 2;
-    }else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){
-      n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName);
-      if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
-        memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n);
-        nQPlan += n;
-        sqlite3_query_plan[nQPlan++] = ' ';
-      }
-    }else{
-      memcpy(&sqlite3_query_plan[nQPlan], "{} ", 3);
-      nQPlan += 3;
-    }
-  }
-  while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){
-    sqlite3_query_plan[--nQPlan] = 0;
-  }
-  sqlite3_query_plan[nQPlan] = 0;
-  nQPlan = 0;
-#endif /* SQLITE_TEST // Testing and debugging use only */
-
-  /* Record the continuation address in the WhereInfo structure.  Then
-  ** clean up and return.
-  */
+  /* Done. */
+  VdbeModuleComment((v, "Begin WHERE-core"));
   return pWInfo;
 
   /* Jump here if malloc fails */
@@ -109996,40 +117272,56 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
   Vdbe *v = pParse->pVdbe;
   int i;
   WhereLevel *pLevel;
+  WhereLoop *pLoop;
   SrcList *pTabList = pWInfo->pTabList;
   sqlite3 *db = pParse->db;
 
   /* Generate loop termination code.
   */
+  VdbeModuleComment((v, "End WHERE-core"));
   sqlite3ExprCacheClear(pParse);
   for(i=pWInfo->nLevel-1; i>=0; i--){
+    int addr;
     pLevel = &pWInfo->a[i];
+    pLoop = pLevel->pWLoop;
     sqlite3VdbeResolveLabel(v, pLevel->addrCont);
     if( pLevel->op!=OP_Noop ){
-      sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2);
+      sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
       sqlite3VdbeChangeP5(v, pLevel->p5);
+      VdbeCoverage(v);
+      VdbeCoverageIf(v, pLevel->op==OP_Next);
+      VdbeCoverageIf(v, pLevel->op==OP_Prev);
+      VdbeCoverageIf(v, pLevel->op==OP_VNext);
     }
-    if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
+    if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
       struct InLoop *pIn;
       int j;
       sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
       for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
         sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
         sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
+        VdbeCoverage(v);
+        VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen);
+        VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
         sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
       }
       sqlite3DbFree(db, pLevel->u.in.aInLoop);
     }
     sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
+    if( pLevel->addrSkip ){
+      sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrSkip);
+      VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
+      sqlite3VdbeJumpHere(v, pLevel->addrSkip);
+      sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
+    }
     if( pLevel->iLeftJoin ){
-      int addr;
-      addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin);
-      assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
-           || (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 );
-      if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 ){
+      addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
+      assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
+           || (pLoop->wsFlags & WHERE_INDEXED)!=0 );
+      if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){
         sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
       }
-      if( pLevel->iIdxCur>=0 ){
+      if( pLoop->wsFlags & WHERE_INDEXED ){
         sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
       }
       if( pLevel->op==OP_Return ){
@@ -110039,6 +117331,8 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
       }
       sqlite3VdbeJumpHere(v, addr);
     }
+    VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
+                     pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
   }
 
   /* The "break" point is here, just past the end of the outer loop.
@@ -110046,33 +117340,65 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
   */
   sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
 
-  /* Close all of the cursors that were opened by sqlite3WhereBegin.
-  */
-  assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
+  assert( pWInfo->nLevel<=pTabList->nSrc );
   for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
+    int k, last;
+    VdbeOp *pOp;
     Index *pIdx = 0;
     struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
     Table *pTab = pTabItem->pTab;
     assert( pTab!=0 );
+    pLoop = pLevel->pWLoop;
+
+    /* For a co-routine, change all OP_Column references to the table of
+    ** the co-routine into OP_SCopy of result contained in a register.
+    ** OP_Rowid becomes OP_Null.
+    */
+    if( pTabItem->viaCoroutine && !db->mallocFailed ){
+      last = sqlite3VdbeCurrentAddr(v);
+      k = pLevel->addrBody;
+      pOp = sqlite3VdbeGetOp(v, k);
+      for(; k<last; k++, pOp++){
+        if( pOp->p1!=pLevel->iTabCur ) continue;
+        if( pOp->opcode==OP_Column ){
+          pOp->opcode = OP_Copy;
+          pOp->p1 = pOp->p2 + pTabItem->regResult;
+          pOp->p2 = pOp->p3;
+          pOp->p3 = 0;
+        }else if( pOp->opcode==OP_Rowid ){
+          pOp->opcode = OP_Null;
+          pOp->p1 = 0;
+          pOp->p3 = 0;
+        }
+      }
+      continue;
+    }
+
+    /* Close all of the cursors that were opened by sqlite3WhereBegin.
+    ** Except, do not close cursors that will be reused by the OR optimization
+    ** (WHERE_OMIT_OPEN_CLOSE).  And do not close the OP_OpenWrite cursors
+    ** created for the ONEPASS optimization.
+    */
     if( (pTab->tabFlags & TF_Ephemeral)==0
      && pTab->pSelect==0
      && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0
     ){
-      int ws = pLevel->plan.wsFlags;
+      int ws = pLoop->wsFlags;
       if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){
         sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
       }
-      if( (ws & WHERE_INDEXED)!=0 && (ws & WHERE_TEMP_INDEX)==0 ){
+      if( (ws & WHERE_INDEXED)!=0
+       && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 
+       && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1]
+      ){
         sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
       }
     }
 
-    /* If this scan uses an index, make code substitutions to read data
-    ** from the index in preference to the table. Sometimes, this means
-    ** the table need never be read from. This is a performance boost,
-    ** as the vdbe level waits until the table is read before actually
-    ** seeking the table cursor to the record corresponding to the current
-    ** position in the index.
+    /* If this scan uses an index, make VDBE code substitutions to read data
+    ** from the index instead of from the table where possible.  In some cases
+    ** this optimization prevents the table from ever being read, which can
+    ** yield a significant performance boost.
     ** 
     ** Calls to the code generator in between sqlite3WhereBegin and
     ** sqlite3WhereEnd will have created code that references the table
@@ -110080,29 +117406,30 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
     ** that reference the table and converts them into opcodes that
     ** reference the index.
     */
-    if( pLevel->plan.wsFlags & WHERE_INDEXED ){
-      pIdx = pLevel->plan.u.pIdx;
-    }else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
+    if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
+      pIdx = pLoop->u.btree.pIndex;
+    }else if( pLoop->wsFlags & WHERE_MULTI_OR ){
       pIdx = pLevel->u.pCovidx;
     }
-    if( pIdx && !db->mallocFailed){
-      int k, j, last;
-      VdbeOp *pOp;
-
-      pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
+    if( pIdx && !db->mallocFailed ){
       last = sqlite3VdbeCurrentAddr(v);
-      for(k=pWInfo->iTop; k<last; k++, pOp++){
+      k = pLevel->addrBody;
+      pOp = sqlite3VdbeGetOp(v, k);
+      for(; k<last; k++, pOp++){
         if( pOp->p1!=pLevel->iTabCur ) continue;
         if( pOp->opcode==OP_Column ){
-          for(j=0; j<pIdx->nColumn; j++){
-            if( pOp->p2==pIdx->aiColumn[j] ){
-              pOp->p2 = j;
-              pOp->p1 = pLevel->iIdxCur;
-              break;
-            }
+          int x = pOp->p2;
+          assert( pIdx->pTable==pTab );
+          if( !HasRowid(pTab) ){
+            Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+            x = pPk->aiColumn[x];
+          }
+          x = sqlite3ColumnOfIndex(pIdx, x);
+          if( x>=0 ){
+            pOp->p2 = x;
+            pOp->p1 = pLevel->iIdxCur;
           }
-          assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
-               || j<pIdx->nColumn );
+          assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 );
         }else if( pOp->opcode==OP_Rowid ){
           pOp->p1 = pLevel->iIdxCur;
           pOp->opcode = OP_IdxRowid;
@@ -110179,14 +117506,6 @@ struct TrigEvent { int a; IdList * b; };
 */
 struct AttachKey { int type;  Token key; };
 
-/*
-** One or more VALUES claues
-*/
-struct ValueList {
-  ExprList *pList;
-  Select *pSelect;
-};
-
 
   /* This is a utility routine used to set the ExprSpan.zStart and
   ** ExprSpan.zEnd values of pOut so that the span covers the complete
@@ -110310,28 +117629,28 @@ struct ValueList {
 **                       defined, then do no error processing.
 */
 #define YYCODETYPE unsigned char
-#define YYNOCODE 251
+#define YYNOCODE 254
 #define YYACTIONTYPE unsigned short int
-#define YYWILDCARD 67
+#define YYWILDCARD 70
 #define sqlite3ParserTOKENTYPE Token
 typedef union {
   int yyinit;
   sqlite3ParserTOKENTYPE yy0;
-  struct LimitVal yy64;
-  Expr* yy122;
-  Select* yy159;
-  IdList* yy180;
-  struct {int value; int mask;} yy207;
-  u8 yy258;
-  u16 yy305;
-  struct LikeOp yy318;
-  TriggerStep* yy327;
-  ExprSpan yy342;
-  SrcList* yy347;
-  int yy392;
-  struct TrigEvent yy410;
-  ExprList* yy442;
-  struct ValueList yy487;
+  Select* yy3;
+  ExprList* yy14;
+  With* yy59;
+  SrcList* yy65;
+  struct LikeOp yy96;
+  Expr* yy132;
+  u8 yy186;
+  int yy328;
+  ExprSpan yy346;
+  struct TrigEvent yy378;
+  u16 yy381;
+  IdList* yy408;
+  struct {int value; int mask;} yy429;
+  TriggerStep* yy473;
+  struct LimitVal yy476;
 } YYMINORTYPE;
 #ifndef YYSTACKDEPTH
 #define YYSTACKDEPTH 100
@@ -110340,7 +117659,7 @@ typedef union {
 #define sqlite3ParserARG_PDECL ,Parse *pParse
 #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
 #define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 627
+#define YYNSTATE 642
 #define YYNRULE 327
 #define YYFALLBACK 1
 #define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
@@ -110411,474 +117730,463 @@ static const YYMINORTYPE yyzerominor = { 0 };
 **                     shifting non-terminals after a reduce.
 **  yy_default[]       Default action for each state.
 */
-#define YY_ACTTAB_COUNT (1564)
+#define YY_ACTTAB_COUNT (1497)
 static const YYACTIONTYPE yy_action[] = {
- /*     0 */   309,  955,  184,  417,    2,  171,  624,  594,   56,   56,
- /*    10 */    56,   56,   49,   54,   54,   54,   54,   53,   53,   52,
- /*    20 */    52,   52,   51,  233,  620,  619,  298,  620,  619,  234,
- /*    30 */   587,  581,   56,   56,   56,   56,   19,   54,   54,   54,
- /*    40 */    54,   53,   53,   52,   52,   52,   51,  233,  605,   57,
- /*    50 */    58,   48,  579,  578,  580,  580,   55,   55,   56,   56,
- /*    60 */    56,   56,  541,   54,   54,   54,   54,   53,   53,   52,
- /*    70 */    52,   52,   51,  233,  309,  594,  325,  196,  195,  194,
- /*    80 */    33,   54,   54,   54,   54,   53,   53,   52,   52,   52,
- /*    90 */    51,  233,  617,  616,  165,  617,  616,  380,  377,  376,
- /*   100 */   407,  532,  576,  576,  587,  581,  303,  422,  375,   59,
- /*   110 */    53,   53,   52,   52,   52,   51,  233,   50,   47,  146,
- /*   120 */   574,  545,   65,   57,   58,   48,  579,  578,  580,  580,
- /*   130 */    55,   55,   56,   56,   56,   56,  213,   54,   54,   54,
- /*   140 */    54,   53,   53,   52,   52,   52,   51,  233,  309,  223,
- /*   150 */   539,  420,  170,  176,  138,  280,  383,  275,  382,  168,
- /*   160 */   489,  551,  409,  668,  620,  619,  271,  438,  409,  438,
- /*   170 */   550,  604,   67,  482,  507,  618,  599,  412,  587,  581,
- /*   180 */   600,  483,  618,  412,  618,  598,   91,  439,  440,  439,
- /*   190 */   335,  598,   73,  669,  222,  266,  480,   57,   58,   48,
- /*   200 */   579,  578,  580,  580,   55,   55,   56,   56,   56,   56,
- /*   210 */   670,   54,   54,   54,   54,   53,   53,   52,   52,   52,
- /*   220 */    51,  233,  309,  279,  232,  231,    1,  132,  200,  385,
- /*   230 */   620,  619,  617,  616,  278,  435,  289,  563,  175,  262,
- /*   240 */   409,  264,  437,  497,  436,  166,  441,  568,  336,  568,
- /*   250 */   201,  537,  587,  581,  599,  412,  165,  594,  600,  380,
- /*   260 */   377,  376,  597,  598,   92,  523,  618,  569,  569,  592,
- /*   270 */   375,   57,   58,   48,  579,  578,  580,  580,   55,   55,
- /*   280 */    56,   56,   56,   56,  597,   54,   54,   54,   54,   53,
- /*   290 */    53,   52,   52,   52,   51,  233,  309,  463,  617,  616,
- /*   300 */   590,  590,  590,  174,  272,  396,  409,  272,  409,  548,
- /*   310 */   397,  620,  619,   68,  326,  620,  619,  620,  619,  618,
- /*   320 */   546,  412,  618,  412,  471,  594,  587,  581,  472,  598,
- /*   330 */    92,  598,   92,   52,   52,   52,   51,  233,  513,  512,
- /*   340 */   206,  322,  363,  464,  221,   57,   58,   48,  579,  578,
- /*   350 */   580,  580,   55,   55,   56,   56,   56,   56,  529,   54,
- /*   360 */    54,   54,   54,   53,   53,   52,   52,   52,   51,  233,
- /*   370 */   309,  396,  409,  396,  597,  372,  386,  530,  347,  617,
- /*   380 */   616,  575,  202,  617,  616,  617,  616,  412,  620,  619,
- /*   390 */   145,  255,  346,  254,  577,  598,   74,  351,   45,  489,
- /*   400 */   587,  581,  235,  189,  464,  544,  167,  296,  187,  469,
- /*   410 */   479,   67,   62,   39,  618,  546,  597,  345,  573,   57,
- /*   420 */    58,   48,  579,  578,  580,  580,   55,   55,   56,   56,
- /*   430 */    56,   56,    6,   54,   54,   54,   54,   53,   53,   52,
- /*   440 */    52,   52,   51,  233,  309,  562,  558,  407,  528,  576,
- /*   450 */   576,  344,  255,  346,  254,  182,  617,  616,  503,  504,
- /*   460 */   314,  409,  557,  235,  166,  271,  409,  352,  564,  181,
- /*   470 */   407,  546,  576,  576,  587,  581,  412,  537,  556,  561,
- /*   480 */   517,  412,  618,  249,  598,   16,    7,   36,  467,  598,
- /*   490 */    92,  516,  618,   57,   58,   48,  579,  578,  580,  580,
- /*   500 */    55,   55,   56,   56,   56,   56,  541,   54,   54,   54,
- /*   510 */    54,   53,   53,   52,   52,   52,   51,  233,  309,  327,
- /*   520 */   572,  571,  525,  558,  560,  394,  871,  246,  409,  248,
- /*   530 */   171,  392,  594,  219,  407,  409,  576,  576,  502,  557,
- /*   540 */   364,  145,  510,  412,  407,  229,  576,  576,  587,  581,
- /*   550 */   412,  598,   92,  381,  269,  556,  166,  400,  598,   69,
- /*   560 */   501,  419,  945,  199,  945,  198,  546,   57,   58,   48,
- /*   570 */   579,  578,  580,  580,   55,   55,   56,   56,   56,   56,
- /*   580 */   568,   54,   54,   54,   54,   53,   53,   52,   52,   52,
- /*   590 */    51,  233,  309,  317,  419,  944,  508,  944,  308,  597,
- /*   600 */   594,  565,  490,  212,  173,  247,  423,  615,  614,  613,
- /*   610 */   323,  197,  143,  405,  572,  571,  489,   66,   50,   47,
- /*   620 */   146,  594,  587,  581,  232,  231,  559,  427,   67,  555,
- /*   630 */    15,  618,  186,  543,  303,  421,   35,  206,  432,  423,
- /*   640 */   552,   57,   58,   48,  579,  578,  580,  580,   55,   55,
- /*   650 */    56,   56,   56,   56,  205,   54,   54,   54,   54,   53,
- /*   660 */    53,   52,   52,   52,   51,  233,  309,  569,  569,  260,
- /*   670 */   268,  597,   12,  373,  568,  166,  409,  313,  409,  420,
- /*   680 */   409,  473,  473,  365,  618,   50,   47,  146,  597,  594,
- /*   690 */   468,  412,  166,  412,  351,  412,  587,  581,   32,  598,
- /*   700 */    94,  598,   97,  598,   95,  627,  625,  329,  142,   50,
- /*   710 */    47,  146,  333,  349,  358,   57,   58,   48,  579,  578,
- /*   720 */   580,  580,   55,   55,   56,   56,   56,   56,  409,   54,
- /*   730 */    54,   54,   54,   53,   53,   52,   52,   52,   51,  233,
- /*   740 */   309,  409,  388,  412,  409,   22,  565,  404,  212,  362,
- /*   750 */   389,  598,  104,  359,  409,  156,  412,  409,  603,  412,
- /*   760 */   537,  331,  569,  569,  598,  103,  493,  598,  105,  412,
- /*   770 */   587,  581,  412,  260,  549,  618,   11,  598,  106,  521,
- /*   780 */   598,  133,  169,  457,  456,  170,   35,  601,  618,   57,
- /*   790 */    58,   48,  579,  578,  580,  580,   55,   55,   56,   56,
- /*   800 */    56,   56,  409,   54,   54,   54,   54,   53,   53,   52,
- /*   810 */    52,   52,   51,  233,  309,  409,  259,  412,  409,   50,
- /*   820 */    47,  146,  357,  318,  355,  598,  134,  527,  352,  337,
- /*   830 */   412,  409,  356,  412,  357,  409,  357,  618,  598,   98,
- /*   840 */   129,  598,  102,  618,  587,  581,  412,   21,  235,  618,
- /*   850 */   412,  618,  211,  143,  598,  101,   30,  167,  598,   93,
- /*   860 */   350,  535,  203,   57,   58,   48,  579,  578,  580,  580,
- /*   870 */    55,   55,   56,   56,   56,   56,  409,   54,   54,   54,
- /*   880 */    54,   53,   53,   52,   52,   52,   51,  233,  309,  409,
- /*   890 */   526,  412,  409,  425,  215,  305,  597,  551,  141,  598,
- /*   900 */   100,   40,  409,   38,  412,  409,  550,  412,  409,  228,
- /*   910 */   220,  314,  598,   77,  500,  598,   96,  412,  587,  581,
- /*   920 */   412,  338,  253,  412,  218,  598,  137,  379,  598,  136,
- /*   930 */    28,  598,  135,  270,  715,  210,  481,   57,   58,   48,
- /*   940 */   579,  578,  580,  580,   55,   55,   56,   56,   56,   56,
- /*   950 */   409,   54,   54,   54,   54,   53,   53,   52,   52,   52,
- /*   960 */    51,  233,  309,  409,  272,  412,  409,  315,  147,  597,
- /*   970 */   272,  626,    2,  598,   76,  209,  409,  127,  412,  618,
- /*   980 */   126,  412,  409,  621,  235,  618,  598,   90,  374,  598,
- /*   990 */    89,  412,  587,  581,   27,  260,  350,  412,  618,  598,
- /*  1000 */    75,  321,  541,  541,  125,  598,   88,  320,  278,  597,
- /*  1010 */   618,   57,   46,   48,  579,  578,  580,  580,   55,   55,
- /*  1020 */    56,   56,   56,   56,  409,   54,   54,   54,   54,   53,
- /*  1030 */    53,   52,   52,   52,   51,  233,  309,  409,  450,  412,
- /*  1040 */   164,  284,  282,  272,  609,  424,  304,  598,   87,  370,
- /*  1050 */   409,  477,  412,  409,  608,  409,  607,  602,  618,  618,
- /*  1060 */   598,   99,  586,  585,  122,  412,  587,  581,  412,  618,
- /*  1070 */   412,  618,  618,  598,   86,  366,  598,   17,  598,   85,
- /*  1080 */   319,  185,  519,  518,  583,  582,   58,   48,  579,  578,
- /*  1090 */   580,  580,   55,   55,   56,   56,   56,   56,  409,   54,
- /*  1100 */    54,   54,   54,   53,   53,   52,   52,   52,   51,  233,
- /*  1110 */   309,  584,  409,  412,  409,  260,  260,  260,  408,  591,
- /*  1120 */   474,  598,   84,  170,  409,  466,  518,  412,  121,  412,
- /*  1130 */   618,  618,  618,  618,  618,  598,   83,  598,   72,  412,
- /*  1140 */   587,  581,   51,  233,  625,  329,  470,  598,   71,  257,
- /*  1150 */   159,  120,   14,  462,  157,  158,  117,  260,  448,  447,
- /*  1160 */   446,   48,  579,  578,  580,  580,   55,   55,   56,   56,
- /*  1170 */    56,   56,  618,   54,   54,   54,   54,   53,   53,   52,
- /*  1180 */    52,   52,   51,  233,   44,  403,  260,    3,  409,  459,
- /*  1190 */   260,  413,  619,  118,  398,   10,   25,   24,  554,  348,
- /*  1200 */   217,  618,  406,  412,  409,  618,    4,   44,  403,  618,
- /*  1210 */     3,  598,   82,  618,  413,  619,  455,  542,  115,  412,
- /*  1220 */   538,  401,  536,  274,  506,  406,  251,  598,   81,  216,
- /*  1230 */   273,  563,  618,  243,  453,  618,  154,  618,  618,  618,
- /*  1240 */   449,  416,  623,  110,  401,  618,  409,  236,   64,  123,
- /*  1250 */   487,   41,   42,  531,  563,  204,  409,  267,   43,  411,
- /*  1260 */   410,  412,  265,  592,  108,  618,  107,  434,  332,  598,
- /*  1270 */    80,  412,  618,  263,   41,   42,  443,  618,  409,  598,
- /*  1280 */    70,   43,  411,  410,  433,  261,  592,  149,  618,  597,
- /*  1290 */   256,  237,  188,  412,  590,  590,  590,  589,  588,   13,
- /*  1300 */   618,  598,   18,  328,  235,  618,   44,  403,  360,    3,
- /*  1310 */   418,  461,  339,  413,  619,  227,  124,  590,  590,  590,
- /*  1320 */   589,  588,   13,  618,  406,  409,  618,  409,  139,   34,
- /*  1330 */   403,  387,    3,  148,  622,  312,  413,  619,  311,  330,
- /*  1340 */   412,  460,  412,  401,  180,  353,  412,  406,  598,   79,
- /*  1350 */   598,   78,  250,  563,  598,    9,  618,  612,  611,  610,
- /*  1360 */   618,    8,  452,  442,  242,  415,  401,  618,  239,  235,
- /*  1370 */   179,  238,  428,   41,   42,  288,  563,  618,  618,  618,
- /*  1380 */    43,  411,  410,  618,  144,  592,  618,  618,  177,   61,
- /*  1390 */   618,  596,  391,  620,  619,  287,   41,   42,  414,  618,
- /*  1400 */   293,   30,  393,   43,  411,  410,  292,  618,  592,   31,
- /*  1410 */   618,  395,  291,   60,  230,   37,  590,  590,  590,  589,
- /*  1420 */   588,   13,  214,  553,  183,  290,  172,  301,  300,  299,
- /*  1430 */   178,  297,  595,  563,  451,   29,  285,  390,  540,  590,
- /*  1440 */   590,  590,  589,  588,   13,  283,  520,  534,  150,  533,
- /*  1450 */   241,  281,  384,  192,  191,  324,  515,  514,  276,  240,
- /*  1460 */   510,  523,  307,  511,  128,  592,  509,  225,  226,  486,
- /*  1470 */   485,  224,  152,  491,  464,  306,  484,  163,  153,  371,
- /*  1480 */   478,  151,  162,  258,  369,  161,  367,  208,  475,  476,
- /*  1490 */    26,  160,  465,  140,  361,  131,  590,  590,  590,  116,
- /*  1500 */   119,  454,  343,  155,  114,  342,  113,  112,  445,  111,
- /*  1510 */   130,  109,  431,  316,  426,  430,   23,  429,   20,  606,
- /*  1520 */   190,  507,  255,  341,  244,   63,  294,  593,  310,  570,
- /*  1530 */   277,  402,  354,  235,  567,  496,  495,  492,  494,  302,
- /*  1540 */   458,  378,  286,  245,  566,    5,  252,  547,  193,  444,
- /*  1550 */   233,  340,  207,  524,  368,  505,  334,  522,  499,  399,
- /*  1560 */   295,  498,  956,  488,
+ /*     0 */   306,  212,  432,  955,  639,  191,  955,  295,  559,   88,
+ /*    10 */    88,   88,   88,   81,   86,   86,   86,   86,   85,   85,
+ /*    20 */    84,   84,   84,   83,  330,  185,  184,  183,  635,  635,
+ /*    30 */   292,  606,  606,   88,   88,   88,   88,  683,   86,   86,
+ /*    40 */    86,   86,   85,   85,   84,   84,   84,   83,  330,   16,
+ /*    50 */   436,  597,   89,   90,   80,  600,  599,  601,  601,   87,
+ /*    60 */    87,   88,   88,   88,   88,  684,   86,   86,   86,   86,
+ /*    70 */    85,   85,   84,   84,   84,   83,  330,  306,  559,   84,
+ /*    80 */    84,   84,   83,  330,   65,   86,   86,   86,   86,   85,
+ /*    90 */    85,   84,   84,   84,   83,  330,  635,  635,  634,  633,
+ /*   100 */   182,  682,  550,  379,  376,  375,   17,  322,  606,  606,
+ /*   110 */   371,  198,  479,   91,  374,   82,   79,  165,   85,   85,
+ /*   120 */    84,   84,   84,   83,  330,  598,  635,  635,  107,   89,
+ /*   130 */    90,   80,  600,  599,  601,  601,   87,   87,   88,   88,
+ /*   140 */    88,   88,  186,   86,   86,   86,   86,   85,   85,   84,
+ /*   150 */    84,   84,   83,  330,  306,  594,  594,  142,  328,  327,
+ /*   160 */   484,  249,  344,  238,  635,  635,  634,  633,  585,  448,
+ /*   170 */   526,  525,  229,  388,    1,  394,  450,  584,  449,  635,
+ /*   180 */   635,  635,  635,  319,  395,  606,  606,  199,  157,  273,
+ /*   190 */   382,  268,  381,  187,  635,  635,  634,  633,  311,  555,
+ /*   200 */   266,  593,  593,  266,  347,  588,   89,   90,   80,  600,
+ /*   210 */   599,  601,  601,   87,   87,   88,   88,   88,   88,  478,
+ /*   220 */    86,   86,   86,   86,   85,   85,   84,   84,   84,   83,
+ /*   230 */   330,  306,  272,  536,  634,  633,  146,  610,  197,  310,
+ /*   240 */   575,  182,  482,  271,  379,  376,  375,  506,   21,  634,
+ /*   250 */   633,  634,  633,  635,  635,  374,  611,  574,  548,  440,
+ /*   260 */   111,  563,  606,  606,  634,  633,  324,  479,  608,  608,
+ /*   270 */   608,  300,  435,  573,  119,  407,  210,  162,  562,  883,
+ /*   280 */   592,  592,  306,   89,   90,   80,  600,  599,  601,  601,
+ /*   290 */    87,   87,   88,   88,   88,   88,  506,   86,   86,   86,
+ /*   300 */    86,   85,   85,   84,   84,   84,   83,  330,  620,  111,
+ /*   310 */   635,  635,  361,  606,  606,  358,  249,  349,  248,  433,
+ /*   320 */   243,  479,  586,  634,  633,  195,  611,   93,  119,  221,
+ /*   330 */   575,  497,  534,  534,   89,   90,   80,  600,  599,  601,
+ /*   340 */   601,   87,   87,   88,   88,   88,   88,  574,   86,   86,
+ /*   350 */    86,   86,   85,   85,   84,   84,   84,   83,  330,  306,
+ /*   360 */    77,  429,  638,  573,  589,  530,  240,  230,  242,  105,
+ /*   370 */   249,  349,  248,  515,  588,  208,  460,  529,  564,  173,
+ /*   380 */   634,  633,  970,  144,  430,    2,  424,  228,  380,  557,
+ /*   390 */   606,  606,  190,  153,  159,  158,  514,   51,  632,  631,
+ /*   400 */   630,   71,  536,  432,  954,  196,  610,  954,  614,   45,
+ /*   410 */    18,   89,   90,   80,  600,  599,  601,  601,   87,   87,
+ /*   420 */    88,   88,   88,   88,  261,   86,   86,   86,   86,   85,
+ /*   430 */    85,   84,   84,   84,   83,  330,  306,  608,  608,  608,
+ /*   440 */   542,  424,  402,  385,  241,  506,  451,  320,  211,  543,
+ /*   450 */   164,  436,  386,  293,  451,  587,  108,  496,  111,  334,
+ /*   460 */   391,  591,  424,  614,   27,  452,  453,  606,  606,   72,
+ /*   470 */   257,   70,  259,  452,  339,  342,  564,  582,   68,  415,
+ /*   480 */   469,  328,  327,   62,  614,   45,  110,  393,   89,   90,
+ /*   490 */    80,  600,  599,  601,  601,   87,   87,   88,   88,   88,
+ /*   500 */    88,  152,   86,   86,   86,   86,   85,   85,   84,   84,
+ /*   510 */    84,   83,  330,  306,  110,  499,  520,  538,  402,  389,
+ /*   520 */   424,  110,  566,  500,  593,  593,  454,   82,   79,  165,
+ /*   530 */   424,  591,  384,  564,  340,  615,  188,  162,  424,  350,
+ /*   540 */   616,  424,  614,   44,  606,  606,  445,  582,  300,  434,
+ /*   550 */   151,   19,  614,    9,  568,  580,  348,  615,  469,  567,
+ /*   560 */   614,   26,  616,  614,   45,   89,   90,   80,  600,  599,
+ /*   570 */   601,  601,   87,   87,   88,   88,   88,   88,  411,   86,
+ /*   580 */    86,   86,   86,   85,   85,   84,   84,   84,   83,  330,
+ /*   590 */   306,  579,  110,  578,  521,  282,  433,  398,  400,  255,
+ /*   600 */   486,   82,   79,  165,  487,  164,   82,   79,  165,  488,
+ /*   610 */   488,  364,  387,  424,  544,  544,  509,  350,  362,  155,
+ /*   620 */   191,  606,  606,  559,  642,  640,  333,   82,   79,  165,
+ /*   630 */   305,  564,  507,  312,  357,  614,   45,  329,  596,  595,
+ /*   640 */   194,  337,   89,   90,   80,  600,  599,  601,  601,   87,
+ /*   650 */    87,   88,   88,   88,   88,  424,   86,   86,   86,   86,
+ /*   660 */    85,   85,   84,   84,   84,   83,  330,  306,   20,  323,
+ /*   670 */   150,  263,  211,  543,  421,  596,  595,  614,   22,  424,
+ /*   680 */   193,  424,  284,  424,  391,  424,  509,  424,  577,  424,
+ /*   690 */   186,  335,  424,  559,  424,  313,  120,  546,  606,  606,
+ /*   700 */    67,  614,   47,  614,   50,  614,   48,  614,  100,  614,
+ /*   710 */    99,  614,  101,  576,  614,  102,  614,  109,  326,   89,
+ /*   720 */    90,   80,  600,  599,  601,  601,   87,   87,   88,   88,
+ /*   730 */    88,   88,  424,   86,   86,   86,   86,   85,   85,   84,
+ /*   740 */    84,   84,   83,  330,  306,  424,  311,  424,  585,   54,
+ /*   750 */   424,  516,  517,  590,  614,  112,  424,  584,  424,  572,
+ /*   760 */   424,  195,  424,  571,  424,   67,  424,  614,   94,  614,
+ /*   770 */    98,  424,  614,   97,  264,  606,  606,  195,  614,   46,
+ /*   780 */   614,   96,  614,   30,  614,   49,  614,  115,  614,  114,
+ /*   790 */   418,  229,  388,  614,  113,  306,   89,   90,   80,  600,
+ /*   800 */   599,  601,  601,   87,   87,   88,   88,   88,   88,  424,
+ /*   810 */    86,   86,   86,   86,   85,   85,   84,   84,   84,   83,
+ /*   820 */   330,  119,  424,  590,  110,  372,  606,  606,  195,   53,
+ /*   830 */   250,  614,   29,  195,  472,  438,  729,  190,  302,  498,
+ /*   840 */    14,  523,  641,    2,  614,   43,  306,   89,   90,   80,
+ /*   850 */   600,  599,  601,  601,   87,   87,   88,   88,   88,   88,
+ /*   860 */   424,   86,   86,   86,   86,   85,   85,   84,   84,   84,
+ /*   870 */    83,  330,  424,  613,  964,  964,  354,  606,  606,  420,
+ /*   880 */   312,   64,  614,   42,  391,  355,  283,  437,  301,  255,
+ /*   890 */   414,  410,  495,  492,  614,   28,  471,  306,   89,   90,
+ /*   900 */    80,  600,  599,  601,  601,   87,   87,   88,   88,   88,
+ /*   910 */    88,  424,   86,   86,   86,   86,   85,   85,   84,   84,
+ /*   920 */    84,   83,  330,  424,  110,  110,  110,  110,  606,  606,
+ /*   930 */   110,  254,   13,  614,   41,  532,  531,  283,  481,  531,
+ /*   940 */   457,  284,  119,  561,  356,  614,   40,  284,  306,   89,
+ /*   950 */    78,   80,  600,  599,  601,  601,   87,   87,   88,   88,
+ /*   960 */    88,   88,  424,   86,   86,   86,   86,   85,   85,   84,
+ /*   970 */    84,   84,   83,  330,  110,  424,  341,  220,  555,  606,
+ /*   980 */   606,  351,  555,  318,  614,   95,  413,  255,   83,  330,
+ /*   990 */   284,  284,  255,  640,  333,  356,  255,  614,   39,  306,
+ /*  1000 */   356,   90,   80,  600,  599,  601,  601,   87,   87,   88,
+ /*  1010 */    88,   88,   88,  424,   86,   86,   86,   86,   85,   85,
+ /*  1020 */    84,   84,   84,   83,  330,  424,  317,  316,  141,  465,
+ /*  1030 */   606,  606,  219,  619,  463,  614,   10,  417,  462,  255,
+ /*  1040 */   189,  510,  553,  351,  207,  363,  161,  614,   38,  315,
+ /*  1050 */   218,  255,  255,   80,  600,  599,  601,  601,   87,   87,
+ /*  1060 */    88,   88,   88,   88,  424,   86,   86,   86,   86,   85,
+ /*  1070 */    85,   84,   84,   84,   83,  330,   76,  419,  255,    3,
+ /*  1080 */   878,  461,  424,  247,  331,  331,  614,   37,  217,   76,
+ /*  1090 */   419,  390,    3,  216,  215,  422,    4,  331,  331,  424,
+ /*  1100 */   547,   12,  424,  545,  614,   36,  424,  541,  422,  424,
+ /*  1110 */   540,  424,  214,  424,  408,  424,  539,  403,  605,  605,
+ /*  1120 */   237,  614,   25,  119,  614,   24,  588,  408,  614,   45,
+ /*  1130 */   118,  614,   35,  614,   34,  614,   33,  614,   23,  588,
+ /*  1140 */    60,  223,  603,  602,  513,  378,   73,   74,  140,  139,
+ /*  1150 */   424,  110,  265,   75,  426,  425,   59,  424,  610,   73,
+ /*  1160 */    74,  549,  402,  404,  424,  373,   75,  426,  425,  604,
+ /*  1170 */   138,  610,  614,   11,  392,   76,  419,  181,    3,  614,
+ /*  1180 */    32,  271,  369,  331,  331,  493,  614,   31,  149,  608,
+ /*  1190 */   608,  608,  607,   15,  422,  365,  614,    8,  137,  489,
+ /*  1200 */   136,  190,  608,  608,  608,  607,   15,  485,  176,  135,
+ /*  1210 */     7,  252,  477,  408,  174,  133,  175,  474,   57,   56,
+ /*  1220 */   132,  130,  119,   76,  419,  588,    3,  468,  245,  464,
+ /*  1230 */   171,  331,  331,  125,  123,  456,  447,  122,  446,  104,
+ /*  1240 */   336,  231,  422,  166,  154,   73,   74,  332,  116,  431,
+ /*  1250 */   121,  309,   75,  426,  425,  222,  106,  610,  308,  637,
+ /*  1260 */   204,  408,  629,  627,  628,    6,  200,  428,  427,  290,
+ /*  1270 */   203,  622,  201,  588,   62,   63,  289,   66,  419,  399,
+ /*  1280 */     3,  401,  288,   92,  143,  331,  331,  287,  608,  608,
+ /*  1290 */   608,  607,   15,   73,   74,  227,  422,  325,   69,  416,
+ /*  1300 */    75,  426,  425,  612,  412,  610,  192,   61,  569,  209,
+ /*  1310 */   396,  226,  278,  225,  383,  408,  527,  558,  276,  533,
+ /*  1320 */   552,  528,  321,  523,  370,  508,  180,  588,  494,  179,
+ /*  1330 */   366,  117,  253,  269,  522,  503,  608,  608,  608,  607,
+ /*  1340 */    15,  551,  502,   58,  274,  524,  178,   73,   74,  304,
+ /*  1350 */   501,  368,  303,  206,   75,  426,  425,  491,  360,  610,
+ /*  1360 */   213,  177,  483,  131,  345,  298,  297,  296,  202,  294,
+ /*  1370 */   480,  490,  466,  134,  172,  129,  444,  346,  470,  128,
+ /*  1380 */   314,  459,  103,  127,  126,  148,  124,  167,  443,  235,
+ /*  1390 */   608,  608,  608,  607,   15,  442,  439,  623,  234,  299,
+ /*  1400 */   145,  583,  291,  377,  581,  160,  119,  156,  270,  636,
+ /*  1410 */   971,  169,  279,  626,  520,  625,  473,  624,  170,  621,
+ /*  1420 */   618,  119,  168,   55,  409,  423,  537,  609,  286,  285,
+ /*  1430 */   405,  570,  560,  556,    5,   52,  458,  554,  147,  267,
+ /*  1440 */   519,  504,  518,  406,  262,  239,  260,  512,  343,  511,
+ /*  1450 */   258,  353,  565,  256,  224,  251,  359,  277,  275,  476,
+ /*  1460 */   475,  246,  352,  244,  467,  455,  236,  233,  232,  307,
+ /*  1470 */   441,  281,  205,  163,  397,  280,  535,  505,  330,  617,
+ /*  1480 */   971,  971,  971,  971,  367,  971,  971,  971,  971,  971,
+ /*  1490 */   971,  971,  971,  971,  971,  971,  338,
 };
 static const YYCODETYPE yy_lookahead[] = {
- /*     0 */    19,  142,  143,  144,  145,   24,    1,   26,   77,   78,
- /*    10 */    79,   80,   81,   82,   83,   84,   85,   86,   87,   88,
- /*    20 */    89,   90,   91,   92,   26,   27,   15,   26,   27,  197,
- /*    30 */    49,   50,   77,   78,   79,   80,  204,   82,   83,   84,
- /*    40 */    85,   86,   87,   88,   89,   90,   91,   92,   23,   68,
- /*    50 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
- /*    60 */    79,   80,  166,   82,   83,   84,   85,   86,   87,   88,
- /*    70 */    89,   90,   91,   92,   19,   94,   19,  105,  106,  107,
- /*    80 */    25,   82,   83,   84,   85,   86,   87,   88,   89,   90,
- /*    90 */    91,   92,   94,   95,   96,   94,   95,   99,  100,  101,
- /*   100 */   112,  205,  114,  115,   49,   50,   22,   23,  110,   54,
- /*   110 */    86,   87,   88,   89,   90,   91,   92,  221,  222,  223,
- /*   120 */    23,  120,   25,   68,   69,   70,   71,   72,   73,   74,
- /*   130 */    75,   76,   77,   78,   79,   80,   22,   82,   83,   84,
- /*   140 */    85,   86,   87,   88,   89,   90,   91,   92,   19,   92,
- /*   150 */    23,   67,   25,   96,   97,   98,   99,  100,  101,  102,
- /*   160 */   150,   32,  150,  118,   26,   27,  109,  150,  150,  150,
- /*   170 */    41,  161,  162,  180,  181,  165,  113,  165,   49,   50,
- /*   180 */   117,  188,  165,  165,  165,  173,  174,  170,  171,  170,
- /*   190 */   171,  173,  174,  118,  184,   16,  186,   68,   69,   70,
- /*   200 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
- /*   210 */   118,   82,   83,   84,   85,   86,   87,   88,   89,   90,
- /*   220 */    91,   92,   19,   98,   86,   87,   22,   24,  160,   88,
- /*   230 */    26,   27,   94,   95,  109,   97,  224,   66,  118,   60,
- /*   240 */   150,   62,  104,   23,  106,   25,  229,  230,  229,  230,
- /*   250 */   160,  150,   49,   50,  113,  165,   96,   26,  117,   99,
- /*   260 */   100,  101,  194,  173,  174,   94,  165,  129,  130,   98,
- /*   270 */   110,   68,   69,   70,   71,   72,   73,   74,   75,   76,
- /*   280 */    77,   78,   79,   80,  194,   82,   83,   84,   85,   86,
- /*   290 */    87,   88,   89,   90,   91,   92,   19,   11,   94,   95,
- /*   300 */   129,  130,  131,  118,  150,  215,  150,  150,  150,   25,
- /*   310 */   220,   26,   27,   22,  213,   26,   27,   26,   27,  165,
- /*   320 */    25,  165,  165,  165,   30,   94,   49,   50,   34,  173,
- /*   330 */   174,  173,  174,   88,   89,   90,   91,   92,    7,    8,
- /*   340 */   160,  187,   48,   57,  187,   68,   69,   70,   71,   72,
- /*   350 */    73,   74,   75,   76,   77,   78,   79,   80,   23,   82,
- /*   360 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
- /*   370 */    19,  215,  150,  215,  194,   19,  220,   88,  220,   94,
- /*   380 */    95,   23,  160,   94,   95,   94,   95,  165,   26,   27,
- /*   390 */    95,  105,  106,  107,  113,  173,  174,  217,   22,  150,
- /*   400 */    49,   50,  116,  119,   57,  120,   50,  158,   22,   21,
- /*   410 */   161,  162,  232,  136,  165,  120,  194,  237,   23,   68,
- /*   420 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
- /*   430 */    79,   80,   22,   82,   83,   84,   85,   86,   87,   88,
- /*   440 */    89,   90,   91,   92,   19,   23,   12,  112,   23,  114,
- /*   450 */   115,   63,  105,  106,  107,   23,   94,   95,   97,   98,
- /*   460 */   104,  150,   28,  116,   25,  109,  150,  150,   23,   23,
- /*   470 */   112,   25,  114,  115,   49,   50,  165,  150,   44,   11,
- /*   480 */    46,  165,  165,   16,  173,  174,   76,  136,  100,  173,
- /*   490 */   174,   57,  165,   68,   69,   70,   71,   72,   73,   74,
- /*   500 */    75,   76,   77,   78,   79,   80,  166,   82,   83,   84,
- /*   510 */    85,   86,   87,   88,   89,   90,   91,   92,   19,  169,
- /*   520 */   170,  171,   23,   12,   23,  214,  138,   60,  150,   62,
- /*   530 */    24,  215,   26,  216,  112,  150,  114,  115,   36,   28,
- /*   540 */   213,   95,  103,  165,  112,  205,  114,  115,   49,   50,
- /*   550 */   165,  173,  174,   51,   23,   44,   25,   46,  173,  174,
- /*   560 */    58,   22,   23,   22,   25,  160,  120,   68,   69,   70,
- /*   570 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
- /*   580 */   230,   82,   83,   84,   85,   86,   87,   88,   89,   90,
- /*   590 */    91,   92,   19,  215,   22,   23,   23,   25,  163,  194,
- /*   600 */    94,  166,  167,  168,   25,  138,   67,    7,    8,    9,
- /*   610 */   108,  206,  207,  169,  170,  171,  150,   22,  221,  222,
- /*   620 */   223,   26,   49,   50,   86,   87,   23,  161,  162,   23,
- /*   630 */    22,  165,   24,  120,   22,   23,   25,  160,  241,   67,
- /*   640 */   176,   68,   69,   70,   71,   72,   73,   74,   75,   76,
- /*   650 */    77,   78,   79,   80,  160,   82,   83,   84,   85,   86,
- /*   660 */    87,   88,   89,   90,   91,   92,   19,  129,  130,  150,
- /*   670 */    23,  194,   35,   23,  230,   25,  150,  155,  150,   67,
- /*   680 */   150,  105,  106,  107,  165,  221,  222,  223,  194,   94,
- /*   690 */    23,  165,   25,  165,  217,  165,   49,   50,   25,  173,
- /*   700 */   174,  173,  174,  173,  174,    0,    1,    2,  118,  221,
- /*   710 */   222,  223,  193,  219,  237,   68,   69,   70,   71,   72,
- /*   720 */    73,   74,   75,   76,   77,   78,   79,   80,  150,   82,
- /*   730 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
- /*   740 */    19,  150,   19,  165,  150,   24,  166,  167,  168,  227,
- /*   750 */    27,  173,  174,  231,  150,   25,  165,  150,  172,  165,
- /*   760 */   150,  242,  129,  130,  173,  174,  180,  173,  174,  165,
- /*   770 */    49,   50,  165,  150,  176,  165,   35,  173,  174,  165,
- /*   780 */   173,  174,   35,   23,   23,   25,   25,  173,  165,   68,
- /*   790 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
- /*   800 */    79,   80,  150,   82,   83,   84,   85,   86,   87,   88,
- /*   810 */    89,   90,   91,   92,   19,  150,  193,  165,  150,  221,
- /*   820 */   222,  223,  150,  213,   19,  173,  174,   23,  150,   97,
- /*   830 */   165,  150,   27,  165,  150,  150,  150,  165,  173,  174,
- /*   840 */    22,  173,  174,  165,   49,   50,  165,   52,  116,  165,
- /*   850 */   165,  165,  206,  207,  173,  174,  126,   50,  173,  174,
- /*   860 */   128,   27,  160,   68,   69,   70,   71,   72,   73,   74,
- /*   870 */    75,   76,   77,   78,   79,   80,  150,   82,   83,   84,
- /*   880 */    85,   86,   87,   88,   89,   90,   91,   92,   19,  150,
- /*   890 */    23,  165,  150,   23,  216,   25,  194,   32,   39,  173,
- /*   900 */   174,  135,  150,  137,  165,  150,   41,  165,  150,   52,
- /*   910 */   238,  104,  173,  174,   29,  173,  174,  165,   49,   50,
- /*   920 */   165,  219,  238,  165,  238,  173,  174,   52,  173,  174,
- /*   930 */    22,  173,  174,   23,   23,  160,   25,   68,   69,   70,
- /*   940 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
- /*   950 */   150,   82,   83,   84,   85,   86,   87,   88,   89,   90,
- /*   960 */    91,   92,   19,  150,  150,  165,  150,  245,  246,  194,
- /*   970 */   150,  144,  145,  173,  174,  160,  150,   22,  165,  165,
- /*   980 */    22,  165,  150,  150,  116,  165,  173,  174,   52,  173,
- /*   990 */   174,  165,   49,   50,   22,  150,  128,  165,  165,  173,
- /*  1000 */   174,  187,  166,  166,   22,  173,  174,  187,  109,  194,
- /*  1010 */   165,   68,   69,   70,   71,   72,   73,   74,   75,   76,
- /*  1020 */    77,   78,   79,   80,  150,   82,   83,   84,   85,   86,
- /*  1030 */    87,   88,   89,   90,   91,   92,   19,  150,  193,  165,
- /*  1040 */   102,  205,  205,  150,  150,  247,  248,  173,  174,   19,
- /*  1050 */   150,   20,  165,  150,  150,  150,  150,  150,  165,  165,
- /*  1060 */   173,  174,   49,   50,  104,  165,   49,   50,  165,  165,
- /*  1070 */   165,  165,  165,  173,  174,   43,  173,  174,  173,  174,
- /*  1080 */   187,   24,  190,  191,   71,   72,   69,   70,   71,   72,
- /*  1090 */    73,   74,   75,   76,   77,   78,   79,   80,  150,   82,
- /*  1100 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
- /*  1110 */    19,   98,  150,  165,  150,  150,  150,  150,  150,  150,
- /*  1120 */    59,  173,  174,   25,  150,  190,  191,  165,   53,  165,
- /*  1130 */   165,  165,  165,  165,  165,  173,  174,  173,  174,  165,
- /*  1140 */    49,   50,   91,   92,    1,    2,   53,  173,  174,  138,
- /*  1150 */   104,   22,    5,    1,   35,  118,  127,  150,  193,  193,
- /*  1160 */   193,   70,   71,   72,   73,   74,   75,   76,   77,   78,
- /*  1170 */    79,   80,  165,   82,   83,   84,   85,   86,   87,   88,
- /*  1180 */    89,   90,   91,   92,   19,   20,  150,   22,  150,   27,
- /*  1190 */   150,   26,   27,  108,  150,   22,   76,   76,  150,   25,
- /*  1200 */   193,  165,   37,  165,  150,  165,   22,   19,   20,  165,
- /*  1210 */    22,  173,  174,  165,   26,   27,   23,  150,  119,  165,
- /*  1220 */   150,   56,  150,  150,  150,   37,   16,  173,  174,  193,
- /*  1230 */   150,   66,  165,  193,    1,  165,  121,  165,  165,  165,
- /*  1240 */    20,  146,  147,  119,   56,  165,  150,  152,   16,  154,
- /*  1250 */   150,   86,   87,   88,   66,  160,  150,  150,   93,   94,
- /*  1260 */    95,  165,  150,   98,  108,  165,  127,   23,   65,  173,
- /*  1270 */   174,  165,  165,  150,   86,   87,  128,  165,  150,  173,
- /*  1280 */   174,   93,   94,   95,   23,  150,   98,   15,  165,  194,
- /*  1290 */   150,  140,   22,  165,  129,  130,  131,  132,  133,  134,
- /*  1300 */   165,  173,  174,    3,  116,  165,   19,   20,  150,   22,
- /*  1310 */     4,  150,  217,   26,   27,  179,  179,  129,  130,  131,
- /*  1320 */   132,  133,  134,  165,   37,  150,  165,  150,  164,   19,
- /*  1330 */    20,  150,   22,  246,  149,  249,   26,   27,  249,  244,
- /*  1340 */   165,  150,  165,   56,    6,  150,  165,   37,  173,  174,
- /*  1350 */   173,  174,  150,   66,  173,  174,  165,  149,  149,   13,
- /*  1360 */   165,   25,  150,  150,  150,  149,   56,  165,  150,  116,
- /*  1370 */   151,  150,  150,   86,   87,  150,   66,  165,  165,  165,
- /*  1380 */    93,   94,   95,  165,  150,   98,  165,  165,  151,   22,
- /*  1390 */   165,  194,  150,   26,   27,  150,   86,   87,  159,  165,
- /*  1400 */   199,  126,  123,   93,   94,   95,  200,  165,   98,  124,
- /*  1410 */   165,  122,  201,  125,  225,  135,  129,  130,  131,  132,
- /*  1420 */   133,  134,    5,  157,  157,  202,  118,   10,   11,   12,
- /*  1430 */    13,   14,  203,   66,   17,  104,  210,  121,  211,  129,
- /*  1440 */   130,  131,  132,  133,  134,  210,  175,  211,   31,  211,
- /*  1450 */    33,  210,  104,   86,   87,   47,  175,  183,  175,   42,
- /*  1460 */   103,   94,  178,  177,   22,   98,  175,   92,  228,  175,
- /*  1470 */   175,  228,   55,  183,   57,  178,  175,  156,   61,   18,
- /*  1480 */   157,   64,  156,  235,  157,  156,   45,  157,  236,  157,
- /*  1490 */   135,  156,  189,   68,  157,  218,  129,  130,  131,   22,
- /*  1500 */   189,  199,  157,  156,  192,   18,  192,  192,  199,  192,
- /*  1510 */   218,  189,   40,  157,   38,  157,  240,  157,  240,  153,
- /*  1520 */   196,  181,  105,  106,  107,  243,  198,  166,  111,  230,
- /*  1530 */   176,  226,  239,  116,  230,  176,  166,  166,  176,  148,
- /*  1540 */   199,  177,  209,  209,  166,  196,  239,  208,  185,  199,
- /*  1550 */    92,  209,  233,  173,  234,  182,  139,  173,  182,  191,
- /*  1560 */   195,  182,  250,  186,
+ /*     0 */    19,   22,   22,   23,    1,   24,   26,   15,   27,   80,
+ /*    10 */    81,   82,   83,   84,   85,   86,   87,   88,   89,   90,
+ /*    20 */    91,   92,   93,   94,   95,  108,  109,  110,   27,   28,
+ /*    30 */    23,   50,   51,   80,   81,   82,   83,  122,   85,   86,
+ /*    40 */    87,   88,   89,   90,   91,   92,   93,   94,   95,   22,
+ /*    50 */    70,   23,   71,   72,   73,   74,   75,   76,   77,   78,
+ /*    60 */    79,   80,   81,   82,   83,  122,   85,   86,   87,   88,
+ /*    70 */    89,   90,   91,   92,   93,   94,   95,   19,   97,   91,
+ /*    80 */    92,   93,   94,   95,   26,   85,   86,   87,   88,   89,
+ /*    90 */    90,   91,   92,   93,   94,   95,   27,   28,   97,   98,
+ /*   100 */    99,  122,  211,  102,  103,  104,   79,   19,   50,   51,
+ /*   110 */    19,  122,   59,   55,  113,  224,  225,  226,   89,   90,
+ /*   120 */    91,   92,   93,   94,   95,   23,   27,   28,   26,   71,
+ /*   130 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81,
+ /*   140 */    82,   83,   51,   85,   86,   87,   88,   89,   90,   91,
+ /*   150 */    92,   93,   94,   95,   19,  132,  133,   58,   89,   90,
+ /*   160 */    21,  108,  109,  110,   27,   28,   97,   98,   33,  100,
+ /*   170 */     7,    8,  119,  120,   22,   19,  107,   42,  109,   27,
+ /*   180 */    28,   27,   28,   95,   28,   50,   51,   99,  100,  101,
+ /*   190 */   102,  103,  104,  105,   27,   28,   97,   98,  107,  152,
+ /*   200 */   112,  132,  133,  112,   65,   69,   71,   72,   73,   74,
+ /*   210 */    75,   76,   77,   78,   79,   80,   81,   82,   83,   11,
+ /*   220 */    85,   86,   87,   88,   89,   90,   91,   92,   93,   94,
+ /*   230 */    95,   19,  101,   97,   97,   98,   24,  101,  122,  157,
+ /*   240 */    12,   99,  103,  112,  102,  103,  104,  152,   22,   97,
+ /*   250 */    98,   97,   98,   27,   28,  113,   27,   29,   91,  164,
+ /*   260 */   165,  124,   50,   51,   97,   98,  219,   59,  132,  133,
+ /*   270 */   134,   22,   23,   45,   66,   47,  212,  213,  124,  140,
+ /*   280 */   132,  133,   19,   71,   72,   73,   74,   75,   76,   77,
+ /*   290 */    78,   79,   80,   81,   82,   83,  152,   85,   86,   87,
+ /*   300 */    88,   89,   90,   91,   92,   93,   94,   95,  164,  165,
+ /*   310 */    27,   28,  230,   50,   51,  233,  108,  109,  110,   70,
+ /*   320 */    16,   59,   23,   97,   98,   26,   97,   22,   66,  185,
+ /*   330 */    12,  187,   27,   28,   71,   72,   73,   74,   75,   76,
+ /*   340 */    77,   78,   79,   80,   81,   82,   83,   29,   85,   86,
+ /*   350 */    87,   88,   89,   90,   91,   92,   93,   94,   95,   19,
+ /*   360 */    22,  148,  149,   45,   23,   47,   62,  154,   64,  156,
+ /*   370 */   108,  109,  110,   37,   69,   23,  163,   59,   26,   26,
+ /*   380 */    97,   98,  144,  145,  146,  147,  152,  200,   52,   23,
+ /*   390 */    50,   51,   26,   22,   89,   90,   60,  210,    7,    8,
+ /*   400 */     9,  138,   97,   22,   23,   26,  101,   26,  174,  175,
+ /*   410 */   197,   71,   72,   73,   74,   75,   76,   77,   78,   79,
+ /*   420 */    80,   81,   82,   83,   16,   85,   86,   87,   88,   89,
+ /*   430 */    90,   91,   92,   93,   94,   95,   19,  132,  133,  134,
+ /*   440 */    23,  152,  208,  209,  140,  152,  152,  111,  195,  196,
+ /*   450 */    98,   70,  163,  160,  152,   23,   22,  164,  165,  246,
+ /*   460 */   207,   27,  152,  174,  175,  171,  172,   50,   51,  137,
+ /*   470 */    62,  139,   64,  171,  172,  222,  124,   27,  138,   24,
+ /*   480 */   163,   89,   90,  130,  174,  175,  197,  163,   71,   72,
+ /*   490 */    73,   74,   75,   76,   77,   78,   79,   80,   81,   82,
+ /*   500 */    83,   22,   85,   86,   87,   88,   89,   90,   91,   92,
+ /*   510 */    93,   94,   95,   19,  197,  181,  182,   23,  208,  209,
+ /*   520 */   152,  197,   26,  189,  132,  133,  232,  224,  225,  226,
+ /*   530 */   152,   97,   91,   26,  232,  116,  212,  213,  152,  222,
+ /*   540 */   121,  152,  174,  175,   50,   51,  243,   97,   22,   23,
+ /*   550 */    22,  234,  174,  175,  177,   23,  239,  116,  163,  177,
+ /*   560 */   174,  175,  121,  174,  175,   71,   72,   73,   74,   75,
+ /*   570 */    76,   77,   78,   79,   80,   81,   82,   83,   24,   85,
+ /*   580 */    86,   87,   88,   89,   90,   91,   92,   93,   94,   95,
+ /*   590 */    19,   23,  197,   11,   23,  227,   70,  208,  220,  152,
+ /*   600 */    31,  224,  225,  226,   35,   98,  224,  225,  226,  108,
+ /*   610 */   109,  110,  115,  152,  117,  118,   27,  222,   49,  123,
+ /*   620 */    24,   50,   51,   27,    0,    1,    2,  224,  225,  226,
+ /*   630 */   166,  124,  168,  169,  239,  174,  175,  170,  171,  172,
+ /*   640 */    22,  194,   71,   72,   73,   74,   75,   76,   77,   78,
+ /*   650 */    79,   80,   81,   82,   83,  152,   85,   86,   87,   88,
+ /*   660 */    89,   90,   91,   92,   93,   94,   95,   19,   22,  208,
+ /*   670 */    24,   23,  195,  196,  170,  171,  172,  174,  175,  152,
+ /*   680 */    26,  152,  152,  152,  207,  152,   97,  152,   23,  152,
+ /*   690 */    51,  244,  152,   97,  152,  247,  248,   23,   50,   51,
+ /*   700 */    26,  174,  175,  174,  175,  174,  175,  174,  175,  174,
+ /*   710 */   175,  174,  175,   23,  174,  175,  174,  175,  188,   71,
+ /*   720 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81,
+ /*   730 */    82,   83,  152,   85,   86,   87,   88,   89,   90,   91,
+ /*   740 */    92,   93,   94,   95,   19,  152,  107,  152,   33,   24,
+ /*   750 */   152,  100,  101,   27,  174,  175,  152,   42,  152,   23,
+ /*   760 */   152,   26,  152,   23,  152,   26,  152,  174,  175,  174,
+ /*   770 */   175,  152,  174,  175,   23,   50,   51,   26,  174,  175,
+ /*   780 */   174,  175,  174,  175,  174,  175,  174,  175,  174,  175,
+ /*   790 */   163,  119,  120,  174,  175,   19,   71,   72,   73,   74,
+ /*   800 */    75,   76,   77,   78,   79,   80,   81,   82,   83,  152,
+ /*   810 */    85,   86,   87,   88,   89,   90,   91,   92,   93,   94,
+ /*   820 */    95,   66,  152,   97,  197,   23,   50,   51,   26,   53,
+ /*   830 */    23,  174,  175,   26,   23,   23,   23,   26,   26,   26,
+ /*   840 */    36,  106,  146,  147,  174,  175,   19,   71,   72,   73,
+ /*   850 */    74,   75,   76,   77,   78,   79,   80,   81,   82,   83,
+ /*   860 */   152,   85,   86,   87,   88,   89,   90,   91,   92,   93,
+ /*   870 */    94,   95,  152,  196,  119,  120,   19,   50,   51,  168,
+ /*   880 */   169,   26,  174,  175,  207,   28,  152,  249,  250,  152,
+ /*   890 */   163,  163,  163,  163,  174,  175,  163,   19,   71,   72,
+ /*   900 */    73,   74,   75,   76,   77,   78,   79,   80,   81,   82,
+ /*   910 */    83,  152,   85,   86,   87,   88,   89,   90,   91,   92,
+ /*   920 */    93,   94,   95,  152,  197,  197,  197,  197,   50,   51,
+ /*   930 */   197,  194,   36,  174,  175,  191,  192,  152,  191,  192,
+ /*   940 */   163,  152,   66,  124,  152,  174,  175,  152,   19,   71,
+ /*   950 */    72,   73,   74,   75,   76,   77,   78,   79,   80,   81,
+ /*   960 */    82,   83,  152,   85,   86,   87,   88,   89,   90,   91,
+ /*   970 */    92,   93,   94,   95,  197,  152,  100,  188,  152,   50,
+ /*   980 */    51,  152,  152,  188,  174,  175,  252,  152,   94,   95,
+ /*   990 */   152,  152,  152,    1,    2,  152,  152,  174,  175,   19,
+ /*  1000 */   152,   72,   73,   74,   75,   76,   77,   78,   79,   80,
+ /*  1010 */    81,   82,   83,  152,   85,   86,   87,   88,   89,   90,
+ /*  1020 */    91,   92,   93,   94,   95,  152,  188,  188,   22,  194,
+ /*  1030 */    50,   51,  240,  173,  194,  174,  175,  252,  194,  152,
+ /*  1040 */    36,  181,   28,  152,   23,  219,  122,  174,  175,  219,
+ /*  1050 */   221,  152,  152,   73,   74,   75,   76,   77,   78,   79,
+ /*  1060 */    80,   81,   82,   83,  152,   85,   86,   87,   88,   89,
+ /*  1070 */    90,   91,   92,   93,   94,   95,   19,   20,  152,   22,
+ /*  1080 */    23,  194,  152,  240,   27,   28,  174,  175,  240,   19,
+ /*  1090 */    20,   26,   22,  194,  194,   38,   22,   27,   28,  152,
+ /*  1100 */    23,   22,  152,  116,  174,  175,  152,   23,   38,  152,
+ /*  1110 */    23,  152,  221,  152,   57,  152,   23,  163,   50,   51,
+ /*  1120 */   194,  174,  175,   66,  174,  175,   69,   57,  174,  175,
+ /*  1130 */    40,  174,  175,  174,  175,  174,  175,  174,  175,   69,
+ /*  1140 */    22,   53,   74,   75,   30,   53,   89,   90,   22,   22,
+ /*  1150 */   152,  197,   23,   96,   97,   98,   22,  152,  101,   89,
+ /*  1160 */    90,   91,  208,  209,  152,   53,   96,   97,   98,  101,
+ /*  1170 */    22,  101,  174,  175,  152,   19,   20,  105,   22,  174,
+ /*  1180 */   175,  112,   19,   27,   28,   20,  174,  175,   24,  132,
+ /*  1190 */   133,  134,  135,  136,   38,   44,  174,  175,  107,   61,
+ /*  1200 */    54,   26,  132,  133,  134,  135,  136,   54,  107,   22,
+ /*  1210 */     5,  140,    1,   57,   36,  111,  122,   28,   79,   79,
+ /*  1220 */   131,  123,   66,   19,   20,   69,   22,    1,   16,   20,
+ /*  1230 */   125,   27,   28,  123,  111,  120,   23,  131,   23,   16,
+ /*  1240 */    68,  142,   38,   15,   22,   89,   90,    3,  167,    4,
+ /*  1250 */   248,  251,   96,   97,   98,  180,  180,  101,  251,  151,
+ /*  1260 */     6,   57,  151,   13,  151,   26,   25,  151,  161,  202,
+ /*  1270 */   153,  162,  153,   69,  130,  128,  203,   19,   20,  127,
+ /*  1280 */    22,  126,  204,  129,   22,   27,   28,  205,  132,  133,
+ /*  1290 */   134,  135,  136,   89,   90,  231,   38,   95,  137,  179,
+ /*  1300 */    96,   97,   98,  206,  179,  101,  122,  107,  159,  159,
+ /*  1310 */   125,  231,  216,  228,  107,   57,  184,  217,  216,  176,
+ /*  1320 */   217,  176,   48,  106,   18,  184,  158,   69,  159,  158,
+ /*  1330 */    46,   71,  237,  176,  176,  176,  132,  133,  134,  135,
+ /*  1340 */   136,  217,  176,  137,  216,  178,  158,   89,   90,  179,
+ /*  1350 */   176,  159,  179,  159,   96,   97,   98,  159,  159,  101,
+ /*  1360 */     5,  158,  202,   22,   18,   10,   11,   12,   13,   14,
+ /*  1370 */   190,  238,   17,  190,  158,  193,   41,  159,  202,  193,
+ /*  1380 */   159,  202,  245,  193,  193,  223,  190,   32,  159,   34,
+ /*  1390 */   132,  133,  134,  135,  136,  159,   39,  155,   43,  150,
+ /*  1400 */   223,  177,  201,  178,  177,  186,   66,  199,  177,  152,
+ /*  1410 */   253,   56,  215,  152,  182,  152,  202,  152,   63,  152,
+ /*  1420 */   152,   66,   67,  242,  229,  152,  174,  152,  152,  152,
+ /*  1430 */   152,  152,  152,  152,  199,  242,  202,  152,  198,  152,
+ /*  1440 */   152,  152,  183,  192,  152,  215,  152,  183,  215,  183,
+ /*  1450 */   152,  241,  214,  152,  211,  152,  152,  211,  211,  152,
+ /*  1460 */   152,  241,  152,  152,  152,  152,  152,  152,  152,  114,
+ /*  1470 */   152,  152,  235,  152,  152,  152,  174,  187,   95,  174,
+ /*  1480 */   253,  253,  253,  253,  236,  253,  253,  253,  253,  253,
+ /*  1490 */   253,  253,  253,  253,  253,  253,  141,
 };
-#define YY_SHIFT_USE_DFLT (-70)
-#define YY_SHIFT_COUNT (416)
-#define YY_SHIFT_MIN   (-69)
-#define YY_SHIFT_MAX   (1487)
+#define YY_SHIFT_USE_DFLT (-86)
+#define YY_SHIFT_COUNT (429)
+#define YY_SHIFT_MIN   (-85)
+#define YY_SHIFT_MAX   (1383)
 static const short yy_shift_ofst[] = {
- /*     0 */  1143, 1188, 1417, 1188, 1287, 1287,  138,  138,   -2,  -19,
- /*    10 */  1287, 1287, 1287, 1287,  347,  362,  129,  129,  795, 1165,
- /*    20 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
- /*    30 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
- /*    40 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1310, 1287,
- /*    50 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
- /*    60 */  1287, 1287,  286,  362,  362,  538,  538,  231, 1253,   55,
- /*    70 */   721,  647,  573,  499,  425,  351,  277,  203,  869,  869,
- /*    80 */   869,  869,  869,  869,  869,  869,  869,  869,  869,  869,
- /*    90 */   869,  869,  869,  943,  869, 1017, 1091, 1091,  -69,  -45,
- /*   100 */   -45,  -45,  -45,  -45,   -1,   24,  245,  362,  362,  362,
- /*   110 */   362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
- /*   120 */   362,  362,  362,  388,  356,  362,  362,  362,  362,  362,
- /*   130 */   732,  868,  231, 1051, 1458,  -70,  -70,  -70, 1367,   57,
- /*   140 */   434,  434,  289,  291,  285,    1,  204,  572,  539,  362,
- /*   150 */   362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
- /*   160 */   362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
- /*   170 */   362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
- /*   180 */   362,  506,  506,  506,  705, 1253, 1253, 1253,  -70,  -70,
- /*   190 */   -70,  171,  171,  160,  502,  502,  502,  446,  432,  511,
- /*   200 */   422,  358,  335,  -12,  -12,  -12,  -12,  576,  294,  -12,
- /*   210 */   -12,  295,  595,  141,  600,  730,  723,  723,  805,  730,
- /*   220 */   805,  439,  911,  231,  865,  231,  865,  807,  865,  723,
- /*   230 */   766,  633,  633,  231,  284,   63,  608, 1476, 1308, 1308,
- /*   240 */  1472, 1472, 1308, 1477, 1425, 1275, 1487, 1487, 1487, 1487,
- /*   250 */  1308, 1461, 1275, 1477, 1425, 1425, 1308, 1461, 1355, 1441,
- /*   260 */  1308, 1308, 1461, 1308, 1461, 1308, 1461, 1442, 1348, 1348,
- /*   270 */  1348, 1408, 1375, 1375, 1442, 1348, 1357, 1348, 1408, 1348,
- /*   280 */  1348, 1316, 1331, 1316, 1331, 1316, 1331, 1308, 1308, 1280,
- /*   290 */  1288, 1289, 1285, 1279, 1275, 1253, 1336, 1346, 1346, 1338,
- /*   300 */  1338, 1338, 1338,  -70,  -70,  -70,  -70,  -70,  -70, 1013,
- /*   310 */   467,  612,   84,  179,  -28,  870,  410,  761,  760,  667,
- /*   320 */   650,  531,  220,  361,  331,  125,  127,   97, 1306, 1300,
- /*   330 */  1270, 1151, 1272, 1203, 1232, 1261, 1244, 1148, 1174, 1139,
- /*   340 */  1156, 1124, 1220, 1115, 1210, 1233, 1099, 1193, 1184, 1174,
- /*   350 */  1173, 1029, 1121, 1120, 1085, 1162, 1119, 1037, 1152, 1147,
- /*   360 */  1129, 1046, 1011, 1093, 1098, 1075, 1061, 1032,  960, 1057,
- /*   370 */  1031, 1030,  899,  938,  982,  936,  972,  958,  910,  955,
- /*   380 */   875,  885,  908,  857,  859,  867,  804,  590,  834,  747,
- /*   390 */   818,  513,  611,  741,  673,  637,  611,  606,  603,  579,
- /*   400 */   501,  541,  468,  386,  445,  395,  376,  281,  185,  120,
- /*   410 */    92,   75,   45,  114,   25,   11,    5,
+ /*     0 */   992, 1057, 1355, 1156, 1204, 1204,    1,  262,  -19,  135,
+ /*    10 */   135,  776, 1204, 1204, 1204, 1204,   69,   69,   53,  208,
+ /*    20 */   283,  755,   58,  725,  648,  571,  494,  417,  340,  263,
+ /*    30 */   212,  827,  827,  827,  827,  827,  827,  827,  827,  827,
+ /*    40 */   827,  827,  827,  827,  827,  827,  878,  827,  929,  980,
+ /*    50 */   980, 1070, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
+ /*    60 */  1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
+ /*    70 */  1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
+ /*    80 */  1258, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
+ /*    90 */  1204, 1204, 1204, 1204,  -71,  -47,  -47,  -47,  -47,  -47,
+ /*   100 */     0,   29,  -12,  283,  283,  139,   91,  392,  392,  894,
+ /*   110 */   672,  726, 1383,  -86,  -86,  -86,   88,  318,  318,   99,
+ /*   120 */   381,  -20,  283,  283,  283,  283,  283,  283,  283,  283,
+ /*   130 */   283,  283,  283,  283,  283,  283,  283,  283,  283,  283,
+ /*   140 */   283,  283,  283,  283,  624,  876,  726,  672, 1340, 1340,
+ /*   150 */  1340, 1340, 1340, 1340,  -86,  -86,  -86,  305,  136,  136,
+ /*   160 */   142,  167,  226,  154,  137,  152,  283,  283,  283,  283,
+ /*   170 */   283,  283,  283,  283,  283,  283,  283,  283,  283,  283,
+ /*   180 */   283,  283,  283,  336,  336,  336,  283,  283,  352,  283,
+ /*   190 */   283,  283,  283,  283,  228,  283,  283,  283,  283,  283,
+ /*   200 */   283,  283,  283,  283,  283,  501,  569,  596,  596,  596,
+ /*   210 */   507,  497,  441,  391,  353,  156,  156,  857,  353,  857,
+ /*   220 */   735,  813,  639,  715,  156,  332,  715,  715,  496,  419,
+ /*   230 */   646, 1357, 1184, 1184, 1335, 1335, 1184, 1341, 1260, 1144,
+ /*   240 */  1346, 1346, 1346, 1346, 1184, 1306, 1144, 1341, 1260, 1260,
+ /*   250 */  1144, 1184, 1306, 1206, 1284, 1184, 1184, 1306, 1184, 1306,
+ /*   260 */  1184, 1306, 1262, 1207, 1207, 1207, 1274, 1262, 1207, 1217,
+ /*   270 */  1207, 1274, 1207, 1207, 1185, 1200, 1185, 1200, 1185, 1200,
+ /*   280 */  1184, 1184, 1161, 1262, 1202, 1202, 1262, 1154, 1155, 1147,
+ /*   290 */  1152, 1144, 1241, 1239, 1250, 1250, 1254, 1254, 1254, 1254,
+ /*   300 */   -86,  -86,  -86,  -86,  -86,  -86, 1068,  304,  526,  249,
+ /*   310 */   408,  -83,  434,  812,   27,  811,  807,  802,  751,  589,
+ /*   320 */   651,  163,  131,  674,  366,  450,  299,  148,   23,  102,
+ /*   330 */   229,  -21, 1245, 1244, 1222, 1099, 1228, 1172, 1223, 1215,
+ /*   340 */  1213, 1115, 1106, 1123, 1110, 1209, 1105, 1212, 1226, 1098,
+ /*   350 */  1089, 1140, 1139, 1104, 1189, 1178, 1094, 1211, 1205, 1187,
+ /*   360 */  1101, 1071, 1153, 1175, 1146, 1138, 1151, 1091, 1164, 1165,
+ /*   370 */  1163, 1069, 1072, 1148, 1112, 1134, 1127, 1129, 1126, 1092,
+ /*   380 */  1114, 1118, 1088, 1090, 1093, 1087, 1084,  987, 1079, 1077,
+ /*   390 */  1074, 1065,  924, 1021, 1014, 1004, 1006,  819,  739,  896,
+ /*   400 */   855,  804,  739,  740,  736,  690,  654,  665,  618,  582,
+ /*   410 */   568,  528,  554,  379,  532,  479,  455,  379,  432,  371,
+ /*   420 */   341,   28,  338,  116,  -11,  -57,  -85,    7,   -8,    3,
 };
-#define YY_REDUCE_USE_DFLT (-169)
-#define YY_REDUCE_COUNT (308)
-#define YY_REDUCE_MIN   (-168)
-#define YY_REDUCE_MAX   (1391)
+#define YY_REDUCE_USE_DFLT (-110)
+#define YY_REDUCE_COUNT (305)
+#define YY_REDUCE_MIN   (-109)
+#define YY_REDUCE_MAX   (1323)
 static const short yy_reduce_ofst[] = {
- /*     0 */  -141,   90, 1095,  222,  158,  156,   19,   17,   10, -104,
- /*    10 */   378,  316,  311,   12,  180,  249,  598,  464,  397, 1181,
- /*    20 */  1177, 1175, 1128, 1106, 1096, 1054, 1038,  974,  964,  962,
- /*    30 */   948,  905,  903,  900,  887,  874,  832,  826,  816,  813,
- /*    40 */   800,  758,  755,  752,  742,  739,  726,  685,  681,  668,
- /*    50 */   665,  652,  607,  604,  594,  591,  578,  530,  528,  526,
- /*    60 */   385,   18,  477,  466,  519,  444,  350,  435,  405,  488,
- /*    70 */   488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
- /*    80 */   488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
- /*    90 */   488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
- /*   100 */   488,  488,  488,  488,  488,  488,  488, 1040,  678, 1036,
- /*   110 */  1007,  967,  966,  965,  845,  686,  610,  684,  317,  672,
- /*   120 */   893,  327,  623,  522,   -7,  820,  814,  157,  154,  101,
- /*   130 */   702,  494,  580,  488,  488,  488,  488,  488,  614,  586,
- /*   140 */   935,  892,  968, 1245, 1242, 1234, 1225,  798,  798, 1222,
- /*   150 */  1221, 1218, 1214, 1213, 1212, 1202, 1195, 1191, 1161, 1158,
- /*   160 */  1140, 1135, 1123, 1112, 1107, 1100, 1080, 1074, 1073, 1072,
- /*   170 */  1070, 1067, 1048, 1044,  969,  968,  907,  906,  904,  894,
- /*   180 */   833,  837,  836,  340,  827,  815,  775,   68,  722,  646,
- /*   190 */  -168, 1384, 1380, 1377, 1379, 1376, 1373, 1339, 1365, 1368,
- /*   200 */  1365, 1365, 1365, 1365, 1365, 1365, 1365, 1320, 1319, 1365,
- /*   210 */  1365, 1339, 1378, 1349, 1391, 1350, 1342, 1334, 1307, 1341,
- /*   220 */  1293, 1364, 1363, 1371, 1362, 1370, 1359, 1340, 1354, 1333,
- /*   230 */  1305, 1304, 1299, 1361, 1328, 1324, 1366, 1282, 1360, 1358,
- /*   240 */  1278, 1276, 1356, 1292, 1322, 1309, 1317, 1315, 1314, 1312,
- /*   250 */  1345, 1347, 1302, 1277, 1311, 1303, 1337, 1335, 1252, 1248,
- /*   260 */  1332, 1330, 1329, 1327, 1326, 1323, 1321, 1297, 1301, 1295,
- /*   270 */  1294, 1290, 1243, 1240, 1284, 1291, 1286, 1283, 1274, 1281,
- /*   280 */  1271, 1238, 1241, 1236, 1235, 1227, 1226, 1267, 1266, 1189,
- /*   290 */  1229, 1223, 1211, 1206, 1201, 1197, 1239, 1237, 1219, 1216,
- /*   300 */  1209, 1208, 1185, 1089, 1086, 1087, 1137, 1136, 1164,
+ /*     0 */   238,  954,  213,  289,  310,  234,  144,  317, -109,  382,
+ /*    10 */   377,  303,  461,  389,  378,  368,  302,  294,  253,  395,
+ /*    20 */   293,  324,  403,  403,  403,  403,  403,  403,  403,  403,
+ /*    30 */   403,  403,  403,  403,  403,  403,  403,  403,  403,  403,
+ /*    40 */   403,  403,  403,  403,  403,  403,  403,  403,  403,  403,
+ /*    50 */   403, 1022, 1012, 1005,  998,  963,  961,  959,  957,  950,
+ /*    60 */   947,  930,  912,  873,  861,  823,  810,  771,  759,  720,
+ /*    70 */   708,  670,  657,  619,  614,  612,  610,  608,  606,  604,
+ /*    80 */   598,  595,  593,  580,  542,  540,  537,  535,  533,  531,
+ /*    90 */   529,  527,  503,  386,  403,  403,  403,  403,  403,  403,
+ /*   100 */   403,  403,  403,   95,  447,   82,  334,  504,  467,  403,
+ /*   110 */   477,  464,  403,  403,  403,  403,  860,  747,  744,  785,
+ /*   120 */   638,  638,  926,  891,  900,  899,  887,  844,  840,  835,
+ /*   130 */   848,  830,  843,  829,  792,  839,  826,  737,  838,  795,
+ /*   140 */   789,   47,  734,  530,  696,  777,  711,  677,  733,  730,
+ /*   150 */   729,  728,  727,  627,  448,   64,  187, 1305, 1302, 1252,
+ /*   160 */  1290, 1273, 1323, 1322, 1321, 1319, 1318, 1316, 1315, 1314,
+ /*   170 */  1313, 1312, 1311, 1310, 1308, 1307, 1304, 1303, 1301, 1298,
+ /*   180 */  1294, 1292, 1289, 1266, 1264, 1259, 1288, 1287, 1238, 1285,
+ /*   190 */  1281, 1280, 1279, 1278, 1251, 1277, 1276, 1275, 1273, 1268,
+ /*   200 */  1267, 1265, 1263, 1261, 1257, 1248, 1237, 1247, 1246, 1243,
+ /*   210 */  1238, 1240, 1235, 1249, 1234, 1233, 1230, 1220, 1214, 1210,
+ /*   220 */  1225, 1219, 1232, 1231, 1197, 1195, 1227, 1224, 1201, 1208,
+ /*   230 */  1242, 1137, 1236, 1229, 1193, 1181, 1221, 1177, 1196, 1179,
+ /*   240 */  1191, 1190, 1186, 1182, 1218, 1216, 1176, 1162, 1183, 1180,
+ /*   250 */  1160, 1199, 1203, 1133, 1095, 1198, 1194, 1188, 1192, 1171,
+ /*   260 */  1169, 1168, 1173, 1174, 1166, 1159, 1141, 1170, 1158, 1167,
+ /*   270 */  1157, 1132, 1145, 1143, 1124, 1128, 1103, 1102, 1100, 1096,
+ /*   280 */  1150, 1149, 1085, 1125, 1080, 1064, 1120, 1097, 1082, 1078,
+ /*   290 */  1073, 1067, 1109, 1107, 1119, 1117, 1116, 1113, 1111, 1108,
+ /*   300 */  1007, 1000, 1002, 1076, 1075, 1081,
 };
 static const YYACTIONTYPE yy_default[] = {
- /*     0 */   632,  866,  954,  954,  866,  866,  954,  954,  954,  756,
- /*    10 */   954,  954,  954,  864,  954,  954,  784,  784,  928,  954,
- /*    20 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*    30 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*    40 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*    50 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*    60 */   954,  954,  954,  954,  954,  954,  954,  671,  760,  790,
- /*    70 */   954,  954,  954,  954,  954,  954,  954,  954,  927,  929,
- /*    80 */   798,  797,  907,  771,  795,  788,  792,  867,  860,  861,
- /*    90 */   859,  863,  868,  954,  791,  827,  844,  826,  838,  843,
- /*   100 */   850,  842,  839,  829,  828,  830,  831,  954,  954,  954,
- /*   110 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*   120 */   954,  954,  954,  658,  725,  954,  954,  954,  954,  954,
- /*   130 */   954,  954,  954,  832,  833,  847,  846,  845,  954,  663,
- /*   140 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*   150 */   934,  932,  954,  879,  954,  954,  954,  954,  954,  954,
- /*   160 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*   170 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*   180 */   638,  756,  756,  756,  632,  954,  954,  954,  946,  760,
- /*   190 */   750,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*   200 */   954,  954,  954,  800,  739,  917,  919,  954,  900,  737,
- /*   210 */   660,  758,  673,  748,  640,  794,  773,  773,  912,  794,
- /*   220 */   912,  696,  719,  954,  784,  954,  784,  693,  784,  773,
- /*   230 */   862,  954,  954,  954,  757,  748,  954,  939,  764,  764,
- /*   240 */   931,  931,  764,  806,  729,  794,  736,  736,  736,  736,
- /*   250 */   764,  655,  794,  806,  729,  729,  764,  655,  906,  904,
- /*   260 */   764,  764,  655,  764,  655,  764,  655,  872,  727,  727,
- /*   270 */   727,  711,  876,  876,  872,  727,  696,  727,  711,  727,
- /*   280 */   727,  777,  772,  777,  772,  777,  772,  764,  764,  954,
- /*   290 */   789,  778,  787,  785,  794,  954,  714,  648,  648,  637,
- /*   300 */   637,  637,  637,  951,  951,  946,  698,  698,  681,  954,
- /*   310 */   954,  954,  954,  954,  954,  954,  881,  954,  954,  954,
- /*   320 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  633,
- /*   330 */   941,  954,  954,  938,  954,  954,  954,  954,  799,  954,
- /*   340 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  916,
- /*   350 */   954,  954,  954,  954,  954,  954,  954,  910,  954,  954,
- /*   360 */   954,  954,  954,  954,  903,  902,  954,  954,  954,  954,
- /*   370 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*   380 */   954,  954,  954,  954,  954,  954,  954,  954,  954,  954,
- /*   390 */   954,  954,  786,  954,  779,  954,  865,  954,  954,  954,
- /*   400 */   954,  954,  954,  954,  954,  954,  954,  742,  815,  954,
- /*   410 */   814,  818,  813,  665,  954,  646,  954,  629,  634,  950,
- /*   420 */   953,  952,  949,  948,  947,  942,  940,  937,  936,  935,
- /*   430 */   933,  930,  926,  885,  883,  890,  889,  888,  887,  886,
- /*   440 */   884,  882,  880,  801,  796,  793,  925,  878,  738,  735,
- /*   450 */   734,  654,  943,  909,  918,  805,  804,  807,  915,  914,
- /*   460 */   913,  911,  908,  895,  803,  802,  730,  870,  869,  657,
- /*   470 */   899,  898,  897,  901,  905,  896,  766,  656,  653,  662,
- /*   480 */   717,  718,  726,  724,  723,  722,  721,  720,  716,  664,
- /*   490 */   672,  710,  695,  694,  875,  877,  874,  873,  703,  702,
- /*   500 */   708,  707,  706,  705,  704,  701,  700,  699,  692,  691,
- /*   510 */   697,  690,  713,  712,  709,  689,  733,  732,  731,  728,
- /*   520 */   688,  687,  686,  818,  685,  684,  824,  823,  811,  854,
- /*   530 */   753,  752,  751,  763,  762,  775,  774,  809,  808,  776,
- /*   540 */   761,  755,  754,  770,  769,  768,  767,  759,  749,  781,
- /*   550 */   783,  782,  780,  856,  765,  853,  924,  923,  922,  921,
- /*   560 */   920,  858,  857,  825,  822,  676,  677,  893,  892,  894,
- /*   570 */   891,  679,  678,  675,  674,  855,  744,  743,  851,  848,
- /*   580 */   840,  836,  852,  849,  841,  837,  835,  834,  820,  819,
- /*   590 */   817,  816,  812,  821,  667,  745,  741,  740,  810,  747,
- /*   600 */   746,  683,  682,  680,  661,  659,  652,  650,  649,  651,
- /*   610 */   647,  645,  644,  643,  642,  641,  670,  669,  668,  666,
- /*   620 */   665,  639,  636,  635,  631,  630,  628,
+ /*     0 */   647,  964,  964,  964,  878,  878,  969,  964,  774,  802,
+ /*    10 */   802,  938,  969,  969,  969,  876,  969,  969,  969,  964,
+ /*    20 */   969,  778,  808,  969,  969,  969,  969,  969,  969,  969,
+ /*    30 */   969,  937,  939,  816,  815,  918,  789,  813,  806,  810,
+ /*    40 */   879,  872,  873,  871,  875,  880,  969,  809,  841,  856,
+ /*    50 */   840,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*    60 */   969,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*    70 */   969,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*    80 */   969,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*    90 */   969,  969,  969,  969,  850,  855,  862,  854,  851,  843,
+ /*   100 */   842,  844,  845,  969,  969,  673,  739,  969,  969,  846,
+ /*   110 */   969,  685,  847,  859,  858,  857,  680,  969,  969,  969,
+ /*   120 */   969,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*   130 */   969,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*   140 */   969,  969,  969,  969,  647,  964,  969,  969,  964,  964,
+ /*   150 */   964,  964,  964,  964,  956,  778,  768,  969,  969,  969,
+ /*   160 */   969,  969,  969,  969,  969,  969,  969,  944,  942,  969,
+ /*   170 */   891,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*   180 */   969,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*   190 */   969,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*   200 */   969,  969,  969,  969,  653,  969,  911,  774,  774,  774,
+ /*   210 */   776,  754,  766,  655,  812,  791,  791,  923,  812,  923,
+ /*   220 */   710,  733,  707,  802,  791,  874,  802,  802,  775,  766,
+ /*   230 */   969,  949,  782,  782,  941,  941,  782,  821,  743,  812,
+ /*   240 */   750,  750,  750,  750,  782,  670,  812,  821,  743,  743,
+ /*   250 */   812,  782,  670,  917,  915,  782,  782,  670,  782,  670,
+ /*   260 */   782,  670,  884,  741,  741,  741,  725,  884,  741,  710,
+ /*   270 */   741,  725,  741,  741,  795,  790,  795,  790,  795,  790,
+ /*   280 */   782,  782,  969,  884,  888,  888,  884,  807,  796,  805,
+ /*   290 */   803,  812,  676,  728,  663,  663,  652,  652,  652,  652,
+ /*   300 */   961,  961,  956,  712,  712,  695,  969,  969,  969,  969,
+ /*   310 */   969,  969,  687,  969,  893,  969,  969,  969,  969,  969,
+ /*   320 */   969,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*   330 */   969,  828,  969,  648,  951,  969,  969,  948,  969,  969,
+ /*   340 */   969,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*   350 */   969,  969,  969,  969,  969,  969,  921,  969,  969,  969,
+ /*   360 */   969,  969,  969,  914,  913,  969,  969,  969,  969,  969,
+ /*   370 */   969,  969,  969,  969,  969,  969,  969,  969,  969,  969,
+ /*   380 */   969,  969,  969,  969,  969,  969,  969,  757,  969,  969,
+ /*   390 */   969,  761,  969,  969,  969,  969,  969,  969,  804,  969,
+ /*   400 */   797,  969,  877,  969,  969,  969,  969,  969,  969,  969,
+ /*   410 */   969,  969,  969,  966,  969,  969,  969,  965,  969,  969,
+ /*   420 */   969,  969,  969,  830,  969,  829,  833,  969,  661,  969,
+ /*   430 */   644,  649,  960,  963,  962,  959,  958,  957,  952,  950,
+ /*   440 */   947,  946,  945,  943,  940,  936,  897,  895,  902,  901,
+ /*   450 */   900,  899,  898,  896,  894,  892,  818,  817,  814,  811,
+ /*   460 */   753,  935,  890,  752,  749,  748,  669,  953,  920,  929,
+ /*   470 */   928,  927,  822,  926,  925,  924,  922,  919,  906,  820,
+ /*   480 */   819,  744,  882,  881,  672,  910,  909,  908,  912,  916,
+ /*   490 */   907,  784,  751,  671,  668,  675,  679,  731,  732,  740,
+ /*   500 */   738,  737,  736,  735,  734,  730,  681,  686,  724,  709,
+ /*   510 */   708,  717,  716,  722,  721,  720,  719,  718,  715,  714,
+ /*   520 */   713,  706,  705,  711,  704,  727,  726,  723,  703,  747,
+ /*   530 */   746,  745,  742,  702,  701,  700,  833,  699,  698,  838,
+ /*   540 */   837,  866,  826,  755,  759,  758,  762,  763,  771,  770,
+ /*   550 */   769,  780,  781,  793,  792,  824,  823,  794,  779,  773,
+ /*   560 */   772,  788,  787,  786,  785,  777,  767,  799,  798,  868,
+ /*   570 */   783,  867,  865,  934,  933,  932,  931,  930,  870,  967,
+ /*   580 */   968,  887,  889,  886,  801,  800,  885,  869,  839,  836,
+ /*   590 */   690,  691,  905,  904,  903,  693,  692,  689,  688,  863,
+ /*   600 */   860,  852,  864,  861,  853,  849,  848,  834,  832,  831,
+ /*   610 */   827,  835,  760,  756,  825,  765,  764,  697,  696,  694,
+ /*   620 */   678,  677,  674,  667,  665,  664,  666,  662,  660,  659,
+ /*   630 */   658,  657,  656,  684,  683,  682,  654,  651,  650,  646,
+ /*   640 */   645,  643,
 };
 
 /* The next table maps tokens into fallback tokens.  If a construct
@@ -110895,71 +118203,74 @@ static const YYACTIONTYPE yy_default[] = {
 static const YYCODETYPE yyFallback[] = {
     0,  /*          $ => nothing */
     0,  /*       SEMI => nothing */
-   26,  /*    EXPLAIN => ID */
-   26,  /*      QUERY => ID */
-   26,  /*       PLAN => ID */
-   26,  /*      BEGIN => ID */
+   27,  /*    EXPLAIN => ID */
+   27,  /*      QUERY => ID */
+   27,  /*       PLAN => ID */
+   27,  /*      BEGIN => ID */
     0,  /* TRANSACTION => nothing */
-   26,  /*   DEFERRED => ID */
-   26,  /*  IMMEDIATE => ID */
-   26,  /*  EXCLUSIVE => ID */
+   27,  /*   DEFERRED => ID */
+   27,  /*  IMMEDIATE => ID */
+   27,  /*  EXCLUSIVE => ID */
     0,  /*     COMMIT => nothing */
-   26,  /*        END => ID */
-   26,  /*   ROLLBACK => ID */
-   26,  /*  SAVEPOINT => ID */
-   26,  /*    RELEASE => ID */
+   27,  /*        END => ID */
+   27,  /*   ROLLBACK => ID */
+   27,  /*  SAVEPOINT => ID */
+   27,  /*    RELEASE => ID */
     0,  /*         TO => nothing */
     0,  /*      TABLE => nothing */
     0,  /*     CREATE => nothing */
-   26,  /*         IF => ID */
+   27,  /*         IF => ID */
     0,  /*        NOT => nothing */
     0,  /*     EXISTS => nothing */
-   26,  /*       TEMP => ID */
+   27,  /*       TEMP => ID */
     0,  /*         LP => nothing */
     0,  /*         RP => nothing */
     0,  /*         AS => nothing */
+   27,  /*    WITHOUT => ID */
     0,  /*      COMMA => nothing */
     0,  /*         ID => nothing */
     0,  /*    INDEXED => nothing */
-   26,  /*      ABORT => ID */
-   26,  /*     ACTION => ID */
-   26,  /*      AFTER => ID */
-   26,  /*    ANALYZE => ID */
-   26,  /*        ASC => ID */
-   26,  /*     ATTACH => ID */
-   26,  /*     BEFORE => ID */
-   26,  /*         BY => ID */
-   26,  /*    CASCADE => ID */
-   26,  /*       CAST => ID */
-   26,  /*   COLUMNKW => ID */
-   26,  /*   CONFLICT => ID */
-   26,  /*   DATABASE => ID */
-   26,  /*       DESC => ID */
-   26,  /*     DETACH => ID */
-   26,  /*       EACH => ID */
-   26,  /*       FAIL => ID */
-   26,  /*        FOR => ID */
-   26,  /*     IGNORE => ID */
-   26,  /*  INITIALLY => ID */
-   26,  /*    INSTEAD => ID */
-   26,  /*    LIKE_KW => ID */
-   26,  /*      MATCH => ID */
-   26,  /*         NO => ID */
-   26,  /*        KEY => ID */
-   26,  /*         OF => ID */
-   26,  /*     OFFSET => ID */
-   26,  /*     PRAGMA => ID */
-   26,  /*      RAISE => ID */
-   26,  /*    REPLACE => ID */
-   26,  /*   RESTRICT => ID */
-   26,  /*        ROW => ID */
-   26,  /*    TRIGGER => ID */
-   26,  /*     VACUUM => ID */
-   26,  /*       VIEW => ID */
-   26,  /*    VIRTUAL => ID */
-   26,  /*    REINDEX => ID */
-   26,  /*     RENAME => ID */
-   26,  /*   CTIME_KW => ID */
+   27,  /*      ABORT => ID */
+   27,  /*     ACTION => ID */
+   27,  /*      AFTER => ID */
+   27,  /*    ANALYZE => ID */
+   27,  /*        ASC => ID */
+   27,  /*     ATTACH => ID */
+   27,  /*     BEFORE => ID */
+   27,  /*         BY => ID */
+   27,  /*    CASCADE => ID */
+   27,  /*       CAST => ID */
+   27,  /*   COLUMNKW => ID */
+   27,  /*   CONFLICT => ID */
+   27,  /*   DATABASE => ID */
+   27,  /*       DESC => ID */
+   27,  /*     DETACH => ID */
+   27,  /*       EACH => ID */
+   27,  /*       FAIL => ID */
+   27,  /*        FOR => ID */
+   27,  /*     IGNORE => ID */
+   27,  /*  INITIALLY => ID */
+   27,  /*    INSTEAD => ID */
+   27,  /*    LIKE_KW => ID */
+   27,  /*      MATCH => ID */
+   27,  /*         NO => ID */
+   27,  /*        KEY => ID */
+   27,  /*         OF => ID */
+   27,  /*     OFFSET => ID */
+   27,  /*     PRAGMA => ID */
+   27,  /*      RAISE => ID */
+   27,  /*  RECURSIVE => ID */
+   27,  /*    REPLACE => ID */
+   27,  /*   RESTRICT => ID */
+   27,  /*        ROW => ID */
+   27,  /*    TRIGGER => ID */
+   27,  /*     VACUUM => ID */
+   27,  /*       VIEW => ID */
+   27,  /*    VIRTUAL => ID */
+   27,  /*       WITH => ID */
+   27,  /*    REINDEX => ID */
+   27,  /*     RENAME => ID */
+   27,  /*   CTIME_KW => ID */
 };
 #endif /* YYFALLBACK */
 
@@ -111044,63 +118355,64 @@ static const char *const yyTokenName[] = {
   "ROLLBACK",      "SAVEPOINT",     "RELEASE",       "TO",          
   "TABLE",         "CREATE",        "IF",            "NOT",         
   "EXISTS",        "TEMP",          "LP",            "RP",          
-  "AS",            "COMMA",         "ID",            "INDEXED",     
-  "ABORT",         "ACTION",        "AFTER",         "ANALYZE",     
-  "ASC",           "ATTACH",        "BEFORE",        "BY",          
-  "CASCADE",       "CAST",          "COLUMNKW",      "CONFLICT",    
-  "DATABASE",      "DESC",          "DETACH",        "EACH",        
-  "FAIL",          "FOR",           "IGNORE",        "INITIALLY",   
-  "INSTEAD",       "LIKE_KW",       "MATCH",         "NO",          
-  "KEY",           "OF",            "OFFSET",        "PRAGMA",      
-  "RAISE",         "REPLACE",       "RESTRICT",      "ROW",         
-  "TRIGGER",       "VACUUM",        "VIEW",          "VIRTUAL",     
-  "REINDEX",       "RENAME",        "CTIME_KW",      "ANY",         
-  "OR",            "AND",           "IS",            "BETWEEN",     
-  "IN",            "ISNULL",        "NOTNULL",       "NE",          
-  "EQ",            "GT",            "LE",            "LT",          
-  "GE",            "ESCAPE",        "BITAND",        "BITOR",       
-  "LSHIFT",        "RSHIFT",        "PLUS",          "MINUS",       
-  "STAR",          "SLASH",         "REM",           "CONCAT",      
-  "COLLATE",       "BITNOT",        "STRING",        "JOIN_KW",     
-  "CONSTRAINT",    "DEFAULT",       "NULL",          "PRIMARY",     
-  "UNIQUE",        "CHECK",         "REFERENCES",    "AUTOINCR",    
-  "ON",            "INSERT",        "DELETE",        "UPDATE",      
-  "SET",           "DEFERRABLE",    "FOREIGN",       "DROP",        
-  "UNION",         "ALL",           "EXCEPT",        "INTERSECT",   
-  "SELECT",        "DISTINCT",      "DOT",           "FROM",        
+  "AS",            "WITHOUT",       "COMMA",         "ID",          
+  "INDEXED",       "ABORT",         "ACTION",        "AFTER",       
+  "ANALYZE",       "ASC",           "ATTACH",        "BEFORE",      
+  "BY",            "CASCADE",       "CAST",          "COLUMNKW",    
+  "CONFLICT",      "DATABASE",      "DESC",          "DETACH",      
+  "EACH",          "FAIL",          "FOR",           "IGNORE",      
+  "INITIALLY",     "INSTEAD",       "LIKE_KW",       "MATCH",       
+  "NO",            "KEY",           "OF",            "OFFSET",      
+  "PRAGMA",        "RAISE",         "RECURSIVE",     "REPLACE",     
+  "RESTRICT",      "ROW",           "TRIGGER",       "VACUUM",      
+  "VIEW",          "VIRTUAL",       "WITH",          "REINDEX",     
+  "RENAME",        "CTIME_KW",      "ANY",           "OR",          
+  "AND",           "IS",            "BETWEEN",       "IN",          
+  "ISNULL",        "NOTNULL",       "NE",            "EQ",          
+  "GT",            "LE",            "LT",            "GE",          
+  "ESCAPE",        "BITAND",        "BITOR",         "LSHIFT",      
+  "RSHIFT",        "PLUS",          "MINUS",         "STAR",        
+  "SLASH",         "REM",           "CONCAT",        "COLLATE",     
+  "BITNOT",        "STRING",        "JOIN_KW",       "CONSTRAINT",  
+  "DEFAULT",       "NULL",          "PRIMARY",       "UNIQUE",      
+  "CHECK",         "REFERENCES",    "AUTOINCR",      "ON",          
+  "INSERT",        "DELETE",        "UPDATE",        "SET",         
+  "DEFERRABLE",    "FOREIGN",       "DROP",          "UNION",       
+  "ALL",           "EXCEPT",        "INTERSECT",     "SELECT",      
+  "VALUES",        "DISTINCT",      "DOT",           "FROM",        
   "JOIN",          "USING",         "ORDER",         "GROUP",       
   "HAVING",        "LIMIT",         "WHERE",         "INTO",        
-  "VALUES",        "INTEGER",       "FLOAT",         "BLOB",        
-  "REGISTER",      "VARIABLE",      "CASE",          "WHEN",        
-  "THEN",          "ELSE",          "INDEX",         "ALTER",       
-  "ADD",           "error",         "input",         "cmdlist",     
-  "ecmd",          "explain",       "cmdx",          "cmd",         
-  "transtype",     "trans_opt",     "nm",            "savepoint_opt",
-  "create_table",  "create_table_args",  "createkw",      "temp",        
-  "ifnotexists",   "dbnm",          "columnlist",    "conslist_opt",
-  "select",        "column",        "columnid",      "type",        
-  "carglist",      "id",            "ids",           "typetoken",   
-  "typename",      "signed",        "plus_num",      "minus_num",   
-  "ccons",         "term",          "expr",          "onconf",      
-  "sortorder",     "autoinc",       "idxlist_opt",   "refargs",     
-  "defer_subclause",  "refarg",        "refact",        "init_deferred_pred_opt",
-  "conslist",      "tconscomma",    "tcons",         "idxlist",     
-  "defer_subclause_opt",  "orconf",        "resolvetype",   "raisetype",   
-  "ifexists",      "fullname",      "oneselect",     "multiselect_op",
-  "distinct",      "selcollist",    "from",          "where_opt",   
-  "groupby_opt",   "having_opt",    "orderby_opt",   "limit_opt",   
-  "sclp",          "as",            "seltablist",    "stl_prefix",  
-  "joinop",        "indexed_opt",   "on_opt",        "using_opt",   
-  "joinop2",       "inscollist",    "sortlist",      "nexprlist",   
-  "setlist",       "insert_cmd",    "inscollist_opt",  "valuelist",   
-  "exprlist",      "likeop",        "between_op",    "in_op",       
-  "case_operand",  "case_exprlist",  "case_else",     "uniqueflag",  
-  "collate",       "nmnum",         "number",        "trigger_decl",
-  "trigger_cmd_list",  "trigger_time",  "trigger_event",  "foreach_clause",
-  "when_clause",   "trigger_cmd",   "trnm",          "tridxby",     
-  "database_kw_opt",  "key_opt",       "add_column_fullname",  "kwcolumn_opt",
-  "create_vtab",   "vtabarglist",   "vtabarg",       "vtabargtoken",
-  "lp",            "anylist",     
+  "INTEGER",       "FLOAT",         "BLOB",          "VARIABLE",    
+  "CASE",          "WHEN",          "THEN",          "ELSE",        
+  "INDEX",         "ALTER",         "ADD",           "error",       
+  "input",         "cmdlist",       "ecmd",          "explain",     
+  "cmdx",          "cmd",           "transtype",     "trans_opt",   
+  "nm",            "savepoint_opt",  "create_table",  "create_table_args",
+  "createkw",      "temp",          "ifnotexists",   "dbnm",        
+  "columnlist",    "conslist_opt",  "table_options",  "select",      
+  "column",        "columnid",      "type",          "carglist",    
+  "typetoken",     "typename",      "signed",        "plus_num",    
+  "minus_num",     "ccons",         "term",          "expr",        
+  "onconf",        "sortorder",     "autoinc",       "idxlist_opt", 
+  "refargs",       "defer_subclause",  "refarg",        "refact",      
+  "init_deferred_pred_opt",  "conslist",      "tconscomma",    "tcons",       
+  "idxlist",       "defer_subclause_opt",  "orconf",        "resolvetype", 
+  "raisetype",     "ifexists",      "fullname",      "selectnowith",
+  "oneselect",     "with",          "multiselect_op",  "distinct",    
+  "selcollist",    "from",          "where_opt",     "groupby_opt", 
+  "having_opt",    "orderby_opt",   "limit_opt",     "values",      
+  "nexprlist",     "exprlist",      "sclp",          "as",          
+  "seltablist",    "stl_prefix",    "joinop",        "indexed_opt", 
+  "on_opt",        "using_opt",     "joinop2",       "idlist",      
+  "sortlist",      "setlist",       "insert_cmd",    "inscollist_opt",
+  "likeop",        "between_op",    "in_op",         "case_operand",
+  "case_exprlist",  "case_else",     "uniqueflag",    "collate",     
+  "nmnum",         "trigger_decl",  "trigger_cmd_list",  "trigger_time",
+  "trigger_event",  "foreach_clause",  "when_clause",   "trigger_cmd", 
+  "trnm",          "tridxby",       "database_kw_opt",  "key_opt",     
+  "add_column_fullname",  "kwcolumn_opt",  "create_vtab",   "vtabarglist", 
+  "vtabarg",       "vtabargtoken",  "lp",            "anylist",     
+  "wqlist",      
 };
 #endif /* NDEBUG */
 
@@ -111140,301 +118452,301 @@ static const char *const yyRuleName[] = {
  /*  29 */ "ifnotexists ::= IF NOT EXISTS",
  /*  30 */ "temp ::= TEMP",
  /*  31 */ "temp ::=",
- /*  32 */ "create_table_args ::= LP columnlist conslist_opt RP",
+ /*  32 */ "create_table_args ::= LP columnlist conslist_opt RP table_options",
  /*  33 */ "create_table_args ::= AS select",
- /*  34 */ "columnlist ::= columnlist COMMA column",
- /*  35 */ "columnlist ::= column",
- /*  36 */ "column ::= columnid type carglist",
- /*  37 */ "columnid ::= nm",
- /*  38 */ "id ::= ID",
- /*  39 */ "id ::= INDEXED",
- /*  40 */ "ids ::= ID|STRING",
- /*  41 */ "nm ::= id",
- /*  42 */ "nm ::= STRING",
- /*  43 */ "nm ::= JOIN_KW",
- /*  44 */ "type ::=",
- /*  45 */ "type ::= typetoken",
- /*  46 */ "typetoken ::= typename",
- /*  47 */ "typetoken ::= typename LP signed RP",
- /*  48 */ "typetoken ::= typename LP signed COMMA signed RP",
- /*  49 */ "typename ::= ids",
- /*  50 */ "typename ::= typename ids",
- /*  51 */ "signed ::= plus_num",
- /*  52 */ "signed ::= minus_num",
- /*  53 */ "carglist ::= carglist ccons",
- /*  54 */ "carglist ::=",
- /*  55 */ "ccons ::= CONSTRAINT nm",
- /*  56 */ "ccons ::= DEFAULT term",
- /*  57 */ "ccons ::= DEFAULT LP expr RP",
- /*  58 */ "ccons ::= DEFAULT PLUS term",
- /*  59 */ "ccons ::= DEFAULT MINUS term",
- /*  60 */ "ccons ::= DEFAULT id",
- /*  61 */ "ccons ::= NULL onconf",
- /*  62 */ "ccons ::= NOT NULL onconf",
- /*  63 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
- /*  64 */ "ccons ::= UNIQUE onconf",
- /*  65 */ "ccons ::= CHECK LP expr RP",
- /*  66 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
- /*  67 */ "ccons ::= defer_subclause",
- /*  68 */ "ccons ::= COLLATE ids",
- /*  69 */ "autoinc ::=",
- /*  70 */ "autoinc ::= AUTOINCR",
- /*  71 */ "refargs ::=",
- /*  72 */ "refargs ::= refargs refarg",
- /*  73 */ "refarg ::= MATCH nm",
- /*  74 */ "refarg ::= ON INSERT refact",
- /*  75 */ "refarg ::= ON DELETE refact",
- /*  76 */ "refarg ::= ON UPDATE refact",
- /*  77 */ "refact ::= SET NULL",
- /*  78 */ "refact ::= SET DEFAULT",
- /*  79 */ "refact ::= CASCADE",
- /*  80 */ "refact ::= RESTRICT",
- /*  81 */ "refact ::= NO ACTION",
- /*  82 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
- /*  83 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
- /*  84 */ "init_deferred_pred_opt ::=",
- /*  85 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
- /*  86 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
- /*  87 */ "conslist_opt ::=",
- /*  88 */ "conslist_opt ::= COMMA conslist",
- /*  89 */ "conslist ::= conslist tconscomma tcons",
- /*  90 */ "conslist ::= tcons",
- /*  91 */ "tconscomma ::= COMMA",
- /*  92 */ "tconscomma ::=",
- /*  93 */ "tcons ::= CONSTRAINT nm",
- /*  94 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
- /*  95 */ "tcons ::= UNIQUE LP idxlist RP onconf",
- /*  96 */ "tcons ::= CHECK LP expr RP onconf",
- /*  97 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
- /*  98 */ "defer_subclause_opt ::=",
- /*  99 */ "defer_subclause_opt ::= defer_subclause",
- /* 100 */ "onconf ::=",
- /* 101 */ "onconf ::= ON CONFLICT resolvetype",
- /* 102 */ "orconf ::=",
- /* 103 */ "orconf ::= OR resolvetype",
- /* 104 */ "resolvetype ::= raisetype",
- /* 105 */ "resolvetype ::= IGNORE",
- /* 106 */ "resolvetype ::= REPLACE",
- /* 107 */ "cmd ::= DROP TABLE ifexists fullname",
- /* 108 */ "ifexists ::= IF EXISTS",
- /* 109 */ "ifexists ::=",
- /* 110 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
- /* 111 */ "cmd ::= DROP VIEW ifexists fullname",
- /* 112 */ "cmd ::= select",
- /* 113 */ "select ::= oneselect",
- /* 114 */ "select ::= select multiselect_op oneselect",
+ /*  34 */ "table_options ::=",
+ /*  35 */ "table_options ::= WITHOUT nm",
+ /*  36 */ "columnlist ::= columnlist COMMA column",
+ /*  37 */ "columnlist ::= column",
+ /*  38 */ "column ::= columnid type carglist",
+ /*  39 */ "columnid ::= nm",
+ /*  40 */ "nm ::= ID|INDEXED",
+ /*  41 */ "nm ::= STRING",
+ /*  42 */ "nm ::= JOIN_KW",
+ /*  43 */ "type ::=",
+ /*  44 */ "type ::= typetoken",
+ /*  45 */ "typetoken ::= typename",
+ /*  46 */ "typetoken ::= typename LP signed RP",
+ /*  47 */ "typetoken ::= typename LP signed COMMA signed RP",
+ /*  48 */ "typename ::= ID|STRING",
+ /*  49 */ "typename ::= typename ID|STRING",
+ /*  50 */ "signed ::= plus_num",
+ /*  51 */ "signed ::= minus_num",
+ /*  52 */ "carglist ::= carglist ccons",
+ /*  53 */ "carglist ::=",
+ /*  54 */ "ccons ::= CONSTRAINT nm",
+ /*  55 */ "ccons ::= DEFAULT term",
+ /*  56 */ "ccons ::= DEFAULT LP expr RP",
+ /*  57 */ "ccons ::= DEFAULT PLUS term",
+ /*  58 */ "ccons ::= DEFAULT MINUS term",
+ /*  59 */ "ccons ::= DEFAULT ID|INDEXED",
+ /*  60 */ "ccons ::= NULL onconf",
+ /*  61 */ "ccons ::= NOT NULL onconf",
+ /*  62 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
+ /*  63 */ "ccons ::= UNIQUE onconf",
+ /*  64 */ "ccons ::= CHECK LP expr RP",
+ /*  65 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
+ /*  66 */ "ccons ::= defer_subclause",
+ /*  67 */ "ccons ::= COLLATE ID|STRING",
+ /*  68 */ "autoinc ::=",
+ /*  69 */ "autoinc ::= AUTOINCR",
+ /*  70 */ "refargs ::=",
+ /*  71 */ "refargs ::= refargs refarg",
+ /*  72 */ "refarg ::= MATCH nm",
+ /*  73 */ "refarg ::= ON INSERT refact",
+ /*  74 */ "refarg ::= ON DELETE refact",
+ /*  75 */ "refarg ::= ON UPDATE refact",
+ /*  76 */ "refact ::= SET NULL",
+ /*  77 */ "refact ::= SET DEFAULT",
+ /*  78 */ "refact ::= CASCADE",
+ /*  79 */ "refact ::= RESTRICT",
+ /*  80 */ "refact ::= NO ACTION",
+ /*  81 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
+ /*  82 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
+ /*  83 */ "init_deferred_pred_opt ::=",
+ /*  84 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
+ /*  85 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
+ /*  86 */ "conslist_opt ::=",
+ /*  87 */ "conslist_opt ::= COMMA conslist",
+ /*  88 */ "conslist ::= conslist tconscomma tcons",
+ /*  89 */ "conslist ::= tcons",
+ /*  90 */ "tconscomma ::= COMMA",
+ /*  91 */ "tconscomma ::=",
+ /*  92 */ "tcons ::= CONSTRAINT nm",
+ /*  93 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
+ /*  94 */ "tcons ::= UNIQUE LP idxlist RP onconf",
+ /*  95 */ "tcons ::= CHECK LP expr RP onconf",
+ /*  96 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
+ /*  97 */ "defer_subclause_opt ::=",
+ /*  98 */ "defer_subclause_opt ::= defer_subclause",
+ /*  99 */ "onconf ::=",
+ /* 100 */ "onconf ::= ON CONFLICT resolvetype",
+ /* 101 */ "orconf ::=",
+ /* 102 */ "orconf ::= OR resolvetype",
+ /* 103 */ "resolvetype ::= raisetype",
+ /* 104 */ "resolvetype ::= IGNORE",
+ /* 105 */ "resolvetype ::= REPLACE",
+ /* 106 */ "cmd ::= DROP TABLE ifexists fullname",
+ /* 107 */ "ifexists ::= IF EXISTS",
+ /* 108 */ "ifexists ::=",
+ /* 109 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
+ /* 110 */ "cmd ::= DROP VIEW ifexists fullname",
+ /* 111 */ "cmd ::= select",
+ /* 112 */ "select ::= with selectnowith",
+ /* 113 */ "selectnowith ::= oneselect",
+ /* 114 */ "selectnowith ::= selectnowith multiselect_op oneselect",
  /* 115 */ "multiselect_op ::= UNION",
  /* 116 */ "multiselect_op ::= UNION ALL",
  /* 117 */ "multiselect_op ::= EXCEPT|INTERSECT",
  /* 118 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 119 */ "distinct ::= DISTINCT",
- /* 120 */ "distinct ::= ALL",
- /* 121 */ "distinct ::=",
- /* 122 */ "sclp ::= selcollist COMMA",
- /* 123 */ "sclp ::=",
- /* 124 */ "selcollist ::= sclp expr as",
- /* 125 */ "selcollist ::= sclp STAR",
- /* 126 */ "selcollist ::= sclp nm DOT STAR",
- /* 127 */ "as ::= AS nm",
- /* 128 */ "as ::= ids",
- /* 129 */ "as ::=",
- /* 130 */ "from ::=",
- /* 131 */ "from ::= FROM seltablist",
- /* 132 */ "stl_prefix ::= seltablist joinop",
- /* 133 */ "stl_prefix ::=",
- /* 134 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
- /* 135 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
- /* 136 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
- /* 137 */ "dbnm ::=",
- /* 138 */ "dbnm ::= DOT nm",
- /* 139 */ "fullname ::= nm dbnm",
- /* 140 */ "joinop ::= COMMA|JOIN",
- /* 141 */ "joinop ::= JOIN_KW JOIN",
- /* 142 */ "joinop ::= JOIN_KW nm JOIN",
- /* 143 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 144 */ "on_opt ::= ON expr",
- /* 145 */ "on_opt ::=",
- /* 146 */ "indexed_opt ::=",
- /* 147 */ "indexed_opt ::= INDEXED BY nm",
- /* 148 */ "indexed_opt ::= NOT INDEXED",
- /* 149 */ "using_opt ::= USING LP inscollist RP",
- /* 150 */ "using_opt ::=",
- /* 151 */ "orderby_opt ::=",
- /* 152 */ "orderby_opt ::= ORDER BY sortlist",
- /* 153 */ "sortlist ::= sortlist COMMA expr sortorder",
- /* 154 */ "sortlist ::= expr sortorder",
- /* 155 */ "sortorder ::= ASC",
- /* 156 */ "sortorder ::= DESC",
- /* 157 */ "sortorder ::=",
- /* 158 */ "groupby_opt ::=",
- /* 159 */ "groupby_opt ::= GROUP BY nexprlist",
- /* 160 */ "having_opt ::=",
- /* 161 */ "having_opt ::= HAVING expr",
- /* 162 */ "limit_opt ::=",
- /* 163 */ "limit_opt ::= LIMIT expr",
- /* 164 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 165 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 166 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
- /* 167 */ "where_opt ::=",
- /* 168 */ "where_opt ::= WHERE expr",
- /* 169 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
- /* 170 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 171 */ "setlist ::= nm EQ expr",
- /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
- /* 173 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
- /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
- /* 175 */ "insert_cmd ::= INSERT orconf",
- /* 176 */ "insert_cmd ::= REPLACE",
- /* 177 */ "valuelist ::= VALUES LP nexprlist RP",
- /* 178 */ "valuelist ::= valuelist COMMA LP exprlist RP",
+ /* 119 */ "oneselect ::= values",
+ /* 120 */ "values ::= VALUES LP nexprlist RP",
+ /* 121 */ "values ::= values COMMA LP exprlist RP",
+ /* 122 */ "distinct ::= DISTINCT",
+ /* 123 */ "distinct ::= ALL",
+ /* 124 */ "distinct ::=",
+ /* 125 */ "sclp ::= selcollist COMMA",
+ /* 126 */ "sclp ::=",
+ /* 127 */ "selcollist ::= sclp expr as",
+ /* 128 */ "selcollist ::= sclp STAR",
+ /* 129 */ "selcollist ::= sclp nm DOT STAR",
+ /* 130 */ "as ::= AS nm",
+ /* 131 */ "as ::= ID|STRING",
+ /* 132 */ "as ::=",
+ /* 133 */ "from ::=",
+ /* 134 */ "from ::= FROM seltablist",
+ /* 135 */ "stl_prefix ::= seltablist joinop",
+ /* 136 */ "stl_prefix ::=",
+ /* 137 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
+ /* 138 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
+ /* 139 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
+ /* 140 */ "dbnm ::=",
+ /* 141 */ "dbnm ::= DOT nm",
+ /* 142 */ "fullname ::= nm dbnm",
+ /* 143 */ "joinop ::= COMMA|JOIN",
+ /* 144 */ "joinop ::= JOIN_KW JOIN",
+ /* 145 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 146 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 147 */ "on_opt ::= ON expr",
+ /* 148 */ "on_opt ::=",
+ /* 149 */ "indexed_opt ::=",
+ /* 150 */ "indexed_opt ::= INDEXED BY nm",
+ /* 151 */ "indexed_opt ::= NOT INDEXED",
+ /* 152 */ "using_opt ::= USING LP idlist RP",
+ /* 153 */ "using_opt ::=",
+ /* 154 */ "orderby_opt ::=",
+ /* 155 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 156 */ "sortlist ::= sortlist COMMA expr sortorder",
+ /* 157 */ "sortlist ::= expr sortorder",
+ /* 158 */ "sortorder ::= ASC",
+ /* 159 */ "sortorder ::= DESC",
+ /* 160 */ "sortorder ::=",
+ /* 161 */ "groupby_opt ::=",
+ /* 162 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 163 */ "having_opt ::=",
+ /* 164 */ "having_opt ::= HAVING expr",
+ /* 165 */ "limit_opt ::=",
+ /* 166 */ "limit_opt ::= LIMIT expr",
+ /* 167 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 168 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 169 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt",
+ /* 170 */ "where_opt ::=",
+ /* 171 */ "where_opt ::= WHERE expr",
+ /* 172 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt",
+ /* 173 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 174 */ "setlist ::= nm EQ expr",
+ /* 175 */ "cmd ::= with insert_cmd INTO fullname inscollist_opt select",
+ /* 176 */ "cmd ::= with insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
+ /* 177 */ "insert_cmd ::= INSERT orconf",
+ /* 178 */ "insert_cmd ::= REPLACE",
  /* 179 */ "inscollist_opt ::=",
- /* 180 */ "inscollist_opt ::= LP inscollist RP",
- /* 181 */ "inscollist ::= inscollist COMMA nm",
- /* 182 */ "inscollist ::= nm",
+ /* 180 */ "inscollist_opt ::= LP idlist RP",
+ /* 181 */ "idlist ::= idlist COMMA nm",
+ /* 182 */ "idlist ::= nm",
  /* 183 */ "expr ::= term",
  /* 184 */ "expr ::= LP expr RP",
  /* 185 */ "term ::= NULL",
- /* 186 */ "expr ::= id",
+ /* 186 */ "expr ::= ID|INDEXED",
  /* 187 */ "expr ::= JOIN_KW",
  /* 188 */ "expr ::= nm DOT nm",
  /* 189 */ "expr ::= nm DOT nm DOT nm",
  /* 190 */ "term ::= INTEGER|FLOAT|BLOB",
  /* 191 */ "term ::= STRING",
- /* 192 */ "expr ::= REGISTER",
- /* 193 */ "expr ::= VARIABLE",
- /* 194 */ "expr ::= expr COLLATE ids",
- /* 195 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 196 */ "expr ::= ID LP distinct exprlist RP",
- /* 197 */ "expr ::= ID LP STAR RP",
- /* 198 */ "term ::= CTIME_KW",
- /* 199 */ "expr ::= expr AND expr",
- /* 200 */ "expr ::= expr OR expr",
- /* 201 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 202 */ "expr ::= expr EQ|NE expr",
- /* 203 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 204 */ "expr ::= expr PLUS|MINUS expr",
- /* 205 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 206 */ "expr ::= expr CONCAT expr",
- /* 207 */ "likeop ::= LIKE_KW",
- /* 208 */ "likeop ::= NOT LIKE_KW",
- /* 209 */ "likeop ::= MATCH",
- /* 210 */ "likeop ::= NOT MATCH",
- /* 211 */ "expr ::= expr likeop expr",
- /* 212 */ "expr ::= expr likeop expr ESCAPE expr",
- /* 213 */ "expr ::= expr ISNULL|NOTNULL",
- /* 214 */ "expr ::= expr NOT NULL",
- /* 215 */ "expr ::= expr IS expr",
- /* 216 */ "expr ::= expr IS NOT expr",
- /* 217 */ "expr ::= NOT expr",
- /* 218 */ "expr ::= BITNOT expr",
- /* 219 */ "expr ::= MINUS expr",
- /* 220 */ "expr ::= PLUS expr",
- /* 221 */ "between_op ::= BETWEEN",
- /* 222 */ "between_op ::= NOT BETWEEN",
- /* 223 */ "expr ::= expr between_op expr AND expr",
- /* 224 */ "in_op ::= IN",
- /* 225 */ "in_op ::= NOT IN",
- /* 226 */ "expr ::= expr in_op LP exprlist RP",
- /* 227 */ "expr ::= LP select RP",
- /* 228 */ "expr ::= expr in_op LP select RP",
- /* 229 */ "expr ::= expr in_op nm dbnm",
- /* 230 */ "expr ::= EXISTS LP select RP",
- /* 231 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 232 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 233 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 234 */ "case_else ::= ELSE expr",
- /* 235 */ "case_else ::=",
- /* 236 */ "case_operand ::= expr",
- /* 237 */ "case_operand ::=",
- /* 238 */ "exprlist ::= nexprlist",
- /* 239 */ "exprlist ::=",
- /* 240 */ "nexprlist ::= nexprlist COMMA expr",
- /* 241 */ "nexprlist ::= expr",
- /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
- /* 243 */ "uniqueflag ::= UNIQUE",
- /* 244 */ "uniqueflag ::=",
- /* 245 */ "idxlist_opt ::=",
- /* 246 */ "idxlist_opt ::= LP idxlist RP",
- /* 247 */ "idxlist ::= idxlist COMMA nm collate sortorder",
- /* 248 */ "idxlist ::= nm collate sortorder",
- /* 249 */ "collate ::=",
- /* 250 */ "collate ::= COLLATE ids",
- /* 251 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 252 */ "cmd ::= VACUUM",
- /* 253 */ "cmd ::= VACUUM nm",
- /* 254 */ "cmd ::= PRAGMA nm dbnm",
- /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 256 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 257 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 258 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
- /* 259 */ "nmnum ::= plus_num",
- /* 260 */ "nmnum ::= nm",
- /* 261 */ "nmnum ::= ON",
- /* 262 */ "nmnum ::= DELETE",
- /* 263 */ "nmnum ::= DEFAULT",
- /* 264 */ "plus_num ::= PLUS number",
- /* 265 */ "plus_num ::= number",
- /* 266 */ "minus_num ::= MINUS number",
- /* 267 */ "number ::= INTEGER|FLOAT",
- /* 268 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
- /* 269 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 270 */ "trigger_time ::= BEFORE",
- /* 271 */ "trigger_time ::= AFTER",
- /* 272 */ "trigger_time ::= INSTEAD OF",
- /* 273 */ "trigger_time ::=",
- /* 274 */ "trigger_event ::= DELETE|INSERT",
- /* 275 */ "trigger_event ::= UPDATE",
- /* 276 */ "trigger_event ::= UPDATE OF inscollist",
- /* 277 */ "foreach_clause ::=",
- /* 278 */ "foreach_clause ::= FOR EACH ROW",
- /* 279 */ "when_clause ::=",
- /* 280 */ "when_clause ::= WHEN expr",
- /* 281 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 283 */ "trnm ::= nm",
- /* 284 */ "trnm ::= nm DOT nm",
- /* 285 */ "tridxby ::=",
- /* 286 */ "tridxby ::= INDEXED BY nm",
- /* 287 */ "tridxby ::= NOT INDEXED",
- /* 288 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
- /* 289 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
- /* 290 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
- /* 291 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
- /* 292 */ "trigger_cmd ::= select",
- /* 293 */ "expr ::= RAISE LP IGNORE RP",
- /* 294 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 295 */ "raisetype ::= ROLLBACK",
- /* 296 */ "raisetype ::= ABORT",
- /* 297 */ "raisetype ::= FAIL",
- /* 298 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 299 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 300 */ "cmd ::= DETACH database_kw_opt expr",
- /* 301 */ "key_opt ::=",
- /* 302 */ "key_opt ::= KEY expr",
- /* 303 */ "database_kw_opt ::= DATABASE",
- /* 304 */ "database_kw_opt ::=",
- /* 305 */ "cmd ::= REINDEX",
- /* 306 */ "cmd ::= REINDEX nm dbnm",
- /* 307 */ "cmd ::= ANALYZE",
- /* 308 */ "cmd ::= ANALYZE nm dbnm",
- /* 309 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 310 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
- /* 311 */ "add_column_fullname ::= fullname",
- /* 312 */ "kwcolumn_opt ::=",
- /* 313 */ "kwcolumn_opt ::= COLUMNKW",
- /* 314 */ "cmd ::= create_vtab",
- /* 315 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 316 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
- /* 317 */ "vtabarglist ::= vtabarg",
- /* 318 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 319 */ "vtabarg ::=",
- /* 320 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 321 */ "vtabargtoken ::= ANY",
- /* 322 */ "vtabargtoken ::= lp anylist RP",
- /* 323 */ "lp ::= LP",
- /* 324 */ "anylist ::=",
- /* 325 */ "anylist ::= anylist LP anylist RP",
- /* 326 */ "anylist ::= anylist ANY",
+ /* 192 */ "expr ::= VARIABLE",
+ /* 193 */ "expr ::= expr COLLATE ID|STRING",
+ /* 194 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 195 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
+ /* 196 */ "expr ::= ID|INDEXED LP STAR RP",
+ /* 197 */ "term ::= CTIME_KW",
+ /* 198 */ "expr ::= expr AND expr",
+ /* 199 */ "expr ::= expr OR expr",
+ /* 200 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 201 */ "expr ::= expr EQ|NE expr",
+ /* 202 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 203 */ "expr ::= expr PLUS|MINUS expr",
+ /* 204 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 205 */ "expr ::= expr CONCAT expr",
+ /* 206 */ "likeop ::= LIKE_KW|MATCH",
+ /* 207 */ "likeop ::= NOT LIKE_KW|MATCH",
+ /* 208 */ "expr ::= expr likeop expr",
+ /* 209 */ "expr ::= expr likeop expr ESCAPE expr",
+ /* 210 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 211 */ "expr ::= expr NOT NULL",
+ /* 212 */ "expr ::= expr IS expr",
+ /* 213 */ "expr ::= expr IS NOT expr",
+ /* 214 */ "expr ::= NOT expr",
+ /* 215 */ "expr ::= BITNOT expr",
+ /* 216 */ "expr ::= MINUS expr",
+ /* 217 */ "expr ::= PLUS expr",
+ /* 218 */ "between_op ::= BETWEEN",
+ /* 219 */ "between_op ::= NOT BETWEEN",
+ /* 220 */ "expr ::= expr between_op expr AND expr",
+ /* 221 */ "in_op ::= IN",
+ /* 222 */ "in_op ::= NOT IN",
+ /* 223 */ "expr ::= expr in_op LP exprlist RP",
+ /* 224 */ "expr ::= LP select RP",
+ /* 225 */ "expr ::= expr in_op LP select RP",
+ /* 226 */ "expr ::= expr in_op nm dbnm",
+ /* 227 */ "expr ::= EXISTS LP select RP",
+ /* 228 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 229 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 230 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 231 */ "case_else ::= ELSE expr",
+ /* 232 */ "case_else ::=",
+ /* 233 */ "case_operand ::= expr",
+ /* 234 */ "case_operand ::=",
+ /* 235 */ "exprlist ::= nexprlist",
+ /* 236 */ "exprlist ::=",
+ /* 237 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 238 */ "nexprlist ::= expr",
+ /* 239 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt",
+ /* 240 */ "uniqueflag ::= UNIQUE",
+ /* 241 */ "uniqueflag ::=",
+ /* 242 */ "idxlist_opt ::=",
+ /* 243 */ "idxlist_opt ::= LP idxlist RP",
+ /* 244 */ "idxlist ::= idxlist COMMA nm collate sortorder",
+ /* 245 */ "idxlist ::= nm collate sortorder",
+ /* 246 */ "collate ::=",
+ /* 247 */ "collate ::= COLLATE ID|STRING",
+ /* 248 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 249 */ "cmd ::= VACUUM",
+ /* 250 */ "cmd ::= VACUUM nm",
+ /* 251 */ "cmd ::= PRAGMA nm dbnm",
+ /* 252 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 253 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 254 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 255 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
+ /* 256 */ "nmnum ::= plus_num",
+ /* 257 */ "nmnum ::= nm",
+ /* 258 */ "nmnum ::= ON",
+ /* 259 */ "nmnum ::= DELETE",
+ /* 260 */ "nmnum ::= DEFAULT",
+ /* 261 */ "plus_num ::= PLUS INTEGER|FLOAT",
+ /* 262 */ "plus_num ::= INTEGER|FLOAT",
+ /* 263 */ "minus_num ::= MINUS INTEGER|FLOAT",
+ /* 264 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 265 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 266 */ "trigger_time ::= BEFORE",
+ /* 267 */ "trigger_time ::= AFTER",
+ /* 268 */ "trigger_time ::= INSTEAD OF",
+ /* 269 */ "trigger_time ::=",
+ /* 270 */ "trigger_event ::= DELETE|INSERT",
+ /* 271 */ "trigger_event ::= UPDATE",
+ /* 272 */ "trigger_event ::= UPDATE OF idlist",
+ /* 273 */ "foreach_clause ::=",
+ /* 274 */ "foreach_clause ::= FOR EACH ROW",
+ /* 275 */ "when_clause ::=",
+ /* 276 */ "when_clause ::= WHEN expr",
+ /* 277 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 278 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 279 */ "trnm ::= nm",
+ /* 280 */ "trnm ::= nm DOT nm",
+ /* 281 */ "tridxby ::=",
+ /* 282 */ "tridxby ::= INDEXED BY nm",
+ /* 283 */ "tridxby ::= NOT INDEXED",
+ /* 284 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
+ /* 285 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
+ /* 286 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
+ /* 287 */ "trigger_cmd ::= select",
+ /* 288 */ "expr ::= RAISE LP IGNORE RP",
+ /* 289 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 290 */ "raisetype ::= ROLLBACK",
+ /* 291 */ "raisetype ::= ABORT",
+ /* 292 */ "raisetype ::= FAIL",
+ /* 293 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 294 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 295 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 296 */ "key_opt ::=",
+ /* 297 */ "key_opt ::= KEY expr",
+ /* 298 */ "database_kw_opt ::= DATABASE",
+ /* 299 */ "database_kw_opt ::=",
+ /* 300 */ "cmd ::= REINDEX",
+ /* 301 */ "cmd ::= REINDEX nm dbnm",
+ /* 302 */ "cmd ::= ANALYZE",
+ /* 303 */ "cmd ::= ANALYZE nm dbnm",
+ /* 304 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 305 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
+ /* 306 */ "add_column_fullname ::= fullname",
+ /* 307 */ "kwcolumn_opt ::=",
+ /* 308 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 309 */ "cmd ::= create_vtab",
+ /* 310 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 311 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 312 */ "vtabarglist ::= vtabarg",
+ /* 313 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 314 */ "vtabarg ::=",
+ /* 315 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 316 */ "vtabargtoken ::= ANY",
+ /* 317 */ "vtabargtoken ::= lp anylist RP",
+ /* 318 */ "lp ::= LP",
+ /* 319 */ "anylist ::=",
+ /* 320 */ "anylist ::= anylist LP anylist RP",
+ /* 321 */ "anylist ::= anylist ANY",
+ /* 322 */ "with ::=",
+ /* 323 */ "with ::= WITH wqlist",
+ /* 324 */ "with ::= WITH RECURSIVE wqlist",
+ /* 325 */ "wqlist ::= nm idxlist_opt AS LP select RP",
+ /* 326 */ "wqlist ::= wqlist COMMA nm idxlist_opt AS LP select RP",
 };
 #endif /* NDEBUG */
 
@@ -111513,76 +118825,76 @@ static void yy_destructor(
     ** which appear on the RHS of the rule, but which are not used
     ** inside the C code.
     */
-    case 160: /* select */
-    case 194: /* oneselect */
+    case 163: /* select */
+    case 195: /* selectnowith */
+    case 196: /* oneselect */
+    case 207: /* values */
 {
-sqlite3SelectDelete(pParse->db, (yypminor->yy159));
+sqlite3SelectDelete(pParse->db, (yypminor->yy3));
 }
       break;
-    case 173: /* term */
-    case 174: /* expr */
+    case 174: /* term */
+    case 175: /* expr */
 {
-sqlite3ExprDelete(pParse->db, (yypminor->yy342).pExpr);
+sqlite3ExprDelete(pParse->db, (yypminor->yy346).pExpr);
 }
       break;
-    case 178: /* idxlist_opt */
-    case 187: /* idxlist */
-    case 197: /* selcollist */
-    case 200: /* groupby_opt */
-    case 202: /* orderby_opt */
-    case 204: /* sclp */
-    case 214: /* sortlist */
-    case 215: /* nexprlist */
-    case 216: /* setlist */
-    case 220: /* exprlist */
-    case 225: /* case_exprlist */
+    case 179: /* idxlist_opt */
+    case 188: /* idxlist */
+    case 200: /* selcollist */
+    case 203: /* groupby_opt */
+    case 205: /* orderby_opt */
+    case 208: /* nexprlist */
+    case 209: /* exprlist */
+    case 210: /* sclp */
+    case 220: /* sortlist */
+    case 221: /* setlist */
+    case 228: /* case_exprlist */
 {
-sqlite3ExprListDelete(pParse->db, (yypminor->yy442));
+sqlite3ExprListDelete(pParse->db, (yypminor->yy14));
 }
       break;
-    case 193: /* fullname */
-    case 198: /* from */
-    case 206: /* seltablist */
-    case 207: /* stl_prefix */
+    case 194: /* fullname */
+    case 201: /* from */
+    case 212: /* seltablist */
+    case 213: /* stl_prefix */
 {
-sqlite3SrcListDelete(pParse->db, (yypminor->yy347));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy65));
 }
       break;
-    case 199: /* where_opt */
-    case 201: /* having_opt */
-    case 210: /* on_opt */
-    case 224: /* case_operand */
-    case 226: /* case_else */
-    case 236: /* when_clause */
-    case 241: /* key_opt */
+    case 197: /* with */
+    case 252: /* wqlist */
 {
-sqlite3ExprDelete(pParse->db, (yypminor->yy122));
+sqlite3WithDelete(pParse->db, (yypminor->yy59));
 }
       break;
-    case 211: /* using_opt */
-    case 213: /* inscollist */
-    case 218: /* inscollist_opt */
+    case 202: /* where_opt */
+    case 204: /* having_opt */
+    case 216: /* on_opt */
+    case 227: /* case_operand */
+    case 229: /* case_else */
+    case 238: /* when_clause */
+    case 243: /* key_opt */
 {
-sqlite3IdListDelete(pParse->db, (yypminor->yy180));
+sqlite3ExprDelete(pParse->db, (yypminor->yy132));
 }
       break;
-    case 219: /* valuelist */
+    case 217: /* using_opt */
+    case 219: /* idlist */
+    case 223: /* inscollist_opt */
 {
-
-  sqlite3ExprListDelete(pParse->db, (yypminor->yy487).pList);
-  sqlite3SelectDelete(pParse->db, (yypminor->yy487).pSelect);
-
+sqlite3IdListDelete(pParse->db, (yypminor->yy408));
 }
       break;
-    case 232: /* trigger_cmd_list */
-    case 237: /* trigger_cmd */
+    case 234: /* trigger_cmd_list */
+    case 239: /* trigger_cmd */
 {
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy327));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy473));
 }
       break;
-    case 234: /* trigger_event */
+    case 236: /* trigger_event */
 {
-sqlite3IdListDelete(pParse->db, (yypminor->yy410).b);
+sqlite3IdListDelete(pParse->db, (yypminor->yy378).b);
 }
       break;
     default:  break;   /* If no destructor action specified: do nothing */
@@ -111827,333 +119139,333 @@ static const struct {
   YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
   unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
 } yyRuleInfo[] = {
-  { 142, 1 },
-  { 143, 2 },
-  { 143, 1 },
   { 144, 1 },
-  { 144, 3 },
-  { 145, 0 },
+  { 145, 2 },
   { 145, 1 },
-  { 145, 3 },
   { 146, 1 },
+  { 146, 3 },
+  { 147, 0 },
+  { 147, 1 },
   { 147, 3 },
-  { 149, 0 },
-  { 149, 1 },
-  { 149, 2 },
-  { 148, 0 },
-  { 148, 1 },
   { 148, 1 },
-  { 148, 1 },
-  { 147, 2 },
-  { 147, 2 },
-  { 147, 2 },
-  { 151, 1 },
+  { 149, 3 },
   { 151, 0 },
-  { 147, 2 },
-  { 147, 3 },
-  { 147, 5 },
-  { 147, 2 },
-  { 152, 6 },
-  { 154, 1 },
-  { 156, 0 },
-  { 156, 3 },
-  { 155, 1 },
-  { 155, 0 },
-  { 153, 4 },
-  { 153, 2 },
-  { 158, 3 },
-  { 158, 1 },
-  { 161, 3 },
-  { 162, 1 },
-  { 165, 1 },
-  { 165, 1 },
-  { 166, 1 },
+  { 151, 1 },
+  { 151, 2 },
+  { 150, 0 },
   { 150, 1 },
   { 150, 1 },
   { 150, 1 },
-  { 163, 0 },
-  { 163, 1 },
-  { 167, 1 },
-  { 167, 4 },
-  { 167, 6 },
+  { 149, 2 },
+  { 149, 2 },
+  { 149, 2 },
+  { 153, 1 },
+  { 153, 0 },
+  { 149, 2 },
+  { 149, 3 },
+  { 149, 5 },
+  { 149, 2 },
+  { 154, 6 },
+  { 156, 1 },
+  { 158, 0 },
+  { 158, 3 },
+  { 157, 1 },
+  { 157, 0 },
+  { 155, 5 },
+  { 155, 2 },
+  { 162, 0 },
+  { 162, 2 },
+  { 160, 3 },
+  { 160, 1 },
+  { 164, 3 },
+  { 165, 1 },
+  { 152, 1 },
+  { 152, 1 },
+  { 152, 1 },
+  { 166, 0 },
+  { 166, 1 },
   { 168, 1 },
-  { 168, 2 },
-  { 169, 1 },
+  { 168, 4 },
+  { 168, 6 },
   { 169, 1 },
-  { 164, 2 },
-  { 164, 0 },
-  { 172, 2 },
-  { 172, 2 },
-  { 172, 4 },
-  { 172, 3 },
-  { 172, 3 },
-  { 172, 2 },
-  { 172, 2 },
-  { 172, 3 },
-  { 172, 5 },
-  { 172, 2 },
-  { 172, 4 },
-  { 172, 4 },
-  { 172, 1 },
-  { 172, 2 },
-  { 177, 0 },
-  { 177, 1 },
-  { 179, 0 },
-  { 179, 2 },
-  { 181, 2 },
-  { 181, 3 },
-  { 181, 3 },
-  { 181, 3 },
-  { 182, 2 },
-  { 182, 2 },
-  { 182, 1 },
-  { 182, 1 },
-  { 182, 2 },
-  { 180, 3 },
+  { 169, 2 },
+  { 170, 1 },
+  { 170, 1 },
+  { 167, 2 },
+  { 167, 0 },
+  { 173, 2 },
+  { 173, 2 },
+  { 173, 4 },
+  { 173, 3 },
+  { 173, 3 },
+  { 173, 2 },
+  { 173, 2 },
+  { 173, 3 },
+  { 173, 5 },
+  { 173, 2 },
+  { 173, 4 },
+  { 173, 4 },
+  { 173, 1 },
+  { 173, 2 },
+  { 178, 0 },
+  { 178, 1 },
+  { 180, 0 },
   { 180, 2 },
-  { 183, 0 },
+  { 182, 2 },
+  { 182, 3 },
+  { 182, 3 },
+  { 182, 3 },
   { 183, 2 },
   { 183, 2 },
-  { 159, 0 },
-  { 159, 2 },
-  { 184, 3 },
-  { 184, 1 },
+  { 183, 1 },
+  { 183, 1 },
+  { 183, 2 },
+  { 181, 3 },
+  { 181, 2 },
+  { 184, 0 },
+  { 184, 2 },
+  { 184, 2 },
+  { 161, 0 },
+  { 161, 2 },
+  { 185, 3 },
   { 185, 1 },
-  { 185, 0 },
-  { 186, 2 },
-  { 186, 7 },
-  { 186, 5 },
-  { 186, 5 },
-  { 186, 10 },
-  { 188, 0 },
-  { 188, 1 },
-  { 175, 0 },
-  { 175, 3 },
+  { 186, 1 },
+  { 186, 0 },
+  { 187, 2 },
+  { 187, 7 },
+  { 187, 5 },
+  { 187, 5 },
+  { 187, 10 },
   { 189, 0 },
-  { 189, 2 },
-  { 190, 1 },
-  { 190, 1 },
-  { 190, 1 },
-  { 147, 4 },
-  { 192, 2 },
-  { 192, 0 },
-  { 147, 8 },
-  { 147, 4 },
-  { 147, 1 },
-  { 160, 1 },
-  { 160, 3 },
-  { 195, 1 },
-  { 195, 2 },
+  { 189, 1 },
+  { 176, 0 },
+  { 176, 3 },
+  { 190, 0 },
+  { 190, 2 },
+  { 191, 1 },
+  { 191, 1 },
+  { 191, 1 },
+  { 149, 4 },
+  { 193, 2 },
+  { 193, 0 },
+  { 149, 8 },
+  { 149, 4 },
+  { 149, 1 },
+  { 163, 2 },
   { 195, 1 },
-  { 194, 9 },
-  { 196, 1 },
-  { 196, 1 },
-  { 196, 0 },
-  { 204, 2 },
-  { 204, 0 },
-  { 197, 3 },
-  { 197, 2 },
-  { 197, 4 },
-  { 205, 2 },
-  { 205, 1 },
-  { 205, 0 },
-  { 198, 0 },
+  { 195, 3 },
+  { 198, 1 },
   { 198, 2 },
-  { 207, 2 },
-  { 207, 0 },
-  { 206, 7 },
-  { 206, 7 },
-  { 206, 7 },
-  { 157, 0 },
-  { 157, 2 },
-  { 193, 2 },
-  { 208, 1 },
-  { 208, 2 },
-  { 208, 3 },
-  { 208, 4 },
+  { 198, 1 },
+  { 196, 9 },
+  { 196, 1 },
+  { 207, 4 },
+  { 207, 5 },
+  { 199, 1 },
+  { 199, 1 },
+  { 199, 0 },
   { 210, 2 },
   { 210, 0 },
-  { 209, 0 },
-  { 209, 3 },
-  { 209, 2 },
-  { 211, 4 },
-  { 211, 0 },
-  { 202, 0 },
-  { 202, 3 },
-  { 214, 4 },
-  { 214, 2 },
-  { 176, 1 },
-  { 176, 1 },
-  { 176, 0 },
-  { 200, 0 },
   { 200, 3 },
+  { 200, 2 },
+  { 200, 4 },
+  { 211, 2 },
+  { 211, 1 },
+  { 211, 0 },
   { 201, 0 },
   { 201, 2 },
+  { 213, 2 },
+  { 213, 0 },
+  { 212, 7 },
+  { 212, 7 },
+  { 212, 7 },
+  { 159, 0 },
+  { 159, 2 },
+  { 194, 2 },
+  { 214, 1 },
+  { 214, 2 },
+  { 214, 3 },
+  { 214, 4 },
+  { 216, 2 },
+  { 216, 0 },
+  { 215, 0 },
+  { 215, 3 },
+  { 215, 2 },
+  { 217, 4 },
+  { 217, 0 },
+  { 205, 0 },
+  { 205, 3 },
+  { 220, 4 },
+  { 220, 2 },
+  { 177, 1 },
+  { 177, 1 },
+  { 177, 0 },
   { 203, 0 },
-  { 203, 2 },
-  { 203, 4 },
-  { 203, 4 },
-  { 147, 5 },
-  { 199, 0 },
-  { 199, 2 },
-  { 147, 7 },
-  { 216, 5 },
-  { 216, 3 },
-  { 147, 5 },
-  { 147, 5 },
-  { 147, 6 },
-  { 217, 2 },
-  { 217, 1 },
-  { 219, 4 },
-  { 219, 5 },
-  { 218, 0 },
-  { 218, 3 },
-  { 213, 3 },
-  { 213, 1 },
-  { 174, 1 },
-  { 174, 3 },
-  { 173, 1 },
+  { 203, 3 },
+  { 204, 0 },
+  { 204, 2 },
+  { 206, 0 },
+  { 206, 2 },
+  { 206, 4 },
+  { 206, 4 },
+  { 149, 6 },
+  { 202, 0 },
+  { 202, 2 },
+  { 149, 8 },
+  { 221, 5 },
+  { 221, 3 },
+  { 149, 6 },
+  { 149, 7 },
+  { 222, 2 },
+  { 222, 1 },
+  { 223, 0 },
+  { 223, 3 },
+  { 219, 3 },
+  { 219, 1 },
+  { 175, 1 },
+  { 175, 3 },
   { 174, 1 },
+  { 175, 1 },
+  { 175, 1 },
+  { 175, 3 },
+  { 175, 5 },
   { 174, 1 },
-  { 174, 3 },
-  { 174, 5 },
-  { 173, 1 },
-  { 173, 1 },
   { 174, 1 },
+  { 175, 1 },
+  { 175, 3 },
+  { 175, 6 },
+  { 175, 5 },
+  { 175, 4 },
   { 174, 1 },
-  { 174, 3 },
-  { 174, 6 },
-  { 174, 5 },
-  { 174, 4 },
-  { 173, 1 },
-  { 174, 3 },
-  { 174, 3 },
-  { 174, 3 },
-  { 174, 3 },
-  { 174, 3 },
-  { 174, 3 },
-  { 174, 3 },
-  { 174, 3 },
-  { 221, 1 },
-  { 221, 2 },
-  { 221, 1 },
-  { 221, 2 },
-  { 174, 3 },
-  { 174, 5 },
-  { 174, 2 },
-  { 174, 3 },
-  { 174, 3 },
-  { 174, 4 },
-  { 174, 2 },
-  { 174, 2 },
-  { 174, 2 },
-  { 174, 2 },
-  { 222, 1 },
-  { 222, 2 },
-  { 174, 5 },
-  { 223, 1 },
-  { 223, 2 },
-  { 174, 5 },
-  { 174, 3 },
-  { 174, 5 },
-  { 174, 4 },
-  { 174, 4 },
-  { 174, 5 },
-  { 225, 5 },
-  { 225, 4 },
-  { 226, 2 },
-  { 226, 0 },
+  { 175, 3 },
+  { 175, 3 },
+  { 175, 3 },
+  { 175, 3 },
+  { 175, 3 },
+  { 175, 3 },
+  { 175, 3 },
+  { 175, 3 },
   { 224, 1 },
-  { 224, 0 },
-  { 220, 1 },
-  { 220, 0 },
-  { 215, 3 },
-  { 215, 1 },
-  { 147, 11 },
+  { 224, 2 },
+  { 175, 3 },
+  { 175, 5 },
+  { 175, 2 },
+  { 175, 3 },
+  { 175, 3 },
+  { 175, 4 },
+  { 175, 2 },
+  { 175, 2 },
+  { 175, 2 },
+  { 175, 2 },
+  { 225, 1 },
+  { 225, 2 },
+  { 175, 5 },
+  { 226, 1 },
+  { 226, 2 },
+  { 175, 5 },
+  { 175, 3 },
+  { 175, 5 },
+  { 175, 4 },
+  { 175, 4 },
+  { 175, 5 },
+  { 228, 5 },
+  { 228, 4 },
+  { 229, 2 },
+  { 229, 0 },
   { 227, 1 },
   { 227, 0 },
-  { 178, 0 },
-  { 178, 3 },
-  { 187, 5 },
-  { 187, 3 },
-  { 228, 0 },
-  { 228, 2 },
-  { 147, 4 },
-  { 147, 1 },
-  { 147, 2 },
-  { 147, 3 },
-  { 147, 5 },
-  { 147, 6 },
-  { 147, 5 },
-  { 147, 6 },
-  { 229, 1 },
-  { 229, 1 },
-  { 229, 1 },
-  { 229, 1 },
-  { 229, 1 },
-  { 170, 2 },
-  { 170, 1 },
-  { 171, 2 },
+  { 209, 1 },
+  { 209, 0 },
+  { 208, 3 },
+  { 208, 1 },
+  { 149, 12 },
   { 230, 1 },
-  { 147, 5 },
-  { 231, 11 },
-  { 233, 1 },
-  { 233, 1 },
-  { 233, 2 },
-  { 233, 0 },
-  { 234, 1 },
-  { 234, 1 },
-  { 234, 3 },
+  { 230, 0 },
+  { 179, 0 },
+  { 179, 3 },
+  { 188, 5 },
+  { 188, 3 },
+  { 231, 0 },
+  { 231, 2 },
+  { 149, 4 },
+  { 149, 1 },
+  { 149, 2 },
+  { 149, 3 },
+  { 149, 5 },
+  { 149, 6 },
+  { 149, 5 },
+  { 149, 6 },
+  { 232, 1 },
+  { 232, 1 },
+  { 232, 1 },
+  { 232, 1 },
+  { 232, 1 },
+  { 171, 2 },
+  { 171, 1 },
+  { 172, 2 },
+  { 149, 5 },
+  { 233, 11 },
+  { 235, 1 },
+  { 235, 1 },
+  { 235, 2 },
   { 235, 0 },
-  { 235, 3 },
-  { 236, 0 },
-  { 236, 2 },
-  { 232, 3 },
-  { 232, 2 },
-  { 238, 1 },
-  { 238, 3 },
-  { 239, 0 },
-  { 239, 3 },
-  { 239, 2 },
-  { 237, 7 },
-  { 237, 5 },
-  { 237, 5 },
-  { 237, 5 },
-  { 237, 1 },
-  { 174, 4 },
-  { 174, 6 },
-  { 191, 1 },
-  { 191, 1 },
-  { 191, 1 },
-  { 147, 4 },
-  { 147, 6 },
-  { 147, 3 },
+  { 236, 1 },
+  { 236, 1 },
+  { 236, 3 },
+  { 237, 0 },
+  { 237, 3 },
+  { 238, 0 },
+  { 238, 2 },
+  { 234, 3 },
+  { 234, 2 },
+  { 240, 1 },
+  { 240, 3 },
   { 241, 0 },
+  { 241, 3 },
   { 241, 2 },
-  { 240, 1 },
-  { 240, 0 },
-  { 147, 1 },
-  { 147, 3 },
-  { 147, 1 },
-  { 147, 3 },
-  { 147, 6 },
-  { 147, 6 },
-  { 242, 1 },
+  { 239, 7 },
+  { 239, 5 },
+  { 239, 5 },
+  { 239, 1 },
+  { 175, 4 },
+  { 175, 6 },
+  { 192, 1 },
+  { 192, 1 },
+  { 192, 1 },
+  { 149, 4 },
+  { 149, 6 },
+  { 149, 3 },
   { 243, 0 },
-  { 243, 1 },
-  { 147, 1 },
-  { 147, 4 },
-  { 244, 8 },
+  { 243, 2 },
+  { 242, 1 },
+  { 242, 0 },
+  { 149, 1 },
+  { 149, 3 },
+  { 149, 1 },
+  { 149, 3 },
+  { 149, 6 },
+  { 149, 6 },
+  { 244, 1 },
+  { 245, 0 },
   { 245, 1 },
-  { 245, 3 },
-  { 246, 0 },
-  { 246, 2 },
+  { 149, 1 },
+  { 149, 4 },
+  { 246, 8 },
   { 247, 1 },
   { 247, 3 },
-  { 248, 1 },
-  { 249, 0 },
-  { 249, 4 },
-  { 249, 2 },
+  { 248, 0 },
+  { 248, 2 },
+  { 249, 1 },
+  { 249, 3 },
+  { 250, 1 },
+  { 251, 0 },
+  { 251, 4 },
+  { 251, 2 },
+  { 197, 0 },
+  { 197, 2 },
+  { 197, 3 },
+  { 252, 6 },
+  { 252, 8 },
 };
 
 static void yy_accept(yyParser*);  /* Forward Declaration */
@@ -112221,17 +119533,17 @@ static void yy_reduce(
 { sqlite3FinishCoding(pParse); }
         break;
       case 9: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy392);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy328);}
         break;
       case 13: /* transtype ::= */
-{yygotominor.yy392 = TK_DEFERRED;}
+{yygotominor.yy328 = TK_DEFERRED;}
         break;
       case 14: /* transtype ::= DEFERRED */
       case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
       case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
       case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115);
       case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117);
-{yygotominor.yy392 = yymsp[0].major;}
+{yygotominor.yy328 = yymsp[0].major;}
         break;
       case 17: /* cmd ::= COMMIT trans_opt */
       case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
@@ -112257,7 +119569,7 @@ static void yy_reduce(
         break;
       case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
 {
-   sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy392,0,0,yymsp[-2].minor.yy392);
+   sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy328,0,0,yymsp[-2].minor.yy328);
 }
         break;
       case 27: /* createkw ::= CREATE */
@@ -112268,532 +119580,569 @@ static void yy_reduce(
         break;
       case 28: /* ifnotexists ::= */
       case 31: /* temp ::= */ yytestcase(yyruleno==31);
-      case 69: /* autoinc ::= */ yytestcase(yyruleno==69);
-      case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82);
-      case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84);
-      case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
-      case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
-      case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
-      case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
-      case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
-{yygotominor.yy392 = 0;}
+      case 68: /* autoinc ::= */ yytestcase(yyruleno==68);
+      case 81: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==81);
+      case 83: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==83);
+      case 85: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==85);
+      case 97: /* defer_subclause_opt ::= */ yytestcase(yyruleno==97);
+      case 108: /* ifexists ::= */ yytestcase(yyruleno==108);
+      case 218: /* between_op ::= BETWEEN */ yytestcase(yyruleno==218);
+      case 221: /* in_op ::= IN */ yytestcase(yyruleno==221);
+{yygotominor.yy328 = 0;}
         break;
       case 29: /* ifnotexists ::= IF NOT EXISTS */
       case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
-      case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70);
-      case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
-      case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
-      case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
-      case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
-{yygotominor.yy392 = 1;}
+      case 69: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==69);
+      case 84: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==84);
+      case 107: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==107);
+      case 219: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==219);
+      case 222: /* in_op ::= NOT IN */ yytestcase(yyruleno==222);
+{yygotominor.yy328 = 1;}
         break;
-      case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
+      case 32: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
 {
-  sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
+  sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy186,0);
 }
         break;
       case 33: /* create_table_args ::= AS select */
 {
-  sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy159);
-  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
+  sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy3);
+  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy3);
 }
         break;
-      case 36: /* column ::= columnid type carglist */
+      case 34: /* table_options ::= */
+{yygotominor.yy186 = 0;}
+        break;
+      case 35: /* table_options ::= WITHOUT nm */
+{
+  if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
+    yygotominor.yy186 = TF_WithoutRowid;
+  }else{
+    yygotominor.yy186 = 0;
+    sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
+  }
+}
+        break;
+      case 38: /* column ::= columnid type carglist */
 {
   yygotominor.yy0.z = yymsp[-2].minor.yy0.z;
   yygotominor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n;
 }
         break;
-      case 37: /* columnid ::= nm */
+      case 39: /* columnid ::= nm */
 {
   sqlite3AddColumn(pParse,&yymsp[0].minor.yy0);
   yygotominor.yy0 = yymsp[0].minor.yy0;
   pParse->constraintName.n = 0;
 }
         break;
-      case 38: /* id ::= ID */
-      case 39: /* id ::= INDEXED */ yytestcase(yyruleno==39);
-      case 40: /* ids ::= ID|STRING */ yytestcase(yyruleno==40);
-      case 41: /* nm ::= id */ yytestcase(yyruleno==41);
-      case 42: /* nm ::= STRING */ yytestcase(yyruleno==42);
-      case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
-      case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
-      case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
-      case 127: /* as ::= AS nm */ yytestcase(yyruleno==127);
-      case 128: /* as ::= ids */ yytestcase(yyruleno==128);
-      case 138: /* dbnm ::= DOT nm */ yytestcase(yyruleno==138);
-      case 147: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==147);
-      case 250: /* collate ::= COLLATE ids */ yytestcase(yyruleno==250);
-      case 259: /* nmnum ::= plus_num */ yytestcase(yyruleno==259);
-      case 260: /* nmnum ::= nm */ yytestcase(yyruleno==260);
-      case 261: /* nmnum ::= ON */ yytestcase(yyruleno==261);
-      case 262: /* nmnum ::= DELETE */ yytestcase(yyruleno==262);
-      case 263: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==263);
-      case 264: /* plus_num ::= PLUS number */ yytestcase(yyruleno==264);
-      case 265: /* plus_num ::= number */ yytestcase(yyruleno==265);
-      case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266);
-      case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267);
-      case 283: /* trnm ::= nm */ yytestcase(yyruleno==283);
+      case 40: /* nm ::= ID|INDEXED */
+      case 41: /* nm ::= STRING */ yytestcase(yyruleno==41);
+      case 42: /* nm ::= JOIN_KW */ yytestcase(yyruleno==42);
+      case 45: /* typetoken ::= typename */ yytestcase(yyruleno==45);
+      case 48: /* typename ::= ID|STRING */ yytestcase(yyruleno==48);
+      case 130: /* as ::= AS nm */ yytestcase(yyruleno==130);
+      case 131: /* as ::= ID|STRING */ yytestcase(yyruleno==131);
+      case 141: /* dbnm ::= DOT nm */ yytestcase(yyruleno==141);
+      case 150: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==150);
+      case 247: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==247);
+      case 256: /* nmnum ::= plus_num */ yytestcase(yyruleno==256);
+      case 257: /* nmnum ::= nm */ yytestcase(yyruleno==257);
+      case 258: /* nmnum ::= ON */ yytestcase(yyruleno==258);
+      case 259: /* nmnum ::= DELETE */ yytestcase(yyruleno==259);
+      case 260: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==260);
+      case 261: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==261);
+      case 262: /* plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==262);
+      case 263: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==263);
+      case 279: /* trnm ::= nm */ yytestcase(yyruleno==279);
 {yygotominor.yy0 = yymsp[0].minor.yy0;}
         break;
-      case 45: /* type ::= typetoken */
+      case 44: /* type ::= typetoken */
 {sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
         break;
-      case 47: /* typetoken ::= typename LP signed RP */
+      case 46: /* typetoken ::= typename LP signed RP */
 {
   yygotominor.yy0.z = yymsp[-3].minor.yy0.z;
   yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z);
 }
         break;
-      case 48: /* typetoken ::= typename LP signed COMMA signed RP */
+      case 47: /* typetoken ::= typename LP signed COMMA signed RP */
 {
   yygotominor.yy0.z = yymsp[-5].minor.yy0.z;
   yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
 }
         break;
-      case 50: /* typename ::= typename ids */
+      case 49: /* typename ::= typename ID|STRING */
 {yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
         break;
-      case 55: /* ccons ::= CONSTRAINT nm */
-      case 93: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==93);
+      case 54: /* ccons ::= CONSTRAINT nm */
+      case 92: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==92);
 {pParse->constraintName = yymsp[0].minor.yy0;}
         break;
-      case 56: /* ccons ::= DEFAULT term */
-      case 58: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==58);
-{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);}
+      case 55: /* ccons ::= DEFAULT term */
+      case 57: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==57);
+{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy346);}
         break;
-      case 57: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy342);}
+      case 56: /* ccons ::= DEFAULT LP expr RP */
+{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy346);}
         break;
-      case 59: /* ccons ::= DEFAULT MINUS term */
+      case 58: /* ccons ::= DEFAULT MINUS term */
 {
   ExprSpan v;
-  v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy342.pExpr, 0, 0);
+  v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy346.pExpr, 0, 0);
   v.zStart = yymsp[-1].minor.yy0.z;
-  v.zEnd = yymsp[0].minor.yy342.zEnd;
+  v.zEnd = yymsp[0].minor.yy346.zEnd;
   sqlite3AddDefaultValue(pParse,&v);
 }
         break;
-      case 60: /* ccons ::= DEFAULT id */
+      case 59: /* ccons ::= DEFAULT ID|INDEXED */
 {
   ExprSpan v;
   spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0);
   sqlite3AddDefaultValue(pParse,&v);
 }
         break;
-      case 62: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy392);}
+      case 61: /* ccons ::= NOT NULL onconf */
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy328);}
         break;
-      case 63: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy392,yymsp[0].minor.yy392,yymsp[-2].minor.yy392);}
+      case 62: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy328,yymsp[0].minor.yy328,yymsp[-2].minor.yy328);}
         break;
-      case 64: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy392,0,0,0,0);}
+      case 63: /* ccons ::= UNIQUE onconf */
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy328,0,0,0,0);}
         break;
-      case 65: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy342.pExpr);}
+      case 64: /* ccons ::= CHECK LP expr RP */
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy346.pExpr);}
         break;
-      case 66: /* ccons ::= REFERENCES nm idxlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy442,yymsp[0].minor.yy392);}
+      case 65: /* ccons ::= REFERENCES nm idxlist_opt refargs */
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy14,yymsp[0].minor.yy328);}
         break;
-      case 67: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy392);}
+      case 66: /* ccons ::= defer_subclause */
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy328);}
         break;
-      case 68: /* ccons ::= COLLATE ids */
+      case 67: /* ccons ::= COLLATE ID|STRING */
 {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
         break;
-      case 71: /* refargs ::= */
-{ yygotominor.yy392 = OE_None*0x0101; /* EV: R-19803-45884 */}
+      case 70: /* refargs ::= */
+{ yygotominor.yy328 = OE_None*0x0101; /* EV: R-19803-45884 */}
         break;
-      case 72: /* refargs ::= refargs refarg */
-{ yygotominor.yy392 = (yymsp[-1].minor.yy392 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
+      case 71: /* refargs ::= refargs refarg */
+{ yygotominor.yy328 = (yymsp[-1].minor.yy328 & ~yymsp[0].minor.yy429.mask) | yymsp[0].minor.yy429.value; }
         break;
-      case 73: /* refarg ::= MATCH nm */
-      case 74: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==74);
-{ yygotominor.yy207.value = 0;     yygotominor.yy207.mask = 0x000000; }
+      case 72: /* refarg ::= MATCH nm */
+      case 73: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==73);
+{ yygotominor.yy429.value = 0;     yygotominor.yy429.mask = 0x000000; }
         break;
-      case 75: /* refarg ::= ON DELETE refact */
-{ yygotominor.yy207.value = yymsp[0].minor.yy392;     yygotominor.yy207.mask = 0x0000ff; }
+      case 74: /* refarg ::= ON DELETE refact */
+{ yygotominor.yy429.value = yymsp[0].minor.yy328;     yygotominor.yy429.mask = 0x0000ff; }
         break;
-      case 76: /* refarg ::= ON UPDATE refact */
-{ yygotominor.yy207.value = yymsp[0].minor.yy392<<8;  yygotominor.yy207.mask = 0x00ff00; }
+      case 75: /* refarg ::= ON UPDATE refact */
+{ yygotominor.yy429.value = yymsp[0].minor.yy328<<8;  yygotominor.yy429.mask = 0x00ff00; }
         break;
-      case 77: /* refact ::= SET NULL */
-{ yygotominor.yy392 = OE_SetNull;  /* EV: R-33326-45252 */}
+      case 76: /* refact ::= SET NULL */
+{ yygotominor.yy328 = OE_SetNull;  /* EV: R-33326-45252 */}
         break;
-      case 78: /* refact ::= SET DEFAULT */
-{ yygotominor.yy392 = OE_SetDflt;  /* EV: R-33326-45252 */}
+      case 77: /* refact ::= SET DEFAULT */
+{ yygotominor.yy328 = OE_SetDflt;  /* EV: R-33326-45252 */}
         break;
-      case 79: /* refact ::= CASCADE */
-{ yygotominor.yy392 = OE_Cascade;  /* EV: R-33326-45252 */}
+      case 78: /* refact ::= CASCADE */
+{ yygotominor.yy328 = OE_Cascade;  /* EV: R-33326-45252 */}
         break;
-      case 80: /* refact ::= RESTRICT */
-{ yygotominor.yy392 = OE_Restrict; /* EV: R-33326-45252 */}
+      case 79: /* refact ::= RESTRICT */
+{ yygotominor.yy328 = OE_Restrict; /* EV: R-33326-45252 */}
         break;
-      case 81: /* refact ::= NO ACTION */
-{ yygotominor.yy392 = OE_None;     /* EV: R-33326-45252 */}
+      case 80: /* refact ::= NO ACTION */
+{ yygotominor.yy328 = OE_None;     /* EV: R-33326-45252 */}
         break;
-      case 83: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
-      case 99: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==99);
-      case 101: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==101);
-      case 104: /* resolvetype ::= raisetype */ yytestcase(yyruleno==104);
-{yygotominor.yy392 = yymsp[0].minor.yy392;}
+      case 82: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+      case 98: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==98);
+      case 100: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==100);
+      case 103: /* resolvetype ::= raisetype */ yytestcase(yyruleno==103);
+{yygotominor.yy328 = yymsp[0].minor.yy328;}
         break;
-      case 87: /* conslist_opt ::= */
+      case 86: /* conslist_opt ::= */
 {yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
         break;
-      case 88: /* conslist_opt ::= COMMA conslist */
+      case 87: /* conslist_opt ::= COMMA conslist */
 {yygotominor.yy0 = yymsp[-1].minor.yy0;}
         break;
-      case 91: /* tconscomma ::= COMMA */
+      case 90: /* tconscomma ::= COMMA */
 {pParse->constraintName.n = 0;}
         break;
-      case 94: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);}
+      case 93: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy14,yymsp[0].minor.yy328,yymsp[-2].minor.yy328,0);}
         break;
-      case 95: /* tcons ::= UNIQUE LP idxlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);}
+      case 94: /* tcons ::= UNIQUE LP idxlist RP onconf */
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy14,yymsp[0].minor.yy328,0,0,0,0);}
         break;
-      case 96: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);}
+      case 95: /* tcons ::= CHECK LP expr RP onconf */
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy346.pExpr);}
         break;
-      case 97: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
+      case 96: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
 {
-    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392);
-    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392);
+    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy14, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[-1].minor.yy328);
+    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy328);
 }
         break;
-      case 100: /* onconf ::= */
-{yygotominor.yy392 = OE_Default;}
+      case 99: /* onconf ::= */
+{yygotominor.yy328 = OE_Default;}
         break;
-      case 102: /* orconf ::= */
-{yygotominor.yy258 = OE_Default;}
+      case 101: /* orconf ::= */
+{yygotominor.yy186 = OE_Default;}
         break;
-      case 103: /* orconf ::= OR resolvetype */
-{yygotominor.yy258 = (u8)yymsp[0].minor.yy392;}
+      case 102: /* orconf ::= OR resolvetype */
+{yygotominor.yy186 = (u8)yymsp[0].minor.yy328;}
         break;
-      case 105: /* resolvetype ::= IGNORE */
-{yygotominor.yy392 = OE_Ignore;}
+      case 104: /* resolvetype ::= IGNORE */
+{yygotominor.yy328 = OE_Ignore;}
         break;
-      case 106: /* resolvetype ::= REPLACE */
-{yygotominor.yy392 = OE_Replace;}
+      case 105: /* resolvetype ::= REPLACE */
+{yygotominor.yy328 = OE_Replace;}
         break;
-      case 107: /* cmd ::= DROP TABLE ifexists fullname */
+      case 106: /* cmd ::= DROP TABLE ifexists fullname */
 {
-  sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392);
+  sqlite3DropTable(pParse, yymsp[0].minor.yy65, 0, yymsp[-1].minor.yy328);
 }
         break;
-      case 110: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
+      case 109: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
 {
-  sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy159, yymsp[-6].minor.yy392, yymsp[-4].minor.yy392);
+  sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy3, yymsp[-6].minor.yy328, yymsp[-4].minor.yy328);
 }
         break;
-      case 111: /* cmd ::= DROP VIEW ifexists fullname */
+      case 110: /* cmd ::= DROP VIEW ifexists fullname */
 {
-  sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392);
+  sqlite3DropTable(pParse, yymsp[0].minor.yy65, 1, yymsp[-1].minor.yy328);
 }
         break;
-      case 112: /* cmd ::= select */
+      case 111: /* cmd ::= select */
 {
-  SelectDest dest = {SRT_Output, 0, 0, 0, 0};
-  sqlite3Select(pParse, yymsp[0].minor.yy159, &dest);
+  SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
+  sqlite3Select(pParse, yymsp[0].minor.yy3, &dest);
   sqlite3ExplainBegin(pParse->pVdbe);
-  sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy159);
+  sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy3);
   sqlite3ExplainFinish(pParse->pVdbe);
-  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
+  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy3);
 }
         break;
-      case 113: /* select ::= oneselect */
-{yygotominor.yy159 = yymsp[0].minor.yy159;}
+      case 112: /* select ::= with selectnowith */
+{
+  Select *p = yymsp[0].minor.yy3, *pNext, *pLoop;
+  if( p ){
+    int cnt = 0, mxSelect;
+    p->pWith = yymsp[-1].minor.yy59;
+    if( p->pPrior ){
+      pNext = 0;
+      for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
+        pLoop->pNext = pNext;
+        pLoop->selFlags |= SF_Compound;
+      }
+      mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
+      if( mxSelect && cnt>mxSelect ){
+        sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
+      }
+    }
+  }else{
+    sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy59);
+  }
+  yygotominor.yy3 = p;
+}
         break;
-      case 114: /* select ::= select multiselect_op oneselect */
+      case 113: /* selectnowith ::= oneselect */
+      case 119: /* oneselect ::= values */ yytestcase(yyruleno==119);
+{yygotominor.yy3 = yymsp[0].minor.yy3;}
+        break;
+      case 114: /* selectnowith ::= selectnowith multiselect_op oneselect */
 {
-  if( yymsp[0].minor.yy159 ){
-    yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392;
-    yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159;
+  Select *pRhs = yymsp[0].minor.yy3;
+  if( pRhs && pRhs->pPrior ){
+    SrcList *pFrom;
+    Token x;
+    x.n = 0;
+    pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
+    pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0);
+  }
+  if( pRhs ){
+    pRhs->op = (u8)yymsp[-1].minor.yy328;
+    pRhs->pPrior = yymsp[-2].minor.yy3;
+    if( yymsp[-1].minor.yy328!=TK_ALL ) pParse->hasCompound = 1;
   }else{
-    sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159);
+    sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy3);
   }
-  yygotominor.yy159 = yymsp[0].minor.yy159;
+  yygotominor.yy3 = pRhs;
 }
         break;
       case 116: /* multiselect_op ::= UNION ALL */
-{yygotominor.yy392 = TK_ALL;}
+{yygotominor.yy328 = TK_ALL;}
         break;
       case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
 {
-  yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
+  yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy65,yymsp[-4].minor.yy132,yymsp[-3].minor.yy14,yymsp[-2].minor.yy132,yymsp[-1].minor.yy14,yymsp[-7].minor.yy381,yymsp[0].minor.yy476.pLimit,yymsp[0].minor.yy476.pOffset);
 }
         break;
-      case 119: /* distinct ::= DISTINCT */
-{yygotominor.yy305 = SF_Distinct;}
+      case 120: /* values ::= VALUES LP nexprlist RP */
+{
+  yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0,0);
+}
+        break;
+      case 121: /* values ::= values COMMA LP exprlist RP */
+{
+  Select *pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0,0);
+  if( pRight ){
+    pRight->op = TK_ALL;
+    pRight->pPrior = yymsp[-4].minor.yy3;
+    yygotominor.yy3 = pRight;
+  }else{
+    yygotominor.yy3 = yymsp[-4].minor.yy3;
+  }
+}
         break;
-      case 120: /* distinct ::= ALL */
-      case 121: /* distinct ::= */ yytestcase(yyruleno==121);
-{yygotominor.yy305 = 0;}
+      case 122: /* distinct ::= DISTINCT */
+{yygotominor.yy381 = SF_Distinct;}
         break;
-      case 122: /* sclp ::= selcollist COMMA */
-      case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
-{yygotominor.yy442 = yymsp[-1].minor.yy442;}
+      case 123: /* distinct ::= ALL */
+      case 124: /* distinct ::= */ yytestcase(yyruleno==124);
+{yygotominor.yy381 = 0;}
         break;
-      case 123: /* sclp ::= */
-      case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151);
-      case 158: /* groupby_opt ::= */ yytestcase(yyruleno==158);
-      case 239: /* exprlist ::= */ yytestcase(yyruleno==239);
-      case 245: /* idxlist_opt ::= */ yytestcase(yyruleno==245);
-{yygotominor.yy442 = 0;}
+      case 125: /* sclp ::= selcollist COMMA */
+      case 243: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==243);
+{yygotominor.yy14 = yymsp[-1].minor.yy14;}
         break;
-      case 124: /* selcollist ::= sclp expr as */
+      case 126: /* sclp ::= */
+      case 154: /* orderby_opt ::= */ yytestcase(yyruleno==154);
+      case 161: /* groupby_opt ::= */ yytestcase(yyruleno==161);
+      case 236: /* exprlist ::= */ yytestcase(yyruleno==236);
+      case 242: /* idxlist_opt ::= */ yytestcase(yyruleno==242);
+{yygotominor.yy14 = 0;}
+        break;
+      case 127: /* selcollist ::= sclp expr as */
 {
-   yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr);
-   if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[0].minor.yy0, 1);
-   sqlite3ExprListSetSpan(pParse,yygotominor.yy442,&yymsp[-1].minor.yy342);
+   yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy14, yymsp[-1].minor.yy346.pExpr);
+   if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[0].minor.yy0, 1);
+   sqlite3ExprListSetSpan(pParse,yygotominor.yy14,&yymsp[-1].minor.yy346);
 }
         break;
-      case 125: /* selcollist ::= sclp STAR */
+      case 128: /* selcollist ::= sclp STAR */
 {
   Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p);
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy14, p);
 }
         break;
-      case 126: /* selcollist ::= sclp nm DOT STAR */
+      case 129: /* selcollist ::= sclp nm DOT STAR */
 {
   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.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot);
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14, pDot);
 }
         break;
-      case 129: /* as ::= */
+      case 132: /* as ::= */
 {yygotominor.yy0.n = 0;}
         break;
-      case 130: /* from ::= */
-{yygotominor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy347));}
+      case 133: /* from ::= */
+{yygotominor.yy65 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy65));}
         break;
-      case 131: /* from ::= FROM seltablist */
+      case 134: /* from ::= FROM seltablist */
 {
-  yygotominor.yy347 = yymsp[0].minor.yy347;
-  sqlite3SrcListShiftJoinType(yygotominor.yy347);
+  yygotominor.yy65 = yymsp[0].minor.yy65;
+  sqlite3SrcListShiftJoinType(yygotominor.yy65);
 }
         break;
-      case 132: /* stl_prefix ::= seltablist joinop */
+      case 135: /* stl_prefix ::= seltablist joinop */
 {
-   yygotominor.yy347 = yymsp[-1].minor.yy347;
-   if( ALWAYS(yygotominor.yy347 && yygotominor.yy347->nSrc>0) ) yygotominor.yy347->a[yygotominor.yy347->nSrc-1].jointype = (u8)yymsp[0].minor.yy392;
+   yygotominor.yy65 = yymsp[-1].minor.yy65;
+   if( ALWAYS(yygotominor.yy65 && yygotominor.yy65->nSrc>0) ) yygotominor.yy65->a[yygotominor.yy65->nSrc-1].jointype = (u8)yymsp[0].minor.yy328;
 }
         break;
-      case 133: /* stl_prefix ::= */
-{yygotominor.yy347 = 0;}
+      case 136: /* stl_prefix ::= */
+{yygotominor.yy65 = 0;}
         break;
-      case 134: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+      case 137: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
 {
-  yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
-  sqlite3SrcListIndexedBy(pParse, yygotominor.yy347, &yymsp[-2].minor.yy0);
+  yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy132,yymsp[0].minor.yy408);
+  sqlite3SrcListIndexedBy(pParse, yygotominor.yy65, &yymsp[-2].minor.yy0);
 }
         break;
-      case 135: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+      case 138: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
 {
-    yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+    yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy3,yymsp[-1].minor.yy132,yymsp[0].minor.yy408);
   }
         break;
-      case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+      case 139: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
 {
-    if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
-      yygotominor.yy347 = yymsp[-4].minor.yy347;
-    }else if( yymsp[-4].minor.yy347->nSrc==1 ){
-      yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
-      if( yygotominor.yy347 ){
-        struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1];
-        struct SrcList_item *pOld = yymsp[-4].minor.yy347->a;
+    if( yymsp[-6].minor.yy65==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy132==0 && yymsp[0].minor.yy408==0 ){
+      yygotominor.yy65 = yymsp[-4].minor.yy65;
+    }else if( yymsp[-4].minor.yy65->nSrc==1 ){
+      yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy132,yymsp[0].minor.yy408);
+      if( yygotominor.yy65 ){
+        struct SrcList_item *pNew = &yygotominor.yy65->a[yygotominor.yy65->nSrc-1];
+        struct SrcList_item *pOld = yymsp[-4].minor.yy65->a;
         pNew->zName = pOld->zName;
         pNew->zDatabase = pOld->zDatabase;
         pNew->pSelect = pOld->pSelect;
         pOld->zName = pOld->zDatabase = 0;
         pOld->pSelect = 0;
       }
-      sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347);
+      sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy65);
     }else{
       Select *pSubquery;
-      sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
-      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0);
-      yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+      sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy65);
+      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy65,0,0,0,0,SF_NestedFrom,0,0);
+      yygotominor.yy65 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy65,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy132,yymsp[0].minor.yy408);
     }
   }
         break;
-      case 137: /* dbnm ::= */
-      case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146);
+      case 140: /* dbnm ::= */
+      case 149: /* indexed_opt ::= */ yytestcase(yyruleno==149);
 {yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
         break;
-      case 139: /* fullname ::= nm dbnm */
-{yygotominor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
+      case 142: /* fullname ::= nm dbnm */
+{yygotominor.yy65 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
         break;
-      case 140: /* joinop ::= COMMA|JOIN */
-{ yygotominor.yy392 = JT_INNER; }
+      case 143: /* joinop ::= COMMA|JOIN */
+{ yygotominor.yy328 = JT_INNER; }
         break;
-      case 141: /* joinop ::= JOIN_KW JOIN */
-{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+      case 144: /* joinop ::= JOIN_KW JOIN */
+{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
         break;
-      case 142: /* joinop ::= JOIN_KW nm JOIN */
-{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
+      case 145: /* joinop ::= JOIN_KW nm JOIN */
+{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
         break;
-      case 143: /* joinop ::= JOIN_KW nm nm JOIN */
-{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
+      case 146: /* joinop ::= JOIN_KW nm nm JOIN */
+{ yygotominor.yy328 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
         break;
-      case 144: /* on_opt ::= ON expr */
-      case 161: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==161);
-      case 168: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==168);
-      case 234: /* case_else ::= ELSE expr */ yytestcase(yyruleno==234);
-      case 236: /* case_operand ::= expr */ yytestcase(yyruleno==236);
-{yygotominor.yy122 = yymsp[0].minor.yy342.pExpr;}
+      case 147: /* on_opt ::= ON expr */
+      case 164: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==164);
+      case 171: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==171);
+      case 231: /* case_else ::= ELSE expr */ yytestcase(yyruleno==231);
+      case 233: /* case_operand ::= expr */ yytestcase(yyruleno==233);
+{yygotominor.yy132 = yymsp[0].minor.yy346.pExpr;}
         break;
-      case 145: /* on_opt ::= */
-      case 160: /* having_opt ::= */ yytestcase(yyruleno==160);
-      case 167: /* where_opt ::= */ yytestcase(yyruleno==167);
-      case 235: /* case_else ::= */ yytestcase(yyruleno==235);
-      case 237: /* case_operand ::= */ yytestcase(yyruleno==237);
-{yygotominor.yy122 = 0;}
+      case 148: /* on_opt ::= */
+      case 163: /* having_opt ::= */ yytestcase(yyruleno==163);
+      case 170: /* where_opt ::= */ yytestcase(yyruleno==170);
+      case 232: /* case_else ::= */ yytestcase(yyruleno==232);
+      case 234: /* case_operand ::= */ yytestcase(yyruleno==234);
+{yygotominor.yy132 = 0;}
         break;
-      case 148: /* indexed_opt ::= NOT INDEXED */
+      case 151: /* indexed_opt ::= NOT INDEXED */
 {yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
         break;
-      case 149: /* using_opt ::= USING LP inscollist RP */
-      case 180: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==180);
-{yygotominor.yy180 = yymsp[-1].minor.yy180;}
+      case 152: /* using_opt ::= USING LP idlist RP */
+      case 180: /* inscollist_opt ::= LP idlist RP */ yytestcase(yyruleno==180);
+{yygotominor.yy408 = yymsp[-1].minor.yy408;}
         break;
-      case 150: /* using_opt ::= */
+      case 153: /* using_opt ::= */
       case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179);
-{yygotominor.yy180 = 0;}
+{yygotominor.yy408 = 0;}
         break;
-      case 152: /* orderby_opt ::= ORDER BY sortlist */
-      case 159: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==159);
-      case 238: /* exprlist ::= nexprlist */ yytestcase(yyruleno==238);
-{yygotominor.yy442 = yymsp[0].minor.yy442;}
+      case 155: /* orderby_opt ::= ORDER BY sortlist */
+      case 162: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==162);
+      case 235: /* exprlist ::= nexprlist */ yytestcase(yyruleno==235);
+{yygotominor.yy14 = yymsp[0].minor.yy14;}
         break;
-      case 153: /* sortlist ::= sortlist COMMA expr sortorder */
+      case 156: /* sortlist ::= sortlist COMMA expr sortorder */
 {
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr);
-  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14,yymsp[-1].minor.yy346.pExpr);
+  if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328;
 }
         break;
-      case 154: /* sortlist ::= expr sortorder */
+      case 157: /* sortlist ::= expr sortorder */
 {
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr);
-  if( yygotominor.yy442 && ALWAYS(yygotominor.yy442->a) ) yygotominor.yy442->a[0].sortOrder = (u8)yymsp[0].minor.yy392;
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy346.pExpr);
+  if( yygotominor.yy14 && ALWAYS(yygotominor.yy14->a) ) yygotominor.yy14->a[0].sortOrder = (u8)yymsp[0].minor.yy328;
 }
         break;
-      case 155: /* sortorder ::= ASC */
-      case 157: /* sortorder ::= */ yytestcase(yyruleno==157);
-{yygotominor.yy392 = SQLITE_SO_ASC;}
+      case 158: /* sortorder ::= ASC */
+      case 160: /* sortorder ::= */ yytestcase(yyruleno==160);
+{yygotominor.yy328 = SQLITE_SO_ASC;}
         break;
-      case 156: /* sortorder ::= DESC */
-{yygotominor.yy392 = SQLITE_SO_DESC;}
+      case 159: /* sortorder ::= DESC */
+{yygotominor.yy328 = SQLITE_SO_DESC;}
         break;
-      case 162: /* limit_opt ::= */
-{yygotominor.yy64.pLimit = 0; yygotominor.yy64.pOffset = 0;}
+      case 165: /* limit_opt ::= */
+{yygotominor.yy476.pLimit = 0; yygotominor.yy476.pOffset = 0;}
         break;
-      case 163: /* limit_opt ::= LIMIT expr */
-{yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yygotominor.yy64.pOffset = 0;}
+      case 166: /* limit_opt ::= LIMIT expr */
+{yygotominor.yy476.pLimit = yymsp[0].minor.yy346.pExpr; yygotominor.yy476.pOffset = 0;}
         break;
-      case 164: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yygotominor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;}
+      case 167: /* limit_opt ::= LIMIT expr OFFSET expr */
+{yygotominor.yy476.pLimit = yymsp[-2].minor.yy346.pExpr; yygotominor.yy476.pOffset = yymsp[0].minor.yy346.pExpr;}
         break;
-      case 165: /* limit_opt ::= LIMIT expr COMMA expr */
-{yygotominor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;}
+      case 168: /* limit_opt ::= LIMIT expr COMMA expr */
+{yygotominor.yy476.pOffset = yymsp[-2].minor.yy346.pExpr; yygotominor.yy476.pLimit = yymsp[0].minor.yy346.pExpr;}
         break;
-      case 166: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
+      case 169: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */
 {
-  sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0);
-  sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122);
+  sqlite3WithPush(pParse, yymsp[-5].minor.yy59, 1);
+  sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy65, &yymsp[-1].minor.yy0);
+  sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy65,yymsp[0].minor.yy132);
 }
         break;
-      case 169: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
+      case 172: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */
 {
-  sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0);
-  sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list"); 
-  sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258);
+  sqlite3WithPush(pParse, yymsp[-7].minor.yy59, 1);
+  sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy65, &yymsp[-3].minor.yy0);
+  sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy14,"set list"); 
+  sqlite3Update(pParse,yymsp[-4].minor.yy65,yymsp[-1].minor.yy14,yymsp[0].minor.yy132,yymsp[-5].minor.yy186);
 }
         break;
-      case 170: /* setlist ::= setlist COMMA nm EQ expr */
+      case 173: /* setlist ::= setlist COMMA nm EQ expr */
 {
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr);
-  sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[0].minor.yy346.pExpr);
+  sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1);
 }
         break;
-      case 171: /* setlist ::= nm EQ expr */
+      case 174: /* setlist ::= nm EQ expr */
 {
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr);
-  sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy346.pExpr);
+  sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1);
 }
         break;
-      case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
-{sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
-        break;
-      case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
-{sqlite3Insert(pParse, yymsp[-2].minor.yy347, 0, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
-        break;
-      case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
-{sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy258);}
-        break;
-      case 175: /* insert_cmd ::= INSERT orconf */
-{yygotominor.yy258 = yymsp[0].minor.yy258;}
-        break;
-      case 176: /* insert_cmd ::= REPLACE */
-{yygotominor.yy258 = OE_Replace;}
-        break;
-      case 177: /* valuelist ::= VALUES LP nexprlist RP */
+      case 175: /* cmd ::= with insert_cmd INTO fullname inscollist_opt select */
 {
-  yygotominor.yy487.pList = yymsp[-1].minor.yy442;
-  yygotominor.yy487.pSelect = 0;
+  sqlite3WithPush(pParse, yymsp[-5].minor.yy59, 1);
+  sqlite3Insert(pParse, yymsp[-2].minor.yy65, yymsp[0].minor.yy3, yymsp[-1].minor.yy408, yymsp[-4].minor.yy186);
 }
         break;
-      case 178: /* valuelist ::= valuelist COMMA LP exprlist RP */
+      case 176: /* cmd ::= with insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
 {
-  Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy442, 0, 0, 0, 0, 0, 0, 0, 0);
-  if( yymsp[-4].minor.yy487.pList ){
-    yymsp[-4].minor.yy487.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy487.pList, 0, 0, 0, 0, 0, 0, 0, 0);
-    yymsp[-4].minor.yy487.pList = 0;
-  }
-  yygotominor.yy487.pList = 0;
-  if( yymsp[-4].minor.yy487.pSelect==0 || pRight==0 ){
-    sqlite3SelectDelete(pParse->db, pRight);
-    sqlite3SelectDelete(pParse->db, yymsp[-4].minor.yy487.pSelect);
-    yygotominor.yy487.pSelect = 0;
-  }else{
-    pRight->op = TK_ALL;
-    pRight->pPrior = yymsp[-4].minor.yy487.pSelect;
-    pRight->selFlags |= SF_Values;
-    pRight->pPrior->selFlags |= SF_Values;
-    yygotominor.yy487.pSelect = pRight;
-  }
+  sqlite3WithPush(pParse, yymsp[-6].minor.yy59, 1);
+  sqlite3Insert(pParse, yymsp[-3].minor.yy65, 0, yymsp[-2].minor.yy408, yymsp[-5].minor.yy186);
 }
         break;
-      case 181: /* inscollist ::= inscollist COMMA nm */
-{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);}
+      case 177: /* insert_cmd ::= INSERT orconf */
+{yygotominor.yy186 = yymsp[0].minor.yy186;}
+        break;
+      case 178: /* insert_cmd ::= REPLACE */
+{yygotominor.yy186 = OE_Replace;}
         break;
-      case 182: /* inscollist ::= nm */
-{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
+      case 181: /* idlist ::= idlist COMMA nm */
+{yygotominor.yy408 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy408,&yymsp[0].minor.yy0);}
+        break;
+      case 182: /* idlist ::= nm */
+{yygotominor.yy408 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
         break;
       case 183: /* expr ::= term */
-{yygotominor.yy342 = yymsp[0].minor.yy342;}
+{yygotominor.yy346 = yymsp[0].minor.yy346;}
         break;
       case 184: /* expr ::= LP expr RP */
-{yygotominor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr; spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
+{yygotominor.yy346.pExpr = yymsp[-1].minor.yy346.pExpr; spanSet(&yygotominor.yy346,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
         break;
       case 185: /* term ::= NULL */
       case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190);
       case 191: /* term ::= STRING */ yytestcase(yyruleno==191);
-{spanExpr(&yygotominor.yy342, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
+{spanExpr(&yygotominor.yy346, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
         break;
-      case 186: /* expr ::= id */
+      case 186: /* expr ::= ID|INDEXED */
       case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187);
-{spanExpr(&yygotominor.yy342, pParse, TK_ID, &yymsp[0].minor.yy0);}
+{spanExpr(&yygotominor.yy346, pParse, TK_ID, &yymsp[0].minor.yy0);}
         break;
       case 188: /* 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.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
-  spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+  yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
+  spanSet(&yygotominor.yy346,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
 }
         break;
       case 189: /* expr ::= nm DOT nm DOT nm */
@@ -112802,163 +120151,154 @@ static void yy_reduce(
   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.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
-  spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+  yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
+  spanSet(&yygotominor.yy346,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
 }
         break;
-      case 192: /* expr ::= REGISTER */
+      case 192: /* expr ::= VARIABLE */
 {
-  /* When doing a nested parse, one can include terms in an expression
-  ** that look like this:   #1 #2 ...  These terms refer to registers
-  ** in the virtual machine.  #N is the N-th register. */
-  if( pParse->nested==0 ){
-    sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0);
-    yygotominor.yy342.pExpr = 0;
+  if( yymsp[0].minor.yy0.n>=2 && yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1]) ){
+    /* When doing a nested parse, one can include terms in an expression
+    ** that look like this:   #1 #2 ...  These terms refer to registers
+    ** in the virtual machine.  #N is the N-th register. */
+    if( pParse->nested==0 ){
+      sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0);
+      yygotominor.yy346.pExpr = 0;
+    }else{
+      yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0);
+      if( yygotominor.yy346.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy346.pExpr->iTable);
+    }
   }else{
-    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0);
-    if( yygotominor.yy342.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy342.pExpr->iTable);
+    spanExpr(&yygotominor.yy346, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
+    sqlite3ExprAssignVarNumber(pParse, yygotominor.yy346.pExpr);
   }
-  spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
+  spanSet(&yygotominor.yy346, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
 }
         break;
-      case 193: /* expr ::= VARIABLE */
+      case 193: /* expr ::= expr COLLATE ID|STRING */
 {
-  spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
-  sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr);
-  spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
+  yygotominor.yy346.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy346.pExpr, &yymsp[0].minor.yy0);
+  yygotominor.yy346.zStart = yymsp[-2].minor.yy346.zStart;
+  yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
 }
         break;
-      case 194: /* expr ::= expr COLLATE ids */
+      case 194: /* expr ::= CAST LP expr AS typetoken RP */
 {
-  yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
-  yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
-  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+  yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy346.pExpr, 0, &yymsp[-1].minor.yy0);
+  spanSet(&yygotominor.yy346,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
 }
         break;
-      case 195: /* expr ::= CAST LP expr AS typetoken RP */
+      case 195: /* expr ::= ID|INDEXED LP distinct exprlist RP */
 {
-  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0);
-  spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
-}
-        break;
-      case 196: /* expr ::= ID LP distinct exprlist RP */
-{
-  if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
+  if( yymsp[-1].minor.yy14 && yymsp[-1].minor.yy14->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
     sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
   }
-  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
-  spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
-  if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){
-    yygotominor.yy342.pExpr->flags |= EP_Distinct;
+  yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0);
+  spanSet(&yygotominor.yy346,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+  if( yymsp[-2].minor.yy381 && yygotominor.yy346.pExpr ){
+    yygotominor.yy346.pExpr->flags |= EP_Distinct;
   }
 }
         break;
-      case 197: /* expr ::= ID LP STAR RP */
+      case 196: /* expr ::= ID|INDEXED LP STAR RP */
 {
-  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
-  spanSet(&yygotominor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+  yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
+  spanSet(&yygotominor.yy346,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
 }
         break;
-      case 198: /* term ::= CTIME_KW */
+      case 197: /* term ::= CTIME_KW */
 {
-  /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
-  ** treated as functions that return constants */
-  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
-  if( yygotominor.yy342.pExpr ){
-    yygotominor.yy342.pExpr->op = TK_CONST_FUNC;  
-  }
-  spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
+  yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0);
+  spanSet(&yygotominor.yy346, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
 }
         break;
-      case 199: /* expr ::= expr AND expr */
-      case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200);
-      case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201);
-      case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202);
-      case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203);
-      case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204);
-      case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205);
-      case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206);
-{spanBinaryExpr(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);}
+      case 198: /* expr ::= expr AND expr */
+      case 199: /* expr ::= expr OR expr */ yytestcase(yyruleno==199);
+      case 200: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==200);
+      case 201: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==201);
+      case 202: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==202);
+      case 203: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==203);
+      case 204: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==204);
+      case 205: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==205);
+{spanBinaryExpr(&yygotominor.yy346,pParse,yymsp[-1].major,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy346);}
         break;
-      case 207: /* likeop ::= LIKE_KW */
-      case 209: /* likeop ::= MATCH */ yytestcase(yyruleno==209);
-{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 0;}
+      case 206: /* likeop ::= LIKE_KW|MATCH */
+{yygotominor.yy96.eOperator = yymsp[0].minor.yy0; yygotominor.yy96.bNot = 0;}
         break;
-      case 208: /* likeop ::= NOT LIKE_KW */
-      case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210);
-{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 1;}
+      case 207: /* likeop ::= NOT LIKE_KW|MATCH */
+{yygotominor.yy96.eOperator = yymsp[0].minor.yy0; yygotominor.yy96.bNot = 1;}
         break;
-      case 211: /* expr ::= expr likeop expr */
+      case 208: /* expr ::= expr likeop expr */
 {
   ExprList *pList;
-  pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr);
-  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr);
-  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator);
-  if( yymsp[-1].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
-  yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
-  yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
-  if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
+  pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy346.pExpr);
+  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy346.pExpr);
+  yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy96.eOperator);
+  if( yymsp[-1].minor.yy96.bNot ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0);
+  yygotominor.yy346.zStart = yymsp[-2].minor.yy346.zStart;
+  yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd;
+  if( yygotominor.yy346.pExpr ) yygotominor.yy346.pExpr->flags |= EP_InfixFunc;
 }
         break;
-      case 212: /* expr ::= expr likeop expr ESCAPE expr */
+      case 209: /* expr ::= expr likeop expr ESCAPE expr */
 {
   ExprList *pList;
-  pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
-  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr);
-  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
-  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator);
-  if( yymsp[-3].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
-  yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
-  yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
-  if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
+  pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr);
+  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy346.pExpr);
+  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy346.pExpr);
+  yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy96.eOperator);
+  if( yymsp[-3].minor.yy96.bNot ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0);
+  yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart;
+  yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd;
+  if( yygotominor.yy346.pExpr ) yygotominor.yy346.pExpr->flags |= EP_InfixFunc;
 }
         break;
-      case 213: /* expr ::= expr ISNULL|NOTNULL */
-{spanUnaryPostfix(&yygotominor.yy342,pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);}
+      case 210: /* expr ::= expr ISNULL|NOTNULL */
+{spanUnaryPostfix(&yygotominor.yy346,pParse,yymsp[0].major,&yymsp[-1].minor.yy346,&yymsp[0].minor.yy0);}
         break;
-      case 214: /* expr ::= expr NOT NULL */
-{spanUnaryPostfix(&yygotominor.yy342,pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);}
+      case 211: /* expr ::= expr NOT NULL */
+{spanUnaryPostfix(&yygotominor.yy346,pParse,TK_NOTNULL,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy0);}
         break;
-      case 215: /* expr ::= expr IS expr */
+      case 212: /* expr ::= expr IS expr */
 {
-  spanBinaryExpr(&yygotominor.yy342,pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);
-  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_ISNULL);
+  spanBinaryExpr(&yygotominor.yy346,pParse,TK_IS,&yymsp[-2].minor.yy346,&yymsp[0].minor.yy346);
+  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy346.pExpr, yygotominor.yy346.pExpr, TK_ISNULL);
 }
         break;
-      case 216: /* expr ::= expr IS NOT expr */
+      case 213: /* expr ::= expr IS NOT expr */
 {
-  spanBinaryExpr(&yygotominor.yy342,pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342);
-  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_NOTNULL);
+  spanBinaryExpr(&yygotominor.yy346,pParse,TK_ISNOT,&yymsp[-3].minor.yy346,&yymsp[0].minor.yy346);
+  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy346.pExpr, yygotominor.yy346.pExpr, TK_NOTNULL);
 }
         break;
-      case 217: /* expr ::= NOT expr */
-      case 218: /* expr ::= BITNOT expr */ yytestcase(yyruleno==218);
-{spanUnaryPrefix(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
+      case 214: /* expr ::= NOT expr */
+      case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215);
+{spanUnaryPrefix(&yygotominor.yy346,pParse,yymsp[-1].major,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);}
         break;
-      case 219: /* expr ::= MINUS expr */
-{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
+      case 216: /* expr ::= MINUS expr */
+{spanUnaryPrefix(&yygotominor.yy346,pParse,TK_UMINUS,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);}
         break;
-      case 220: /* expr ::= PLUS expr */
-{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
+      case 217: /* expr ::= PLUS expr */
+{spanUnaryPrefix(&yygotominor.yy346,pParse,TK_UPLUS,&yymsp[0].minor.yy346,&yymsp[-1].minor.yy0);}
         break;
-      case 223: /* expr ::= expr between_op expr AND expr */
+      case 220: /* expr ::= expr between_op expr AND expr */
 {
-  ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
-  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
-  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0);
-  if( yygotominor.yy342.pExpr ){
-    yygotominor.yy342.pExpr->x.pList = pList;
+  ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr);
+  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy346.pExpr);
+  yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy346.pExpr, 0, 0);
+  if( yygotominor.yy346.pExpr ){
+    yygotominor.yy346.pExpr->x.pList = pList;
   }else{
     sqlite3ExprListDelete(pParse->db, pList);
   } 
-  if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
-  yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
-  yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
+  if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0);
+  yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart;
+  yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd;
 }
         break;
-      case 226: /* expr ::= expr in_op LP exprlist RP */
+      case 223: /* expr ::= expr in_op LP exprlist RP */
 {
-    if( yymsp[-1].minor.yy442==0 ){
+    if( yymsp[-1].minor.yy14==0 ){
       /* Expressions of the form
       **
       **      expr1 IN ()
@@ -112967,224 +120307,252 @@ static void yy_reduce(
       ** simplify to constants 0 (false) and 1 (true), respectively,
       ** regardless of the value of expr1.
       */
-      yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy392]);
-      sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy342.pExpr);
+      yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy328]);
+      sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy346.pExpr);
+    }else if( yymsp[-1].minor.yy14->nExpr==1 ){
+      /* Expressions of the form:
+      **
+      **      expr1 IN (?1)
+      **      expr1 NOT IN (?2)
+      **
+      ** with exactly one value on the RHS can be simplified to something
+      ** like this:
+      **
+      **      expr1 == ?1
+      **      expr1 <> ?2
+      **
+      ** But, the RHS of the == or <> is marked with the EP_Generic flag
+      ** so that it may not contribute to the computation of comparison
+      ** affinity or the collating sequence to use for comparison.  Otherwise,
+      ** the semantics would be subtly different from IN or NOT IN.
+      */
+      Expr *pRHS = yymsp[-1].minor.yy14->a[0].pExpr;
+      yymsp[-1].minor.yy14->a[0].pExpr = 0;
+      sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
+      /* pRHS cannot be NULL because a malloc error would have been detected
+      ** before now and control would have never reached this point */
+      if( ALWAYS(pRHS) ){
+        pRHS->flags &= ~EP_Collate;
+        pRHS->flags |= EP_Generic;
+      }
+      yygotominor.yy346.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy328 ? TK_NE : TK_EQ, yymsp[-4].minor.yy346.pExpr, pRHS, 0);
     }else{
-      yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
-      if( yygotominor.yy342.pExpr ){
-        yygotominor.yy342.pExpr->x.pList = yymsp[-1].minor.yy442;
-        sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+      yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0);
+      if( yygotominor.yy346.pExpr ){
+        yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy14;
+        sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
       }else{
-        sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy442);
+        sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
       }
-      if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
+      if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0);
     }
-    yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
-    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+    yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart;
+    yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
   }
         break;
-      case 227: /* expr ::= LP select RP */
+      case 224: /* expr ::= LP select RP */
 {
-    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
-    if( yygotominor.yy342.pExpr ){
-      yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
-      ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
-      sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+    yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
+    if( yygotominor.yy346.pExpr ){
+      yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3;
+      ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect);
+      sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
     }else{
-      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
+      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3);
     }
-    yygotominor.yy342.zStart = yymsp[-2].minor.yy0.z;
-    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+    yygotominor.yy346.zStart = yymsp[-2].minor.yy0.z;
+    yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
   }
         break;
-      case 228: /* expr ::= expr in_op LP select RP */
+      case 225: /* expr ::= expr in_op LP select RP */
 {
-    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
-    if( yygotominor.yy342.pExpr ){
-      yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
-      ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
-      sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+    yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0);
+    if( yygotominor.yy346.pExpr ){
+      yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3;
+      ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect);
+      sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
     }else{
-      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
+      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3);
     }
-    if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
-    yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
-    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+    if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0);
+    yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart;
+    yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
   }
         break;
-      case 229: /* expr ::= expr in_op nm dbnm */
+      case 226: /* expr ::= expr in_op nm dbnm */
 {
     SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
-    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0);
-    if( yygotominor.yy342.pExpr ){
-      yygotominor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
-      ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
-      sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+    yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy346.pExpr, 0, 0);
+    if( yygotominor.yy346.pExpr ){
+      yygotominor.yy346.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
+      ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect);
+      sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
     }else{
       sqlite3SrcListDelete(pParse->db, pSrc);
     }
-    if( yymsp[-2].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
-    yygotominor.yy342.zStart = yymsp[-3].minor.yy342.zStart;
-    yygotominor.yy342.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
+    if( yymsp[-2].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0);
+    yygotominor.yy346.zStart = yymsp[-3].minor.yy346.zStart;
+    yygotominor.yy346.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
   }
         break;
-      case 230: /* expr ::= EXISTS LP select RP */
+      case 227: /* expr ::= EXISTS LP select RP */
 {
-    Expr *p = yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
+    Expr *p = yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
     if( p ){
-      p->x.pSelect = yymsp[-1].minor.yy159;
+      p->x.pSelect = yymsp[-1].minor.yy3;
       ExprSetProperty(p, EP_xIsSelect);
       sqlite3ExprSetHeight(pParse, p);
     }else{
-      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
+      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3);
     }
-    yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
-    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+    yygotominor.yy346.zStart = yymsp[-3].minor.yy0.z;
+    yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
   }
         break;
-      case 231: /* expr ::= CASE case_operand case_exprlist case_else END */
+      case 228: /* expr ::= CASE case_operand case_exprlist case_else END */
 {
-  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, yymsp[-1].minor.yy122, 0);
-  if( yygotominor.yy342.pExpr ){
-    yygotominor.yy342.pExpr->x.pList = yymsp[-2].minor.yy442;
-    sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+  yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy132, 0, 0);
+  if( yygotominor.yy346.pExpr ){
+    yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy132 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy132) : yymsp[-2].minor.yy14;
+    sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
   }else{
-    sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy442);
+    sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14);
+    sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy132);
   }
-  yygotominor.yy342.zStart = yymsp[-4].minor.yy0.z;
-  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+  yygotominor.yy346.zStart = yymsp[-4].minor.yy0.z;
+  yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
 }
         break;
-      case 232: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+      case 229: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
 {
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr);
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[-2].minor.yy346.pExpr);
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse,yygotominor.yy14, yymsp[0].minor.yy346.pExpr);
 }
         break;
-      case 233: /* case_exprlist ::= WHEN expr THEN expr */
+      case 230: /* case_exprlist ::= WHEN expr THEN expr */
 {
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy346.pExpr);
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse,yygotominor.yy14, yymsp[0].minor.yy346.pExpr);
 }
         break;
-      case 240: /* nexprlist ::= nexprlist COMMA expr */
-{yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);}
+      case 237: /* nexprlist ::= nexprlist COMMA expr */
+{yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[0].minor.yy346.pExpr);}
         break;
-      case 241: /* nexprlist ::= expr */
-{yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);}
+      case 238: /* nexprlist ::= expr */
+{yygotominor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy346.pExpr);}
         break;
-      case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
+      case 239: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt */
 {
-  sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, 
-                     sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392,
-                      &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392);
+  sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, 
+                     sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy14, yymsp[-10].minor.yy328,
+                      &yymsp[-11].minor.yy0, yymsp[0].minor.yy132, SQLITE_SO_ASC, yymsp[-8].minor.yy328);
 }
         break;
-      case 243: /* uniqueflag ::= UNIQUE */
-      case 296: /* raisetype ::= ABORT */ yytestcase(yyruleno==296);
-{yygotominor.yy392 = OE_Abort;}
+      case 240: /* uniqueflag ::= UNIQUE */
+      case 291: /* raisetype ::= ABORT */ yytestcase(yyruleno==291);
+{yygotominor.yy328 = OE_Abort;}
         break;
-      case 244: /* uniqueflag ::= */
-{yygotominor.yy392 = OE_None;}
+      case 241: /* uniqueflag ::= */
+{yygotominor.yy328 = OE_None;}
         break;
-      case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
+      case 244: /* idxlist ::= idxlist COMMA nm collate sortorder */
 {
   Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
-  sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
-  sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
-  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, p);
+  sqlite3ExprListSetName(pParse,yygotominor.yy14,&yymsp[-2].minor.yy0,1);
+  sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index");
+  if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328;
 }
         break;
-      case 248: /* idxlist ::= nm collate sortorder */
+      case 245: /* idxlist ::= nm collate sortorder */
 {
   Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
-  yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
-  sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
-  sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
-  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
+  yygotominor.yy14 = sqlite3ExprListAppend(pParse,0, p);
+  sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1);
+  sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index");
+  if( yygotominor.yy14 ) yygotominor.yy14->a[yygotominor.yy14->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy328;
 }
         break;
-      case 249: /* collate ::= */
+      case 246: /* collate ::= */
 {yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
         break;
-      case 251: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);}
+      case 248: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy65, yymsp[-1].minor.yy328);}
         break;
-      case 252: /* cmd ::= VACUUM */
-      case 253: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==253);
+      case 249: /* cmd ::= VACUUM */
+      case 250: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==250);
 {sqlite3Vacuum(pParse);}
         break;
-      case 254: /* cmd ::= PRAGMA nm dbnm */
+      case 251: /* cmd ::= PRAGMA nm dbnm */
 {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
         break;
-      case 255: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+      case 252: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
 {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
         break;
-      case 256: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+      case 253: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
 {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
         break;
-      case 257: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+      case 254: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
 {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
         break;
-      case 258: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
+      case 255: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
 {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
         break;
-      case 268: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+      case 264: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
 {
   Token all;
   all.z = yymsp[-3].minor.yy0.z;
   all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
-  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all);
+  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy473, &all);
 }
         break;
-      case 269: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+      case 265: /* 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.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392);
+  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy328, yymsp[-4].minor.yy378.a, yymsp[-4].minor.yy378.b, yymsp[-2].minor.yy65, yymsp[0].minor.yy132, yymsp[-10].minor.yy328, yymsp[-8].minor.yy328);
   yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
 }
         break;
-      case 270: /* trigger_time ::= BEFORE */
-      case 273: /* trigger_time ::= */ yytestcase(yyruleno==273);
-{ yygotominor.yy392 = TK_BEFORE; }
+      case 266: /* trigger_time ::= BEFORE */
+      case 269: /* trigger_time ::= */ yytestcase(yyruleno==269);
+{ yygotominor.yy328 = TK_BEFORE; }
         break;
-      case 271: /* trigger_time ::= AFTER */
-{ yygotominor.yy392 = TK_AFTER;  }
+      case 267: /* trigger_time ::= AFTER */
+{ yygotominor.yy328 = TK_AFTER;  }
         break;
-      case 272: /* trigger_time ::= INSTEAD OF */
-{ yygotominor.yy392 = TK_INSTEAD;}
+      case 268: /* trigger_time ::= INSTEAD OF */
+{ yygotominor.yy328 = TK_INSTEAD;}
         break;
-      case 274: /* trigger_event ::= DELETE|INSERT */
-      case 275: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==275);
-{yygotominor.yy410.a = yymsp[0].major; yygotominor.yy410.b = 0;}
+      case 270: /* trigger_event ::= DELETE|INSERT */
+      case 271: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==271);
+{yygotominor.yy378.a = yymsp[0].major; yygotominor.yy378.b = 0;}
         break;
-      case 276: /* trigger_event ::= UPDATE OF inscollist */
-{yygotominor.yy410.a = TK_UPDATE; yygotominor.yy410.b = yymsp[0].minor.yy180;}
+      case 272: /* trigger_event ::= UPDATE OF idlist */
+{yygotominor.yy378.a = TK_UPDATE; yygotominor.yy378.b = yymsp[0].minor.yy408;}
         break;
-      case 279: /* when_clause ::= */
-      case 301: /* key_opt ::= */ yytestcase(yyruleno==301);
-{ yygotominor.yy122 = 0; }
+      case 275: /* when_clause ::= */
+      case 296: /* key_opt ::= */ yytestcase(yyruleno==296);
+{ yygotominor.yy132 = 0; }
         break;
-      case 280: /* when_clause ::= WHEN expr */
-      case 302: /* key_opt ::= KEY expr */ yytestcase(yyruleno==302);
-{ yygotominor.yy122 = yymsp[0].minor.yy342.pExpr; }
+      case 276: /* when_clause ::= WHEN expr */
+      case 297: /* key_opt ::= KEY expr */ yytestcase(yyruleno==297);
+{ yygotominor.yy132 = yymsp[0].minor.yy346.pExpr; }
         break;
-      case 281: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+      case 277: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
 {
-  assert( yymsp[-2].minor.yy327!=0 );
-  yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327;
-  yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327;
-  yygotominor.yy327 = yymsp[-2].minor.yy327;
+  assert( yymsp[-2].minor.yy473!=0 );
+  yymsp[-2].minor.yy473->pLast->pNext = yymsp[-1].minor.yy473;
+  yymsp[-2].minor.yy473->pLast = yymsp[-1].minor.yy473;
+  yygotominor.yy473 = yymsp[-2].minor.yy473;
 }
         break;
-      case 282: /* trigger_cmd_list ::= trigger_cmd SEMI */
+      case 278: /* trigger_cmd_list ::= trigger_cmd SEMI */
 { 
-  assert( yymsp[-1].minor.yy327!=0 );
-  yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327;
-  yygotominor.yy327 = yymsp[-1].minor.yy327;
+  assert( yymsp[-1].minor.yy473!=0 );
+  yymsp[-1].minor.yy473->pLast = yymsp[-1].minor.yy473;
+  yygotominor.yy473 = yymsp[-1].minor.yy473;
 }
         break;
-      case 284: /* trnm ::= nm DOT nm */
+      case 280: /* trnm ::= nm DOT nm */
 {
   yygotominor.yy0 = yymsp[0].minor.yy0;
   sqlite3ErrorMsg(pParse, 
@@ -113192,123 +120560,137 @@ static void yy_reduce(
         "statements within triggers");
 }
         break;
-      case 286: /* tridxby ::= INDEXED BY nm */
+      case 282: /* tridxby ::= INDEXED BY nm */
 {
   sqlite3ErrorMsg(pParse,
         "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
         "within triggers");
 }
         break;
-      case 287: /* tridxby ::= NOT INDEXED */
+      case 283: /* tridxby ::= NOT INDEXED */
 {
   sqlite3ErrorMsg(pParse,
         "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
         "within triggers");
 }
         break;
-      case 288: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
-{ yygotominor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy258); }
-        break;
-      case 289: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
-{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-4].minor.yy258);}
+      case 284: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
+{ yygotominor.yy473 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy14, yymsp[0].minor.yy132, yymsp[-5].minor.yy186); }
         break;
-      case 290: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
-{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, 0, yymsp[0].minor.yy159, yymsp[-4].minor.yy258);}
+      case 285: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
+{yygotominor.yy473 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy408, yymsp[0].minor.yy3, yymsp[-4].minor.yy186);}
         break;
-      case 291: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
-{yygotominor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);}
+      case 286: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
+{yygotominor.yy473 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy132);}
         break;
-      case 292: /* trigger_cmd ::= select */
-{yygotominor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); }
+      case 287: /* trigger_cmd ::= select */
+{yygotominor.yy473 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy3); }
         break;
-      case 293: /* expr ::= RAISE LP IGNORE RP */
+      case 288: /* expr ::= RAISE LP IGNORE RP */
 {
-  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); 
-  if( yygotominor.yy342.pExpr ){
-    yygotominor.yy342.pExpr->affinity = OE_Ignore;
+  yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); 
+  if( yygotominor.yy346.pExpr ){
+    yygotominor.yy346.pExpr->affinity = OE_Ignore;
   }
-  yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
-  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+  yygotominor.yy346.zStart = yymsp[-3].minor.yy0.z;
+  yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
 }
         break;
-      case 294: /* expr ::= RAISE LP raisetype COMMA nm RP */
+      case 289: /* expr ::= RAISE LP raisetype COMMA nm RP */
 {
-  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); 
-  if( yygotominor.yy342.pExpr ) {
-    yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392;
+  yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); 
+  if( yygotominor.yy346.pExpr ) {
+    yygotominor.yy346.pExpr->affinity = (char)yymsp[-3].minor.yy328;
   }
-  yygotominor.yy342.zStart = yymsp[-5].minor.yy0.z;
-  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+  yygotominor.yy346.zStart = yymsp[-5].minor.yy0.z;
+  yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
 }
         break;
-      case 295: /* raisetype ::= ROLLBACK */
-{yygotominor.yy392 = OE_Rollback;}
+      case 290: /* raisetype ::= ROLLBACK */
+{yygotominor.yy328 = OE_Rollback;}
         break;
-      case 297: /* raisetype ::= FAIL */
-{yygotominor.yy392 = OE_Fail;}
+      case 292: /* raisetype ::= FAIL */
+{yygotominor.yy328 = OE_Fail;}
         break;
-      case 298: /* cmd ::= DROP TRIGGER ifexists fullname */
+      case 293: /* cmd ::= DROP TRIGGER ifexists fullname */
 {
-  sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392);
+  sqlite3DropTrigger(pParse,yymsp[0].minor.yy65,yymsp[-1].minor.yy328);
 }
         break;
-      case 299: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+      case 294: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
 {
-  sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122);
+  sqlite3Attach(pParse, yymsp[-3].minor.yy346.pExpr, yymsp[-1].minor.yy346.pExpr, yymsp[0].minor.yy132);
 }
         break;
-      case 300: /* cmd ::= DETACH database_kw_opt expr */
+      case 295: /* cmd ::= DETACH database_kw_opt expr */
 {
-  sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr);
+  sqlite3Detach(pParse, yymsp[0].minor.yy346.pExpr);
 }
         break;
-      case 305: /* cmd ::= REINDEX */
+      case 300: /* cmd ::= REINDEX */
 {sqlite3Reindex(pParse, 0, 0);}
         break;
-      case 306: /* cmd ::= REINDEX nm dbnm */
+      case 301: /* cmd ::= REINDEX nm dbnm */
 {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
         break;
-      case 307: /* cmd ::= ANALYZE */
+      case 302: /* cmd ::= ANALYZE */
 {sqlite3Analyze(pParse, 0, 0);}
         break;
-      case 308: /* cmd ::= ANALYZE nm dbnm */
+      case 303: /* cmd ::= ANALYZE nm dbnm */
 {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
         break;
-      case 309: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+      case 304: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
 {
-  sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0);
+  sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy65,&yymsp[0].minor.yy0);
 }
         break;
-      case 310: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
+      case 305: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
 {
   sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
 }
         break;
-      case 311: /* add_column_fullname ::= fullname */
+      case 306: /* add_column_fullname ::= fullname */
 {
   pParse->db->lookaside.bEnabled = 0;
-  sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347);
+  sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy65);
 }
         break;
-      case 314: /* cmd ::= create_vtab */
+      case 309: /* cmd ::= create_vtab */
 {sqlite3VtabFinishParse(pParse,0);}
         break;
-      case 315: /* cmd ::= create_vtab LP vtabarglist RP */
+      case 310: /* cmd ::= create_vtab LP vtabarglist RP */
 {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
         break;
-      case 316: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+      case 311: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
 {
-    sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy392);
+    sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy328);
 }
         break;
-      case 319: /* vtabarg ::= */
+      case 314: /* vtabarg ::= */
 {sqlite3VtabArgInit(pParse);}
         break;
-      case 321: /* vtabargtoken ::= ANY */
-      case 322: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==322);
-      case 323: /* lp ::= LP */ yytestcase(yyruleno==323);
+      case 316: /* vtabargtoken ::= ANY */
+      case 317: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==317);
+      case 318: /* lp ::= LP */ yytestcase(yyruleno==318);
 {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
         break;
+      case 322: /* with ::= */
+{yygotominor.yy59 = 0;}
+        break;
+      case 323: /* with ::= WITH wqlist */
+      case 324: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==324);
+{ yygotominor.yy59 = yymsp[0].minor.yy59; }
+        break;
+      case 325: /* wqlist ::= nm idxlist_opt AS LP select RP */
+{
+  yygotominor.yy59 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy3);
+}
+        break;
+      case 326: /* wqlist ::= wqlist COMMA nm idxlist_opt AS LP select RP */
+{
+  yygotominor.yy59 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy59, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy3);
+}
+        break;
       default:
       /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
       /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
@@ -113321,30 +120703,30 @@ static void yy_reduce(
       /* (20) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==20);
       /* (21) savepoint_opt ::= */ yytestcase(yyruleno==21);
       /* (25) cmd ::= create_table create_table_args */ yytestcase(yyruleno==25);
-      /* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34);
-      /* (35) columnlist ::= column */ yytestcase(yyruleno==35);
-      /* (44) type ::= */ yytestcase(yyruleno==44);
-      /* (51) signed ::= plus_num */ yytestcase(yyruleno==51);
-      /* (52) signed ::= minus_num */ yytestcase(yyruleno==52);
-      /* (53) carglist ::= carglist ccons */ yytestcase(yyruleno==53);
-      /* (54) carglist ::= */ yytestcase(yyruleno==54);
-      /* (61) ccons ::= NULL onconf */ yytestcase(yyruleno==61);
-      /* (89) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==89);
-      /* (90) conslist ::= tcons */ yytestcase(yyruleno==90);
-      /* (92) tconscomma ::= */ yytestcase(yyruleno==92);
-      /* (277) foreach_clause ::= */ yytestcase(yyruleno==277);
-      /* (278) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==278);
-      /* (285) tridxby ::= */ yytestcase(yyruleno==285);
-      /* (303) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==303);
-      /* (304) database_kw_opt ::= */ yytestcase(yyruleno==304);
-      /* (312) kwcolumn_opt ::= */ yytestcase(yyruleno==312);
-      /* (313) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==313);
-      /* (317) vtabarglist ::= vtabarg */ yytestcase(yyruleno==317);
-      /* (318) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==318);
-      /* (320) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==320);
-      /* (324) anylist ::= */ yytestcase(yyruleno==324);
-      /* (325) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==325);
-      /* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
+      /* (36) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==36);
+      /* (37) columnlist ::= column */ yytestcase(yyruleno==37);
+      /* (43) type ::= */ yytestcase(yyruleno==43);
+      /* (50) signed ::= plus_num */ yytestcase(yyruleno==50);
+      /* (51) signed ::= minus_num */ yytestcase(yyruleno==51);
+      /* (52) carglist ::= carglist ccons */ yytestcase(yyruleno==52);
+      /* (53) carglist ::= */ yytestcase(yyruleno==53);
+      /* (60) ccons ::= NULL onconf */ yytestcase(yyruleno==60);
+      /* (88) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==88);
+      /* (89) conslist ::= tcons */ yytestcase(yyruleno==89);
+      /* (91) tconscomma ::= */ yytestcase(yyruleno==91);
+      /* (273) foreach_clause ::= */ yytestcase(yyruleno==273);
+      /* (274) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==274);
+      /* (281) tridxby ::= */ yytestcase(yyruleno==281);
+      /* (298) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==298);
+      /* (299) database_kw_opt ::= */ yytestcase(yyruleno==299);
+      /* (307) kwcolumn_opt ::= */ yytestcase(yyruleno==307);
+      /* (308) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==308);
+      /* (312) vtabarglist ::= vtabarg */ yytestcase(yyruleno==312);
+      /* (313) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==313);
+      /* (315) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==315);
+      /* (319) anylist ::= */ yytestcase(yyruleno==319);
+      /* (320) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==320);
+      /* (321) anylist ::= anylist ANY */ yytestcase(yyruleno==321);
         break;
   };
   assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
@@ -113683,20 +121065,20 @@ const unsigned char ebcdicToAscii[] = {
 ** is substantially reduced.  This is important for embedded applications
 ** on platforms with limited memory.
 */
-/* Hash score: 175 */
+/* Hash score: 182 */
 static int keywordCode(const char *z, int n){
-  /* zText[] encodes 811 bytes of keywords in 541 bytes */
+  /* zText[] encodes 834 bytes of keywords in 554 bytes */
   /*   REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT       */
   /*   ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE         */
   /*   XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY         */
-  /*   UNIQUERYATTACHAVINGROUPDATEBEGINNERELEASEBETWEENOTNULLIKE          */
-  /*   CASCADELETECASECOLLATECREATECURRENT_DATEDETACHIMMEDIATEJOIN        */
-  /*   SERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHENWHERENAME         */
-  /*   AFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSS     */
-  /*   CURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROMFULLGLOBYIF      */
-  /*   ISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVACUUMVIEW         */
-  /*   INITIALLY                                                          */
-  static const char zText[540] = {
+  /*   UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERECURSIVE         */
+  /*   BETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATEDETACH     */
+  /*   IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN     */
+  /*   WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT         */
+  /*   CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAIL        */
+  /*   FROMFULLGLOBYIFISNULLORDERESTRICTRIGHTROLLBACKROWUNIONUSING        */
+  /*   VACUUMVIEWINITIALLY                                                */
+  static const char zText[553] = {
     'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
     'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
     'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
@@ -113707,76 +121089,77 @@ static int keywordCode(const char *z, int n){
     'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E',
     'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T',
     'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q',
-    'U','E','R','Y','A','T','T','A','C','H','A','V','I','N','G','R','O','U',
-    'P','D','A','T','E','B','E','G','I','N','N','E','R','E','L','E','A','S',
-    'E','B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C',
-    'A','S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L',
-    'A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D',
-    'A','T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E',
-    'J','O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A',
-    'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U',
-    'E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W',
-    'H','E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C',
-    'E','A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R',
-    'E','M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M',
-    'M','I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U',
-    'R','R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M',
-    'A','R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T',
-    'D','R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L',
-    'O','B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S',
-    'T','R','I','C','T','O','U','T','E','R','I','G','H','T','R','O','L','L',
-    'B','A','C','K','R','O','W','U','N','I','O','N','U','S','I','N','G','V',
-    'A','C','U','U','M','V','I','E','W','I','N','I','T','I','A','L','L','Y',
+    'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S',
+    'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A',
+    'T','E','B','E','G','I','N','N','E','R','E','C','U','R','S','I','V','E',
+    'B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C','A',
+    'S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L','A',
+    'T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A',
+    'T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E','J',
+    'O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A','L',
+    'Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U','E',
+    'S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W','H',
+    'E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C','E',
+    'A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E',
+    'M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M',
+    'I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R',
+    'R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M','A',
+    'R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D',
+    'R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L','O',
+    'B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T',
+    'R','I','C','T','R','I','G','H','T','R','O','L','L','B','A','C','K','R',
+    'O','W','U','N','I','O','N','U','S','I','N','G','V','A','C','U','U','M',
+    'V','I','E','W','I','N','I','T','I','A','L','L','Y',
   };
   static const unsigned char aHash[127] = {
-      72, 101, 114,  70,   0,  45,   0,   0,  78,   0,  73,   0,   0,
-      42,  12,  74,  15,   0, 113,  81,  50, 108,   0,  19,   0,   0,
-     118,   0, 116, 111,   0,  22,  89,   0,   9,   0,   0,  66,  67,
-       0,  65,   6,   0,  48,  86,  98,   0, 115,  97,   0,   0,  44,
-       0,  99,  24,   0,  17,   0, 119,  49,  23,   0,   5, 106,  25,
-      92,   0,   0, 121, 102,  56, 120,  53,  28,  51,   0,  87,   0,
-      96,  26,   0,  95,   0,   0,   0,  91,  88,  93,  84, 105,  14,
-      39, 104,   0,  77,   0,  18,  85, 107,  32,   0, 117,  76, 109,
-      58,  46,  80,   0,   0,  90,  40,   0, 112,   0,  36,   0,   0,
-      29,   0,  82,  59,  60,   0,  20,  57,   0,  52,
+      76, 105, 117,  74,   0,  45,   0,   0,  82,   0,  77,   0,   0,
+      42,  12,  78,  15,   0, 116,  85,  54, 112,   0,  19,   0,   0,
+     121,   0, 119, 115,   0,  22,  93,   0,   9,   0,   0,  70,  71,
+       0,  69,   6,   0,  48,  90, 102,   0, 118, 101,   0,   0,  44,
+       0, 103,  24,   0,  17,   0, 122,  53,  23,   0,   5, 110,  25,
+      96,   0,   0, 124, 106,  60, 123,  57,  28,  55,   0,  91,   0,
+     100,  26,   0,  99,   0,   0,   0,  95,  92,  97,  88, 109,  14,
+      39, 108,   0,  81,   0,  18,  89, 111,  32,   0, 120,  80, 113,
+      62,  46,  84,   0,   0,  94,  40,  59, 114,   0,  36,   0,   0,
+      29,   0,  86,  63,  64,   0,  20,  61,   0,  56,
   };
-  static const unsigned char aNext[121] = {
+  static const unsigned char aNext[124] = {
        0,   0,   0,   0,   4,   0,   0,   0,   0,   0,   0,   0,   0,
        0,   2,   0,   0,   0,   0,   0,   0,  13,   0,   0,   0,   0,
        0,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-       0,   0,   0,   0,  33,   0,  21,   0,   0,   0,  43,   3,  47,
-       0,   0,   0,   0,  30,   0,  54,   0,  38,   0,   0,   0,   1,
-      62,   0,   0,  63,   0,  41,   0,   0,   0,   0,   0,   0,   0,
-      61,   0,   0,   0,   0,  31,  55,  16,  34,  10,   0,   0,   0,
-       0,   0,   0,   0,  11,  68,  75,   0,   8,   0, 100,  94,   0,
-     103,   0,  83,   0,  71,   0,   0, 110,  27,  37,  69,  79,   0,
-      35,  64,   0,   0,
+       0,   0,   0,   0,  33,   0,  21,   0,   0,   0,   0,   0,  50,
+       0,  43,   3,  47,   0,   0,   0,   0,  30,   0,  58,   0,  38,
+       0,   0,   0,   1,  66,   0,   0,  67,   0,  41,   0,   0,   0,
+       0,   0,   0,  49,  65,   0,   0,   0,   0,  31,  52,  16,  34,
+      10,   0,   0,   0,   0,   0,   0,   0,  11,  72,  79,   0,   8,
+       0, 104,  98,   0, 107,   0,  87,   0,  75,  51,   0,  27,  37,
+      73,  83,   0,  35,  68,   0,   0,
   };
-  static const unsigned char aLen[121] = {
+  static const unsigned char aLen[124] = {
        7,   7,   5,   4,   6,   4,   5,   3,   6,   7,   3,   6,   6,
        7,   7,   3,   8,   2,   6,   5,   4,   4,   3,  10,   4,   6,
       11,   6,   2,   7,   5,   5,   9,   6,   9,   9,   7,  10,  10,
-       4,   6,   2,   3,   9,   4,   2,   6,   5,   6,   6,   5,   6,
-       5,   5,   7,   7,   7,   3,   2,   4,   4,   7,   3,   6,   4,
-       7,   6,  12,   6,   9,   4,   6,   5,   4,   7,   6,   5,   6,
-       7,   5,   4,   5,   6,   5,   7,   3,   7,  13,   2,   2,   4,
-       6,   6,   8,   5,  17,  12,   7,   8,   8,   2,   4,   4,   4,
-       4,   4,   2,   2,   6,   5,   8,   5,   5,   8,   3,   5,   5,
-       6,   4,   9,   3,
+       4,   6,   2,   3,   9,   4,   2,   6,   5,   7,   4,   5,   7,
+       6,   6,   5,   6,   5,   5,   9,   7,   7,   3,   2,   4,   4,
+       7,   3,   6,   4,   7,   6,  12,   6,   9,   4,   6,   5,   4,
+       7,   6,   5,   6,   7,   5,   4,   5,   6,   5,   7,   3,   7,
+      13,   2,   2,   4,   6,   6,   8,   5,  17,  12,   7,   8,   8,
+       2,   4,   4,   4,   4,   4,   2,   2,   6,   5,   8,   5,   8,
+       3,   5,   5,   6,   4,   9,   3,
   };
-  static const unsigned short int aOffset[121] = {
+  static const unsigned short int aOffset[124] = {
        0,   2,   2,   8,   9,  14,  16,  20,  23,  25,  25,  29,  33,
       36,  41,  46,  48,  53,  54,  59,  62,  65,  67,  69,  78,  81,
       86,  91,  95,  96, 101, 105, 109, 117, 122, 128, 136, 142, 152,
-     159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 189, 194, 197,
-     203, 206, 210, 217, 223, 223, 223, 226, 229, 233, 234, 238, 244,
-     248, 255, 261, 273, 279, 288, 290, 296, 301, 303, 310, 315, 320,
-     326, 332, 337, 341, 344, 350, 354, 361, 363, 370, 372, 374, 383,
-     387, 393, 399, 407, 412, 412, 428, 435, 442, 443, 450, 454, 458,
-     462, 466, 469, 471, 473, 479, 483, 491, 495, 500, 508, 511, 516,
-     521, 527, 531, 536,
+     159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192,
+     199, 204, 209, 212, 218, 221, 225, 234, 240, 240, 240, 243, 246,
+     250, 251, 255, 261, 265, 272, 278, 290, 296, 305, 307, 313, 318,
+     320, 327, 332, 337, 343, 349, 354, 358, 361, 367, 371, 378, 380,
+     387, 389, 391, 400, 404, 410, 416, 424, 429, 429, 445, 452, 459,
+     460, 467, 471, 475, 479, 483, 486, 488, 490, 496, 500, 508, 513,
+     521, 524, 529, 534, 540, 544, 549,
   };
-  static const unsigned char aCode[121] = {
+  static const unsigned char aCode[124] = {
     TK_REINDEX,    TK_INDEXED,    TK_INDEX,      TK_DESC,       TK_ESCAPE,     
     TK_EACH,       TK_CHECK,      TK_KEY,        TK_BEFORE,     TK_FOREIGN,    
     TK_FOR,        TK_IGNORE,     TK_LIKE_KW,    TK_EXPLAIN,    TK_INSTEAD,    
@@ -113786,22 +121169,22 @@ static int keywordCode(const char *z, int n){
     TK_ALTER,      TK_RAISE,      TK_EXCLUSIVE,  TK_EXISTS,     TK_SAVEPOINT,  
     TK_INTERSECT,  TK_TRIGGER,    TK_REFERENCES, TK_CONSTRAINT, TK_INTO,       
     TK_OFFSET,     TK_OF,         TK_SET,        TK_TEMP,       TK_TEMP,       
-    TK_OR,         TK_UNIQUE,     TK_QUERY,      TK_ATTACH,     TK_HAVING,     
-    TK_GROUP,      TK_UPDATE,     TK_BEGIN,      TK_JOIN_KW,    TK_RELEASE,    
-    TK_BETWEEN,    TK_NOTNULL,    TK_NOT,        TK_NO,         TK_NULL,       
-    TK_LIKE_KW,    TK_CASCADE,    TK_ASC,        TK_DELETE,     TK_CASE,       
-    TK_COLLATE,    TK_CREATE,     TK_CTIME_KW,   TK_DETACH,     TK_IMMEDIATE,  
-    TK_JOIN,       TK_INSERT,     TK_MATCH,      TK_PLAN,       TK_ANALYZE,    
-    TK_PRAGMA,     TK_ABORT,      TK_VALUES,     TK_VIRTUAL,    TK_LIMIT,      
-    TK_WHEN,       TK_WHERE,      TK_RENAME,     TK_AFTER,      TK_REPLACE,    
-    TK_AND,        TK_DEFAULT,    TK_AUTOINCR,   TK_TO,         TK_IN,         
-    TK_CAST,       TK_COLUMNKW,   TK_COMMIT,     TK_CONFLICT,   TK_JOIN_KW,    
-    TK_CTIME_KW,   TK_CTIME_KW,   TK_PRIMARY,    TK_DEFERRED,   TK_DISTINCT,   
-    TK_IS,         TK_DROP,       TK_FAIL,       TK_FROM,       TK_JOIN_KW,    
-    TK_LIKE_KW,    TK_BY,         TK_IF,         TK_ISNULL,     TK_ORDER,      
-    TK_RESTRICT,   TK_JOIN_KW,    TK_JOIN_KW,    TK_ROLLBACK,   TK_ROW,        
-    TK_UNION,      TK_USING,      TK_VACUUM,     TK_VIEW,       TK_INITIALLY,  
-    TK_ALL,        
+    TK_OR,         TK_UNIQUE,     TK_QUERY,      TK_WITHOUT,    TK_WITH,       
+    TK_JOIN_KW,    TK_RELEASE,    TK_ATTACH,     TK_HAVING,     TK_GROUP,      
+    TK_UPDATE,     TK_BEGIN,      TK_JOIN_KW,    TK_RECURSIVE,  TK_BETWEEN,    
+    TK_NOTNULL,    TK_NOT,        TK_NO,         TK_NULL,       TK_LIKE_KW,    
+    TK_CASCADE,    TK_ASC,        TK_DELETE,     TK_CASE,       TK_COLLATE,    
+    TK_CREATE,     TK_CTIME_KW,   TK_DETACH,     TK_IMMEDIATE,  TK_JOIN,       
+    TK_INSERT,     TK_MATCH,      TK_PLAN,       TK_ANALYZE,    TK_PRAGMA,     
+    TK_ABORT,      TK_VALUES,     TK_VIRTUAL,    TK_LIMIT,      TK_WHEN,       
+    TK_WHERE,      TK_RENAME,     TK_AFTER,      TK_REPLACE,    TK_AND,        
+    TK_DEFAULT,    TK_AUTOINCR,   TK_TO,         TK_IN,         TK_CAST,       
+    TK_COLUMNKW,   TK_COMMIT,     TK_CONFLICT,   TK_JOIN_KW,    TK_CTIME_KW,   
+    TK_CTIME_KW,   TK_PRIMARY,    TK_DEFERRED,   TK_DISTINCT,   TK_IS,         
+    TK_DROP,       TK_FAIL,       TK_FROM,       TK_JOIN_KW,    TK_LIKE_KW,    
+    TK_BY,         TK_IF,         TK_ISNULL,     TK_ORDER,      TK_RESTRICT,   
+    TK_JOIN_KW,    TK_ROLLBACK,   TK_ROW,        TK_UNION,      TK_USING,      
+    TK_VACUUM,     TK_VIEW,       TK_INITIALLY,  TK_ALL,        
   };
   int h, i;
   if( n<2 ) return TK_ID;
@@ -113858,79 +121241,82 @@ static int keywordCode(const char *z, int n){
       testcase( i==45 ); /* OR */
       testcase( i==46 ); /* UNIQUE */
       testcase( i==47 ); /* QUERY */
-      testcase( i==48 ); /* ATTACH */
-      testcase( i==49 ); /* HAVING */
-      testcase( i==50 ); /* GROUP */
-      testcase( i==51 ); /* UPDATE */
-      testcase( i==52 ); /* BEGIN */
-      testcase( i==53 ); /* INNER */
-      testcase( i==54 ); /* RELEASE */
-      testcase( i==55 ); /* BETWEEN */
-      testcase( i==56 ); /* NOTNULL */
-      testcase( i==57 ); /* NOT */
-      testcase( i==58 ); /* NO */
-      testcase( i==59 ); /* NULL */
-      testcase( i==60 ); /* LIKE */
-      testcase( i==61 ); /* CASCADE */
-      testcase( i==62 ); /* ASC */
-      testcase( i==63 ); /* DELETE */
-      testcase( i==64 ); /* CASE */
-      testcase( i==65 ); /* COLLATE */
-      testcase( i==66 ); /* CREATE */
-      testcase( i==67 ); /* CURRENT_DATE */
-      testcase( i==68 ); /* DETACH */
-      testcase( i==69 ); /* IMMEDIATE */
-      testcase( i==70 ); /* JOIN */
-      testcase( i==71 ); /* INSERT */
-      testcase( i==72 ); /* MATCH */
-      testcase( i==73 ); /* PLAN */
-      testcase( i==74 ); /* ANALYZE */
-      testcase( i==75 ); /* PRAGMA */
-      testcase( i==76 ); /* ABORT */
-      testcase( i==77 ); /* VALUES */
-      testcase( i==78 ); /* VIRTUAL */
-      testcase( i==79 ); /* LIMIT */
-      testcase( i==80 ); /* WHEN */
-      testcase( i==81 ); /* WHERE */
-      testcase( i==82 ); /* RENAME */
-      testcase( i==83 ); /* AFTER */
-      testcase( i==84 ); /* REPLACE */
-      testcase( i==85 ); /* AND */
-      testcase( i==86 ); /* DEFAULT */
-      testcase( i==87 ); /* AUTOINCREMENT */
-      testcase( i==88 ); /* TO */
-      testcase( i==89 ); /* IN */
-      testcase( i==90 ); /* CAST */
-      testcase( i==91 ); /* COLUMN */
-      testcase( i==92 ); /* COMMIT */
-      testcase( i==93 ); /* CONFLICT */
-      testcase( i==94 ); /* CROSS */
-      testcase( i==95 ); /* CURRENT_TIMESTAMP */
-      testcase( i==96 ); /* CURRENT_TIME */
-      testcase( i==97 ); /* PRIMARY */
-      testcase( i==98 ); /* DEFERRED */
-      testcase( i==99 ); /* DISTINCT */
-      testcase( i==100 ); /* IS */
-      testcase( i==101 ); /* DROP */
-      testcase( i==102 ); /* FAIL */
-      testcase( i==103 ); /* FROM */
-      testcase( i==104 ); /* FULL */
-      testcase( i==105 ); /* GLOB */
-      testcase( i==106 ); /* BY */
-      testcase( i==107 ); /* IF */
-      testcase( i==108 ); /* ISNULL */
-      testcase( i==109 ); /* ORDER */
-      testcase( i==110 ); /* RESTRICT */
-      testcase( i==111 ); /* OUTER */
-      testcase( i==112 ); /* RIGHT */
-      testcase( i==113 ); /* ROLLBACK */
-      testcase( i==114 ); /* ROW */
-      testcase( i==115 ); /* UNION */
-      testcase( i==116 ); /* USING */
-      testcase( i==117 ); /* VACUUM */
-      testcase( i==118 ); /* VIEW */
-      testcase( i==119 ); /* INITIALLY */
-      testcase( i==120 ); /* ALL */
+      testcase( i==48 ); /* WITHOUT */
+      testcase( i==49 ); /* WITH */
+      testcase( i==50 ); /* OUTER */
+      testcase( i==51 ); /* RELEASE */
+      testcase( i==52 ); /* ATTACH */
+      testcase( i==53 ); /* HAVING */
+      testcase( i==54 ); /* GROUP */
+      testcase( i==55 ); /* UPDATE */
+      testcase( i==56 ); /* BEGIN */
+      testcase( i==57 ); /* INNER */
+      testcase( i==58 ); /* RECURSIVE */
+      testcase( i==59 ); /* BETWEEN */
+      testcase( i==60 ); /* NOTNULL */
+      testcase( i==61 ); /* NOT */
+      testcase( i==62 ); /* NO */
+      testcase( i==63 ); /* NULL */
+      testcase( i==64 ); /* LIKE */
+      testcase( i==65 ); /* CASCADE */
+      testcase( i==66 ); /* ASC */
+      testcase( i==67 ); /* DELETE */
+      testcase( i==68 ); /* CASE */
+      testcase( i==69 ); /* COLLATE */
+      testcase( i==70 ); /* CREATE */
+      testcase( i==71 ); /* CURRENT_DATE */
+      testcase( i==72 ); /* DETACH */
+      testcase( i==73 ); /* IMMEDIATE */
+      testcase( i==74 ); /* JOIN */
+      testcase( i==75 ); /* INSERT */
+      testcase( i==76 ); /* MATCH */
+      testcase( i==77 ); /* PLAN */
+      testcase( i==78 ); /* ANALYZE */
+      testcase( i==79 ); /* PRAGMA */
+      testcase( i==80 ); /* ABORT */
+      testcase( i==81 ); /* VALUES */
+      testcase( i==82 ); /* VIRTUAL */
+      testcase( i==83 ); /* LIMIT */
+      testcase( i==84 ); /* WHEN */
+      testcase( i==85 ); /* WHERE */
+      testcase( i==86 ); /* RENAME */
+      testcase( i==87 ); /* AFTER */
+      testcase( i==88 ); /* REPLACE */
+      testcase( i==89 ); /* AND */
+      testcase( i==90 ); /* DEFAULT */
+      testcase( i==91 ); /* AUTOINCREMENT */
+      testcase( i==92 ); /* TO */
+      testcase( i==93 ); /* IN */
+      testcase( i==94 ); /* CAST */
+      testcase( i==95 ); /* COLUMN */
+      testcase( i==96 ); /* COMMIT */
+      testcase( i==97 ); /* CONFLICT */
+      testcase( i==98 ); /* CROSS */
+      testcase( i==99 ); /* CURRENT_TIMESTAMP */
+      testcase( i==100 ); /* CURRENT_TIME */
+      testcase( i==101 ); /* PRIMARY */
+      testcase( i==102 ); /* DEFERRED */
+      testcase( i==103 ); /* DISTINCT */
+      testcase( i==104 ); /* IS */
+      testcase( i==105 ); /* DROP */
+      testcase( i==106 ); /* FAIL */
+      testcase( i==107 ); /* FROM */
+      testcase( i==108 ); /* FULL */
+      testcase( i==109 ); /* GLOB */
+      testcase( i==110 ); /* BY */
+      testcase( i==111 ); /* IF */
+      testcase( i==112 ); /* ISNULL */
+      testcase( i==113 ); /* ORDER */
+      testcase( i==114 ); /* RESTRICT */
+      testcase( i==115 ); /* RIGHT */
+      testcase( i==116 ); /* ROLLBACK */
+      testcase( i==117 ); /* ROW */
+      testcase( i==118 ); /* UNION */
+      testcase( i==119 ); /* USING */
+      testcase( i==120 ); /* VACUUM */
+      testcase( i==121 ); /* VIEW */
+      testcase( i==122 ); /* INITIALLY */
+      testcase( i==123 ); /* ALL */
       return aCode[i];
     }
   }
@@ -113939,7 +121325,7 @@ static int keywordCode(const char *z, int n){
 SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){
   return keywordCode((char*)z, n);
 }
-#define SQLITE_N_KEYWORD 121
+#define SQLITE_N_KEYWORD 124
 
 /************** End of keywordhash.h *****************************************/
 /************** Continuing where we left off in tokenize.c *******************/
@@ -114003,7 +121389,6 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
     }
     case '-': {
       if( z[1]=='-' ){
-        /* IMP: R-50417-27976 -- syntax diagram for comments */
         for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
         *tokenType = TK_SPACE;   /* IMP: R-22934-25134 */
         return i;
@@ -114036,7 +121421,6 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
         *tokenType = TK_SLASH;
         return 1;
       }
-      /* IMP: R-50417-27976 -- syntax diagram for comments */
       for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
       if( c ) i++;
       *tokenType = TK_SPACE;   /* IMP: R-22934-25134 */
@@ -114152,6 +121536,12 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
       testcase( z[0]=='6' );  testcase( z[0]=='7' );  testcase( z[0]=='8' );
       testcase( z[0]=='9' );
       *tokenType = TK_INTEGER;
+#ifndef SQLITE_OMIT_HEX_INTEGER
+      if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
+        for(i=3; sqlite3Isxdigit(z[i]); i++){}
+        return i;
+      }
+#endif
       for(i=0; sqlite3Isdigit(z[i]); i++){}
 #ifndef SQLITE_OMIT_FLOATING_POINT
       if( z[i]=='.' ){
@@ -114185,24 +121575,15 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
       for(i=1; sqlite3Isdigit(z[i]); i++){}
       return i;
     }
-    case '#': {
-      for(i=1; sqlite3Isdigit(z[i]); i++){}
-      if( i>1 ){
-        /* Parameters of the form #NNN (where NNN is a number) are used
-        ** internally by sqlite3NestedParse.  */
-        *tokenType = TK_REGISTER;
-        return i;
-      }
-      /* Fall through into the next case if the '#' is not followed by
-      ** a digit. Try to match #AAAA where AAAA is a parameter name. */
-    }
 #ifndef SQLITE_OMIT_TCL_VARIABLE
     case '$':
 #endif
     case '@':  /* For compatibility with MS SQL Server */
+    case '#':
     case ':': {
       int n = 0;
-      testcase( z[0]=='$' );  testcase( z[0]=='@' );  testcase( z[0]==':' );
+      testcase( z[0]=='$' );  testcase( z[0]=='@' );
+      testcase( z[0]==':' );  testcase( z[0]=='#' );
       *tokenType = TK_VARIABLE;
       for(i=1; (c=z[i])!=0; i++){
         if( IdChar(c) ){
@@ -114276,7 +121657,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
 
 
   mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
-  if( db->activeVdbeCnt==0 ){
+  if( db->nVdbeActive==0 ){
     db->u1.isInterrupted = 0;
   }
   pParse->rc = SQLITE_OK;
@@ -114385,10 +121766,10 @@ abort_parse:
     sqlite3DeleteTable(db, pParse->pNewTable);
   }
 
+  if( pParse->bFreeWith ) sqlite3WithDelete(db, pParse->pWith);
   sqlite3DeleteTrigger(db, pParse->pNewTrigger);
   for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
   sqlite3DbFree(db, pParse->azVar);
-  sqlite3DbFree(db, pParse->aAlias);
   while( pParse->pAinc ){
     AutoincInfo *p = pParse->pAinc;
     pParse->pAinc = p->pNext;
@@ -114898,6 +122279,9 @@ SQLITE_API char *sqlite3_data_directory = 0;
 SQLITE_API int sqlite3_initialize(void){
   MUTEX_LOGIC( sqlite3_mutex *pMaster; )       /* The main static mutex */
   int rc;                                      /* Result code */
+#ifdef SQLITE_EXTRA_INIT
+  int bRunExtraInit = 0;                       /* Extra initialization needed */
+#endif
 
 #ifdef SQLITE_OMIT_WSD
   rc = sqlite3_wsd_init(4096, 24);
@@ -114913,13 +122297,6 @@ SQLITE_API int sqlite3_initialize(void){
   */
   if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
 
-#ifdef SQLITE_ENABLE_SQLLOG
-  {
-    extern void sqlite3_init_sqllog(void);
-    sqlite3_init_sqllog();
-  }
-#endif
-
   /* 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,
@@ -114995,6 +122372,9 @@ SQLITE_API int sqlite3_initialize(void){
       sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, 
           sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
       sqlite3GlobalConfig.isInit = 1;
+#ifdef SQLITE_EXTRA_INIT
+      bRunExtraInit = 1;
+#endif
     }
     sqlite3GlobalConfig.inProgress = 0;
   }
@@ -115035,7 +122415,7 @@ SQLITE_API int sqlite3_initialize(void){
   ** compile-time option.
   */
 #ifdef SQLITE_EXTRA_INIT
-  if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
+  if( bRunExtraInit ){
     int SQLITE_EXTRA_INIT(const char*);
     rc = SQLITE_EXTRA_INIT(0);
   }
@@ -115223,8 +122603,8 @@ SQLITE_API int sqlite3_config(int op, ...){
         memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
       }else{
         /* The heap pointer is not NULL, then install one of the
-        ** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
-        ** ENABLE_MEMSYS5 is defined, return an error.
+        ** mem5.c/mem3.c methods.  The enclosing #if guarantees at
+        ** least one of these methods is currently enabled.
         */
 #ifdef SQLITE_ENABLE_MEMSYS3
         sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
@@ -115243,7 +122623,7 @@ SQLITE_API int sqlite3_config(int op, ...){
       break;
     }
     
-    /* Record a pointer to the logger funcction and its first argument.
+    /* Record a pointer to the logger function and its first argument.
     ** The default is NULL.  Logging is disabled if the function pointer is
     ** NULL.
     */
@@ -115290,6 +122670,13 @@ SQLITE_API int sqlite3_config(int op, ...){
       break;
     }
 
+#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC)
+    case SQLITE_CONFIG_WIN32_HEAPSIZE: {
+      sqlite3GlobalConfig.nHeap = va_arg(ap, int);
+      break;
+    }
+#endif
+
     default: {
       rc = SQLITE_ERROR;
       break;
@@ -115356,7 +122743,8 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
     db->lookaside.bEnabled = 1;
     db->lookaside.bMalloced = pBuf==0 ?1:0;
   }else{
-    db->lookaside.pEnd = 0;
+    db->lookaside.pStart = db;
+    db->lookaside.pEnd = db;
     db->lookaside.bEnabled = 0;
     db->lookaside.bMalloced = 0;
   }
@@ -115482,7 +122870,7 @@ static int binCollFunc(
 /*
 ** Another built-in collating sequence: NOCASE. 
 **
-** This collating sequence is intended to be used for "case independant
+** This collating sequence is intended to be used for "case independent
 ** comparison". SQLite's knowledge of upper and lower case equivalents
 ** extends only to the 26 characters used in the English language.
 **
@@ -115574,6 +122962,7 @@ static void disconnectAllVtab(sqlite3 *db){
       }
     }
   }
+  sqlite3VtabUnlockList(db);
   sqlite3BtreeLeaveAll(db);
 #else
   UNUSED_PARAMETER(db);
@@ -115600,6 +122989,8 @@ static int connectionIsBusy(sqlite3 *db){
 */
 static int sqlite3Close(sqlite3 *db, int forceZombie){
   if( !db ){
+    /* EVIDENCE-OF: R-63257-11740 Calling sqlite3_close() or
+    ** sqlite3_close_v2() with a NULL pointer argument is a harmless no-op. */
     return SQLITE_OK;
   }
   if( !sqlite3SafetyCheckSickOrOk(db) ){
@@ -115754,9 +123145,7 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
 #endif
 
   sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
-  if( db->pErr ){
-    sqlite3ValueFree(db->pErr);
-  }
+  sqlite3ValueFree(db->pErr);
   sqlite3CloseExtensions(db);
 
   db->magic = SQLITE_MAGIC_ERROR;
@@ -115805,7 +123194,6 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
         inTrans = 1;
       }
       sqlite3BtreeRollback(p, tripCode);
-      db->aDb[i].inTrans = 0;
     }
   }
   sqlite3VtabRollback(db);
@@ -115819,6 +123207,8 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
 
   /* Any deferred constraint violations have now been resolved. */
   db->nDeferredCons = 0;
+  db->nDeferredImmCons = 0;
+  db->flags &= ~SQLITE_DeferFKs;
 
   /* If one has been configured, invoke the rollback-hook callback */
   if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
@@ -115830,8 +123220,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
 ** Return a static string containing the name corresponding to the error code
 ** specified in the argument.
 */
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \
-    defined(SQLITE_DEBUG_OS_TRACE)
+#if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST)
 SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
   const char *zName = 0;
   int i, origRc = rc;
@@ -115845,6 +123234,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
       case SQLITE_ABORT_ROLLBACK:     zName = "SQLITE_ABORT_ROLLBACK";    break;
       case SQLITE_BUSY:               zName = "SQLITE_BUSY";              break;
       case SQLITE_BUSY_RECOVERY:      zName = "SQLITE_BUSY_RECOVERY";     break;
+      case SQLITE_BUSY_SNAPSHOT:      zName = "SQLITE_BUSY_SNAPSHOT";     break;
       case SQLITE_LOCKED:             zName = "SQLITE_LOCKED";            break;
       case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break;
       case SQLITE_NOMEM:              zName = "SQLITE_NOMEM";             break;
@@ -115852,6 +123242,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
       case SQLITE_READONLY_RECOVERY:  zName = "SQLITE_READONLY_RECOVERY"; break;
       case SQLITE_READONLY_CANTLOCK:  zName = "SQLITE_READONLY_CANTLOCK"; break;
       case SQLITE_READONLY_ROLLBACK:  zName = "SQLITE_READONLY_ROLLBACK"; break;
+      case SQLITE_READONLY_DBMOVED:   zName = "SQLITE_READONLY_DBMOVED";  break;
       case SQLITE_INTERRUPT:          zName = "SQLITE_INTERRUPT";         break;
       case SQLITE_IOERR:              zName = "SQLITE_IOERR";             break;
       case SQLITE_IOERR_READ:         zName = "SQLITE_IOERR_READ";        break;
@@ -115864,7 +123255,6 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
       case SQLITE_IOERR_UNLOCK:       zName = "SQLITE_IOERR_UNLOCK";      break;
       case SQLITE_IOERR_RDLOCK:       zName = "SQLITE_IOERR_RDLOCK";      break;
       case SQLITE_IOERR_DELETE:       zName = "SQLITE_IOERR_DELETE";      break;
-      case SQLITE_IOERR_BLOCKED:      zName = "SQLITE_IOERR_BLOCKED";     break;
       case SQLITE_IOERR_NOMEM:        zName = "SQLITE_IOERR_NOMEM";       break;
       case SQLITE_IOERR_ACCESS:       zName = "SQLITE_IOERR_ACCESS";      break;
       case SQLITE_IOERR_CHECKRESERVEDLOCK:
@@ -115879,6 +123269,8 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
       case SQLITE_IOERR_SEEK:         zName = "SQLITE_IOERR_SEEK";        break;
       case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break;
       case SQLITE_IOERR_MMAP:         zName = "SQLITE_IOERR_MMAP";        break;
+      case SQLITE_IOERR_GETTEMPPATH:  zName = "SQLITE_IOERR_GETTEMPPATH"; break;
+      case SQLITE_IOERR_CONVPATH:     zName = "SQLITE_IOERR_CONVPATH";    break;
       case SQLITE_CORRUPT:            zName = "SQLITE_CORRUPT";           break;
       case SQLITE_CORRUPT_VTAB:       zName = "SQLITE_CORRUPT_VTAB";      break;
       case SQLITE_NOTFOUND:           zName = "SQLITE_NOTFOUND";          break;
@@ -115887,6 +123279,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
       case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break;
       case SQLITE_CANTOPEN_ISDIR:     zName = "SQLITE_CANTOPEN_ISDIR";    break;
       case SQLITE_CANTOPEN_FULLPATH:  zName = "SQLITE_CANTOPEN_FULLPATH"; break;
+      case SQLITE_CANTOPEN_CONVPATH:  zName = "SQLITE_CANTOPEN_CONVPATH"; break;
       case SQLITE_PROTOCOL:           zName = "SQLITE_PROTOCOL";          break;
       case SQLITE_EMPTY:              zName = "SQLITE_EMPTY";             break;
       case SQLITE_SCHEMA:             zName = "SQLITE_SCHEMA";            break;
@@ -115905,6 +123298,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
       case SQLITE_CONSTRAINT_VTAB:    zName = "SQLITE_CONSTRAINT_VTAB";   break;
       case SQLITE_CONSTRAINT_FUNCTION:
                                 zName = "SQLITE_CONSTRAINT_FUNCTION";     break;
+      case SQLITE_CONSTRAINT_ROWID:   zName = "SQLITE_CONSTRAINT_ROWID";  break;
       case SQLITE_MISMATCH:           zName = "SQLITE_MISMATCH";          break;
       case SQLITE_MISUSE:             zName = "SQLITE_MISUSE";            break;
       case SQLITE_NOLFS:              zName = "SQLITE_NOLFS";             break;
@@ -115918,6 +123312,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
       case SQLITE_NOTICE_RECOVER_ROLLBACK:
                                 zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break;
       case SQLITE_WARNING:            zName = "SQLITE_WARNING";           break;
+      case SQLITE_WARNING_AUTOINDEX:  zName = "SQLITE_WARNING_AUTOINDEX"; break;
       case SQLITE_DONE:               zName = "SQLITE_DONE";              break;
     }
   }
@@ -116078,7 +123473,7 @@ SQLITE_API void sqlite3_progress_handler(
   sqlite3_mutex_enter(db->mutex);
   if( nOps>0 ){
     db->xProgress = xProgress;
-    db->nProgressOps = nOps;
+    db->nProgressOps = (unsigned)nOps;
     db->pProgressArg = pArg;
   }else{
     db->xProgress = 0;
@@ -116131,6 +123526,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
 ){
   FuncDef *p;
   int nName;
+  int extraFlags;
 
   assert( sqlite3_mutex_held(db->mutex) );
   if( zFunctionName==0 ||
@@ -116141,6 +123537,10 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
       (255<(nName = sqlite3Strlen30( zFunctionName))) ){
     return SQLITE_MISUSE_BKPT;
   }
+
+  assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
+  extraFlags = enc &  SQLITE_DETERMINISTIC;
+  enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
   
 #ifndef SQLITE_OMIT_UTF16
   /* If SQLITE_UTF16 is specified as the encoding type, transform this
@@ -116154,10 +123554,10 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
     enc = SQLITE_UTF16NATIVE;
   }else if( enc==SQLITE_ANY ){
     int rc;
-    rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8,
+    rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags,
          pUserData, xFunc, xStep, xFinal, pDestructor);
     if( rc==SQLITE_OK ){
-      rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE,
+      rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags,
           pUserData, xFunc, xStep, xFinal, pDestructor);
     }
     if( rc!=SQLITE_OK ){
@@ -116175,8 +123575,8 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
   ** operation to continue but invalidate all precompiled statements.
   */
   p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0);
-  if( p && p->iPrefEnc==enc && p->nArg==nArg ){
-    if( db->activeVdbeCnt ){
+  if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){
+    if( db->nVdbeActive ){
       sqlite3Error(db, SQLITE_BUSY, 
         "unable to delete/modify user-function due to active statements");
       assert( !db->mallocFailed );
@@ -116200,7 +123600,8 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
     pDestructor->nRef++;
   }
   p->pDestructor = pDestructor;
-  p->flags = 0;
+  p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags;
+  testcase( p->funcFlags & SQLITE_DETERMINISTIC );
   p->xFunc = xFunc;
   p->xStep = xStep;
   p->xFinalize = xFinal;
@@ -116630,6 +124031,7 @@ SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){
   if( db->mallocFailed ){
     z = sqlite3ErrStr(SQLITE_NOMEM);
   }else{
+    testcase( db->pErr==0 );
     z = (char*)sqlite3_value_text(db->pErr);
     assert( !db->mallocFailed );
     if( z==0 ){
@@ -116671,8 +124073,7 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){
   }else{
     z = sqlite3_value_text16(db->pErr);
     if( z==0 ){
-      sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode),
-           SQLITE_UTF8, SQLITE_STATIC);
+      sqlite3Error(db, db->errCode, sqlite3ErrStr(db->errCode));
       z = sqlite3_value_text16(db->pErr);
     }
     /* A malloc() may have failed within the call to sqlite3_value_text16()
@@ -116720,6 +124121,32 @@ SQLITE_API const char *sqlite3_errstr(int rc){
 }
 
 /*
+** Invalidate all cached KeyInfo objects for database connection "db"
+*/
+static void invalidateCachedKeyInfo(sqlite3 *db){
+  Db *pDb;                    /* A single database */
+  int iDb;                    /* The database index number */
+  HashElem *k;                /* For looping over tables in pDb */
+  Table *pTab;                /* A table in the database */
+  Index *pIdx;                /* Each index */
+
+  for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
+    if( pDb->pBt==0 ) continue;
+    sqlite3BtreeEnter(pDb->pBt);
+    for(k=sqliteHashFirst(&pDb->pSchema->tblHash);  k; k=sqliteHashNext(k)){
+      pTab = (Table*)sqliteHashData(k);
+      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+        if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){
+          sqlite3KeyInfoUnref(pIdx->pKeyInfo);
+          pIdx->pKeyInfo = 0;
+        }
+      }
+    }
+    sqlite3BtreeLeave(pDb->pBt);
+  }
+}
+
+/*
 ** Create a new collating function for database "db".  The name is zName
 ** and the encoding is enc.
 */
@@ -116757,12 +124184,13 @@ static int createCollation(
   */
   pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0);
   if( pColl && pColl->xCmp ){
-    if( db->activeVdbeCnt ){
+    if( db->nVdbeActive ){
       sqlite3Error(db, SQLITE_BUSY, 
         "unable to delete/modify collation sequence due to active statements");
       return SQLITE_BUSY;
     }
     sqlite3ExpirePreparedStatements(db);
+    invalidateCachedKeyInfo(db);
 
     /* If collation sequence pColl was created directly by a call to
     ** sqlite3_create_collation, and not generated by synthCollSeq(),
@@ -116811,7 +124239,7 @@ static const int aHardLimit[] = {
   SQLITE_MAX_FUNCTION_ARG,
   SQLITE_MAX_ATTACHED,
   SQLITE_MAX_LIKE_PATTERN_LENGTH,
-  SQLITE_MAX_VARIABLE_NUMBER,
+  SQLITE_MAX_VARIABLE_NUMBER,      /* IMP: R-38091-32352 */
   SQLITE_MAX_TRIGGER_DEPTH,
 };
 
@@ -116836,8 +124264,8 @@ static const int aHardLimit[] = {
 #if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000
 # error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000
 #endif
-#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>62
-# error SQLITE_MAX_ATTACHED must be between 0 and 62
+#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125
+# error SQLITE_MAX_ATTACHED must be between 0 and 125
 #endif
 #if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
 # error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
@@ -116955,20 +124383,20 @@ SQLITE_PRIVATE int sqlite3ParseUri(
     zFile = sqlite3_malloc(nByte);
     if( !zFile ) return SQLITE_NOMEM;
 
+    iIn = 5;
+#ifndef SQLITE_ALLOW_URI_AUTHORITY
     /* Discard the scheme and authority segments of the URI. */
     if( zUri[5]=='/' && zUri[6]=='/' ){
       iIn = 7;
       while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
-
       if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
         *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s", 
             iIn-7, &zUri[7]);
         rc = SQLITE_ERROR;
         goto parse_uri_out;
       }
-    }else{
-      iIn = 5;
     }
+#endif
 
     /* Copy the filename and any query parameters into the zFile buffer. 
     ** Decode %HH escape codes along the way. 
@@ -117232,7 +124660,10 @@ static int openDatabase(
   db->nextAutovac = -1;
   db->szMmap = sqlite3GlobalConfig.szMmap;
   db->nextPagesize = 0;
-  db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger
+  db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill
+#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX
+                 | SQLITE_AutoIndex
+#endif
 #if SQLITE_DEFAULT_FILE_FORMAT<4
                  | SQLITE_LegacyFileFmt
 #endif
@@ -117356,8 +124787,6 @@ static int openDatabase(
   }
 #endif
 
-  sqlite3Error(db, rc, 0);
-
   /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
   ** mode.  -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
   ** mode.  Doing nothing at all also makes NORMAL the default.
@@ -117368,6 +124797,8 @@ static int openDatabase(
                           SQLITE_DEFAULT_LOCKING_MODE);
 #endif
 
+  if( rc ) sqlite3Error(db, rc, 0);
+
   /* Enable the lookaside-malloc subsystem */
   setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
                         sqlite3GlobalConfig.nLookaside);
@@ -117572,8 +125003,6 @@ SQLITE_API int sqlite3_global_recover(void){
 ** mode.  Return TRUE if it is and FALSE if not.  Autocommit mode is on
 ** by default.  Autocommit is disabled by a BEGIN statement and reenabled
 ** by the next COMMIT or ROLLBACK.
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
 */
 SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){
   return db->autoCommit;
@@ -117829,7 +125258,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
     ** to the xRandomness method of the default VFS.
     */
     case SQLITE_TESTCTRL_PRNG_RESET: {
-      sqlite3PrngResetState();
+      sqlite3_randomness(0,0);
       break;
     }
 
@@ -117849,6 +125278,28 @@ SQLITE_API int sqlite3_test_control(int op, ...){
     }
 
     /*
+    **  sqlite3_test_control(FAULT_INSTALL, xCallback)
+    **
+    ** Arrange to invoke xCallback() whenever sqlite3FaultSim() is called,
+    ** if xCallback is not NULL.
+    **
+    ** As a test of the fault simulator mechanism itself, sqlite3FaultSim(0)
+    ** is called immediately after installing the new callback and the return
+    ** value from sqlite3FaultSim(0) becomes the return from
+    ** sqlite3_test_control().
+    */
+    case SQLITE_TESTCTRL_FAULT_INSTALL: {
+      /* MSVC is picky about pulling func ptrs from va lists.
+      ** http://support.microsoft.com/kb/47961
+      ** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int));
+      */
+      typedef int(*TESTCALLBACKFUNC_t)(int);
+      sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
+      rc = sqlite3FaultSim(0);
+      break;
+    }
+
+    /*
     **  sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
     **
     ** Register hooks to call to indicate which malloc() failures 
@@ -117939,6 +125390,22 @@ SQLITE_API int sqlite3_test_control(int op, ...){
       break;
     }
 
+    /*
+    **   sqlite3_test_control(SQLITE_TESTCTRL_BYTEORDER);
+    **
+    ** The integer returned reveals the byte-order of the computer on which
+    ** SQLite is running:
+    **
+    **       1     big-endian,    determined at run-time
+    **      10     little-endian, determined at run-time
+    **  432101     big-endian,    determined at compile-time
+    **  123410     little-endian, determined at compile-time
+    */ 
+    case SQLITE_TESTCTRL_BYTEORDER: {
+      rc = SQLITE_BYTEORDER*100 + SQLITE_LITTLEENDIAN*10 + SQLITE_BIGENDIAN;
+      break;
+    }
+
     /*   sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
     **
     ** Set the nReserve size to N for the main database on the database
@@ -118029,6 +125496,44 @@ SQLITE_API int sqlite3_test_control(int op, ...){
     }
 #endif
 
+    /*   sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
+    **
+    ** Set or clear a flag that indicates that the database file is always well-
+    ** formed and never corrupt.  This flag is clear by default, indicating that
+    ** database files might have arbitrary corruption.  Setting the flag during
+    ** testing causes certain assert() statements in the code to be activated
+    ** that demonstrat invariants on well-formed database files.
+    */
+    case SQLITE_TESTCTRL_NEVER_CORRUPT: {
+      sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
+      break;
+    }
+
+
+    /*   sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr);
+    **
+    ** Set the VDBE coverage callback function to xCallback with context 
+    ** pointer ptr.
+    */
+    case SQLITE_TESTCTRL_VDBE_COVERAGE: {
+#ifdef SQLITE_VDBE_COVERAGE
+      typedef void (*branch_callback)(void*,int,u8,u8);
+      sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback);
+      sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*);
+#endif
+      break;
+    }
+
+    /*   sqlite3_test_control(SQLITE_TESTCTRL_ISINIT);
+    **
+    ** Return SQLITE_OK if SQLite has been initialized and SQLITE_ERROR if
+    ** not.
+    */
+    case SQLITE_TESTCTRL_ISINIT: {
+      if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
+      break;
+    }
+
   }
   va_end(ap);
 #endif /* SQLITE_OMIT_BUILTIN_TEST */
@@ -118077,7 +125582,7 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(
 ){
   const char *z = sqlite3_uri_parameter(zFilename, zParam);
   sqlite3_int64 v;
-  if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){
+  if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){
     bDflt = v;
   }
   return bDflt;
@@ -118113,7 +125618,7 @@ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
 */
 SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
   Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
-  return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1;
+  return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
 }
 
 /************** End of main.c ************************************************/
@@ -118776,7 +126281,7 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
 
 /* If not building as part of the core, include sqlite3ext.h. */
 #ifndef SQLITE_CORE
-SQLITE_API extern const sqlite3_api_routines *sqlite3_api;
+SQLITE_EXTENSION_INIT3
 #endif
 
 /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
@@ -119063,6 +126568,18 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi
 /************** Continuing where we left off in fts3Int.h ********************/
 
 /*
+** This constant determines the maximum depth of an FTS expression tree
+** that the library will create and use. FTS uses recursion to perform 
+** various operations on the query tree, so the disadvantage of a large
+** limit is that it may allow very large queries to use large amounts
+** of stack space (perhaps causing a stack overflow).
+*/
+#ifndef SQLITE_FTS3_MAX_EXPR_DEPTH
+# define SQLITE_FTS3_MAX_EXPR_DEPTH 12
+#endif
+
+
+/*
 ** This constant controls how often segments are merged. Once there are
 ** FTS3_MERGE_COUNT segments of level N, they are merged into a single
 ** segment of level N+1.
@@ -119217,23 +126734,24 @@ struct Fts3Table {
   const char *zName;              /* virtual table name */
   int nColumn;                    /* number of named columns in virtual table */
   char **azColumn;                /* column names.  malloced */
+  u8 *abNotindexed;               /* True for 'notindexed' columns */
   sqlite3_tokenizer *pTokenizer;  /* tokenizer for inserts and queries */
   char *zContentTbl;              /* content=xxx option, or NULL */
   char *zLanguageid;              /* languageid=xxx option, or NULL */
-  u8 bAutoincrmerge;              /* True if automerge=1 */
+  int nAutoincrmerge;             /* Value configured by 'automerge' */
   u32 nLeafAdd;                   /* Number of leaf blocks added this trans */
 
   /* Precompiled statements used by the implementation. Each of these 
   ** statements is run and reset within a single virtual table API call. 
   */
-  sqlite3_stmt *aStmt[37];
+  sqlite3_stmt *aStmt[40];
 
   char *zReadExprlist;
   char *zWriteExprlist;
 
   int nNodeSize;                  /* Soft limit for node size */
   u8 bFts4;                       /* True for FTS4, false for FTS3 */
-  u8 bHasStat;                    /* True if %_stat table exists */
+  u8 bHasStat;                    /* True if %_stat table exists (2==unknown) */
   u8 bHasDocsize;                 /* True if %_docsize table exists */
   u8 bDescIdx;                    /* True if doclists are in reverse order */
   u8 bIgnoreSavepoint;            /* True to ignore xSavepoint invocations */
@@ -119277,6 +126795,12 @@ struct Fts3Table {
   int inTransaction;     /* True after xBegin but before xCommit/xRollback */
   int mxSavepoint;       /* Largest valid xSavepoint integer */
 #endif
+
+#ifdef SQLITE_TEST
+  /* True to disable the incremental doclist optimization. This is controled
+  ** by special insert command 'test-no-incr-doclist'.  */
+  int bNoIncrDoclist;
+#endif
 };
 
 /*
@@ -119302,7 +126826,8 @@ struct Fts3Cursor {
   int eEvalmode;                  /* An FTS3_EVAL_XX constant */
   int nRowAvg;                    /* Average size of database rows, in pages */
   sqlite3_int64 nDoc;             /* Documents in table */
-
+  i64 iMinDocid;                  /* Minimum docid to return */
+  i64 iMaxDocid;                  /* Maximum docid to return */
   int isMatchinfoNeeded;          /* True when aMatchinfo[] needs filling in */
   u32 *aMatchinfo;                /* Information about most recent match */
   int nMatchinfo;                 /* Number of elements in aMatchinfo[] */
@@ -119332,6 +126857,15 @@ struct Fts3Cursor {
 #define FTS3_DOCID_SEARCH    1    /* Lookup by rowid on %_content table */
 #define FTS3_FULLTEXT_SEARCH 2    /* Full-text index search */
 
+/*
+** The lower 16-bits of the sqlite3_index_info.idxNum value set by
+** the xBestIndex() method contains the Fts3Cursor.eSearch value described
+** above. The upper 16-bits contain a combination of the following
+** bits, used to describe extra constraints on full-text searches.
+*/
+#define FTS3_HAVE_LANGID    0x00010000      /* languageid=? */
+#define FTS3_HAVE_DOCID_GE  0x00020000      /* docid>=? */
+#define FTS3_HAVE_DOCID_LE  0x00040000      /* docid<=? */
 
 struct Fts3Doclist {
   char *aAll;                    /* Array containing doclist (or NULL) */
@@ -119444,7 +126978,6 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
   Fts3Table*,int,const char*,int,int,Fts3SegReader**);
 SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
 SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **);
-SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
 SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
 
 SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
@@ -119519,6 +127052,10 @@ struct Fts3MultiSegReader {
 
 SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
 
+#define fts3GetVarint32(p, piVal) (                                           \
+  (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \
+)
+
 /* fts3.c */
 SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
 SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
@@ -119576,7 +127113,7 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
 SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
 
 /* fts3_unicode2.c (functions generated by parsing unicode text files) */
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
 SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int);
 SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int);
 SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int);
@@ -119626,21 +127163,37 @@ SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
   return (int) (q - (unsigned char *)p);
 }
 
+#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
+  v = (v & mask1) | ( (*ptr++) << shift );                    \
+  if( (v & mask2)==0 ){ var = v; return ret; }
+#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
+  v = (*ptr++);                                               \
+  if( (v & mask2)==0 ){ var = v; return ret; }
+
 /* 
 ** Read a 64-bit variable-length integer from memory starting at p[0].
 ** Return the number of bytes read, or 0 on error.
 ** The value is stored in *v.
 */
 SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
-  const unsigned char *q = (const unsigned char *) p;
-  sqlite_uint64 x = 0, y = 1;
-  while( (*q&0x80)==0x80 && q-(unsigned char *)p<FTS3_VARINT_MAX ){
-    x += y * (*q++ & 0x7f);
-    y <<= 7;
-  }
-  x += y * (*q++);
-  *v = (sqlite_int64) x;
-  return (int) (q - (unsigned char *)p);
+  const char *pStart = p;
+  u32 a;
+  u64 b;
+  int shift;
+
+  GETVARINT_INIT(a, p, 0,  0x00,     0x80, *v, 1);
+  GETVARINT_STEP(a, p, 7,  0x7F,     0x4000, *v, 2);
+  GETVARINT_STEP(a, p, 14, 0x3FFF,   0x200000, *v, 3);
+  GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *v, 4);
+  b = (a & 0x0FFFFFFF );
+
+  for(shift=28; shift<=63; shift+=7){
+    u64 c = *p++;
+    b += (c&0x7F) << shift;
+    if( (c & 0x80)==0 ) break;
+  }
+  *v = b;
+  return (int)(p - pStart);
 }
 
 /*
@@ -119648,10 +127201,21 @@ SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
 ** 32-bit integer before it is returned.
 */
 SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *p, int *pi){
- sqlite_int64 i;
- int ret = sqlite3Fts3GetVarint(p, &i);
- *pi = (int) i;
- return ret;
+  u32 a;
+
+#ifndef fts3GetVarint32
+  GETVARINT_INIT(a, p, 0,  0x00,     0x80, *pi, 1);
+#else
+  a = (*p++);
+  assert( a & 0x80 );
+#endif
+
+  GETVARINT_STEP(a, p, 7,  0x7F,     0x4000, *pi, 2);
+  GETVARINT_STEP(a, p, 14, 0x3FFF,   0x200000, *pi, 3);
+  GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
+  a = (a & 0x0FFFFFFF );
+  *pi = (int)(a | ((u32)(*p & 0x0F) << 28));
+  return 5;
 }
 
 /*
@@ -120377,6 +127941,8 @@ static int fts3InitVtab(
   char *zUncompress = 0;          /* uncompress=? parameter (or NULL) */
   char *zContent = 0;             /* content=? parameter (or NULL) */
   char *zLanguageid = 0;          /* languageid=? parameter (or NULL) */
+  char **azNotindexed = 0;        /* The set of notindexed= columns */
+  int nNotindexed = 0;            /* Size of azNotindexed[] array */
 
   assert( strlen(argv[0])==4 );
   assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
@@ -120386,9 +127952,19 @@ static int fts3InitVtab(
   nDb = (int)strlen(argv[1]) + 1;
   nName = (int)strlen(argv[2]) + 1;
 
-  aCol = (const char **)sqlite3_malloc(sizeof(const char *) * (argc-2) );
-  if( !aCol ) return SQLITE_NOMEM;
-  memset((void *)aCol, 0, sizeof(const char *) * (argc-2));
+  nByte = sizeof(const char *) * (argc-2);
+  aCol = (const char **)sqlite3_malloc(nByte);
+  if( aCol ){
+    memset((void*)aCol, 0, nByte);
+    azNotindexed = (char **)sqlite3_malloc(nByte);
+  }
+  if( azNotindexed ){
+    memset(azNotindexed, 0, nByte);
+  }
+  if( !aCol || !azNotindexed ){
+    rc = SQLITE_NOMEM;
+    goto fts3_init_out;
+  }
 
   /* Loop through all of the arguments passed by the user to the FTS3/4
   ** module (i.e. all the column names and special arguments). This loop
@@ -120427,7 +128003,8 @@ static int fts3InitVtab(
         { "uncompress", 10 },     /* 3 -> UNCOMPRESS */
         { "order",       5 },     /* 4 -> ORDER */
         { "content",     7 },     /* 5 -> CONTENT */
-        { "languageid", 10 }      /* 6 -> LANGUAGEID */
+        { "languageid", 10 },     /* 6 -> LANGUAGEID */
+        { "notindexed", 10 }      /* 7 -> NOTINDEXED */
       };
 
       int iOpt;
@@ -120493,6 +128070,11 @@ static int fts3InitVtab(
               zLanguageid = zVal;
               zVal = 0;
               break;
+
+            case 7:              /* NOTINDEXED */
+              azNotindexed[nNotindexed++] = zVal;
+              zVal = 0;
+              break;
           }
         }
         sqlite3_free(zVal);
@@ -120564,6 +128146,7 @@ static int fts3InitVtab(
   nByte = sizeof(Fts3Table) +                  /* Fts3Table */
           nCol * sizeof(char *) +              /* azColumn */
           nIndex * sizeof(struct Fts3Index) +  /* aIndex */
+          nCol * sizeof(u8) +                  /* abNotindexed */
           nName +                              /* zName */
           nDb +                                /* zDb */
           nString;                             /* Space for azColumn strings */
@@ -120583,7 +128166,7 @@ static int fts3InitVtab(
   p->bHasStat = isFts4;
   p->bFts4 = isFts4;
   p->bDescIdx = bDescIdx;
-  p->bAutoincrmerge = 0xff;   /* 0xff means setting unknown */
+  p->nAutoincrmerge = 0xff;   /* 0xff means setting unknown */
   p->zContentTbl = zContent;
   p->zLanguageid = zLanguageid;
   zContent = 0;
@@ -120597,9 +128180,10 @@ static int fts3InitVtab(
   for(i=0; i<nIndex; i++){
     fts3HashInit(&p->aIndex[i].hPending, FTS3_HASH_STRING, 1);
   }
+  p->abNotindexed = (u8 *)&p->aIndex[nIndex];
 
   /* Fill in the zName and zDb fields of the vtab structure. */
-  zCsr = (char *)&p->aIndex[nIndex];
+  zCsr = (char *)&p->abNotindexed[nCol];
   p->zName = zCsr;
   memcpy(zCsr, argv[2], nName);
   zCsr += nName;
@@ -120620,7 +128204,28 @@ static int fts3InitVtab(
     assert( zCsr <= &((char *)p)[nByte] );
   }
 
-  if( (zCompress==0)!=(zUncompress==0) ){
+  /* Fill in the abNotindexed array */
+  for(iCol=0; iCol<nCol; iCol++){
+    int n = (int)strlen(p->azColumn[iCol]);
+    for(i=0; i<nNotindexed; i++){
+      char *zNot = azNotindexed[i];
+      if( zNot && n==(int)strlen(zNot)
+       && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) 
+      ){
+        p->abNotindexed[iCol] = 1;
+        sqlite3_free(zNot);
+        azNotindexed[i] = 0;
+      }
+    }
+  }
+  for(i=0; i<nNotindexed; i++){
+    if( azNotindexed[i] ){
+      *pzErr = sqlite3_mprintf("no such column: %s", azNotindexed[i]);
+      rc = SQLITE_ERROR;
+    }
+  }
+
+  if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){
     char const *zMiss = (zCompress==0 ? "compress" : "uncompress");
     rc = SQLITE_ERROR;
     *pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss);
@@ -120640,10 +128245,7 @@ static int fts3InitVtab(
   ** addition of a %_stat table so that it can use incremental merge.
   */
   if( !isFts4 && !isCreate ){
-    int rc2 = SQLITE_OK;
-    fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2",
-               p->zDb, p->zName);
-    if( rc2==SQLITE_OK ) p->bHasStat = 1;
+    p->bHasStat = 2;
   }
 
   /* Figure out the page-size for the database. This is required in order to
@@ -120661,7 +128263,9 @@ fts3_init_out:
   sqlite3_free(zUncompress);
   sqlite3_free(zContent);
   sqlite3_free(zLanguageid);
+  for(i=0; i<nNotindexed; i++) sqlite3_free(azNotindexed[i]);
   sqlite3_free((void *)aCol);
+  sqlite3_free((void *)azNotindexed);
   if( rc!=SQLITE_OK ){
     if( p ){
       fts3DisconnectMethod((sqlite3_vtab *)p);
@@ -120700,6 +128304,19 @@ static int fts3CreateMethod(
   return fts3InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr);
 }
 
+/*
+** Set the pIdxInfo->estimatedRows variable to nRow. Unless this
+** extension is currently being used by a version of SQLite too old to
+** support estimatedRows. In that case this function is a no-op.
+*/
+static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
+#if SQLITE_VERSION_NUMBER>=3008002
+  if( sqlite3_libversion_number()>=3008002 ){
+    pIdxInfo->estimatedRows = nRow;
+  }
+#endif
+}
+
 /* 
 ** Implementation of the xBestIndex method for FTS3 tables. There
 ** are three possible strategies, in order of preference:
@@ -120712,23 +128329,40 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
   Fts3Table *p = (Fts3Table *)pVTab;
   int i;                          /* Iterator variable */
   int iCons = -1;                 /* Index of constraint to use */
+
   int iLangidCons = -1;           /* Index of langid=x constraint, if present */
+  int iDocidGe = -1;              /* Index of docid>=x constraint, if present */
+  int iDocidLe = -1;              /* Index of docid<=x constraint, if present */
+  int iIdx;
 
   /* By default use a full table scan. This is an expensive option,
   ** so search through the constraints to see if a more efficient 
   ** strategy is possible.
   */
   pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
-  pInfo->estimatedCost = 500000;
+  pInfo->estimatedCost = 5000000;
   for(i=0; i<pInfo->nConstraint; i++){
+    int bDocid;                 /* True if this constraint is on docid */
     struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
-    if( pCons->usable==0 ) continue;
+    if( pCons->usable==0 ){
+      if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
+        /* There exists an unusable MATCH constraint. This means that if
+        ** the planner does elect to use the results of this call as part
+        ** of the overall query plan the user will see an "unable to use
+        ** function MATCH in the requested context" error. To discourage
+        ** this, return a very high cost here.  */
+        pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
+        pInfo->estimatedCost = 1e50;
+        fts3SetEstimatedRows(pInfo, ((sqlite3_int64)1) << 50);
+        return SQLITE_OK;
+      }
+      continue;
+    }
+
+    bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1);
 
     /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
-    if( iCons<0 
-     && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ 
-     && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
-    ){
+    if( iCons<0 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && bDocid ){
       pInfo->idxNum = FTS3_DOCID_SEARCH;
       pInfo->estimatedCost = 1.0;
       iCons = i;
@@ -120757,14 +128391,38 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
     ){
       iLangidCons = i;
     }
+
+    if( bDocid ){
+      switch( pCons->op ){
+        case SQLITE_INDEX_CONSTRAINT_GE:
+        case SQLITE_INDEX_CONSTRAINT_GT:
+          iDocidGe = i;
+          break;
+
+        case SQLITE_INDEX_CONSTRAINT_LE:
+        case SQLITE_INDEX_CONSTRAINT_LT:
+          iDocidLe = i;
+          break;
+      }
+    }
   }
 
+  iIdx = 1;
   if( iCons>=0 ){
-    pInfo->aConstraintUsage[iCons].argvIndex = 1;
+    pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
     pInfo->aConstraintUsage[iCons].omit = 1;
   } 
   if( iLangidCons>=0 ){
-    pInfo->aConstraintUsage[iLangidCons].argvIndex = 2;
+    pInfo->idxNum |= FTS3_HAVE_LANGID;
+    pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++;
+  } 
+  if( iDocidGe>=0 ){
+    pInfo->idxNum |= FTS3_HAVE_DOCID_GE;
+    pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++;
+  } 
+  if( iDocidLe>=0 ){
+    pInfo->idxNum |= FTS3_HAVE_DOCID_LE;
+    pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++;
   } 
 
   /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
@@ -120942,10 +128600,10 @@ static int fts3ScanInteriorNode(
     /* Load the next term on the node into zBuffer. Use realloc() to expand
     ** the size of zBuffer if required.  */
     if( !isFirstTerm ){
-      zCsr += sqlite3Fts3GetVarint32(zCsr, &nPrefix);
+      zCsr += fts3GetVarint32(zCsr, &nPrefix);
     }
     isFirstTerm = 0;
-    zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
+    zCsr += fts3GetVarint32(zCsr, &nSuffix);
     
     if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
       rc = FTS_CORRUPT_VTAB;
@@ -121033,7 +128691,7 @@ static int fts3SelectLeaf(
 
   assert( piLeaf || piLeaf2 );
 
-  sqlite3Fts3GetVarint32(zNode, &iHeight);
+  fts3GetVarint32(zNode, &iHeight);
   rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
   assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
 
@@ -121235,11 +128893,11 @@ static void fts3PoslistMerge(
     int iCol1;         /* The current column index in pp1 */
     int iCol2;         /* The current column index in pp2 */
 
-    if( *p1==POS_COLUMN ) sqlite3Fts3GetVarint32(&p1[1], &iCol1);
+    if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1);
     else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
     else iCol1 = 0;
 
-    if( *p2==POS_COLUMN ) sqlite3Fts3GetVarint32(&p2[1], &iCol2);
+    if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2);
     else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
     else iCol2 = 0;
 
@@ -121332,11 +128990,11 @@ static int fts3PoslistPhraseMerge(
   assert( p!=0 && *p1!=0 && *p2!=0 );
   if( *p1==POS_COLUMN ){ 
     p1++;
-    p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
+    p1 += fts3GetVarint32(p1, &iCol1);
   }
   if( *p2==POS_COLUMN ){ 
     p2++;
-    p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
+    p2 += fts3GetVarint32(p2, &iCol2);
   }
 
   while( 1 ){
@@ -121386,9 +129044,9 @@ static int fts3PoslistPhraseMerge(
       if( 0==*p1 || 0==*p2 ) break;
 
       p1++;
-      p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
+      p1 += fts3GetVarint32(p1, &iCol1);
       p2++;
-      p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
+      p2 += fts3GetVarint32(p2, &iCol2);
     }
 
     /* Advance pointer p1 or p2 (whichever corresponds to the smaller of
@@ -121400,12 +129058,12 @@ static int fts3PoslistPhraseMerge(
       fts3ColumnlistCopy(0, &p1);
       if( 0==*p1 ) break;
       p1++;
-      p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
+      p1 += fts3GetVarint32(p1, &iCol1);
     }else{
       fts3ColumnlistCopy(0, &p2);
       if( 0==*p2 ) break;
       p2++;
-      p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
+      p2 += fts3GetVarint32(p2, &iCol2);
     }
   }
 
@@ -122212,6 +129870,33 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
 }
 
 /*
+** The following are copied from sqliteInt.h.
+**
+** Constants for the largest and smallest possible 64-bit signed integers.
+** These macros are designed to work correctly on both 32-bit and 64-bit
+** compilers.
+*/
+#ifndef SQLITE_AMALGAMATION
+# define LARGEST_INT64  (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
+# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
+#endif
+
+/*
+** If the numeric type of argument pVal is "integer", then return it
+** converted to a 64-bit signed integer. Otherwise, return a copy of
+** the second parameter, iDefault.
+*/
+static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){
+  if( pVal ){
+    int eType = sqlite3_value_numeric_type(pVal);
+    if( eType==SQLITE_INTEGER ){
+      return sqlite3_value_int64(pVal);
+    }
+  }
+  return iDefault;
+}
+
+/*
 ** This is the xFilter interface for the virtual table.  See
 ** the virtual table xFilter method documentation for additional
 ** information.
@@ -122236,40 +129921,58 @@ static int fts3FilterMethod(
 ){
   int rc;
   char *zSql;                     /* SQL statement used to access %_content */
+  int eSearch;
   Fts3Table *p = (Fts3Table *)pCursor->pVtab;
   Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
 
+  sqlite3_value *pCons = 0;       /* The MATCH or rowid constraint, if any */
+  sqlite3_value *pLangid = 0;     /* The "langid = ?" constraint, if any */
+  sqlite3_value *pDocidGe = 0;    /* The "docid >= ?" constraint, if any */
+  sqlite3_value *pDocidLe = 0;    /* The "docid <= ?" constraint, if any */
+  int iIdx;
+
   UNUSED_PARAMETER(idxStr);
   UNUSED_PARAMETER(nVal);
 
-  assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
-  assert( nVal==0 || nVal==1 || nVal==2 );
-  assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
+  eSearch = (idxNum & 0x0000FFFF);
+  assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
   assert( p->pSegments==0 );
 
+  /* Collect arguments into local variables */
+  iIdx = 0;
+  if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++];
+  if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++];
+  if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++];
+  if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++];
+  assert( iIdx==nVal );
+
   /* In case the cursor has been used before, clear it now. */
   sqlite3_finalize(pCsr->pStmt);
   sqlite3_free(pCsr->aDoclist);
   sqlite3Fts3ExprFree(pCsr->pExpr);
   memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
 
+  /* Set the lower and upper bounds on docids to return */
+  pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
+  pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64);
+
   if( idxStr ){
     pCsr->bDesc = (idxStr[0]=='D');
   }else{
     pCsr->bDesc = p->bDescIdx;
   }
-  pCsr->eSearch = (i16)idxNum;
+  pCsr->eSearch = (i16)eSearch;
 
-  if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
-    int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
-    const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
+  if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){
+    int iCol = eSearch-FTS3_FULLTEXT_SEARCH;
+    const char *zQuery = (const char *)sqlite3_value_text(pCons);
 
-    if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
+    if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){
       return SQLITE_NOMEM;
     }
 
     pCsr->iLangid = 0;
-    if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
+    if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid);
 
     assert( p->base.zErrMsg==0 );
     rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
@@ -122280,11 +129983,7 @@ static int fts3FilterMethod(
       return rc;
     }
 
-    rc = sqlite3Fts3ReadLock(p);
-    if( rc!=SQLITE_OK ) return rc;
-
     rc = fts3EvalStart(pCsr);
-
     sqlite3Fts3SegmentsClose(p);
     if( rc!=SQLITE_OK ) return rc;
     pCsr->pNextId = pCsr->aDoclist;
@@ -122296,7 +129995,7 @@ static int fts3FilterMethod(
   ** full-text query or docid lookup, the statement retrieves a single
   ** row by docid.
   */
-  if( idxNum==FTS3_FULLSCAN_SEARCH ){
+  if( eSearch==FTS3_FULLSCAN_SEARCH ){
     zSql = sqlite3_mprintf(
         "SELECT %s ORDER BY rowid %s",
         p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
@@ -122307,10 +130006,10 @@ static int fts3FilterMethod(
     }else{
       rc = SQLITE_NOMEM;
     }
-  }else if( idxNum==FTS3_DOCID_SEARCH ){
+  }else if( eSearch==FTS3_DOCID_SEARCH ){
     rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
     if( rc==SQLITE_OK ){
-      rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
+      rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
     }
   }
   if( rc!=SQLITE_OK ) return rc;
@@ -122438,7 +130137,10 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
   Fts3Table *p = (Fts3Table*)pVtab;
   int rc = sqlite3Fts3PendingTermsFlush(p);
 
-  if( rc==SQLITE_OK && p->bAutoincrmerge==1 && p->nLeafAdd>(nMinMerge/16) ){
+  if( rc==SQLITE_OK 
+   && p->nLeafAdd>(nMinMerge/16) 
+   && p->nAutoincrmerge && p->nAutoincrmerge!=0xff
+  ){
     int mxLevel = 0;              /* Maximum relative level value in db */
     int A;                        /* Incr-merge parameter A */
 
@@ -122446,14 +130148,41 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
     assert( rc==SQLITE_OK || mxLevel==0 );
     A = p->nLeafAdd * mxLevel;
     A += (A/2);
-    if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8);
+    if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
   }
   sqlite3Fts3SegmentsClose(p);
   return rc;
 }
 
 /*
-** Implementation of xBegin() method. This is a no-op.
+** If it is currently unknown whether or not the FTS table has an %_stat
+** table (if p->bHasStat==2), attempt to determine this (set p->bHasStat
+** to 0 or 1). Return SQLITE_OK if successful, or an SQLite error code
+** if an error occurs.
+*/
+static int fts3SetHasStat(Fts3Table *p){
+  int rc = SQLITE_OK;
+  if( p->bHasStat==2 ){
+    const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'";
+    char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
+    if( zSql ){
+      sqlite3_stmt *pStmt = 0;
+      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+      if( rc==SQLITE_OK ){
+        int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
+        rc = sqlite3_finalize(pStmt);
+        if( rc==SQLITE_OK ) p->bHasStat = bHasStat;
+      }
+      sqlite3_free(zSql);
+    }else{
+      rc = SQLITE_NOMEM;
+    }
+  }
+  return rc;
+}
+
+/*
+** Implementation of xBegin() method. 
 */
 static int fts3BeginMethod(sqlite3_vtab *pVtab){
   Fts3Table *p = (Fts3Table*)pVtab;
@@ -122464,7 +130193,7 @@ static int fts3BeginMethod(sqlite3_vtab *pVtab){
   TESTONLY( p->inTransaction = 1 );
   TESTONLY( p->mxSavepoint = -1; );
   p->nLeafAdd = 0;
-  return SQLITE_OK;
+  return fts3SetHasStat(p);
 }
 
 /*
@@ -122713,6 +130442,10 @@ static int fts3RenameMethod(
   sqlite3 *db = p->db;            /* Database connection */
   int rc;                         /* Return Code */
 
+  /* At this point it must be known if the %_stat table exists or not.
+  ** So bHasStat may not be 2.  */
+  rc = fts3SetHasStat(p);
+  
   /* As it happens, the pending terms table is always empty here. This is
   ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction 
   ** always opens a savepoint transaction. And the xSavepoint() method 
@@ -122720,7 +130453,9 @@ static int fts3RenameMethod(
   ** PendingTermsFlush() in in case that changes.
   */
   assert( p->nPendingData==0 );
-  rc = sqlite3Fts3PendingTermsFlush(p);
+  if( rc==SQLITE_OK ){
+    rc = sqlite3Fts3PendingTermsFlush(p);
+  }
 
   if( p->zContentTbl==0 ){
     fts3DbExec(&rc, db,
@@ -122848,7 +130583,7 @@ static void hashDestroy(void *p){
 */
 SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
 SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
 SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule);
 #endif
 #ifdef SQLITE_ENABLE_ICU
@@ -122866,7 +130601,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
   Fts3Hash *pHash = 0;
   const sqlite3_tokenizer_module *pSimple = 0;
   const sqlite3_tokenizer_module *pPorter = 0;
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
   const sqlite3_tokenizer_module *pUnicode = 0;
 #endif
 
@@ -122875,7 +130610,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
   sqlite3Fts3IcuTokenizerModule(&pIcu);
 #endif
 
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
   sqlite3Fts3UnicodeTokenizer(&pUnicode);
 #endif
 
@@ -122903,7 +130638,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
     if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
      || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) 
 
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
      || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode) 
 #endif
 #ifdef SQLITE_ENABLE_ICU
@@ -123202,6 +130937,12 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
 }
 
 /*
+** Maximum number of tokens a phrase may have to be considered for the
+** incremental doclists strategy.
+*/
+#define MAX_INCR_PHRASE_TOKENS 4
+
+/*
 ** This function is called for each Fts3Phrase in a full-text query 
 ** expression to initialize the mechanism for returning rows. Once this
 ** function has been called successfully on an Fts3Phrase, it may be
@@ -123214,23 +130955,43 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
 */
 static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
-  int rc;                         /* Error code */
-  Fts3PhraseToken *pFirst = &p->aToken[0];
   Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+  int rc = SQLITE_OK;             /* Error code */
+  int i;
 
-  if( pCsr->bDesc==pTab->bDescIdx 
-   && bOptOk==1 
-   && p->nToken==1 
-   && pFirst->pSegcsr 
-   && pFirst->pSegcsr->bLookup 
-   && pFirst->bFirst==0
-  ){
+  /* Determine if doclists may be loaded from disk incrementally. This is
+  ** possible if the bOptOk argument is true, the FTS doclists will be
+  ** scanned in forward order, and the phrase consists of 
+  ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first"
+  ** tokens or prefix tokens that cannot use a prefix-index.  */
+  int bHaveIncr = 0;
+  int bIncrOk = (bOptOk 
+   && pCsr->bDesc==pTab->bDescIdx 
+   && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
+   && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
+#ifdef SQLITE_TEST
+   && pTab->bNoIncrDoclist==0
+#endif
+  );
+  for(i=0; bIncrOk==1 && i<p->nToken; i++){
+    Fts3PhraseToken *pToken = &p->aToken[i];
+    if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){
+      bIncrOk = 0;
+    }
+    if( pToken->pSegcsr ) bHaveIncr = 1;
+  }
+
+  if( bIncrOk && bHaveIncr ){
     /* Use the incremental approach. */
     int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
-    rc = sqlite3Fts3MsrIncrStart(
-        pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
+    for(i=0; rc==SQLITE_OK && i<p->nToken; i++){
+      Fts3PhraseToken *pToken = &p->aToken[i];
+      Fts3MultiSegReader *pSegcsr = pToken->pSegcsr;
+      if( pSegcsr ){
+        rc = sqlite3Fts3MsrIncrStart(pTab, pSegcsr, iCol, pToken->z, pToken->n);
+      }
+    }
     p->bIncr = 1;
-
   }else{
     /* Load the full doclist for the phrase into memory. */
     rc = fts3EvalPhraseLoad(pCsr, p);
@@ -123340,15 +131101,125 @@ SQLITE_PRIVATE void sqlite3Fts3DoclistNext(
 }
 
 /*
-** Attempt to move the phrase iterator to point to the next matching docid. 
+** Advance the iterator pDL to the next entry in pDL->aAll/nAll. Set *pbEof
+** to true if EOF is reached.
+*/
+static void fts3EvalDlPhraseNext(
+  Fts3Table *pTab,
+  Fts3Doclist *pDL,
+  u8 *pbEof
+){
+  char *pIter;                            /* Used to iterate through aAll */
+  char *pEnd = &pDL->aAll[pDL->nAll];     /* 1 byte past end of aAll */
+ 
+  if( pDL->pNextDocid ){
+    pIter = pDL->pNextDocid;
+  }else{
+    pIter = pDL->aAll;
+  }
+
+  if( pIter>=pEnd ){
+    /* We have already reached the end of this doclist. EOF. */
+    *pbEof = 1;
+  }else{
+    sqlite3_int64 iDelta;
+    pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
+    if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
+      pDL->iDocid += iDelta;
+    }else{
+      pDL->iDocid -= iDelta;
+    }
+    pDL->pList = pIter;
+    fts3PoslistCopy(0, &pIter);
+    pDL->nList = (int)(pIter - pDL->pList);
+
+    /* pIter now points just past the 0x00 that terminates the position-
+    ** list for document pDL->iDocid. However, if this position-list was
+    ** edited in place by fts3EvalNearTrim(), then pIter may not actually
+    ** point to the start of the next docid value. The following line deals
+    ** with this case by advancing pIter past the zero-padding added by
+    ** fts3EvalNearTrim().  */
+    while( pIter<pEnd && *pIter==0 ) pIter++;
+
+    pDL->pNextDocid = pIter;
+    assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
+    *pbEof = 0;
+  }
+}
+
+/*
+** Helper type used by fts3EvalIncrPhraseNext() and incrPhraseTokenNext().
+*/
+typedef struct TokenDoclist TokenDoclist;
+struct TokenDoclist {
+  int bIgnore;
+  sqlite3_int64 iDocid;
+  char *pList;
+  int nList;
+};
+
+/*
+** Token pToken is an incrementally loaded token that is part of a 
+** multi-token phrase. Advance it to the next matching document in the
+** database and populate output variable *p with the details of the new
+** entry. Or, if the iterator has reached EOF, set *pbEof to true.
+**
 ** If an error occurs, return an SQLite error code. Otherwise, return 
 ** SQLITE_OK.
+*/
+static int incrPhraseTokenNext(
+  Fts3Table *pTab,                /* Virtual table handle */
+  Fts3Phrase *pPhrase,            /* Phrase to advance token of */
+  int iToken,                     /* Specific token to advance */
+  TokenDoclist *p,                /* OUT: Docid and doclist for new entry */
+  u8 *pbEof                       /* OUT: True if iterator is at EOF */
+){
+  int rc = SQLITE_OK;
+
+  if( pPhrase->iDoclistToken==iToken ){
+    assert( p->bIgnore==0 );
+    assert( pPhrase->aToken[iToken].pSegcsr==0 );
+    fts3EvalDlPhraseNext(pTab, &pPhrase->doclist, pbEof);
+    p->pList = pPhrase->doclist.pList;
+    p->nList = pPhrase->doclist.nList;
+    p->iDocid = pPhrase->doclist.iDocid;
+  }else{
+    Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
+    assert( pToken->pDeferred==0 );
+    assert( pToken->pSegcsr || pPhrase->iDoclistToken>=0 );
+    if( pToken->pSegcsr ){
+      assert( p->bIgnore==0 );
+      rc = sqlite3Fts3MsrIncrNext(
+          pTab, pToken->pSegcsr, &p->iDocid, &p->pList, &p->nList
+      );
+      if( p->pList==0 ) *pbEof = 1;
+    }else{
+      p->bIgnore = 1;
+    }
+  }
+
+  return rc;
+}
+
+
+/*
+** The phrase iterator passed as the second argument:
+**
+**   * features at least one token that uses an incremental doclist, and 
+**
+**   * does not contain any deferred tokens.
+**
+** Advance it to the next matching documnent in the database and populate
+** the Fts3Doclist.pList and nList fields. 
 **
 ** If there is no "next" entry and no error occurs, then *pbEof is set to
 ** 1 before returning. Otherwise, if no error occurs and the iterator is
 ** successfully advanced, *pbEof is set to 0.
+**
+** If an error occurs, return an SQLite error code. Otherwise, return 
+** SQLITE_OK.
 */
-static int fts3EvalPhraseNext(
+static int fts3EvalIncrPhraseNext(
   Fts3Cursor *pCsr,               /* FTS Cursor handle */
   Fts3Phrase *p,                  /* Phrase object to advance to next docid */
   u8 *pbEof                       /* OUT: Set to 1 if EOF */
@@ -123356,57 +131227,116 @@ static int fts3EvalPhraseNext(
   int rc = SQLITE_OK;
   Fts3Doclist *pDL = &p->doclist;
   Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+  u8 bEof = 0;
 
-  if( p->bIncr ){
-    assert( p->nToken==1 );
-    assert( pDL->pNextDocid==0 );
+  /* This is only called if it is guaranteed that the phrase has at least
+  ** one incremental token. In which case the bIncr flag is set. */
+  assert( p->bIncr==1 );
+
+  if( p->nToken==1 && p->bIncr ){
     rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr, 
         &pDL->iDocid, &pDL->pList, &pDL->nList
     );
-    if( rc==SQLITE_OK && !pDL->pList ){
-      *pbEof = 1;
+    if( pDL->pList==0 ) bEof = 1;
+  }else{
+    int bDescDoclist = pCsr->bDesc;
+    struct TokenDoclist a[MAX_INCR_PHRASE_TOKENS];
+
+    memset(a, 0, sizeof(a));
+    assert( p->nToken<=MAX_INCR_PHRASE_TOKENS );
+    assert( p->iDoclistToken<MAX_INCR_PHRASE_TOKENS );
+
+    while( bEof==0 ){
+      int bMaxSet = 0;
+      sqlite3_int64 iMax = 0;     /* Largest docid for all iterators */
+      int i;                      /* Used to iterate through tokens */
+
+      /* Advance the iterator for each token in the phrase once. */
+      for(i=0; rc==SQLITE_OK && i<p->nToken && bEof==0; i++){
+        rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
+        if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){
+          iMax = a[i].iDocid;
+          bMaxSet = 1;
+        }
+      }
+      assert( rc!=SQLITE_OK || a[p->nToken-1].bIgnore==0 );
+      assert( rc!=SQLITE_OK || bMaxSet );
+
+      /* Keep advancing iterators until they all point to the same document */
+      for(i=0; i<p->nToken; i++){
+        while( rc==SQLITE_OK && bEof==0 
+            && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0 
+        ){
+          rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
+          if( DOCID_CMP(a[i].iDocid, iMax)>0 ){
+            iMax = a[i].iDocid;
+            i = 0;
+          }
+        }
+      }
+
+      /* Check if the current entries really are a phrase match */
+      if( bEof==0 ){
+        int nList = 0;
+        int nByte = a[p->nToken-1].nList;
+        char *aDoclist = sqlite3_malloc(nByte+1);
+        if( !aDoclist ) return SQLITE_NOMEM;
+        memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
+
+        for(i=0; i<(p->nToken-1); i++){
+          if( a[i].bIgnore==0 ){
+            char *pL = a[i].pList;
+            char *pR = aDoclist;
+            char *pOut = aDoclist;
+            int nDist = p->nToken-1-i;
+            int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR);
+            if( res==0 ) break;
+            nList = (int)(pOut - aDoclist);
+          }
+        }
+        if( i==(p->nToken-1) ){
+          pDL->iDocid = iMax;
+          pDL->pList = aDoclist;
+          pDL->nList = nList;
+          pDL->bFreeList = 1;
+          break;
+        }
+        sqlite3_free(aDoclist);
+      }
     }
+  }
+
+  *pbEof = bEof;
+  return rc;
+}
+
+/*
+** Attempt to move the phrase iterator to point to the next matching docid. 
+** If an error occurs, return an SQLite error code. Otherwise, return 
+** SQLITE_OK.
+**
+** If there is no "next" entry and no error occurs, then *pbEof is set to
+** 1 before returning. Otherwise, if no error occurs and the iterator is
+** successfully advanced, *pbEof is set to 0.
+*/
+static int fts3EvalPhraseNext(
+  Fts3Cursor *pCsr,               /* FTS Cursor handle */
+  Fts3Phrase *p,                  /* Phrase object to advance to next docid */
+  u8 *pbEof                       /* OUT: Set to 1 if EOF */
+){
+  int rc = SQLITE_OK;
+  Fts3Doclist *pDL = &p->doclist;
+  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+
+  if( p->bIncr ){
+    rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof);
   }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
     sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll, 
         &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
     );
     pDL->pList = pDL->pNextDocid;
   }else{
-    char *pIter;                            /* Used to iterate through aAll */
-    char *pEnd = &pDL->aAll[pDL->nAll];     /* 1 byte past end of aAll */
-    if( pDL->pNextDocid ){
-      pIter = pDL->pNextDocid;
-    }else{
-      pIter = pDL->aAll;
-    }
-
-    if( pIter>=pEnd ){
-      /* We have already reached the end of this doclist. EOF. */
-      *pbEof = 1;
-    }else{
-      sqlite3_int64 iDelta;
-      pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
-      if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
-        pDL->iDocid += iDelta;
-      }else{
-        pDL->iDocid -= iDelta;
-      }
-      pDL->pList = pIter;
-      fts3PoslistCopy(0, &pIter);
-      pDL->nList = (int)(pIter - pDL->pList);
-
-      /* pIter now points just past the 0x00 that terminates the position-
-      ** list for document pDL->iDocid. However, if this position-list was
-      ** edited in place by fts3EvalNearTrim(), then pIter may not actually
-      ** point to the start of the next docid value. The following line deals
-      ** with this case by advancing pIter past the zero-padding added by
-      ** fts3EvalNearTrim().  */
-      while( pIter<pEnd && *pIter==0 ) pIter++;
-
-      pDL->pNextDocid = pIter;
-      assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
-      *pbEof = 0;
-    }
+    fts3EvalDlPhraseNext(pTab, pDL, pbEof);
   }
 
   return rc;
@@ -123431,7 +131361,6 @@ static int fts3EvalPhraseNext(
 static void fts3EvalStartReaders(
   Fts3Cursor *pCsr,               /* FTS Cursor handle */
   Fts3Expr *pExpr,                /* Expression to initialize phrases in */
-  int bOptOk,                     /* True to enable incremental loading */
   int *pRc                        /* IN/OUT: Error code */
 ){
   if( pExpr && SQLITE_OK==*pRc ){
@@ -123442,10 +131371,10 @@ static void fts3EvalStartReaders(
         if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
       }
       pExpr->bDeferred = (i==nToken);
-      *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
+      *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase);
     }else{
-      fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
-      fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
+      fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc);
+      fts3EvalStartReaders(pCsr, pExpr->pRight, pRc);
       pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
     }
   }
@@ -123687,7 +131616,7 @@ static int fts3EvalSelectDeferred(
       ** overflowing the 32-bit integer it is stored in. */
       if( ii<12 ) nLoad4 = nLoad4*4;
 
-      if( ii==0 || pTC->pPhrase->nToken>1 ){
+      if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){
         /* Either this is the cheapest token in the entire query, or it is
         ** part of a multi-token phrase. Either way, the entire doclist will
         ** (eventually) be loaded into memory. It may as well be now. */
@@ -123767,7 +131696,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
   }
 #endif
 
-  fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
+  fts3EvalStartReaders(pCsr, pCsr->pExpr, &rc);
   return rc;
 }
 
@@ -124250,6 +132179,16 @@ static int fts3EvalNext(Fts3Cursor *pCsr){
       pCsr->iPrevId = pExpr->iDocid;
     }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
   }
+
+  /* Check if the cursor is past the end of the docid range specified
+  ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag.  */
+  if( rc==SQLITE_OK && (
+        (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid)
+     || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid)
+  )){
+    pCsr->isEof = 1;
+  }
+
   return rc;
 }
 
@@ -124273,12 +132212,16 @@ static void fts3EvalRestart(
     if( pPhrase ){
       fts3EvalInvalidatePoslist(pPhrase);
       if( pPhrase->bIncr ){
-        assert( pPhrase->nToken==1 );
-        assert( pPhrase->aToken[0].pSegcsr );
-        sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
+        int i;
+        for(i=0; i<pPhrase->nToken; i++){
+          Fts3PhraseToken *pToken = &pPhrase->aToken[i];
+          assert( pToken->pDeferred==0 );
+          if( pToken->pSegcsr ){
+            sqlite3Fts3MsrIncrRestart(pToken->pSegcsr);
+          }
+        }
         *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
       }
-
       pPhrase->doclist.pNextDocid = 0;
       pPhrase->doclist.iDocid = 0;
     }
@@ -124323,7 +132266,7 @@ static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
         pExpr->aMI[iCol*3 + 2] += (iCnt>0);
         if( *p==0x00 ) break;
         p++;
-        p += sqlite3Fts3GetVarint32(p, &iCol);
+        p += fts3GetVarint32(p, &iCol);
       }
     }
 
@@ -124527,15 +132470,23 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
   pIter = pPhrase->doclist.pList;
   if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
     int bDescDoclist = pTab->bDescIdx;      /* For DOCID_CMP macro */
+    int iMul;                     /* +1 if csr dir matches index dir, else -1 */
     int bOr = 0;
     u8 bEof = 0;
-    Fts3Expr *p;
+    u8 bTreeEof = 0;
+    Fts3Expr *p;                  /* Used to iterate from pExpr to root */
+    Fts3Expr *pNear;              /* Most senior NEAR ancestor (or pExpr) */
 
     /* Check if this phrase descends from an OR expression node. If not, 
     ** return NULL. Otherwise, the entry that corresponds to docid 
-    ** pCsr->iPrevId may lie earlier in the doclist buffer. */
+    ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the
+    ** tree that the node is part of has been marked as EOF, but the node
+    ** itself is not EOF, then it may point to an earlier entry. */
+    pNear = pExpr;
     for(p=pExpr->pParent; p; p=p->pParent){
       if( p->eType==FTSQUERY_OR ) bOr = 1;
+      if( p->eType==FTSQUERY_NEAR ) pNear = p;
+      if( p->bEof ) bTreeEof = 1;
     }
     if( bOr==0 ) return SQLITE_OK;
 
@@ -124554,29 +132505,59 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
       assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
       if( rc!=SQLITE_OK ) return rc;
     }
-
-    if( pExpr->bEof ){
-      pIter = 0;
-      iDocid = 0;
+    
+    iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1);
+    while( bTreeEof==1 
+        && pNear->bEof==0
+        && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0
+    ){
+      int rc = SQLITE_OK;
+      fts3EvalNextRow(pCsr, pExpr, &rc);
+      if( rc!=SQLITE_OK ) return rc;
+      iDocid = pExpr->iDocid;
+      pIter = pPhrase->doclist.pList;
     }
+
     bEof = (pPhrase->doclist.nAll==0);
     assert( bDescDoclist==0 || bDescDoclist==1 );
     assert( pCsr->bDesc==0 || pCsr->bDesc==1 );
 
-    if( pCsr->bDesc==bDescDoclist ){
-      int dummy;
-      while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
-        sqlite3Fts3DoclistPrev(
-            bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, 
-            &pIter, &iDocid, &dummy, &bEof
-        );
-      }
-    }else{
-      while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
-        sqlite3Fts3DoclistNext(
-            bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, 
-            &pIter, &iDocid, &bEof
-        );
+    if( bEof==0 ){
+      if( pCsr->bDesc==bDescDoclist ){
+        int dummy;
+        if( pNear->bEof ){
+          /* This expression is already at EOF. So position it to point to the
+          ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable
+          ** iDocid is already set for this entry, so all that is required is
+          ** to set pIter to point to the first byte of the last position-list
+          ** in the doclist. 
+          **
+          ** It would also be correct to set pIter and iDocid to zero. In
+          ** this case, the first call to sqltie3Fts4DoclistPrev() below
+          ** would also move the iterator to point to the last entry in the 
+          ** doclist. However, this is expensive, as to do so it has to 
+          ** iterate through the entire doclist from start to finish (since
+          ** it does not know the docid for the last entry).  */
+          pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1];
+          fts3ReversePoslist(pPhrase->doclist.aAll, &pIter);
+        }
+        while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
+          sqlite3Fts3DoclistPrev(
+              bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, 
+              &pIter, &iDocid, &dummy, &bEof
+          );
+        }
+      }else{
+        if( pNear->bEof ){
+          pIter = 0;
+          iDocid = 0;
+        }
+        while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
+          sqlite3Fts3DoclistNext(
+              bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, 
+              &pIter, &iDocid, &bEof
+          );
+        }
       }
     }
 
@@ -124586,7 +132567,7 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
 
   if( *pIter==0x01 ){
     pIter++;
-    pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
+    pIter += fts3GetVarint32(pIter, &iThis);
   }else{
     iThis = 0;
   }
@@ -124594,7 +132575,7 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
     fts3ColumnlistCopy(0, &pIter);
     if( *pIter==0x00 ) return 0;
     pIter++;
-    pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
+    pIter += fts3GetVarint32(pIter, &iThis);
   }
 
   *ppOut = ((iCol==iThis)?pIter:0);
@@ -124635,7 +132616,10 @@ SQLITE_PRIVATE int sqlite3Fts3Corrupt(){
 /*
 ** Initialize API pointer table, if required.
 */
-SQLITE_API int sqlite3_extension_init(
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+SQLITE_API int sqlite3_fts3_init(
   sqlite3 *db, 
   char **pzErrMsg,
   const sqlite3_api_routines *pApi
@@ -124681,6 +132665,7 @@ struct Fts3auxCursor {
   Fts3SegFilter filter;
   char *zStop;
   int nStop;                      /* Byte-length of string zStop */
+  int iLangid;                    /* Language id to query */
   int isEof;                      /* True if cursor is at EOF */
   sqlite3_int64 iRowid;           /* Current rowid */
 
@@ -124695,7 +132680,8 @@ struct Fts3auxCursor {
 /*
 ** Schema of the terms table.
 */
-#define FTS3_TERMS_SCHEMA "CREATE TABLE x(term, col, documents, occurrences)"
+#define FTS3_AUX_SCHEMA \
+  "CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)"
 
 /*
 ** This function does all the work for both the xConnect and xCreate methods.
@@ -124742,7 +132728,7 @@ static int fts3auxConnectMethod(
   }
   nFts3 = (int)strlen(zFts3);
 
-  rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
+  rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA);
   if( rc!=SQLITE_OK ) return rc;
 
   nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
@@ -124802,6 +132788,8 @@ static int fts3auxBestIndexMethod(
   int iEq = -1;
   int iGe = -1;
   int iLe = -1;
+  int iLangid = -1;
+  int iNext = 1;                  /* Next free argvIndex value */
 
   UNUSED_PARAMETER(pVTab);
 
@@ -124813,36 +132801,48 @@ static int fts3auxBestIndexMethod(
     pInfo->orderByConsumed = 1;
   }
 
-  /* Search for equality and range constraints on the "term" column. */
+  /* Search for equality and range constraints on the "term" column. 
+  ** And equality constraints on the hidden "languageid" column. */
   for(i=0; i<pInfo->nConstraint; i++){
-    if( pInfo->aConstraint[i].usable && pInfo->aConstraint[i].iColumn==0 ){
+    if( pInfo->aConstraint[i].usable ){
       int op = pInfo->aConstraint[i].op;
-      if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
-      if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
-      if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
-      if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
-      if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
+      int iCol = pInfo->aConstraint[i].iColumn;
+
+      if( iCol==0 ){
+        if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
+        if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
+        if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
+        if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
+        if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
+      }
+      if( iCol==4 ){
+        if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i;
+      }
     }
   }
 
   if( iEq>=0 ){
     pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT;
-    pInfo->aConstraintUsage[iEq].argvIndex = 1;
+    pInfo->aConstraintUsage[iEq].argvIndex = iNext++;
     pInfo->estimatedCost = 5;
   }else{
     pInfo->idxNum = 0;
     pInfo->estimatedCost = 20000;
     if( iGe>=0 ){
       pInfo->idxNum += FTS4AUX_GE_CONSTRAINT;
-      pInfo->aConstraintUsage[iGe].argvIndex = 1;
+      pInfo->aConstraintUsage[iGe].argvIndex = iNext++;
       pInfo->estimatedCost /= 2;
     }
     if( iLe>=0 ){
       pInfo->idxNum += FTS4AUX_LE_CONSTRAINT;
-      pInfo->aConstraintUsage[iLe].argvIndex = 1 + (iGe>=0);
+      pInfo->aConstraintUsage[iLe].argvIndex = iNext++;
       pInfo->estimatedCost /= 2;
     }
   }
+  if( iLangid>=0 ){
+    pInfo->aConstraintUsage[iLangid].argvIndex = iNext++;
+    pInfo->estimatedCost--;
+  }
 
   return SQLITE_OK;
 }
@@ -125002,7 +133002,14 @@ static int fts3auxFilterMethod(
   Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
   Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
   int rc;
-  int isScan;
+  int isScan = 0;
+  int iLangVal = 0;               /* Language id to query */
+
+  int iEq = -1;                   /* Index of term=? value in apVal */
+  int iGe = -1;                   /* Index of term>=? value in apVal */
+  int iLe = -1;                   /* Index of term<=? value in apVal */
+  int iLangid = -1;               /* Index of languageid=? value in apVal */
+  int iNext = 0;
 
   UNUSED_PARAMETER(nVal);
   UNUSED_PARAMETER(idxStr);
@@ -125012,7 +133019,21 @@ static int fts3auxFilterMethod(
        || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT
        || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT)
   );
-  isScan = (idxNum!=FTS4AUX_EQ_CONSTRAINT);
+
+  if( idxNum==FTS4AUX_EQ_CONSTRAINT ){
+    iEq = iNext++;
+  }else{
+    isScan = 1;
+    if( idxNum & FTS4AUX_GE_CONSTRAINT ){
+      iGe = iNext++;
+    }
+    if( idxNum & FTS4AUX_LE_CONSTRAINT ){
+      iLe = iNext++;
+    }
+  }
+  if( iNext<nVal ){
+    iLangid = iNext++;
+  }
 
   /* In case this cursor is being reused, close and zero it. */
   testcase(pCsr->filter.zTerm);
@@ -125024,22 +133045,35 @@ static int fts3auxFilterMethod(
   pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
   if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
 
-  if( idxNum&(FTS4AUX_EQ_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) ){
+  if( iEq>=0 || iGe>=0 ){
     const unsigned char *zStr = sqlite3_value_text(apVal[0]);
+    assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
     if( zStr ){
       pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
       pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
       if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
     }
   }
-  if( idxNum&FTS4AUX_LE_CONSTRAINT ){
-    int iIdx = (idxNum&FTS4AUX_GE_CONSTRAINT) ? 1 : 0;
-    pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
-    pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
+
+  if( iLe>=0 ){
+    pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
+    pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
     if( pCsr->zStop==0 ) return SQLITE_NOMEM;
   }
+  
+  if( iLangid>=0 ){
+    iLangVal = sqlite3_value_int(apVal[iLangid]);
 
-  rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL,
+    /* If the user specified a negative value for the languageid, use zero
+    ** instead. This works, as the "languageid=?" constraint will also
+    ** be tested by the VDBE layer. The test will always be false (since
+    ** this module will not return a row with a negative languageid), and
+    ** so the overall query will return zero rows.  */
+    if( iLangVal<0 ) iLangVal = 0;
+  }
+  pCsr->iLangid = iLangVal;
+
+  rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL,
       pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
   );
   if( rc==SQLITE_OK ){
@@ -125063,24 +133097,37 @@ static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){
 */
 static int fts3auxColumnMethod(
   sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
-  sqlite3_context *pContext,      /* Context for sqlite3_result_xxx() calls */
+  sqlite3_context *pCtx,          /* Context for sqlite3_result_xxx() calls */
   int iCol                        /* Index of column to read value from */
 ){
   Fts3auxCursor *p = (Fts3auxCursor *)pCursor;
 
   assert( p->isEof==0 );
-  if( iCol==0 ){        /* Column "term" */
-    sqlite3_result_text(pContext, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
-  }else if( iCol==1 ){  /* Column "col" */
-    if( p->iCol ){
-      sqlite3_result_int(pContext, p->iCol-1);
-    }else{
-      sqlite3_result_text(pContext, "*", -1, SQLITE_STATIC);
-    }
-  }else if( iCol==2 ){  /* Column "documents" */
-    sqlite3_result_int64(pContext, p->aStat[p->iCol].nDoc);
-  }else{                /* Column "occurrences" */
-    sqlite3_result_int64(pContext, p->aStat[p->iCol].nOcc);
+  switch( iCol ){
+    case 0: /* term */
+      sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
+      break;
+
+    case 1: /* col */
+      if( p->iCol ){
+        sqlite3_result_int(pCtx, p->iCol-1);
+      }else{
+        sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC);
+      }
+      break;
+
+    case 2: /* documents */
+      sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc);
+      break;
+
+    case 3: /* occurrences */
+      sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc);
+      break;
+
+    default: /* languageid */
+      assert( iCol==4 );
+      sqlite3_result_int(pCtx, p->iLangid);
+      break;
   }
 
   return SQLITE_OK;
@@ -125294,6 +133341,11 @@ SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(
   return rc;
 }
 
+/*
+** Function getNextNode(), which is called by fts3ExprParse(), may itself
+** call fts3ExprParse(). So this forward declaration is required.
+*/
+static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
 
 /*
 ** Extract the next token from buffer z (length n) using the tokenizer
@@ -125319,9 +133371,16 @@ static int getNextToken(
   int rc;
   sqlite3_tokenizer_cursor *pCursor;
   Fts3Expr *pRet = 0;
-  int nConsumed = 0;
+  int i = 0;
 
-  rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
+  /* Set variable i to the maximum number of bytes of input to tokenize. */
+  for(i=0; i<n; i++){
+    if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
+    if( z[i]=='*' || z[i]=='"' ) break;
+  }
+
+  *pnConsumed = i;
+  rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
   if( rc==SQLITE_OK ){
     const char *zToken;
     int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
@@ -125362,13 +133421,14 @@ static int getNextToken(
         }
 
       }
-      nConsumed = iEnd;
+      *pnConsumed = iEnd;
+    }else if( i && rc==SQLITE_DONE ){
+      rc = SQLITE_OK;
     }
 
     pModule->xClose(pCursor);
   }
   
-  *pnConsumed = nConsumed;
   *ppExpr = pRet;
   return rc;
 }
@@ -125509,12 +133569,6 @@ no_mem:
 }
 
 /*
-** Function getNextNode(), which is called by fts3ExprParse(), may itself
-** call fts3ExprParse(). So this forward declaration is required.
-*/
-static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
-
-/*
 ** The output variable *ppExpr is populated with an allocated Fts3Expr 
 ** structure, or set to 0 if the end of the input buffer is reached.
 **
@@ -125610,27 +133664,6 @@ static int getNextNode(
     }
   }
 
-  /* Check for an open bracket. */
-  if( sqlite3_fts3_enable_parentheses ){
-    if( *zInput=='(' ){
-      int nConsumed;
-      pParse->nNest++;
-      rc = fts3ExprParse(pParse, &zInput[1], nInput-1, ppExpr, &nConsumed);
-      if( rc==SQLITE_OK && !*ppExpr ){
-        rc = SQLITE_DONE;
-      }
-      *pnConsumed = (int)((zInput - z) + 1 + nConsumed);
-      return rc;
-    }
-  
-    /* Check for a close bracket. */
-    if( *zInput==')' ){
-      pParse->nNest--;
-      *pnConsumed = (int)((zInput - z) + 1);
-      return SQLITE_DONE;
-    }
-  }
-
   /* See if we are dealing with a quoted phrase. If this is the case, then
   ** search for the closing quote and pass the whole string to getNextString()
   ** for processing. This is easy to do, as fts3 has no syntax for escaping
@@ -125645,6 +133678,21 @@ static int getNextNode(
     return getNextString(pParse, &zInput[1], ii-1, ppExpr);
   }
 
+  if( sqlite3_fts3_enable_parentheses ){
+    if( *zInput=='(' ){
+      int nConsumed = 0;
+      pParse->nNest++;
+      rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
+      if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; }
+      *pnConsumed = (int)(zInput - z) + 1 + nConsumed;
+      return rc;
+    }else if( *zInput==')' ){
+      pParse->nNest--;
+      *pnConsumed = (int)((zInput - z) + 1);
+      *ppExpr = 0;
+      return SQLITE_DONE;
+    }
+  }
 
   /* If control flows to this point, this must be a regular token, or 
   ** the end of the input. Read a regular token using the sqlite3_tokenizer
@@ -125763,96 +133811,100 @@ static int fts3ExprParse(
   while( rc==SQLITE_OK ){
     Fts3Expr *p = 0;
     int nByte = 0;
+
     rc = getNextNode(pParse, zIn, nIn, &p, &nByte);
+    assert( nByte>0 || (rc!=SQLITE_OK && p==0) );
     if( rc==SQLITE_OK ){
-      int isPhrase;
-
-      if( !sqlite3_fts3_enable_parentheses 
-       && p->eType==FTSQUERY_PHRASE && pParse->isNot 
-      ){
-        /* Create an implicit NOT operator. */
-        Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
-        if( !pNot ){
-          sqlite3Fts3ExprFree(p);
-          rc = SQLITE_NOMEM;
-          goto exprparse_out;
-        }
-        pNot->eType = FTSQUERY_NOT;
-        pNot->pRight = p;
-        p->pParent = pNot;
-        if( pNotBranch ){
-          pNot->pLeft = pNotBranch;
-          pNotBranch->pParent = pNot;
-        }
-        pNotBranch = pNot;
-        p = pPrev;
-      }else{
-        int eType = p->eType;
-        isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
+      if( p ){
+        int isPhrase;
 
-        /* The isRequirePhrase variable is set to true if a phrase or
-        ** an expression contained in parenthesis is required. If a
-        ** binary operator (AND, OR, NOT or NEAR) is encounted when
-        ** isRequirePhrase is set, this is a syntax error.
-        */
-        if( !isPhrase && isRequirePhrase ){
-          sqlite3Fts3ExprFree(p);
-          rc = SQLITE_ERROR;
-          goto exprparse_out;
-        }
-  
-        if( isPhrase && !isRequirePhrase ){
-          /* Insert an implicit AND operator. */
-          Fts3Expr *pAnd;
-          assert( pRet && pPrev );
-          pAnd = fts3MallocZero(sizeof(Fts3Expr));
-          if( !pAnd ){
+        if( !sqlite3_fts3_enable_parentheses 
+            && p->eType==FTSQUERY_PHRASE && pParse->isNot 
+        ){
+          /* Create an implicit NOT operator. */
+          Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
+          if( !pNot ){
             sqlite3Fts3ExprFree(p);
             rc = SQLITE_NOMEM;
             goto exprparse_out;
           }
-          pAnd->eType = FTSQUERY_AND;
-          insertBinaryOperator(&pRet, pPrev, pAnd);
-          pPrev = pAnd;
-        }
+          pNot->eType = FTSQUERY_NOT;
+          pNot->pRight = p;
+          p->pParent = pNot;
+          if( pNotBranch ){
+            pNot->pLeft = pNotBranch;
+            pNotBranch->pParent = pNot;
+          }
+          pNotBranch = pNot;
+          p = pPrev;
+        }else{
+          int eType = p->eType;
+          isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
 
-        /* This test catches attempts to make either operand of a NEAR
-        ** operator something other than a phrase. For example, either of
-        ** the following:
-        **
-        **    (bracketed expression) NEAR phrase
-        **    phrase NEAR (bracketed expression)
-        **
-        ** Return an error in either case.
-        */
-        if( pPrev && (
+          /* The isRequirePhrase variable is set to true if a phrase or
+          ** an expression contained in parenthesis is required. If a
+          ** binary operator (AND, OR, NOT or NEAR) is encounted when
+          ** isRequirePhrase is set, this is a syntax error.
+          */
+          if( !isPhrase && isRequirePhrase ){
+            sqlite3Fts3ExprFree(p);
+            rc = SQLITE_ERROR;
+            goto exprparse_out;
+          }
+
+          if( isPhrase && !isRequirePhrase ){
+            /* Insert an implicit AND operator. */
+            Fts3Expr *pAnd;
+            assert( pRet && pPrev );
+            pAnd = fts3MallocZero(sizeof(Fts3Expr));
+            if( !pAnd ){
+              sqlite3Fts3ExprFree(p);
+              rc = SQLITE_NOMEM;
+              goto exprparse_out;
+            }
+            pAnd->eType = FTSQUERY_AND;
+            insertBinaryOperator(&pRet, pPrev, pAnd);
+            pPrev = pAnd;
+          }
+
+          /* This test catches attempts to make either operand of a NEAR
+           ** operator something other than a phrase. For example, either of
+           ** the following:
+           **
+           **    (bracketed expression) NEAR phrase
+           **    phrase NEAR (bracketed expression)
+           **
+           ** Return an error in either case.
+           */
+          if( pPrev && (
             (eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE)
          || (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR)
-        )){
-          sqlite3Fts3ExprFree(p);
-          rc = SQLITE_ERROR;
-          goto exprparse_out;
-        }
-  
-        if( isPhrase ){
-          if( pRet ){
-            assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
-            pPrev->pRight = p;
-            p->pParent = pPrev;
+          )){
+            sqlite3Fts3ExprFree(p);
+            rc = SQLITE_ERROR;
+            goto exprparse_out;
+          }
+
+          if( isPhrase ){
+            if( pRet ){
+              assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
+              pPrev->pRight = p;
+              p->pParent = pPrev;
+            }else{
+              pRet = p;
+            }
           }else{
-            pRet = p;
+            insertBinaryOperator(&pRet, pPrev, p);
           }
-        }else{
-          insertBinaryOperator(&pRet, pPrev, p);
+          isRequirePhrase = !isPhrase;
         }
-        isRequirePhrase = !isPhrase;
+        pPrev = p;
       }
       assert( nByte>0 );
     }
     assert( rc!=SQLITE_OK || (nByte>0 && nByte<=nIn) );
     nIn -= nByte;
     zIn += nByte;
-    pPrev = p;
   }
 
   if( rc==SQLITE_DONE && pRet && isRequirePhrase ){
@@ -126139,17 +134191,16 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(
   Fts3Expr **ppExpr,                  /* OUT: Parsed query structure */
   char **pzErr                        /* OUT: Error message (sqlite3_malloc) */
 ){
-  static const int MAX_EXPR_DEPTH = 12;
   int rc = fts3ExprParseUnbalanced(
       pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr
   );
   
   /* Rebalance the expression. And check that its depth does not exceed
-  ** MAX_EXPR_DEPTH.  */
+  ** SQLITE_FTS3_MAX_EXPR_DEPTH.  */
   if( rc==SQLITE_OK && *ppExpr ){
-    rc = fts3ExprBalance(ppExpr, MAX_EXPR_DEPTH);
+    rc = fts3ExprBalance(ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH);
     if( rc==SQLITE_OK ){
-      rc = fts3ExprCheckDepth(*ppExpr, MAX_EXPR_DEPTH);
+      rc = fts3ExprCheckDepth(*ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH);
     }
   }
 
@@ -126158,7 +134209,8 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(
     *ppExpr = 0;
     if( rc==SQLITE_TOOBIG ){
       *pzErr = sqlite3_mprintf(
-          "FTS expression tree is too large (maximum depth %d)", MAX_EXPR_DEPTH
+          "FTS expression tree is too large (maximum depth %d)", 
+          SQLITE_FTS3_MAX_EXPR_DEPTH
       );
       rc = SQLITE_ERROR;
     }else if( rc==SQLITE_ERROR ){
@@ -126514,13 +134566,13 @@ SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash *pH){
 */
 static int fts3StrHash(const void *pKey, int nKey){
   const char *z = (const char *)pKey;
-  int h = 0;
+  unsigned h = 0;
   if( nKey<=0 ) nKey = (int) strlen(z);
   while( nKey > 0  ){
     h = (h<<3) ^ h ^ *z++;
     nKey--;
   }
-  return h & 0x7fffffff;
+  return (int)(h & 0x7fffffff);
 }
 static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
   if( n1!=n2 ) return 1;
@@ -127205,12 +135257,14 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
   /* Step 2 */
   switch( z[1] ){
    case 'a':
-     stem(&z, "lanoita", "ate", m_gt_0) ||
-     stem(&z, "lanoit", "tion", m_gt_0);
+     if( !stem(&z, "lanoita", "ate", m_gt_0) ){
+       stem(&z, "lanoit", "tion", m_gt_0);
+     }
      break;
    case 'c':
-     stem(&z, "icne", "ence", m_gt_0) ||
-     stem(&z, "icna", "ance", m_gt_0);
+     if( !stem(&z, "icne", "ence", m_gt_0) ){
+       stem(&z, "icna", "ance", m_gt_0);
+     }
      break;
    case 'e':
      stem(&z, "rezi", "ize", m_gt_0);
@@ -127219,43 +135273,54 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
      stem(&z, "igol", "log", m_gt_0);
      break;
    case 'l':
-     stem(&z, "ilb", "ble", m_gt_0) ||
-     stem(&z, "illa", "al", m_gt_0) ||
-     stem(&z, "iltne", "ent", m_gt_0) ||
-     stem(&z, "ile", "e", m_gt_0) ||
-     stem(&z, "ilsuo", "ous", m_gt_0);
+     if( !stem(&z, "ilb", "ble", m_gt_0) 
+      && !stem(&z, "illa", "al", m_gt_0)
+      && !stem(&z, "iltne", "ent", m_gt_0)
+      && !stem(&z, "ile", "e", m_gt_0)
+     ){
+       stem(&z, "ilsuo", "ous", m_gt_0);
+     }
      break;
    case 'o':
-     stem(&z, "noitazi", "ize", m_gt_0) ||
-     stem(&z, "noita", "ate", m_gt_0) ||
-     stem(&z, "rota", "ate", m_gt_0);
+     if( !stem(&z, "noitazi", "ize", m_gt_0)
+      && !stem(&z, "noita", "ate", m_gt_0)
+     ){
+       stem(&z, "rota", "ate", m_gt_0);
+     }
      break;
    case 's':
-     stem(&z, "msila", "al", m_gt_0) ||
-     stem(&z, "ssenevi", "ive", m_gt_0) ||
-     stem(&z, "ssenluf", "ful", m_gt_0) ||
-     stem(&z, "ssensuo", "ous", m_gt_0);
+     if( !stem(&z, "msila", "al", m_gt_0)
+      && !stem(&z, "ssenevi", "ive", m_gt_0)
+      && !stem(&z, "ssenluf", "ful", m_gt_0)
+     ){
+       stem(&z, "ssensuo", "ous", m_gt_0);
+     }
      break;
    case 't':
-     stem(&z, "itila", "al", m_gt_0) ||
-     stem(&z, "itivi", "ive", m_gt_0) ||
-     stem(&z, "itilib", "ble", m_gt_0);
+     if( !stem(&z, "itila", "al", m_gt_0)
+      && !stem(&z, "itivi", "ive", m_gt_0)
+     ){
+       stem(&z, "itilib", "ble", m_gt_0);
+     }
      break;
   }
 
   /* Step 3 */
   switch( z[0] ){
    case 'e':
-     stem(&z, "etaci", "ic", m_gt_0) ||
-     stem(&z, "evita", "", m_gt_0)   ||
-     stem(&z, "ezila", "al", m_gt_0);
+     if( !stem(&z, "etaci", "ic", m_gt_0)
+      && !stem(&z, "evita", "", m_gt_0)
+     ){
+       stem(&z, "ezila", "al", m_gt_0);
+     }
      break;
    case 'i':
      stem(&z, "itici", "ic", m_gt_0);
      break;
    case 'l':
-     stem(&z, "laci", "ic", m_gt_0) ||
-     stem(&z, "luf", "", m_gt_0);
+     if( !stem(&z, "laci", "ic", m_gt_0) ){
+       stem(&z, "luf", "", m_gt_0);
+     }
      break;
    case 's':
      stem(&z, "ssen", "", m_gt_0);
@@ -127296,9 +135361,11 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
            z += 3;
          }
        }else if( z[2]=='e' ){
-         stem(&z, "tneme", "", m_gt_1) ||
-         stem(&z, "tnem", "", m_gt_1) ||
-         stem(&z, "tne", "", m_gt_1);
+         if( !stem(&z, "tneme", "", m_gt_1)
+          && !stem(&z, "tnem", "", m_gt_1)
+         ){
+           stem(&z, "tne", "", m_gt_1);
+         }
        }
      }
      break;
@@ -127317,8 +135384,9 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
      }
      break;
    case 't':
-     stem(&z, "eta", "", m_gt_1) ||
-     stem(&z, "iti", "", m_gt_1);
+     if( !stem(&z, "eta", "", m_gt_1) ){
+       stem(&z, "iti", "", m_gt_1);
+     }
      break;
    case 'u':
      if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){
@@ -127653,7 +135721,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
 
 #ifdef SQLITE_TEST
 
-/* #include <tcl.h> */
+#include <tcl.h>
 /* #include <string.h> */
 
 /*
@@ -128824,6 +136892,7 @@ struct SegmentWriter {
   int nSize;                      /* Size of allocation at aData */
   int nData;                      /* Bytes of data in aData */
   char *aData;                    /* Pointer to block from malloc() */
+  i64 nLeafData;                  /* Number of bytes of leaf data written */
 };
 
 /*
@@ -128899,6 +136968,10 @@ struct SegmentNode {
 #define SQL_SELECT_INDEXES            35
 #define SQL_SELECT_MXLEVEL            36
 
+#define SQL_SELECT_LEVEL_RANGE2       37
+#define SQL_UPDATE_LEVEL_IDX          38
+#define SQL_UPDATE_LEVEL              39
+
 /*
 ** This function is used to obtain an SQLite prepared statement handle
 ** for the statement identified by the second argument. If successful,
@@ -129000,7 +137073,18 @@ static int fts3SqlStmt(
 
 /* SQL_SELECT_MXLEVEL
 **   Return the largest relative level in the FTS index or indexes.  */
-/* 36 */  "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'"
+/* 36 */  "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'",
+
+          /* Return segments in order from oldest to newest.*/ 
+/* 37 */  "SELECT level, idx, end_block "
+            "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? "
+            "ORDER BY level DESC, idx ASC",
+
+          /* Update statements used while promoting segments */
+/* 38 */  "UPDATE OR FAIL %Q.'%q_segdir' SET level=-1,idx=? "
+            "WHERE level=? AND idx=?",
+/* 39 */  "UPDATE OR FAIL %Q.'%q_segdir' SET level=? WHERE level=-1"
+
   };
   int rc = SQLITE_OK;
   sqlite3_stmt *pStmt;
@@ -129120,37 +137204,30 @@ static void fts3SqlExec(
 
 
 /*
-** This function ensures that the caller has obtained a shared-cache
-** table-lock on the %_content table. This is required before reading
-** data from the fts3 table. If this lock is not acquired first, then
-** the caller may end up holding read-locks on the %_segments and %_segdir
-** tables, but no read-lock on the %_content table. If this happens 
-** a second connection will be able to write to the fts3 table, but
-** attempting to commit those writes might return SQLITE_LOCKED or
-** SQLITE_LOCKED_SHAREDCACHE (because the commit attempts to obtain 
-** write-locks on the %_segments and %_segdir ** tables). 
-**
-** We try to avoid this because if FTS3 returns any error when committing
-** a transaction, the whole transaction will be rolled back. And this is
-** not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. It can
-** still happen if the user reads data directly from the %_segments or
-** %_segdir tables instead of going through FTS3 though.
+** This function ensures that the caller has obtained an exclusive 
+** shared-cache table-lock on the %_segdir table. This is required before 
+** writing data to the fts3 table. If this lock is not acquired first, then
+** the caller may end up attempting to take this lock as part of committing
+** a transaction, causing SQLite to return SQLITE_LOCKED or 
+** LOCKED_SHAREDCACHEto a COMMIT command.
 **
-** This reasoning does not apply to a content=xxx table.
+** It is best to avoid this because if FTS3 returns any error when 
+** committing a transaction, the whole transaction will be rolled back. 
+** And this is not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. 
+** It can still happen if the user locks the underlying tables directly 
+** instead of accessing them via FTS.
 */
-SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *p){
-  int rc;                         /* Return code */
-  sqlite3_stmt *pStmt;            /* Statement used to obtain lock */
-
-  if( p->zContentTbl==0 ){
-    rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pStmt, 0);
+static int fts3Writelock(Fts3Table *p){
+  int rc = SQLITE_OK;
+  
+  if( p->nPendingData==0 ){
+    sqlite3_stmt *pStmt;
+    rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pStmt, 0);
     if( rc==SQLITE_OK ){
       sqlite3_bind_null(pStmt, 1);
       sqlite3_step(pStmt);
       rc = sqlite3_reset(pStmt);
     }
-  }else{
-    rc = SQLITE_OK;
   }
 
   return rc;
@@ -129538,12 +137615,15 @@ static int fts3InsertTerms(
 ){
   int i;                          /* Iterator variable */
   for(i=2; i<p->nColumn+2; i++){
-    const char *zText = (const char *)sqlite3_value_text(apVal[i]);
-    int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]);
-    if( rc!=SQLITE_OK ){
-      return rc;
+    int iCol = i-2;
+    if( p->abNotindexed[iCol]==0 ){
+      const char *zText = (const char *)sqlite3_value_text(apVal[i]);
+      int rc = fts3PendingTermsAdd(p, iLangid, zText, iCol, &aSz[iCol]);
+      if( rc!=SQLITE_OK ){
+        return rc;
+      }
+      aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
     }
-    aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
   }
   return SQLITE_OK;
 }
@@ -129690,9 +137770,12 @@ static void fts3DeleteTerms(
       int iLangid = langidFromSelect(p, pSelect);
       rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0));
       for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
-        const char *zText = (const char *)sqlite3_column_text(pSelect, i);
-        rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]);
-        aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
+        int iCol = i-1;
+        if( p->abNotindexed[iCol]==0 ){
+          const char *zText = (const char *)sqlite3_column_text(pSelect, i);
+          rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]);
+          aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
+        }
       }
       if( rc!=SQLITE_OK ){
         sqlite3_reset(pSelect);
@@ -129976,8 +138059,8 @@ static int fts3SegReaderNext(
   
   /* Because of the FTS3_NODE_PADDING bytes of padding, the following is 
   ** safe (no risk of overread) even if the node data is corrupted. */
-  pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
-  pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
+  pNext += fts3GetVarint32(pNext, &nPrefix);
+  pNext += fts3GetVarint32(pNext, &nSuffix);
   if( nPrefix<0 || nSuffix<=0 
    || &pNext[nSuffix]>&pReader->aNode[pReader->nNode] 
   ){
@@ -130000,7 +138083,7 @@ static int fts3SegReaderNext(
   memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix);
   pReader->nTerm = nPrefix+nSuffix;
   pNext += nSuffix;
-  pNext += sqlite3Fts3GetVarint32(pNext, &pReader->nDoclist);
+  pNext += fts3GetVarint32(pNext, &pReader->nDoclist);
   pReader->aDoclist = pNext;
   pReader->pOffsetList = 0;
 
@@ -130093,7 +138176,7 @@ static int fts3SegReaderNextDocid(
       /* The following line of code (and the "p++" below the while() loop) is
       ** normally all that is required to move pointer p to the desired 
       ** position. The exception is if this node is being loaded from disk
-      ** incrementally and pointer "p" now points to the first byte passed
+      ** incrementally and pointer "p" now points to the first byte past
       ** the populated part of pReader->aNode[].
       */
       while( *p | c ) c = *p++ & 0x80;
@@ -130542,6 +138625,7 @@ static int fts3WriteSegdir(
   sqlite3_int64 iStartBlock,      /* Value for "start_block" field */
   sqlite3_int64 iLeafEndBlock,    /* Value for "leaves_end_block" field */
   sqlite3_int64 iEndBlock,        /* Value for "end_block" field */
+  sqlite3_int64 nLeafData,        /* Bytes of leaf data in segment */
   char *zRoot,                    /* Blob value for "root" field */
   int nRoot                       /* Number of bytes in buffer zRoot */
 ){
@@ -130552,7 +138636,13 @@ static int fts3WriteSegdir(
     sqlite3_bind_int(pStmt, 2, iIdx);
     sqlite3_bind_int64(pStmt, 3, iStartBlock);
     sqlite3_bind_int64(pStmt, 4, iLeafEndBlock);
-    sqlite3_bind_int64(pStmt, 5, iEndBlock);
+    if( nLeafData==0 ){
+      sqlite3_bind_int64(pStmt, 5, iEndBlock);
+    }else{
+      char *zEnd = sqlite3_mprintf("%lld %lld", iEndBlock, nLeafData);
+      if( !zEnd ) return SQLITE_NOMEM;
+      sqlite3_bind_text(pStmt, 5, zEnd, -1, sqlite3_free);
+    }
     sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
     sqlite3_step(pStmt);
     rc = sqlite3_reset(pStmt);
@@ -130878,6 +138968,9 @@ static int fts3SegWriterAdd(
       nDoclist;                             /* Doclist data */
   }
 
+  /* Increase the total number of bytes written to account for the new entry. */
+  pWriter->nLeafData += nReq;
+
   /* If the buffer currently allocated is too small for this entry, realloc
   ** the buffer to make it large enough.
   */
@@ -130949,13 +139042,13 @@ static int fts3SegWriterFlush(
           pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot);
     }
     if( rc==SQLITE_OK ){
-      rc = fts3WriteSegdir(
-          p, iLevel, iIdx, pWriter->iFirst, iLastLeaf, iLast, zRoot, nRoot);
+      rc = fts3WriteSegdir(p, iLevel, iIdx, 
+          pWriter->iFirst, iLastLeaf, iLast, pWriter->nLeafData, zRoot, nRoot);
     }
   }else{
     /* The entire tree fits on the root node. Write it to the segdir table. */
-    rc = fts3WriteSegdir(
-        p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData);
+    rc = fts3WriteSegdir(p, iLevel, iIdx, 
+        0, 0, 0, pWriter->nLeafData, pWriter->aData, pWriter->nData);
   }
   p->nLeafAdd++;
   return rc;
@@ -131040,6 +139133,37 @@ static int fts3SegmentMaxLevel(
 }
 
 /*
+** iAbsLevel is an absolute level that may be assumed to exist within
+** the database. This function checks if it is the largest level number
+** within its index. Assuming no error occurs, *pbMax is set to 1 if
+** iAbsLevel is indeed the largest level, or 0 otherwise, and SQLITE_OK
+** is returned. If an error occurs, an error code is returned and the
+** final value of *pbMax is undefined.
+*/
+static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){
+
+  /* Set pStmt to the compiled version of:
+  **
+  **   SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
+  **
+  ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
+  */
+  sqlite3_stmt *pStmt;
+  int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
+  if( rc!=SQLITE_OK ) return rc;
+  sqlite3_bind_int64(pStmt, 1, iAbsLevel+1);
+  sqlite3_bind_int64(pStmt, 2, 
+      ((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
+  );
+
+  *pbMax = 0;
+  if( SQLITE_ROW==sqlite3_step(pStmt) ){
+    *pbMax = sqlite3_column_type(pStmt, 0)==SQLITE_NULL;
+  }
+  return sqlite3_reset(pStmt);
+}
+
+/*
 ** Delete all entries in the %_segments table associated with the segment
 ** opened with seg-reader pSeg. This function does not affect the contents
 ** of the %_segdir table.
@@ -131161,7 +139285,7 @@ static void fts3ColumnFilter(
       break;
     }
     p = &pList[1];
-    p += sqlite3Fts3GetVarint32(p, &iCurrent);
+    p += fts3GetVarint32(p, &iCurrent);
   }
 
   if( bZero && &pList[nList]!=pEnd ){
@@ -131480,8 +139604,8 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
       fts3SegReaderSort(apSegment, nMerge, nMerge, xCmp);
       while( apSegment[0]->pOffsetList ){
         int j;                    /* Number of segments that share a docid */
-        char *pList;
-        int nList;
+        char *pList = 0;
+        int nList = 0;
         int nByte;
         sqlite3_int64 iDocid = apSegment[0]->iDocid;
         fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
@@ -131575,6 +139699,140 @@ SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(
 }
 
 /*
+** Decode the "end_block" field, selected by column iCol of the SELECT 
+** statement passed as the first argument. 
+**
+** The "end_block" field may contain either an integer, or a text field
+** containing the text representation of two non-negative integers separated 
+** by one or more space (0x20) characters. In the first case, set *piEndBlock 
+** to the integer value and *pnByte to zero before returning. In the second, 
+** set *piEndBlock to the first value and *pnByte to the second.
+*/
+static void fts3ReadEndBlockField(
+  sqlite3_stmt *pStmt, 
+  int iCol, 
+  i64 *piEndBlock,
+  i64 *pnByte
+){
+  const unsigned char *zText = sqlite3_column_text(pStmt, iCol);
+  if( zText ){
+    int i;
+    int iMul = 1;
+    i64 iVal = 0;
+    for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
+      iVal = iVal*10 + (zText[i] - '0');
+    }
+    *piEndBlock = iVal;
+    while( zText[i]==' ' ) i++;
+    iVal = 0;
+    if( zText[i]=='-' ){
+      i++;
+      iMul = -1;
+    }
+    for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
+      iVal = iVal*10 + (zText[i] - '0');
+    }
+    *pnByte = (iVal * (i64)iMul);
+  }
+}
+
+
+/*
+** A segment of size nByte bytes has just been written to absolute level
+** iAbsLevel. Promote any segments that should be promoted as a result.
+*/
+static int fts3PromoteSegments(
+  Fts3Table *p,                   /* FTS table handle */
+  sqlite3_int64 iAbsLevel,        /* Absolute level just updated */
+  sqlite3_int64 nByte             /* Size of new segment at iAbsLevel */
+){
+  int rc = SQLITE_OK;
+  sqlite3_stmt *pRange;
+
+  rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE2, &pRange, 0);
+
+  if( rc==SQLITE_OK ){
+    int bOk = 0;
+    i64 iLast = (iAbsLevel/FTS3_SEGDIR_MAXLEVEL + 1) * FTS3_SEGDIR_MAXLEVEL - 1;
+    i64 nLimit = (nByte*3)/2;
+
+    /* Loop through all entries in the %_segdir table corresponding to 
+    ** segments in this index on levels greater than iAbsLevel. If there is
+    ** at least one such segment, and it is possible to determine that all 
+    ** such segments are smaller than nLimit bytes in size, they will be 
+    ** promoted to level iAbsLevel.  */
+    sqlite3_bind_int64(pRange, 1, iAbsLevel+1);
+    sqlite3_bind_int64(pRange, 2, iLast);
+    while( SQLITE_ROW==sqlite3_step(pRange) ){
+      i64 nSize = 0, dummy;
+      fts3ReadEndBlockField(pRange, 2, &dummy, &nSize);
+      if( nSize<=0 || nSize>nLimit ){
+        /* If nSize==0, then the %_segdir.end_block field does not not 
+        ** contain a size value. This happens if it was written by an
+        ** old version of FTS. In this case it is not possible to determine
+        ** the size of the segment, and so segment promotion does not
+        ** take place.  */
+        bOk = 0;
+        break;
+      }
+      bOk = 1;
+    }
+    rc = sqlite3_reset(pRange);
+
+    if( bOk ){
+      int iIdx = 0;
+      sqlite3_stmt *pUpdate1;
+      sqlite3_stmt *pUpdate2;
+
+      if( rc==SQLITE_OK ){
+        rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0);
+      }
+      if( rc==SQLITE_OK ){
+        rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL, &pUpdate2, 0);
+      }
+
+      if( rc==SQLITE_OK ){
+
+        /* Loop through all %_segdir entries for segments in this index with
+        ** levels equal to or greater than iAbsLevel. As each entry is visited,
+        ** updated it to set (level = -1) and (idx = N), where N is 0 for the
+        ** oldest segment in the range, 1 for the next oldest, and so on.
+        **
+        ** In other words, move all segments being promoted to level -1,
+        ** setting the "idx" fields as appropriate to keep them in the same
+        ** order. The contents of level -1 (which is never used, except
+        ** transiently here), will be moved back to level iAbsLevel below.  */
+        sqlite3_bind_int64(pRange, 1, iAbsLevel);
+        while( SQLITE_ROW==sqlite3_step(pRange) ){
+          sqlite3_bind_int(pUpdate1, 1, iIdx++);
+          sqlite3_bind_int(pUpdate1, 2, sqlite3_column_int(pRange, 0));
+          sqlite3_bind_int(pUpdate1, 3, sqlite3_column_int(pRange, 1));
+          sqlite3_step(pUpdate1);
+          rc = sqlite3_reset(pUpdate1);
+          if( rc!=SQLITE_OK ){
+            sqlite3_reset(pRange);
+            break;
+          }
+        }
+      }
+      if( rc==SQLITE_OK ){
+        rc = sqlite3_reset(pRange);
+      }
+
+      /* Move level -1 to level iAbsLevel */
+      if( rc==SQLITE_OK ){
+        sqlite3_bind_int64(pUpdate2, 1, iAbsLevel);
+        sqlite3_step(pUpdate2);
+        rc = sqlite3_reset(pUpdate2);
+      }
+    }
+  }
+
+
+  return rc;
+}
+
+/*
 ** Merge all level iLevel segments in the database into a single 
 ** iLevel+1 segment. Or, if iLevel<0, merge all segments into a
 ** single segment with a level equal to the numerically largest level 
@@ -131598,6 +139856,7 @@ static int fts3SegmentMerge(
   Fts3SegFilter filter;           /* Segment term filter condition */
   Fts3MultiSegReader csr;         /* Cursor to iterate through level(s) */
   int bIgnoreEmpty = 0;           /* True to ignore empty segments */
+  i64 iMaxLevel = 0;              /* Max level number for this index/langid */
 
   assert( iLevel==FTS3_SEGCURSOR_ALL
        || iLevel==FTS3_SEGCURSOR_PENDING
@@ -131609,6 +139868,11 @@ static int fts3SegmentMerge(
   rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr);
   if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
 
+  if( iLevel!=FTS3_SEGCURSOR_PENDING ){
+    rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iMaxLevel);
+    if( rc!=SQLITE_OK ) goto finished;
+  }
+
   if( iLevel==FTS3_SEGCURSOR_ALL ){
     /* This call is to merge all segments in the database to a single
     ** segment. The level of the new segment is equal to the numerically
@@ -131618,21 +139882,21 @@ static int fts3SegmentMerge(
       rc = SQLITE_DONE;
       goto finished;
     }
-    rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel);
+    iNewLevel = iMaxLevel;
     bIgnoreEmpty = 1;
 
-  }else if( iLevel==FTS3_SEGCURSOR_PENDING ){
-    iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0);
-    rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx);
   }else{
     /* This call is to merge all segments at level iLevel. find the next
     ** available segment index at level iLevel+1. The call to
     ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to 
     ** a single iLevel+2 segment if necessary.  */
-    rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
+    assert( FTS3_SEGCURSOR_PENDING==-1 );
     iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
+    rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
+    bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel);
   }
   if( rc!=SQLITE_OK ) goto finished;
+
   assert( csr.nSegment>0 );
   assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
   assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
@@ -131649,7 +139913,7 @@ static int fts3SegmentMerge(
         csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
   }
   if( rc!=SQLITE_OK ) goto finished;
-  assert( pWriter );
+  assert( pWriter || bIgnoreEmpty );
 
   if( iLevel!=FTS3_SEGCURSOR_PENDING ){
     rc = fts3DeleteSegdir(
@@ -131657,7 +139921,14 @@ static int fts3SegmentMerge(
     );
     if( rc!=SQLITE_OK ) goto finished;
   }
-  rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
+  if( pWriter ){
+    rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
+    if( rc==SQLITE_OK ){
+      if( iLevel==FTS3_SEGCURSOR_PENDING || iNewLevel<iMaxLevel ){
+        rc = fts3PromoteSegments(p, iNewLevel, pWriter->nLeafData);
+      }
+    }
+  }
 
  finished:
   fts3SegWriterFree(pWriter);
@@ -131667,7 +139938,7 @@ static int fts3SegmentMerge(
 
 
 /* 
-** Flush the contents of pendingTerms to level 0 segments.
+** Flush the contents of pendingTerms to level 0 segments. 
 */
 SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
   int rc = SQLITE_OK;
@@ -131683,14 +139954,19 @@ SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
   ** estimate the number of leaf blocks of content to be written
   */
   if( rc==SQLITE_OK && p->bHasStat
-   && p->bAutoincrmerge==0xff && p->nLeafAdd>0
+   && p->nAutoincrmerge==0xff && p->nLeafAdd>0
   ){
     sqlite3_stmt *pStmt = 0;
     rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
     if( rc==SQLITE_OK ){
       sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
       rc = sqlite3_step(pStmt);
-      p->bAutoincrmerge = (rc==SQLITE_ROW && sqlite3_column_int(pStmt, 0));
+      if( rc==SQLITE_ROW ){
+        p->nAutoincrmerge = sqlite3_column_int(pStmt, 0);
+        if( p->nAutoincrmerge==1 ) p->nAutoincrmerge = 8;
+      }else if( rc==SQLITE_DONE ){
+        p->nAutoincrmerge = 0;
+      }
       rc = sqlite3_reset(pStmt);
     }
   }
@@ -131934,9 +140210,11 @@ static int fts3DoRebuild(Fts3Table *p){
       rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
       memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
       for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
-        const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
-        rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
-        aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
+        if( p->abNotindexed[iCol]==0 ){
+          const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
+          rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
+          aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
+        }
       }
       if( p->bHasDocsize ){
         fts3InsertDocsize(&rc, p, aSz);
@@ -132056,6 +140334,8 @@ struct IncrmergeWriter {
   int iIdx;                       /* Index of *output* segment in iAbsLevel+1 */
   sqlite3_int64 iStart;           /* Block number of first allocated block */
   sqlite3_int64 iEnd;             /* Block number of last allocated block */
+  sqlite3_int64 nLeafData;        /* Bytes of leaf page data so far */
+  u8 bNoLeafData;                 /* If true, store 0 for segment size */
   NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT];
 };
 
@@ -132124,9 +140404,9 @@ static int nodeReaderNext(NodeReader *p){
     p->aNode = 0;
   }else{
     if( bFirst==0 ){
-      p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
+      p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
     }
-    p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
+    p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
 
     blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
     if( rc==SQLITE_OK ){
@@ -132134,7 +140414,7 @@ static int nodeReaderNext(NodeReader *p){
       p->term.n = nPrefix+nSuffix;
       p->iOff += nSuffix;
       if( p->iChild==0 ){
-        p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
+        p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
         p->aDoclist = &p->aNode[p->iOff];
         p->iOff += p->nDoclist;
       }
@@ -132394,8 +140674,8 @@ static int fts3IncrmergeAppend(
     nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
   }
 
+  pWriter->nLeafData += nSpace;
   blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc);
-
   if( rc==SQLITE_OK ){
     if( pLeaf->block.n==0 ){
       pLeaf->block.n = 1;
@@ -132494,6 +140774,7 @@ static void fts3IncrmergeRelease(
         pWriter->iStart,                    /* start_block */
         pWriter->aNodeWriter[0].iBlock,     /* leaves_end_block */
         pWriter->iEnd,                      /* end_block */
+        (pWriter->bNoLeafData==0 ? pWriter->nLeafData : 0),   /* end_block */
         pRoot->block.a, pRoot->block.n      /* root */
     );
   }
@@ -132595,7 +140876,11 @@ static int fts3IncrmergeLoad(
     if( sqlite3_step(pSelect)==SQLITE_ROW ){
       iStart = sqlite3_column_int64(pSelect, 1);
       iLeafEnd = sqlite3_column_int64(pSelect, 2);
-      iEnd = sqlite3_column_int64(pSelect, 3);
+      fts3ReadEndBlockField(pSelect, 3, &iEnd, &pWriter->nLeafData);
+      if( pWriter->nLeafData<0 ){
+        pWriter->nLeafData = pWriter->nLeafData * -1;
+      }
+      pWriter->bNoLeafData = (pWriter->nLeafData==0);
       nRoot = sqlite3_column_bytes(pSelect, 4);
       aRoot = sqlite3_column_blob(pSelect, 4);
     }else{
@@ -133186,7 +141471,7 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
 
   pHint->n = i;
   i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
-  i += sqlite3Fts3GetVarint32(&pHint->a[i], pnInput);
+  i += fts3GetVarint32(&pHint->a[i], pnInput);
   if( i!=nHint ) return SQLITE_CORRUPT_VTAB;
 
   return SQLITE_OK;
@@ -133196,11 +141481,11 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
 /*
 ** Attempt an incremental merge that writes nMerge leaf blocks.
 **
-** Incremental merges happen nMin segments at a time. The two
-** segments to be merged are the nMin oldest segments (the ones with
-** the smallest indexes) in the highest level that contains at least
-** nMin segments. Multiple merges might occur in an attempt to write the 
-** quota of nMerge leaf blocks.
+** Incremental merges happen nMin segments at a time. The segments 
+** to be merged are the nMin oldest segments (the ones with the smallest 
+** values for the _segdir.idx field) in the highest level that contains 
+** at least nMin segments. Multiple merges might occur in an attempt to 
+** write the quota of nMerge leaf blocks.
 */
 SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
   int rc;                         /* Return code */
@@ -133225,6 +141510,7 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
     const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex;
     sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */
     int bUseHint = 0;             /* True if attempting to append */
+    int iIdx = 0;                 /* Largest idx in level (iAbsLevel+1) */
 
     /* Search the %_segdir table for the absolute level with the smallest
     ** relative level number that contains at least nMin segments, if any.
@@ -133278,6 +141564,19 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
     ** to start work on some other level.  */
     memset(pWriter, 0, nAlloc);
     pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
+
+    if( rc==SQLITE_OK ){
+      rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
+      assert( bUseHint==1 || bUseHint==0 );
+      if( iIdx==0 || (bUseHint && iIdx==1) ){
+        int bIgnore = 0;
+        rc = fts3SegmentIsMaxLevel(p, iAbsLevel+1, &bIgnore);
+        if( bIgnore ){
+          pFilter->flags |= FTS3_SEGMENT_IGNORE_EMPTY;
+        }
+      }
+    }
+
     if( rc==SQLITE_OK ){
       rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr);
     }
@@ -133285,16 +141584,12 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
      && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
      && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
     ){
-      int iIdx = 0;               /* Largest idx in level (iAbsLevel+1) */
-      rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
-      if( rc==SQLITE_OK ){
-        if( bUseHint && iIdx>0 ){
-          const char *zKey = pCsr->zTerm;
-          int nKey = pCsr->nTerm;
-          rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
-        }else{
-          rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
-        }
+      if( bUseHint && iIdx>0 ){
+        const char *zKey = pCsr->zTerm;
+        int nKey = pCsr->nTerm;
+        rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
+      }else{
+        rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
       }
 
       if( rc==SQLITE_OK && pWriter->nLeafEst ){
@@ -133316,7 +141611,13 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
         }
       }
 
+      if( nSeg!=0 ){
+        pWriter->nLeafData = pWriter->nLeafData * -1;
+      }
       fts3IncrmergeRelease(p, pWriter, &rc);
+      if( nSeg==0 && pWriter->bNoLeafData==0 ){
+        fts3PromoteSegments(p, iAbsLevel+1, pWriter->nLeafData);
+      }
     }
 
     sqlite3Fts3SegReaderFinish(pCsr);
@@ -133403,16 +141704,19 @@ static int fts3DoAutoincrmerge(
 ){
   int rc = SQLITE_OK;
   sqlite3_stmt *pStmt = 0;
-  p->bAutoincrmerge = fts3Getint(&zParam)!=0;
+  p->nAutoincrmerge = fts3Getint(&zParam);
+  if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
+    p->nAutoincrmerge = 8;
+  }
   if( !p->bHasStat ){
     assert( p->bFts4==0 );
     sqlite3Fts3CreateStatTable(&rc, p);
     if( rc ) return rc;
   }
   rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
-  if( rc ) return rc;;
+  if( rc ) return rc;
   sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
-  sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
+  sqlite3_bind_int(pStmt, 2, p->nAutoincrmerge);
   sqlite3_step(pStmt);
   rc = sqlite3_reset(pStmt);
   return rc;
@@ -133569,34 +141873,36 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
       int iCol;
 
       for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
-        const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
-        int nText = sqlite3_column_bytes(pStmt, iCol+1);
-        sqlite3_tokenizer_cursor *pT = 0;
-
-        rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT);
-        while( rc==SQLITE_OK ){
-          char const *zToken;       /* Buffer containing token */
-          int nToken = 0;           /* Number of bytes in token */
-          int iDum1 = 0, iDum2 = 0; /* Dummy variables */
-          int iPos = 0;             /* Position of token in zText */
-
-          rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
-          if( rc==SQLITE_OK ){
-            int i;
-            cksum2 = cksum2 ^ fts3ChecksumEntry(
-                zToken, nToken, iLang, 0, iDocid, iCol, iPos
-            );
-            for(i=1; i<p->nIndex; i++){
-              if( p->aIndex[i].nPrefix<=nToken ){
-                cksum2 = cksum2 ^ fts3ChecksumEntry(
-                  zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos
-                );
+        if( p->abNotindexed[iCol]==0 ){
+          const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
+          int nText = sqlite3_column_bytes(pStmt, iCol+1);
+          sqlite3_tokenizer_cursor *pT = 0;
+
+          rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT);
+          while( rc==SQLITE_OK ){
+            char const *zToken;       /* Buffer containing token */
+            int nToken = 0;           /* Number of bytes in token */
+            int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+            int iPos = 0;             /* Position of token in zText */
+
+            rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
+            if( rc==SQLITE_OK ){
+              int i;
+              cksum2 = cksum2 ^ fts3ChecksumEntry(
+                  zToken, nToken, iLang, 0, iDocid, iCol, iPos
+              );
+              for(i=1; i<p->nIndex; i++){
+                if( p->aIndex[i].nPrefix<=nToken ){
+                  cksum2 = cksum2 ^ fts3ChecksumEntry(
+                      zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos
+                  );
+                }
               }
             }
           }
+          if( pT ) pModule->xClose(pT);
+          if( rc==SQLITE_DONE ) rc = SQLITE_OK;
         }
-        if( pT ) pModule->xClose(pT);
-        if( rc==SQLITE_DONE ) rc = SQLITE_OK;
       }
     }
 
@@ -133680,6 +141986,9 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
   }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
     p->nMaxPendingData = atoi(&zVal[11]);
     rc = SQLITE_OK;
+  }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
+    p->bNoIncrDoclist = atoi(&zVal[21]);
+    rc = SQLITE_OK;
 #endif
   }else{
     rc = SQLITE_ERROR;
@@ -133739,32 +142048,34 @@ SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
     iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
   
     for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
-      const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
-      sqlite3_tokenizer_cursor *pTC = 0;
-  
-      rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
-      while( rc==SQLITE_OK ){
-        char const *zToken;       /* Buffer containing token */
-        int nToken = 0;           /* Number of bytes in token */
-        int iDum1 = 0, iDum2 = 0; /* Dummy variables */
-        int iPos = 0;             /* Position of token in zText */
-  
-        rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
-        for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
-          Fts3PhraseToken *pPT = pDef->pToken;
-          if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
-           && (pPT->bFirst==0 || iPos==0)
-           && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
-           && (0==memcmp(zToken, pPT->z, pPT->n))
-          ){
-            fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
+      if( p->abNotindexed[i]==0 ){
+        const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
+        sqlite3_tokenizer_cursor *pTC = 0;
+
+        rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
+        while( rc==SQLITE_OK ){
+          char const *zToken;       /* Buffer containing token */
+          int nToken = 0;           /* Number of bytes in token */
+          int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+          int iPos = 0;             /* Position of token in zText */
+
+          rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
+          for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
+            Fts3PhraseToken *pPT = pDef->pToken;
+            if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
+                && (pPT->bFirst==0 || iPos==0)
+                && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
+                && (0==memcmp(zToken, pPT->z, pPT->n))
+              ){
+              fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
+            }
           }
         }
+        if( pTC ) pModule->xClose(pTC);
+        if( rc==SQLITE_DONE ) rc = SQLITE_OK;
       }
-      if( pTC ) pModule->xClose(pTC);
-      if( rc==SQLITE_DONE ) rc = SQLITE_OK;
     }
-  
+
     for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
       if( pDef->pList ){
         rc = fts3PendingListAppendVarint(&pDef->pList, 0);
@@ -133896,6 +142207,10 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
   int nChng = 0;                  /* Net change in number of documents */
   int bInsertDone = 0;
 
+  /* At this point it must be known if the %_stat table exists or not.
+  ** So bHasStat may not be 2.  */
+  assert( p->bHasStat==0 || p->bHasStat==1 );
+
   assert( p->pSegments==0 );
   assert( 
       nArg==1                     /* DELETE operations */
@@ -133928,6 +142243,9 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
   aSzIns = &aSzDel[p->nColumn+1];
   memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2);
 
+  rc = fts3Writelock(p);
+  if( rc!=SQLITE_OK ) goto update_out;
+
   /* If this is an INSERT operation, or an UPDATE that modifies the rowid
   ** value, then this operation requires constraint handling.
   **
@@ -134171,7 +142489,7 @@ struct StrBuffer {
 */
 static void fts3GetDeltaPosition(char **pp, int *piPos){
   int iVal;
-  *pp += sqlite3Fts3GetVarint32(*pp, &iVal);
+  *pp += fts3GetVarint32(*pp, &iVal);
   *piPos += (iVal-2);
 }
 
@@ -134547,6 +142865,7 @@ static int fts3StringAppend(
     pStr->z = zNew;
     pStr->nAlloc = nAlloc;
   }
+  assert( pStr->z!=0 && (pStr->nAlloc >= pStr->n+nAppend+1) );
 
   /* Append the data to the string buffer. */
   memcpy(&pStr->z[pStr->n], zAppend, nAppend);
@@ -135579,7 +143898,7 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo(
 ** Implementation of the "unicode" full-text-search tokenizer.
 */
 
-#ifdef SQLITE_ENABLE_FTS4_UNICODE61
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
 
 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
 
@@ -135795,7 +144114,7 @@ static int unicodeCreate(
 
   for(i=0; rc==SQLITE_OK && i<nArg; i++){
     const char *z = azArg[i];
-    int n = strlen(z);
+    int n = (int)strlen(z);
 
     if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
       pNew->bRemoveDiacritic = 1;
@@ -135882,7 +144201,7 @@ static int unicodeNext(
 ){
   unicode_cursor *pCsr = (unicode_cursor *)pC;
   unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
-  int iCode;
+  int iCode = 0;
   char *zOut;
   const unsigned char *z = &pCsr->aInput[pCsr->iOff];
   const unsigned char *zStart = z;
@@ -135927,11 +144246,11 @@ static int unicodeNext(
   );
 
   /* Set the output variables and return. */
-  pCsr->iOff = (z - pCsr->aInput);
+  pCsr->iOff = (int)(z - pCsr->aInput);
   *paToken = pCsr->zToken;
-  *pnToken = zOut - pCsr->zToken;
-  *piStart = (zStart - pCsr->aInput);
-  *piEnd = (zEnd - pCsr->aInput);
+  *pnToken = (int)(zOut - pCsr->zToken);
+  *piStart = (int)(zStart - pCsr->aInput);
+  *piEnd = (int)(zEnd - pCsr->aInput);
   *piPos = pCsr->iToken++;
   return SQLITE_OK;
 }
@@ -135954,7 +144273,7 @@ SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const *
 }
 
 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
-#endif /* ifndef SQLITE_ENABLE_FTS4_UNICODE61 */
+#endif /* ifndef SQLITE_DISABLE_FTS3_UNICODE */
 
 /************** End of fts3_unicode.c ****************************************/
 /************** Begin file fts3_unicode2.c ***********************************/
@@ -135975,7 +144294,7 @@ SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const *
 ** DO NOT EDIT THIS MACHINE GENERATED FILE.
 */
 
-#if defined(SQLITE_ENABLE_FTS4_UNICODE61)
+#ifndef SQLITE_DISABLE_FTS3_UNICODE
 #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
 
 /* #include <assert.h> */
@@ -135999,7 +144318,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){
   ** C. It is not possible to represent a range larger than 1023 codepoints 
   ** using this format.
   */
-  const static unsigned int aEntry[] = {
+  static const unsigned int aEntry[] = {
     0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
     0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
     0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
@@ -136061,28 +144380,27 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){
     0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
     0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
     0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
-    0x037FFC02, 0x03E3FC01, 0x03EC7801, 0x03ECA401, 0x03EEC810,
-    0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023,
-    0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807,
-    0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405,
-    0x04040003, 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E,
-    0x040E7C01, 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01,
-    0x04280403, 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01,
-    0x04294009, 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016,
-    0x04420003, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004,
-    0x04460003, 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004,
-    0x05BD442E, 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5,
-    0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01,
-    0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401,
-    0x075EA401, 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064,
-    0x07C2800F, 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F,
-    0x07C4C03C, 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009,
-    0x07C94002, 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014,
-    0x07CE8025, 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001,
-    0x07D108B6, 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018,
-    0x07D7EC46, 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401,
-    0x38008060, 0x380400F0, 0x3C000001, 0x3FFFF401, 0x40000001,
-    0x43FFF401,
+    0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802,
+    0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013,
+    0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06,
+    0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003,
+    0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01,
+    0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403,
+    0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009,
+    0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003,
+    0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003,
+    0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E,
+    0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046,
+    0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401,
+    0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401,
+    0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F,
+    0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C,
+    0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002,
+    0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025,
+    0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6,
+    0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46,
+    0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060,
+    0x380400F0,
   };
   static const unsigned int aAscii[4] = {
     0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
@@ -136092,7 +144410,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){
     return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
   }else if( c<(1<<22) ){
     unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
-    int iRes;
+    int iRes = 0;
     int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
     int iLo = 0;
     while( iHi>=iLo ){
@@ -136163,7 +144481,7 @@ static int remove_diacritic(int c){
   }
   assert( key>=aDia[iRes] );
   return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
-};
+}
 
 
 /*
@@ -136323,7 +144641,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
   return ret;
 }
 #endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */
-#endif /* !defined(SQLITE_ENABLE_FTS4_UNICODE61) */
+#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */
 
 /************** End of fts3_unicode2.c ***************************************/
 /************** Begin file rtree.c *******************************************/
@@ -136383,48 +144701,6 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
 
 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE)
 
-/*
-** This file contains an implementation of a couple of different variants
-** of the r-tree algorithm. See the README file for further details. The 
-** same data-structure is used for all, but the algorithms for insert and
-** delete operations vary. The variants used are selected at compile time 
-** by defining the following symbols:
-*/
-
-/* Either, both or none of the following may be set to activate 
-** r*tree variant algorithms.
-*/
-#define VARIANT_RSTARTREE_CHOOSESUBTREE 0
-#define VARIANT_RSTARTREE_REINSERT      1
-
-/* 
-** Exactly one of the following must be set to 1.
-*/
-#define VARIANT_GUTTMAN_QUADRATIC_SPLIT 0
-#define VARIANT_GUTTMAN_LINEAR_SPLIT    0
-#define VARIANT_RSTARTREE_SPLIT         1
-
-#define VARIANT_GUTTMAN_SPLIT \
-        (VARIANT_GUTTMAN_LINEAR_SPLIT||VARIANT_GUTTMAN_QUADRATIC_SPLIT)
-
-#if VARIANT_GUTTMAN_QUADRATIC_SPLIT
-  #define PickNext QuadraticPickNext
-  #define PickSeeds QuadraticPickSeeds
-  #define AssignCells splitNodeGuttman
-#endif
-#if VARIANT_GUTTMAN_LINEAR_SPLIT
-  #define PickNext LinearPickNext
-  #define PickSeeds LinearPickSeeds
-  #define AssignCells splitNodeGuttman
-#endif
-#if VARIANT_RSTARTREE_SPLIT
-  #define AssignCells splitNodeStartree
-#endif
-
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) 
-# define NDEBUG 1
-#endif
-
 #ifndef SQLITE_CORE
   SQLITE_EXTENSION_INIT1
 #else
@@ -136432,11 +144708,13 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
 
 /* #include <string.h> */
 /* #include <assert.h> */
+/* #include <stdio.h> */
 
 #ifndef SQLITE_AMALGAMATION
 #include "sqlite3rtree.h"
 typedef sqlite3_int64 i64;
 typedef unsigned char u8;
+typedef unsigned short u16;
 typedef unsigned int u32;
 #endif
 
@@ -136454,6 +144732,7 @@ typedef struct RtreeConstraint RtreeConstraint;
 typedef struct RtreeMatchArg RtreeMatchArg;
 typedef struct RtreeGeomCallback RtreeGeomCallback;
 typedef union RtreeCoord RtreeCoord;
+typedef struct RtreeSearchPoint RtreeSearchPoint;
 
 /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */
 #define RTREE_MAX_DIMENSIONS 5
@@ -136462,22 +144741,33 @@ typedef union RtreeCoord RtreeCoord;
 ** ever contain very many entries, so a fixed number of buckets is 
 ** used.
 */
-#define HASHSIZE 128
+#define HASHSIZE 97
+
+/* The xBestIndex method of this virtual table requires an estimate of
+** the number of rows in the virtual table to calculate the costs of
+** various strategies. If possible, this estimate is loaded from the
+** sqlite_stat1 table (with RTREE_MIN_ROWEST as a hard-coded minimum).
+** Otherwise, if no sqlite_stat1 entry is available, use 
+** RTREE_DEFAULT_ROWEST.
+*/
+#define RTREE_DEFAULT_ROWEST 1048576
+#define RTREE_MIN_ROWEST         100
 
 /* 
 ** An rtree virtual-table object.
 */
 struct Rtree {
-  sqlite3_vtab base;
+  sqlite3_vtab base;          /* Base class.  Must be first */
   sqlite3 *db;                /* Host database connection */
   int iNodeSize;              /* Size in bytes of each node in the node table */
-  int nDim;                   /* Number of dimensions */
-  int nBytesPerCell;          /* Bytes consumed per cell */
+  u8 nDim;                    /* Number of dimensions */
+  u8 eCoordType;              /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
+  u8 nBytesPerCell;           /* Bytes consumed per cell */
   int iDepth;                 /* Current depth of the r-tree structure */
   char *zDb;                  /* Name of database containing r-tree table */
   char *zName;                /* Name of r-tree table */ 
-  RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ 
   int nBusy;                  /* Current number of users of this structure */
+  i64 nRowEst;                /* Estimated number of rows in this table */
 
   /* List of nodes removed during a CondenseTree operation. List is
   ** linked together via the pointer normally used for hash chains -
@@ -136502,10 +144792,10 @@ struct Rtree {
   sqlite3_stmt *pWriteParent;
   sqlite3_stmt *pDeleteParent;
 
-  int eCoordType;
+  RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ 
 };
 
-/* Possible values for eCoordType: */
+/* Possible values for Rtree.eCoordType: */
 #define RTREE_COORD_REAL32 0
 #define RTREE_COORD_INT32  1
 
@@ -136517,12 +144807,31 @@ struct Rtree {
 #ifdef SQLITE_RTREE_INT_ONLY
   typedef sqlite3_int64 RtreeDValue;       /* High accuracy coordinate */
   typedef int RtreeValue;                  /* Low accuracy coordinate */
+# define RTREE_ZERO 0
 #else
   typedef double RtreeDValue;              /* High accuracy coordinate */
   typedef float RtreeValue;                /* Low accuracy coordinate */
+# define RTREE_ZERO 0.0
 #endif
 
 /*
+** When doing a search of an r-tree, instances of the following structure
+** record intermediate results from the tree walk.
+**
+** The id is always a node-id.  For iLevel>=1 the id is the node-id of
+** the node that the RtreeSearchPoint represents.  When iLevel==0, however,
+** the id is of the parent node and the cell that RtreeSearchPoint
+** represents is the iCell-th entry in the parent node.
+*/
+struct RtreeSearchPoint {
+  RtreeDValue rScore;    /* The score for this node.  Smallest goes first. */
+  sqlite3_int64 id;      /* Node ID */
+  u8 iLevel;             /* 0=entries.  1=leaf node.  2+ for higher */
+  u8 eWithin;            /* PARTLY_WITHIN or FULLY_WITHIN */
+  u8 iCell;              /* Cell index within the node */
+};
+
+/*
 ** The minimum number of cells allowed for a node is a third of the 
 ** maximum. In Gutman's notation:
 **
@@ -136544,21 +144853,44 @@ struct Rtree {
 */
 #define RTREE_MAX_DEPTH 40
 
+
+/*
+** Number of entries in the cursor RtreeNode cache.  The first entry is
+** used to cache the RtreeNode for RtreeCursor.sPoint.  The remaining
+** entries cache the RtreeNode for the first elements of the priority queue.
+*/
+#define RTREE_CACHE_SZ  5
+
 /* 
 ** An rtree cursor object.
 */
 struct RtreeCursor {
-  sqlite3_vtab_cursor base;
-  RtreeNode *pNode;                 /* Node cursor is currently pointing at */
-  int iCell;                        /* Index of current cell in pNode */
+  sqlite3_vtab_cursor base;         /* Base class.  Must be first */
+  u8 atEOF;                         /* True if at end of search */
+  u8 bPoint;                        /* True if sPoint is valid */
   int iStrategy;                    /* Copy of idxNum search parameter */
   int nConstraint;                  /* Number of entries in aConstraint */
   RtreeConstraint *aConstraint;     /* Search constraints. */
+  int nPointAlloc;                  /* Number of slots allocated for aPoint[] */
+  int nPoint;                       /* Number of slots used in aPoint[] */
+  int mxLevel;                      /* iLevel value for root of the tree */
+  RtreeSearchPoint *aPoint;         /* Priority queue for search points */
+  RtreeSearchPoint sPoint;          /* Cached next search point */
+  RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */
+  u32 anQueue[RTREE_MAX_DEPTH+1];   /* Number of queued entries by iLevel */
 };
 
+/* Return the Rtree of a RtreeCursor */
+#define RTREE_OF_CURSOR(X)   ((Rtree*)((X)->base.pVtab))
+
+/*
+** A coordinate can be either a floating point number or a integer.  All
+** coordinates within a single R-Tree are always of the same time.
+*/
 union RtreeCoord {
-  RtreeValue f;
-  int i;
+  RtreeValue f;      /* Floating point value */
+  int i;             /* Integer value */
+  u32 u;             /* Unsigned for byte-order conversions */
 };
 
 /*
@@ -136583,38 +144915,67 @@ union RtreeCoord {
 struct RtreeConstraint {
   int iCoord;                     /* Index of constrained coordinate */
   int op;                         /* Constraining operation */
-  RtreeDValue rValue;             /* Constraint value. */
-  int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*);
-  sqlite3_rtree_geometry *pGeom;  /* Constraint callback argument for a MATCH */
+  union {
+    RtreeDValue rValue;             /* Constraint value. */
+    int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*);
+    int (*xQueryFunc)(sqlite3_rtree_query_info*);
+  } u;
+  sqlite3_rtree_query_info *pInfo;  /* xGeom and xQueryFunc argument */
 };
 
 /* Possible values for RtreeConstraint.op */
-#define RTREE_EQ    0x41
-#define RTREE_LE    0x42
-#define RTREE_LT    0x43
-#define RTREE_GE    0x44
-#define RTREE_GT    0x45
-#define RTREE_MATCH 0x46
+#define RTREE_EQ    0x41  /* A */
+#define RTREE_LE    0x42  /* B */
+#define RTREE_LT    0x43  /* C */
+#define RTREE_GE    0x44  /* D */
+#define RTREE_GT    0x45  /* E */
+#define RTREE_MATCH 0x46  /* F: Old-style sqlite3_rtree_geometry_callback() */
+#define RTREE_QUERY 0x47  /* G: New-style sqlite3_rtree_query_callback() */
+
 
 /* 
 ** An rtree structure node.
 */
 struct RtreeNode {
-  RtreeNode *pParent;               /* Parent node */
-  i64 iNode;
-  int nRef;
-  int isDirty;
-  u8 *zData;
-  RtreeNode *pNext;                 /* Next node in this hash chain */
+  RtreeNode *pParent;         /* Parent node */
+  i64 iNode;                  /* The node number */
+  int nRef;                   /* Number of references to this node */
+  int isDirty;                /* True if the node needs to be written to disk */
+  u8 *zData;                  /* Content of the node, as should be on disk */
+  RtreeNode *pNext;           /* Next node in this hash collision chain */
 };
+
+/* Return the number of cells in a node  */
 #define NCELL(pNode) readInt16(&(pNode)->zData[2])
 
 /* 
-** Structure to store a deserialized rtree record.
+** A single cell from a node, deserialized
 */
 struct RtreeCell {
-  i64 iRowid;
-  RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2];
+  i64 iRowid;                                 /* Node or entry ID */
+  RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2];  /* Bounding box coordinates */
+};
+
+
+/*
+** This object becomes the sqlite3_user_data() for the SQL functions
+** that are created by sqlite3_rtree_geometry_callback() and
+** sqlite3_rtree_query_callback() and which appear on the right of MATCH
+** operators in order to constrain a search.
+**
+** xGeom and xQueryFunc are the callback functions.  Exactly one of 
+** xGeom and xQueryFunc fields is non-NULL, depending on whether the
+** SQL function was created using sqlite3_rtree_geometry_callback() or
+** sqlite3_rtree_query_callback().
+** 
+** This object is deleted automatically by the destructor mechanism in
+** sqlite3_create_function_v2().
+*/
+struct RtreeGeomCallback {
+  int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*);
+  int (*xQueryFunc)(sqlite3_rtree_query_info*);
+  void (*xDestructor)(void*);
+  void *pContext;
 };
 
 
@@ -136626,29 +144987,16 @@ struct RtreeCell {
 #define RTREE_GEOMETRY_MAGIC 0x891245AB
 
 /*
-** An instance of this structure must be supplied as a blob argument to
-** the right-hand-side of an SQL MATCH operator used to constrain an
-** r-tree query.
+** An instance of this structure (in the form of a BLOB) is returned by
+** the SQL functions that sqlite3_rtree_geometry_callback() and
+** sqlite3_rtree_query_callback() create, and is read as the right-hand
+** operand to the MATCH operator of an R-Tree.
 */
 struct RtreeMatchArg {
-  u32 magic;                      /* Always RTREE_GEOMETRY_MAGIC */
-  int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *);
-  void *pContext;
-  int nParam;
-  RtreeDValue aParam[1];
-};
-
-/*
-** When a geometry callback is created (see sqlite3_rtree_geometry_callback),
-** a single instance of the following structure is allocated. It is used
-** as the context for the user-function created by by s_r_g_c(). The object
-** is eventually deleted by the destructor mechanism provided by
-** sqlite3_create_function_v2() (which is called by s_r_g_c() to create
-** the geometry callback function).
-*/
-struct RtreeGeomCallback {
-  int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*);
-  void *pContext;
+  u32 magic;                  /* Always RTREE_GEOMETRY_MAGIC */
+  RtreeGeomCallback cb;       /* Info about the callback functions */
+  int nParam;                 /* Number of parameters to the SQL function */
+  RtreeDValue aParam[1];      /* Values for parameters to the SQL function */
 };
 
 #ifndef MAX
@@ -136742,10 +145090,7 @@ static void nodeZero(Rtree *pRtree, RtreeNode *p){
 ** in the Rtree.aHash table.
 */
 static int nodeHash(i64 iNode){
-  return (
-    (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^ 
-    (iNode>>24) ^ (iNode>>16) ^ (iNode>> 8) ^ (iNode>> 0)
-  ) % HASHSIZE;
+  return iNode % HASHSIZE;
 }
 
 /*
@@ -136805,8 +145150,7 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
 /*
 ** Obtain a reference to an r-tree node.
 */
-static int
-nodeAcquire(
+static int nodeAcquire(
   Rtree *pRtree,             /* R-tree structure */
   i64 iNode,                 /* Node number to load */
   RtreeNode *pParent,        /* Either the parent node or NULL */
@@ -136895,10 +145239,10 @@ nodeAcquire(
 ** Overwrite cell iCell of node pNode with the contents of pCell.
 */
 static void nodeOverwriteCell(
-  Rtree *pRtree, 
-  RtreeNode *pNode,  
-  RtreeCell *pCell, 
-  int iCell
+  Rtree *pRtree,             /* The overall R-Tree */
+  RtreeNode *pNode,          /* The node into which the cell is to be written */
+  RtreeCell *pCell,          /* The cell to write */
+  int iCell                  /* Index into pNode into which pCell is written */
 ){
   int ii;
   u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
@@ -136910,7 +145254,7 @@ static void nodeOverwriteCell(
 }
 
 /*
-** Remove cell the cell with index iCell from node pNode.
+** Remove the cell with index iCell from node pNode.
 */
 static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){
   u8 *pDst = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
@@ -136927,11 +145271,10 @@ static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){
 **
 ** If there is not enough free space in pNode, return SQLITE_FULL.
 */
-static int
-nodeInsertCell(
-  Rtree *pRtree, 
-  RtreeNode *pNode, 
-  RtreeCell *pCell 
+static int nodeInsertCell(
+  Rtree *pRtree,                /* The overall R-Tree */
+  RtreeNode *pNode,             /* Write new cell into this node */
+  RtreeCell *pCell              /* The cell to be inserted */
 ){
   int nCell;                    /* Current number of cells in pNode */
   int nMaxCell;                 /* Maximum number of cells for pNode */
@@ -136952,8 +145295,7 @@ nodeInsertCell(
 /*
 ** If the node is dirty, write it out to the database.
 */
-static int
-nodeWrite(Rtree *pRtree, RtreeNode *pNode){
+static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){
   int rc = SQLITE_OK;
   if( pNode->isDirty ){
     sqlite3_stmt *p = pRtree->pWriteNode;
@@ -136978,8 +145320,7 @@ nodeWrite(Rtree *pRtree, RtreeNode *pNode){
 ** Release a reference to a node. If the node is dirty and the reference
 ** count drops to zero, the node data is written to the database.
 */
-static int
-nodeRelease(Rtree *pRtree, RtreeNode *pNode){
+static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){
   int rc = SQLITE_OK;
   if( pNode ){
     assert( pNode->nRef>0 );
@@ -137007,9 +145348,9 @@ nodeRelease(Rtree *pRtree, RtreeNode *pNode){
 ** an internal node, then the 64-bit integer is a child page number.
 */
 static i64 nodeGetRowid(
-  Rtree *pRtree, 
-  RtreeNode *pNode, 
-  int iCell
+  Rtree *pRtree,       /* The overall R-Tree */
+  RtreeNode *pNode,    /* The node from which to extract the ID */
+  int iCell            /* The cell index from which to extract the ID */
 ){
   assert( iCell<NCELL(pNode) );
   return readInt64(&pNode->zData[4 + pRtree->nBytesPerCell*iCell]);
@@ -137019,11 +145360,11 @@ static i64 nodeGetRowid(
 ** Return coordinate iCoord from cell iCell in node pNode.
 */
 static void nodeGetCoord(
-  Rtree *pRtree, 
-  RtreeNode *pNode, 
-  int iCell,
-  int iCoord,
-  RtreeCoord *pCoord           /* Space to write result to */
+  Rtree *pRtree,               /* The overall R-Tree */
+  RtreeNode *pNode,            /* The node from which to extract a coordinate */
+  int iCell,                   /* The index of the cell within the node */
+  int iCoord,                  /* Which coordinate to extract */
+  RtreeCoord *pCoord           /* OUT: Space to write result to */
 ){
   readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord);
 }
@@ -137033,15 +145374,20 @@ static void nodeGetCoord(
 ** to by pCell with the results.
 */
 static void nodeGetCell(
-  Rtree *pRtree, 
-  RtreeNode *pNode, 
-  int iCell,
-  RtreeCell *pCell
-){
-  int ii;
+  Rtree *pRtree,               /* The overall R-Tree */
+  RtreeNode *pNode,            /* The node containing the cell to be read */
+  int iCell,                   /* Index of the cell within the node */
+  RtreeCell *pCell             /* OUT: Write the cell contents here */
+){
+  u8 *pData;
+  u8 *pEnd;
+  RtreeCoord *pCoord;
   pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);
-  for(ii=0; ii<pRtree->nDim*2; ii++){
-    nodeGetCoord(pRtree, pNode, iCell, ii, &pCell->aCoord[ii]);
+  pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell);
+  pEnd = pData + pRtree->nDim*8;
+  pCoord = pCell->aCoord;
+  for(; pData<pEnd; pData+=4, pCoord++){
+    readCoord(pData, pCoord);
   }
 }
 
@@ -137167,10 +145513,10 @@ static void freeCursorConstraints(RtreeCursor *pCsr){
   if( pCsr->aConstraint ){
     int i;                        /* Used to iterate through constraint array */
     for(i=0; i<pCsr->nConstraint; i++){
-      sqlite3_rtree_geometry *pGeom = pCsr->aConstraint[i].pGeom;
-      if( pGeom ){
-        if( pGeom->xDelUser ) pGeom->xDelUser(pGeom->pUser);
-        sqlite3_free(pGeom);
+      sqlite3_rtree_query_info *pInfo = pCsr->aConstraint[i].pInfo;
+      if( pInfo ){
+        if( pInfo->xDelUser ) pInfo->xDelUser(pInfo->pUser);
+        sqlite3_free(pInfo);
       }
     }
     sqlite3_free(pCsr->aConstraint);
@@ -137183,12 +145529,13 @@ static void freeCursorConstraints(RtreeCursor *pCsr){
 */
 static int rtreeClose(sqlite3_vtab_cursor *cur){
   Rtree *pRtree = (Rtree *)(cur->pVtab);
-  int rc;
+  int ii;
   RtreeCursor *pCsr = (RtreeCursor *)cur;
   freeCursorConstraints(pCsr);
-  rc = nodeRelease(pRtree, pCsr->pNode);
+  sqlite3_free(pCsr->aPoint);
+  for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
   sqlite3_free(pCsr);
-  return rc;
+  return SQLITE_OK;
 }
 
 /*
@@ -137199,194 +145546,164 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
 */
 static int rtreeEof(sqlite3_vtab_cursor *cur){
   RtreeCursor *pCsr = (RtreeCursor *)cur;
-  return (pCsr->pNode==0);
+  return pCsr->atEOF;
+}
+
+/*
+** Convert raw bits from the on-disk RTree record into a coordinate value.
+** The on-disk format is big-endian and needs to be converted for little-
+** endian platforms.  The on-disk record stores integer coordinates if
+** eInt is true and it stores 32-bit floating point records if eInt is
+** false.  a[] is the four bytes of the on-disk record to be decoded.
+** Store the results in "r".
+**
+** There are three versions of this macro, one each for little-endian and
+** big-endian processors and a third generic implementation.  The endian-
+** specific implementations are much faster and are preferred if the
+** processor endianness is known at compile-time.  The SQLITE_BYTEORDER
+** macro is part of sqliteInt.h and hence the endian-specific
+** implementation will only be used if this module is compiled as part
+** of the amalgamation.
+*/
+#if defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==1234
+#define RTREE_DECODE_COORD(eInt, a, r) {                        \
+    RtreeCoord c;    /* Coordinate decoded */                   \
+    memcpy(&c.u,a,4);                                           \
+    c.u = ((c.u>>24)&0xff)|((c.u>>8)&0xff00)|                   \
+          ((c.u&0xff)<<24)|((c.u&0xff00)<<8);                   \
+    r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
+}
+#elif defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==4321
+#define RTREE_DECODE_COORD(eInt, a, r) {                        \
+    RtreeCoord c;    /* Coordinate decoded */                   \
+    memcpy(&c.u,a,4);                                           \
+    r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
+}
+#else
+#define RTREE_DECODE_COORD(eInt, a, r) {                        \
+    RtreeCoord c;    /* Coordinate decoded */                   \
+    c.u = ((u32)a[0]<<24) + ((u32)a[1]<<16)                     \
+           +((u32)a[2]<<8) + a[3];                              \
+    r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
 }
+#endif
 
 /*
-** The r-tree constraint passed as the second argument to this function is
-** guaranteed to be a MATCH constraint.
+** Check the RTree node or entry given by pCellData and p against the MATCH
+** constraint pConstraint.  
 */
-static int testRtreeGeom(
-  Rtree *pRtree,                  /* R-Tree object */
-  RtreeConstraint *pConstraint,   /* MATCH constraint to test */
-  RtreeCell *pCell,               /* Cell to test */
-  int *pbRes                      /* OUT: Test result */
+static int rtreeCallbackConstraint(
+  RtreeConstraint *pConstraint,  /* The constraint to test */
+  int eInt,                      /* True if RTree holding integer coordinates */
+  u8 *pCellData,                 /* Raw cell content */
+  RtreeSearchPoint *pSearch,     /* Container of this cell */
+  sqlite3_rtree_dbl *prScore,    /* OUT: score for the cell */
+  int *peWithin                  /* OUT: visibility of the cell */
 ){
-  int i;
-  RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2];
-  int nCoord = pRtree->nDim*2;
+  int i;                                                /* Loop counter */
+  sqlite3_rtree_query_info *pInfo = pConstraint->pInfo; /* Callback info */
+  int nCoord = pInfo->nCoord;                           /* No. of coordinates */
+  int rc;                                             /* Callback return code */
+  sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2];   /* Decoded coordinates */
 
-  assert( pConstraint->op==RTREE_MATCH );
-  assert( pConstraint->pGeom );
+  assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY );
+  assert( nCoord==2 || nCoord==4 || nCoord==6 || nCoord==8 || nCoord==10 );
 
-  for(i=0; i<nCoord; i++){
-    aCoord[i] = DCOORD(pCell->aCoord[i]);
+  if( pConstraint->op==RTREE_QUERY && pSearch->iLevel==1 ){
+    pInfo->iRowid = readInt64(pCellData);
   }
-  return pConstraint->xGeom(pConstraint->pGeom, nCoord, aCoord, pbRes);
-}
-
-/* 
-** Cursor pCursor currently points to a cell in a non-leaf page.
-** Set *pbEof to true if the sub-tree headed by the cell is filtered
-** (excluded) by the constraints in the pCursor->aConstraint[] 
-** array, or false otherwise.
-**
-** Return SQLITE_OK if successful or an SQLite error code if an error
-** occurs within a geometry callback.
-*/
-static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){
-  RtreeCell cell;
-  int ii;
-  int bRes = 0;
-  int rc = SQLITE_OK;
-
-  nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell);
-  for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){
-    RtreeConstraint *p = &pCursor->aConstraint[ii];
-    RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]);
-    RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]);
-
-    assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 
-        || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH
-    );
-
-    switch( p->op ){
-      case RTREE_LE: case RTREE_LT: 
-        bRes = p->rValue<cell_min; 
-        break;
-
-      case RTREE_GE: case RTREE_GT: 
-        bRes = p->rValue>cell_max; 
-        break;
-
-      case RTREE_EQ:
-        bRes = (p->rValue>cell_max || p->rValue<cell_min);
-        break;
-
-      default: {
-        assert( p->op==RTREE_MATCH );
-        rc = testRtreeGeom(pRtree, p, &cell, &bRes);
-        bRes = !bRes;
-        break;
-      }
+  pCellData += 8;
+  for(i=0; i<nCoord; i++, pCellData += 4){
+    RTREE_DECODE_COORD(eInt, pCellData, aCoord[i]);
+  }
+  if( pConstraint->op==RTREE_MATCH ){
+    rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pInfo,
+                              nCoord, aCoord, &i);
+    if( i==0 ) *peWithin = NOT_WITHIN;
+    *prScore = RTREE_ZERO;
+  }else{
+    pInfo->aCoord = aCoord;
+    pInfo->iLevel = pSearch->iLevel - 1;
+    pInfo->rScore = pInfo->rParentScore = pSearch->rScore;
+    pInfo->eWithin = pInfo->eParentWithin = pSearch->eWithin;
+    rc = pConstraint->u.xQueryFunc(pInfo);
+    if( pInfo->eWithin<*peWithin ) *peWithin = pInfo->eWithin;
+    if( pInfo->rScore<*prScore || *prScore<RTREE_ZERO ){
+      *prScore = pInfo->rScore;
     }
   }
-
-  *pbEof = bRes;
   return rc;
 }
 
 /* 
-** Test if the cell that cursor pCursor currently points to
-** would be filtered (excluded) by the constraints in the 
-** pCursor->aConstraint[] array. If so, set *pbEof to true before
-** returning. If the cell is not filtered (excluded) by the constraints,
-** set pbEof to zero.
-**
-** Return SQLITE_OK if successful or an SQLite error code if an error
-** occurs within a geometry callback.
-**
-** This function assumes that the cell is part of a leaf node.
+** Check the internal RTree node given by pCellData against constraint p.
+** If this constraint cannot be satisfied by any child within the node,
+** set *peWithin to NOT_WITHIN.
 */
-static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){
-  RtreeCell cell;
-  int ii;
-  *pbEof = 0;
+static void rtreeNonleafConstraint(
+  RtreeConstraint *p,        /* The constraint to test */
+  int eInt,                  /* True if RTree holds integer coordinates */
+  u8 *pCellData,             /* Raw cell content as appears on disk */
+  int *peWithin              /* Adjust downward, as appropriate */
+){
+  sqlite3_rtree_dbl val;     /* Coordinate value convert to a double */
 
-  nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell);
-  for(ii=0; ii<pCursor->nConstraint; ii++){
-    RtreeConstraint *p = &pCursor->aConstraint[ii];
-    RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]);
-    int res;
-    assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 
-        || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH
-    );
-    switch( p->op ){
-      case RTREE_LE: res = (coord<=p->rValue); break;
-      case RTREE_LT: res = (coord<p->rValue);  break;
-      case RTREE_GE: res = (coord>=p->rValue); break;
-      case RTREE_GT: res = (coord>p->rValue);  break;
-      case RTREE_EQ: res = (coord==p->rValue); break;
-      default: {
-        int rc;
-        assert( p->op==RTREE_MATCH );
-        rc = testRtreeGeom(pRtree, p, &cell, &res);
-        if( rc!=SQLITE_OK ){
-          return rc;
-        }
-        break;
-      }
-    }
+  /* p->iCoord might point to either a lower or upper bound coordinate
+  ** in a coordinate pair.  But make pCellData point to the lower bound.
+  */
+  pCellData += 8 + 4*(p->iCoord&0xfe);
 
-    if( !res ){
-      *pbEof = 1;
-      return SQLITE_OK;
-    }
-  }
+  assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 
+      || p->op==RTREE_GT || p->op==RTREE_EQ );
+  switch( p->op ){
+    case RTREE_LE:
+    case RTREE_LT:
+    case RTREE_EQ:
+      RTREE_DECODE_COORD(eInt, pCellData, val);
+      /* val now holds the lower bound of the coordinate pair */
+      if( p->u.rValue>=val ) return;
+      if( p->op!=RTREE_EQ ) break;  /* RTREE_LE and RTREE_LT end here */
+      /* Fall through for the RTREE_EQ case */
 
-  return SQLITE_OK;
+    default: /* RTREE_GT or RTREE_GE,  or fallthrough of RTREE_EQ */
+      pCellData += 4;
+      RTREE_DECODE_COORD(eInt, pCellData, val);
+      /* val now holds the upper bound of the coordinate pair */
+      if( p->u.rValue<=val ) return;
+  }
+  *peWithin = NOT_WITHIN;
 }
 
 /*
-** Cursor pCursor currently points at a node that heads a sub-tree of
-** height iHeight (if iHeight==0, then the node is a leaf). Descend
-** to point to the left-most cell of the sub-tree that matches the 
-** configured constraints.
+** Check the leaf RTree cell given by pCellData against constraint p.
+** If this constraint is not satisfied, set *peWithin to NOT_WITHIN.
+** If the constraint is satisfied, leave *peWithin unchanged.
+**
+** The constraint is of the form:  xN op $val
+**
+** The op is given by p->op.  The xN is p->iCoord-th coordinate in
+** pCellData.  $val is given by p->u.rValue.
 */
-static int descendToCell(
-  Rtree *pRtree, 
-  RtreeCursor *pCursor, 
-  int iHeight,
-  int *pEof                 /* OUT: Set to true if cannot descend */
+static void rtreeLeafConstraint(
+  RtreeConstraint *p,        /* The constraint to test */
+  int eInt,                  /* True if RTree holds integer coordinates */
+  u8 *pCellData,             /* Raw cell content as appears on disk */
+  int *peWithin              /* Adjust downward, as appropriate */
 ){
-  int isEof;
-  int rc;
-  int ii;
-  RtreeNode *pChild;
-  sqlite3_int64 iRowid;
+  RtreeDValue xN;      /* Coordinate value converted to a double */
 
-  RtreeNode *pSavedNode = pCursor->pNode;
-  int iSavedCell = pCursor->iCell;
-
-  assert( iHeight>=0 );
-
-  if( iHeight==0 ){
-    rc = testRtreeEntry(pRtree, pCursor, &isEof);
-  }else{
-    rc = testRtreeCell(pRtree, pCursor, &isEof);
-  }
-  if( rc!=SQLITE_OK || isEof || iHeight==0 ){
-    goto descend_to_cell_out;
-  }
-
-  iRowid = nodeGetRowid(pRtree, pCursor->pNode, pCursor->iCell);
-  rc = nodeAcquire(pRtree, iRowid, pCursor->pNode, &pChild);
-  if( rc!=SQLITE_OK ){
-    goto descend_to_cell_out;
-  }
-
-  nodeRelease(pRtree, pCursor->pNode);
-  pCursor->pNode = pChild;
-  isEof = 1;
-  for(ii=0; isEof && ii<NCELL(pChild); ii++){
-    pCursor->iCell = ii;
-    rc = descendToCell(pRtree, pCursor, iHeight-1, &isEof);
-    if( rc!=SQLITE_OK ){
-      goto descend_to_cell_out;
-    }
-  }
-
-  if( isEof ){
-    assert( pCursor->pNode==pChild );
-    nodeReference(pSavedNode);
-    nodeRelease(pRtree, pChild);
-    pCursor->pNode = pSavedNode;
-    pCursor->iCell = iSavedCell;
+  assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 
+      || p->op==RTREE_GT || p->op==RTREE_EQ );
+  pCellData += 8 + p->iCoord*4;
+  RTREE_DECODE_COORD(eInt, pCellData, xN);
+  switch( p->op ){
+    case RTREE_LE: if( xN <= p->u.rValue ) return;  break;
+    case RTREE_LT: if( xN <  p->u.rValue ) return;  break;
+    case RTREE_GE: if( xN >= p->u.rValue ) return;  break;
+    case RTREE_GT: if( xN >  p->u.rValue ) return;  break;
+    default:       if( xN == p->u.rValue ) return;  break;
   }
-
-descend_to_cell_out:
-  *pEof = isEof;
-  return rc;
+  *peWithin = NOT_WITHIN;
 }
 
 /*
@@ -137401,6 +145718,7 @@ static int nodeRowidIndex(
 ){
   int ii;
   int nCell = NCELL(pNode);
+  assert( nCell<200 );
   for(ii=0; ii<nCell; ii++){
     if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
       *piIndex = ii;
@@ -137423,48 +145741,302 @@ static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
   return SQLITE_OK;
 }
 
-/* 
-** Rtree virtual table module xNext method.
+/*
+** Compare two search points.  Return negative, zero, or positive if the first
+** is less than, equal to, or greater than the second.
+**
+** The rScore is the primary key.  Smaller rScore values come first.
+** If the rScore is a tie, then use iLevel as the tie breaker with smaller
+** iLevel values coming first.  In this way, if rScore is the same for all
+** SearchPoints, then iLevel becomes the deciding factor and the result
+** is a depth-first search, which is the desired default behavior.
 */
-static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
-  Rtree *pRtree = (Rtree *)(pVtabCursor->pVtab);
-  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
-  int rc = SQLITE_OK;
+static int rtreeSearchPointCompare(
+  const RtreeSearchPoint *pA,
+  const RtreeSearchPoint *pB
+){
+  if( pA->rScore<pB->rScore ) return -1;
+  if( pA->rScore>pB->rScore ) return +1;
+  if( pA->iLevel<pB->iLevel ) return -1;
+  if( pA->iLevel>pB->iLevel ) return +1;
+  return 0;
+}
 
-  /* RtreeCursor.pNode must not be NULL. If is is NULL, then this cursor is
-  ** already at EOF. It is against the rules to call the xNext() method of
-  ** a cursor that has already reached EOF.
-  */
-  assert( pCsr->pNode );
-
-  if( pCsr->iStrategy==1 ){
-    /* This "scan" is a direct lookup by rowid. There is no next entry. */
-    nodeRelease(pRtree, pCsr->pNode);
-    pCsr->pNode = 0;
-  }else{
-    /* Move to the next entry that matches the configured constraints. */
-    int iHeight = 0;
-    while( pCsr->pNode ){
-      RtreeNode *pNode = pCsr->pNode;
-      int nCell = NCELL(pNode);
-      for(pCsr->iCell++; pCsr->iCell<nCell; pCsr->iCell++){
-        int isEof;
-        rc = descendToCell(pRtree, pCsr, iHeight, &isEof);
-        if( rc!=SQLITE_OK || !isEof ){
-          return rc;
+/*
+** Interchange to search points in a cursor.
+*/
+static void rtreeSearchPointSwap(RtreeCursor *p, int i, int j){
+  RtreeSearchPoint t = p->aPoint[i];
+  assert( i<j );
+  p->aPoint[i] = p->aPoint[j];
+  p->aPoint[j] = t;
+  i++; j++;
+  if( i<RTREE_CACHE_SZ ){
+    if( j>=RTREE_CACHE_SZ ){
+      nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]);
+      p->aNode[i] = 0;
+    }else{
+      RtreeNode *pTemp = p->aNode[i];
+      p->aNode[i] = p->aNode[j];
+      p->aNode[j] = pTemp;
+    }
+  }
+}
+
+/*
+** Return the search point with the lowest current score.
+*/
+static RtreeSearchPoint *rtreeSearchPointFirst(RtreeCursor *pCur){
+  return pCur->bPoint ? &pCur->sPoint : pCur->nPoint ? pCur->aPoint : 0;
+}
+
+/*
+** Get the RtreeNode for the search point with the lowest score.
+*/
+static RtreeNode *rtreeNodeOfFirstSearchPoint(RtreeCursor *pCur, int *pRC){
+  sqlite3_int64 id;
+  int ii = 1 - pCur->bPoint;
+  assert( ii==0 || ii==1 );
+  assert( pCur->bPoint || pCur->nPoint );
+  if( pCur->aNode[ii]==0 ){
+    assert( pRC!=0 );
+    id = ii ? pCur->aPoint[0].id : pCur->sPoint.id;
+    *pRC = nodeAcquire(RTREE_OF_CURSOR(pCur), id, 0, &pCur->aNode[ii]);
+  }
+  return pCur->aNode[ii];
+}
+
+/*
+** Push a new element onto the priority queue
+*/
+static RtreeSearchPoint *rtreeEnqueue(
+  RtreeCursor *pCur,    /* The cursor */
+  RtreeDValue rScore,   /* Score for the new search point */
+  u8 iLevel             /* Level for the new search point */
+){
+  int i, j;
+  RtreeSearchPoint *pNew;
+  if( pCur->nPoint>=pCur->nPointAlloc ){
+    int nNew = pCur->nPointAlloc*2 + 8;
+    pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
+    if( pNew==0 ) return 0;
+    pCur->aPoint = pNew;
+    pCur->nPointAlloc = nNew;
+  }
+  i = pCur->nPoint++;
+  pNew = pCur->aPoint + i;
+  pNew->rScore = rScore;
+  pNew->iLevel = iLevel;
+  assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH );
+  while( i>0 ){
+    RtreeSearchPoint *pParent;
+    j = (i-1)/2;
+    pParent = pCur->aPoint + j;
+    if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break;
+    rtreeSearchPointSwap(pCur, j, i);
+    i = j;
+    pNew = pParent;
+  }
+  return pNew;
+}
+
+/*
+** Allocate a new RtreeSearchPoint and return a pointer to it.  Return
+** NULL if malloc fails.
+*/
+static RtreeSearchPoint *rtreeSearchPointNew(
+  RtreeCursor *pCur,    /* The cursor */
+  RtreeDValue rScore,   /* Score for the new search point */
+  u8 iLevel             /* Level for the new search point */
+){
+  RtreeSearchPoint *pNew, *pFirst;
+  pFirst = rtreeSearchPointFirst(pCur);
+  pCur->anQueue[iLevel]++;
+  if( pFirst==0
+   || pFirst->rScore>rScore 
+   || (pFirst->rScore==rScore && pFirst->iLevel>iLevel)
+  ){
+    if( pCur->bPoint ){
+      int ii;
+      pNew = rtreeEnqueue(pCur, rScore, iLevel);
+      if( pNew==0 ) return 0;
+      ii = (int)(pNew - pCur->aPoint) + 1;
+      if( ii<RTREE_CACHE_SZ ){
+        assert( pCur->aNode[ii]==0 );
+        pCur->aNode[ii] = pCur->aNode[0];
+       }else{
+        nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]);
+      }
+      pCur->aNode[0] = 0;
+      *pNew = pCur->sPoint;
+    }
+    pCur->sPoint.rScore = rScore;
+    pCur->sPoint.iLevel = iLevel;
+    pCur->bPoint = 1;
+    return &pCur->sPoint;
+  }else{
+    return rtreeEnqueue(pCur, rScore, iLevel);
+  }
+}
+
+#if 0
+/* Tracing routines for the RtreeSearchPoint queue */
+static void tracePoint(RtreeSearchPoint *p, int idx, RtreeCursor *pCur){
+  if( idx<0 ){ printf(" s"); }else{ printf("%2d", idx); }
+  printf(" %d.%05lld.%02d %g %d",
+    p->iLevel, p->id, p->iCell, p->rScore, p->eWithin
+  );
+  idx++;
+  if( idx<RTREE_CACHE_SZ ){
+    printf(" %p\n", pCur->aNode[idx]);
+  }else{
+    printf("\n");
+  }
+}
+static void traceQueue(RtreeCursor *pCur, const char *zPrefix){
+  int ii;
+  printf("=== %9s ", zPrefix);
+  if( pCur->bPoint ){
+    tracePoint(&pCur->sPoint, -1, pCur);
+  }
+  for(ii=0; ii<pCur->nPoint; ii++){
+    if( ii>0 || pCur->bPoint ) printf("              ");
+    tracePoint(&pCur->aPoint[ii], ii, pCur);
+  }
+}
+# define RTREE_QUEUE_TRACE(A,B) traceQueue(A,B)
+#else
+# define RTREE_QUEUE_TRACE(A,B)   /* no-op */
+#endif
+
+/* Remove the search point with the lowest current score.
+*/
+static void rtreeSearchPointPop(RtreeCursor *p){
+  int i, j, k, n;
+  i = 1 - p->bPoint;
+  assert( i==0 || i==1 );
+  if( p->aNode[i] ){
+    nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]);
+    p->aNode[i] = 0;
+  }
+  if( p->bPoint ){
+    p->anQueue[p->sPoint.iLevel]--;
+    p->bPoint = 0;
+  }else if( p->nPoint ){
+    p->anQueue[p->aPoint[0].iLevel]--;
+    n = --p->nPoint;
+    p->aPoint[0] = p->aPoint[n];
+    if( n<RTREE_CACHE_SZ-1 ){
+      p->aNode[1] = p->aNode[n+1];
+      p->aNode[n+1] = 0;
+    }
+    i = 0;
+    while( (j = i*2+1)<n ){
+      k = j+1;
+      if( k<n && rtreeSearchPointCompare(&p->aPoint[k], &p->aPoint[j])<0 ){
+        if( rtreeSearchPointCompare(&p->aPoint[k], &p->aPoint[i])<0 ){
+          rtreeSearchPointSwap(p, i, k);
+          i = k;
+        }else{
+          break;
+        }
+      }else{
+        if( rtreeSearchPointCompare(&p->aPoint[j], &p->aPoint[i])<0 ){
+          rtreeSearchPointSwap(p, i, j);
+          i = j;
+        }else{
+          break;
         }
       }
-      pCsr->pNode = pNode->pParent;
-      rc = nodeParentIndex(pRtree, pNode, &pCsr->iCell);
-      if( rc!=SQLITE_OK ){
-        return rc;
+    }
+  }
+}
+
+
+/*
+** Continue the search on cursor pCur until the front of the queue
+** contains an entry suitable for returning as a result-set row,
+** or until the RtreeSearchPoint queue is empty, indicating that the
+** query has completed.
+*/
+static int rtreeStepToLeaf(RtreeCursor *pCur){
+  RtreeSearchPoint *p;
+  Rtree *pRtree = RTREE_OF_CURSOR(pCur);
+  RtreeNode *pNode;
+  int eWithin;
+  int rc = SQLITE_OK;
+  int nCell;
+  int nConstraint = pCur->nConstraint;
+  int ii;
+  int eInt;
+  RtreeSearchPoint x;
+
+  eInt = pRtree->eCoordType==RTREE_COORD_INT32;
+  while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){
+    pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
+    if( rc ) return rc;
+    nCell = NCELL(pNode);
+    assert( nCell<200 );
+    while( p->iCell<nCell ){
+      sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
+      u8 *pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
+      eWithin = FULLY_WITHIN;
+      for(ii=0; ii<nConstraint; ii++){
+        RtreeConstraint *pConstraint = pCur->aConstraint + ii;
+        if( pConstraint->op>=RTREE_MATCH ){
+          rc = rtreeCallbackConstraint(pConstraint, eInt, pCellData, p,
+                                       &rScore, &eWithin);
+          if( rc ) return rc;
+        }else if( p->iLevel==1 ){
+          rtreeLeafConstraint(pConstraint, eInt, pCellData, &eWithin);
+        }else{
+          rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin);
+        }
+        if( eWithin==NOT_WITHIN ) break;
       }
-      nodeReference(pCsr->pNode);
-      nodeRelease(pRtree, pNode);
-      iHeight++;
+      p->iCell++;
+      if( eWithin==NOT_WITHIN ) continue;
+      x.iLevel = p->iLevel - 1;
+      if( x.iLevel ){
+        x.id = readInt64(pCellData);
+        x.iCell = 0;
+      }else{
+        x.id = p->id;
+        x.iCell = p->iCell - 1;
+      }
+      if( p->iCell>=nCell ){
+        RTREE_QUEUE_TRACE(pCur, "POP-S:");
+        rtreeSearchPointPop(pCur);
+      }
+      if( rScore<RTREE_ZERO ) rScore = RTREE_ZERO;
+      p = rtreeSearchPointNew(pCur, rScore, x.iLevel);
+      if( p==0 ) return SQLITE_NOMEM;
+      p->eWithin = eWithin;
+      p->id = x.id;
+      p->iCell = x.iCell;
+      RTREE_QUEUE_TRACE(pCur, "PUSH-S:");
+      break;
+    }
+    if( p->iCell>=nCell ){
+      RTREE_QUEUE_TRACE(pCur, "POP-Se:");
+      rtreeSearchPointPop(pCur);
     }
   }
+  pCur->atEOF = p==0;
+  return SQLITE_OK;
+}
 
+/* 
+** Rtree virtual table module xNext method.
+*/
+static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
+  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
+  int rc = SQLITE_OK;
+
+  /* Move to the next entry that matches the configured constraints. */
+  RTREE_QUEUE_TRACE(pCsr, "POP-Nx:");
+  rtreeSearchPointPop(pCsr);
+  rc = rtreeStepToLeaf(pCsr);
   return rc;
 }
 
@@ -137472,13 +146044,14 @@ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
 ** Rtree virtual table module xRowid method.
 */
 static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
-  Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
   RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
-
-  assert(pCsr->pNode);
-  *pRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell);
-
-  return SQLITE_OK;
+  RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
+  int rc = SQLITE_OK;
+  RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
+  if( rc==SQLITE_OK && p ){
+    *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
+  }
+  return rc;
 }
 
 /* 
@@ -137487,13 +146060,18 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
 static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
   Rtree *pRtree = (Rtree *)cur->pVtab;
   RtreeCursor *pCsr = (RtreeCursor *)cur;
+  RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
+  RtreeCoord c;
+  int rc = SQLITE_OK;
+  RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
 
+  if( rc ) return rc;
+  if( p==0 ) return SQLITE_OK;
   if( i==0 ){
-    i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell);
-    sqlite3_result_int64(ctx, iRowid);
+    sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
   }else{
-    RtreeCoord c;
-    nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c);
+    if( rc ) return rc;
+    nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c);
 #ifndef SQLITE_RTREE_INT_ONLY
     if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
       sqlite3_result_double(ctx, c.f);
@@ -137504,7 +146082,6 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
       sqlite3_result_int(ctx, c.i);
     }
   }
-
   return SQLITE_OK;
 }
 
@@ -137515,12 +146092,18 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
 ** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf
 ** to zero and return an SQLite error code.
 */
-static int findLeafNode(Rtree *pRtree, i64 iRowid, RtreeNode **ppLeaf){
+static int findLeafNode(
+  Rtree *pRtree,              /* RTree to search */
+  i64 iRowid,                 /* The rowid searching for */
+  RtreeNode **ppLeaf,         /* Write the node here */
+  sqlite3_int64 *piNode       /* Write the node-id here */
+){
   int rc;
   *ppLeaf = 0;
   sqlite3_bind_int64(pRtree->pReadRowid, 1, iRowid);
   if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){
     i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0);
+    if( piNode ) *piNode = iNode;
     rc = nodeAcquire(pRtree, iNode, 0, ppLeaf);
     sqlite3_reset(pRtree->pReadRowid);
   }else{
@@ -137536,9 +146119,10 @@ static int findLeafNode(Rtree *pRtree, i64 iRowid, RtreeNode **ppLeaf){
 ** operator.
 */
 static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
-  RtreeMatchArg *p;
-  sqlite3_rtree_geometry *pGeom;
-  int nBlob;
+  RtreeMatchArg *pBlob;              /* BLOB returned by geometry function */
+  sqlite3_rtree_query_info *pInfo;   /* Callback information */
+  int nBlob;                         /* Size of the geometry function blob */
+  int nExpected;                     /* Expected size of the BLOB */
 
   /* Check that value is actually a blob. */
   if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR;
@@ -137551,27 +146135,29 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
     return SQLITE_ERROR;
   }
 
-  pGeom = (sqlite3_rtree_geometry *)sqlite3_malloc(
-      sizeof(sqlite3_rtree_geometry) + nBlob
-  );
-  if( !pGeom ) return SQLITE_NOMEM;
-  memset(pGeom, 0, sizeof(sqlite3_rtree_geometry));
-  p = (RtreeMatchArg *)&pGeom[1];
+  pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob );
+  if( !pInfo ) return SQLITE_NOMEM;
+  memset(pInfo, 0, sizeof(*pInfo));
+  pBlob = (RtreeMatchArg*)&pInfo[1];
 
-  memcpy(p, sqlite3_value_blob(pValue), nBlob);
-  if( p->magic!=RTREE_GEOMETRY_MAGIC 
-   || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue))
-  ){
-    sqlite3_free(pGeom);
+  memcpy(pBlob, sqlite3_value_blob(pValue), nBlob);
+  nExpected = (int)(sizeof(RtreeMatchArg) +
+                    (pBlob->nParam-1)*sizeof(RtreeDValue));
+  if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){
+    sqlite3_free(pInfo);
     return SQLITE_ERROR;
   }
+  pInfo->pContext = pBlob->cb.pContext;
+  pInfo->nParam = pBlob->nParam;
+  pInfo->aParam = pBlob->aParam;
 
-  pGeom->pContext = p->pContext;
-  pGeom->nParam = p->nParam;
-  pGeom->aParam = p->aParam;
-
-  pCons->xGeom = p->xGeom;
-  pCons->pGeom = pGeom;
+  if( pBlob->cb.xGeom ){
+    pCons->u.xGeom = pBlob->cb.xGeom;
+  }else{
+    pCons->op = RTREE_QUERY;
+    pCons->u.xQueryFunc = pBlob->cb.xQueryFunc;
+  }
+  pCons->pInfo = pInfo;
   return SQLITE_OK;
 }
 
@@ -137585,44 +146171,59 @@ static int rtreeFilter(
 ){
   Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
   RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
-
   RtreeNode *pRoot = 0;
   int ii;
   int rc = SQLITE_OK;
+  int iCell = 0;
 
   rtreeReference(pRtree);
 
+  /* Reset the cursor to the same state as rtreeOpen() leaves it in. */
   freeCursorConstraints(pCsr);
-  pCsr->iStrategy = idxNum;
+  sqlite3_free(pCsr->aPoint);
+  memset(pCsr, 0, sizeof(RtreeCursor));
+  pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
 
+  pCsr->iStrategy = idxNum;
   if( idxNum==1 ){
     /* Special case - lookup by rowid. */
     RtreeNode *pLeaf;        /* Leaf on which the required cell resides */
+    RtreeSearchPoint *p;     /* Search point for the the leaf */
     i64 iRowid = sqlite3_value_int64(argv[0]);
-    rc = findLeafNode(pRtree, iRowid, &pLeaf);
-    pCsr->pNode = pLeaf; 
-    if( pLeaf ){
-      assert( rc==SQLITE_OK );
-      rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &pCsr->iCell);
+    i64 iNode = 0;
+    rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
+    if( rc==SQLITE_OK && pLeaf!=0 ){
+      p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0);
+      assert( p!=0 );  /* Always returns pCsr->sPoint */
+      pCsr->aNode[0] = pLeaf;
+      p->id = iNode;
+      p->eWithin = PARTLY_WITHIN;
+      rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell);
+      p->iCell = iCell;
+      RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:");
+    }else{
+      pCsr->atEOF = 1;
     }
   }else{
     /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array 
     ** with the configured constraints. 
     */
-    if( argc>0 ){
+    rc = nodeAcquire(pRtree, 1, 0, &pRoot);
+    if( rc==SQLITE_OK && argc>0 ){
       pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);
       pCsr->nConstraint = argc;
       if( !pCsr->aConstraint ){
         rc = SQLITE_NOMEM;
       }else{
         memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc);
+        memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1));
         assert( (idxStr==0 && argc==0)
                 || (idxStr && (int)strlen(idxStr)==argc*2) );
         for(ii=0; ii<argc; ii++){
           RtreeConstraint *p = &pCsr->aConstraint[ii];
           p->op = idxStr[ii*2];
-          p->iCoord = idxStr[ii*2+1]-'a';
-          if( p->op==RTREE_MATCH ){
+          p->iCoord = idxStr[ii*2+1]-'0';
+          if( p->op>=RTREE_MATCH ){
             /* A MATCH operator. The right-hand-side must be a blob that
             ** can be cast into an RtreeMatchArg object. One created using
             ** an sqlite3_rtree_geometry_callback() SQL user function.
@@ -137631,46 +146232,53 @@ static int rtreeFilter(
             if( rc!=SQLITE_OK ){
               break;
             }
+            p->pInfo->nCoord = pRtree->nDim*2;
+            p->pInfo->anQueue = pCsr->anQueue;
+            p->pInfo->mxLevel = pRtree->iDepth + 1;
           }else{
 #ifdef SQLITE_RTREE_INT_ONLY
-            p->rValue = sqlite3_value_int64(argv[ii]);
+            p->u.rValue = sqlite3_value_int64(argv[ii]);
 #else
-            p->rValue = sqlite3_value_double(argv[ii]);
+            p->u.rValue = sqlite3_value_double(argv[ii]);
 #endif
           }
         }
       }
     }
-  
     if( rc==SQLITE_OK ){
-      pCsr->pNode = 0;
-      rc = nodeAcquire(pRtree, 1, 0, &pRoot);
-    }
-    if( rc==SQLITE_OK ){
-      int isEof = 1;
-      int nCell = NCELL(pRoot);
-      pCsr->pNode = pRoot;
-      for(pCsr->iCell=0; rc==SQLITE_OK && pCsr->iCell<nCell; pCsr->iCell++){
-        assert( pCsr->pNode==pRoot );
-        rc = descendToCell(pRtree, pCsr, pRtree->iDepth, &isEof);
-        if( !isEof ){
-          break;
-        }
-      }
-      if( rc==SQLITE_OK && isEof ){
-        assert( pCsr->pNode==pRoot );
-        nodeRelease(pRtree, pRoot);
-        pCsr->pNode = 0;
-      }
-      assert( rc!=SQLITE_OK || !pCsr->pNode || pCsr->iCell<NCELL(pCsr->pNode) );
+      RtreeSearchPoint *pNew;
+      pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, pRtree->iDepth+1);
+      if( pNew==0 ) return SQLITE_NOMEM;
+      pNew->id = 1;
+      pNew->iCell = 0;
+      pNew->eWithin = PARTLY_WITHIN;
+      assert( pCsr->bPoint==1 );
+      pCsr->aNode[0] = pRoot;
+      pRoot = 0;
+      RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:");
+      rc = rtreeStepToLeaf(pCsr);
     }
   }
 
+  nodeRelease(pRtree, pRoot);
   rtreeRelease(pRtree);
   return rc;
 }
 
 /*
+** Set the pIdxInfo->estimatedRows variable to nRow. Unless this
+** extension is currently being used by a version of SQLite too old to
+** support estimatedRows. In that case this function is a no-op.
+*/
+static void setEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
+#if SQLITE_VERSION_NUMBER>=3008002
+  if( sqlite3_libversion_number()>=3008002 ){
+    pIdxInfo->estimatedRows = nRow;
+  }
+#endif
+}
+
+/*
 ** Rtree virtual table module xBestIndex method. There are three
 ** table scan strategies to choose from (in order from most to 
 ** least desirable):
@@ -137705,13 +146313,14 @@ static int rtreeFilter(
 ** is 'a', the second from the left 'b' etc.
 */
 static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
+  Rtree *pRtree = (Rtree*)tab;
   int rc = SQLITE_OK;
   int ii;
+  i64 nRow;                       /* Estimated rows returned by this scan */
 
   int iIdx = 0;
   char zIdxStr[RTREE_MAX_DIMENSIONS*8+1];
   memset(zIdxStr, 0, sizeof(zIdxStr));
-  UNUSED_PARAMETER(tab);
 
   assert( pIdxInfo->idxStr==0 );
   for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){
@@ -137731,9 +146340,11 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
       /* This strategy involves a two rowid lookups on an B-Tree structures
       ** and then a linear search of an R-Tree node. This should be 
       ** considered almost as quick as a direct rowid lookup (for which 
-      ** sqlite uses an internal cost of 0.0).
+      ** sqlite uses an internal cost of 0.0). It is expected to return
+      ** a single row.
       */ 
-      pIdxInfo->estimatedCost = 10.0;
+      pIdxInfo->estimatedCost = 30.0;
+      setEstimatedRows(pIdxInfo, 1);
       return SQLITE_OK;
     }
 
@@ -137751,7 +146362,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
           break;
       }
       zIdxStr[iIdx++] = op;
-      zIdxStr[iIdx++] = p->iColumn - 1 + 'a';
+      zIdxStr[iIdx++] = p->iColumn - 1 + '0';
       pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
       pIdxInfo->aConstraintUsage[ii].omit = 1;
     }
@@ -137762,8 +146373,11 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
   if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){
     return SQLITE_NOMEM;
   }
-  assert( iIdx>=0 );
-  pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1));
+
+  nRow = pRtree->nRowEst / (iIdx + 1);
+  pIdxInfo->estimatedCost = (double)6.0 * (double)nRow;
+  setEstimatedRows(pIdxInfo, nRow);
+
   return rc;
 }
 
@@ -137841,62 +146455,32 @@ static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){
   return (cellArea(pRtree, &cell)-area);
 }
 
-#if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT
 static RtreeDValue cellOverlap(
   Rtree *pRtree, 
   RtreeCell *p, 
   RtreeCell *aCell, 
-  int nCell, 
-  int iExclude
+  int nCell
 ){
   int ii;
-  RtreeDValue overlap = 0.0;
+  RtreeDValue overlap = RTREE_ZERO;
   for(ii=0; ii<nCell; ii++){
-#if VARIANT_RSTARTREE_CHOOSESUBTREE
-    if( ii!=iExclude )
-#else
-    assert( iExclude==-1 );
-    UNUSED_PARAMETER(iExclude);
-#endif
-    {
-      int jj;
-      RtreeDValue o = (RtreeDValue)1;
-      for(jj=0; jj<(pRtree->nDim*2); jj+=2){
-        RtreeDValue x1, x2;
-
-        x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj]));
-        x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1]));
-
-        if( x2<x1 ){
-          o = 0.0;
-          break;
-        }else{
-          o = o * (x2-x1);
-        }
+    int jj;
+    RtreeDValue o = (RtreeDValue)1;
+    for(jj=0; jj<(pRtree->nDim*2); jj+=2){
+      RtreeDValue x1, x2;
+      x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj]));
+      x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1]));
+      if( x2<x1 ){
+        o = (RtreeDValue)0;
+        break;
+      }else{
+        o = o * (x2-x1);
       }
-      overlap += o;
     }
+    overlap += o;
   }
   return overlap;
 }
-#endif
-
-#if VARIANT_RSTARTREE_CHOOSESUBTREE
-static RtreeDValue cellOverlapEnlargement(
-  Rtree *pRtree, 
-  RtreeCell *p, 
-  RtreeCell *pInsert, 
-  RtreeCell *aCell, 
-  int nCell, 
-  int iExclude
-){
-  RtreeDValue before, after;
-  before = cellOverlap(pRtree, p, aCell, nCell, iExclude);
-  cellUnion(pRtree, p, pInsert);
-  after = cellOverlap(pRtree, p, aCell, nCell, iExclude);
-  return (after-before);
-}
-#endif
 
 
 /*
@@ -137918,12 +146502,8 @@ static int ChooseLeaf(
     int iCell;
     sqlite3_int64 iBest = 0;
 
-    RtreeDValue fMinGrowth = 0.0;
-    RtreeDValue fMinArea = 0.0;
-#if VARIANT_RSTARTREE_CHOOSESUBTREE
-    RtreeDValue fMinOverlap = 0.0;
-    RtreeDValue overlap;
-#endif
+    RtreeDValue fMinGrowth = RTREE_ZERO;
+    RtreeDValue fMinArea = RTREE_ZERO;
 
     int nCell = NCELL(pNode);
     RtreeCell cell;
@@ -137931,22 +146511,6 @@ static int ChooseLeaf(
 
     RtreeCell *aCell = 0;
 
-#if VARIANT_RSTARTREE_CHOOSESUBTREE
-    if( ii==(pRtree->iDepth-1) ){
-      int jj;
-      aCell = sqlite3_malloc(sizeof(RtreeCell)*nCell);
-      if( !aCell ){
-        rc = SQLITE_NOMEM;
-        nodeRelease(pRtree, pNode);
-        pNode = 0;
-        continue;
-      }
-      for(jj=0; jj<nCell; jj++){
-        nodeGetCell(pRtree, pNode, jj, &aCell[jj]);
-      }
-    }
-#endif
-
     /* Select the child node which will be enlarged the least if pCell
     ** is inserted into it. Resolve ties by choosing the entry with
     ** the smallest area.
@@ -137958,26 +146522,9 @@ static int ChooseLeaf(
       nodeGetCell(pRtree, pNode, iCell, &cell);
       growth = cellGrowth(pRtree, &cell, pCell);
       area = cellArea(pRtree, &cell);
-
-#if VARIANT_RSTARTREE_CHOOSESUBTREE
-      if( ii==(pRtree->iDepth-1) ){
-        overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell);
-      }else{
-        overlap = 0.0;
-      }
-      if( (iCell==0) 
-       || (overlap<fMinOverlap) 
-       || (overlap==fMinOverlap && growth<fMinGrowth)
-       || (overlap==fMinOverlap && growth==fMinGrowth && area<fMinArea)
-      ){
-        bBest = 1;
-        fMinOverlap = overlap;
-      }
-#else
       if( iCell==0||growth<fMinGrowth||(growth==fMinGrowth && area<fMinArea) ){
         bBest = 1;
       }
-#endif
       if( bBest ){
         fMinGrowth = growth;
         fMinArea = area;
@@ -138048,155 +146595,6 @@ static int parentWrite(Rtree *pRtree, sqlite3_int64 iNode, sqlite3_int64 iPar){
 
 static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int);
 
-#if VARIANT_GUTTMAN_LINEAR_SPLIT
-/*
-** Implementation of the linear variant of the PickNext() function from
-** Guttman[84].
-*/
-static RtreeCell *LinearPickNext(
-  Rtree *pRtree,
-  RtreeCell *aCell, 
-  int nCell, 
-  RtreeCell *pLeftBox, 
-  RtreeCell *pRightBox,
-  int *aiUsed
-){
-  int ii;
-  for(ii=0; aiUsed[ii]; ii++);
-  aiUsed[ii] = 1;
-  return &aCell[ii];
-}
-
-/*
-** Implementation of the linear variant of the PickSeeds() function from
-** Guttman[84].
-*/
-static void LinearPickSeeds(
-  Rtree *pRtree,
-  RtreeCell *aCell, 
-  int nCell, 
-  int *piLeftSeed, 
-  int *piRightSeed
-){
-  int i;
-  int iLeftSeed = 0;
-  int iRightSeed = 1;
-  RtreeDValue maxNormalInnerWidth = (RtreeDValue)0;
-
-  /* Pick two "seed" cells from the array of cells. The algorithm used
-  ** here is the LinearPickSeeds algorithm from Gutman[1984]. The 
-  ** indices of the two seed cells in the array are stored in local
-  ** variables iLeftSeek and iRightSeed.
-  */
-  for(i=0; i<pRtree->nDim; i++){
-    RtreeDValue x1 = DCOORD(aCell[0].aCoord[i*2]);
-    RtreeDValue x2 = DCOORD(aCell[0].aCoord[i*2+1]);
-    RtreeDValue x3 = x1;
-    RtreeDValue x4 = x2;
-    int jj;
-
-    int iCellLeft = 0;
-    int iCellRight = 0;
-
-    for(jj=1; jj<nCell; jj++){
-      RtreeDValue left = DCOORD(aCell[jj].aCoord[i*2]);
-      RtreeDValue right = DCOORD(aCell[jj].aCoord[i*2+1]);
-
-      if( left<x1 ) x1 = left;
-      if( right>x4 ) x4 = right;
-      if( left>x3 ){
-        x3 = left;
-        iCellRight = jj;
-      }
-      if( right<x2 ){
-        x2 = right;
-        iCellLeft = jj;
-      }
-    }
-
-    if( x4!=x1 ){
-      RtreeDValue normalwidth = (x3 - x2) / (x4 - x1);
-      if( normalwidth>maxNormalInnerWidth ){
-        iLeftSeed = iCellLeft;
-        iRightSeed = iCellRight;
-      }
-    }
-  }
-
-  *piLeftSeed = iLeftSeed;
-  *piRightSeed = iRightSeed;
-}
-#endif /* VARIANT_GUTTMAN_LINEAR_SPLIT */
-
-#if VARIANT_GUTTMAN_QUADRATIC_SPLIT
-/*
-** Implementation of the quadratic variant of the PickNext() function from
-** Guttman[84].
-*/
-static RtreeCell *QuadraticPickNext(
-  Rtree *pRtree,
-  RtreeCell *aCell, 
-  int nCell, 
-  RtreeCell *pLeftBox, 
-  RtreeCell *pRightBox,
-  int *aiUsed
-){
-  #define FABS(a) ((a)<0.0?-1.0*(a):(a))
-
-  int iSelect = -1;
-  RtreeDValue fDiff;
-  int ii;
-  for(ii=0; ii<nCell; ii++){
-    if( aiUsed[ii]==0 ){
-      RtreeDValue left = cellGrowth(pRtree, pLeftBox, &aCell[ii]);
-      RtreeDValue right = cellGrowth(pRtree, pLeftBox, &aCell[ii]);
-      RtreeDValue diff = FABS(right-left);
-      if( iSelect<0 || diff>fDiff ){
-        fDiff = diff;
-        iSelect = ii;
-      }
-    }
-  }
-  aiUsed[iSelect] = 1;
-  return &aCell[iSelect];
-}
-
-/*
-** Implementation of the quadratic variant of the PickSeeds() function from
-** Guttman[84].
-*/
-static void QuadraticPickSeeds(
-  Rtree *pRtree,
-  RtreeCell *aCell, 
-  int nCell, 
-  int *piLeftSeed, 
-  int *piRightSeed
-){
-  int ii;
-  int jj;
-
-  int iLeftSeed = 0;
-  int iRightSeed = 1;
-  RtreeDValue fWaste = 0.0;
-
-  for(ii=0; ii<nCell; ii++){
-    for(jj=ii+1; jj<nCell; jj++){
-      RtreeDValue right = cellArea(pRtree, &aCell[jj]);
-      RtreeDValue growth = cellGrowth(pRtree, &aCell[ii], &aCell[jj]);
-      RtreeDValue waste = growth - right;
-
-      if( waste>fWaste ){
-        iLeftSeed = ii;
-        iRightSeed = jj;
-        fWaste = waste;
-      }
-    }
-  }
-
-  *piLeftSeed = iLeftSeed;
-  *piRightSeed = iRightSeed;
-}
-#endif /* VARIANT_GUTTMAN_QUADRATIC_SPLIT */
 
 /*
 ** Arguments aIdx, aDistance and aSpare all point to arrays of size
@@ -138337,7 +146735,6 @@ static void SortByDimension(
   }
 }
 
-#if VARIANT_RSTARTREE_SPLIT
 /*
 ** Implementation of the R*-tree variant of SplitNode from Beckman[1990].
 */
@@ -138356,7 +146753,7 @@ static int splitNodeStartree(
 
   int iBestDim = 0;
   int iBestSplit = 0;
-  RtreeDValue fBestMargin = 0.0;
+  RtreeDValue fBestMargin = RTREE_ZERO;
 
   int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
 
@@ -138377,9 +146774,9 @@ static int splitNodeStartree(
   }
 
   for(ii=0; ii<pRtree->nDim; ii++){
-    RtreeDValue margin = 0.0;
-    RtreeDValue fBestOverlap = 0.0;
-    RtreeDValue fBestArea = 0.0;
+    RtreeDValue margin = RTREE_ZERO;
+    RtreeDValue fBestOverlap = RTREE_ZERO;
+    RtreeDValue fBestArea = RTREE_ZERO;
     int iBestLeft = 0;
     int nLeft;
 
@@ -138405,7 +146802,7 @@ static int splitNodeStartree(
       }
       margin += cellMargin(pRtree, &left);
       margin += cellMargin(pRtree, &right);
-      overlap = cellOverlap(pRtree, &left, &right, 1, -1);
+      overlap = cellOverlap(pRtree, &left, &right, 1);
       area = cellArea(pRtree, &left) + cellArea(pRtree, &right);
       if( (nLeft==RTREE_MINCELLS(pRtree))
        || (overlap<fBestOverlap)
@@ -138437,63 +146834,7 @@ static int splitNodeStartree(
   sqlite3_free(aaSorted);
   return SQLITE_OK;
 }
-#endif
 
-#if VARIANT_GUTTMAN_SPLIT
-/*
-** Implementation of the regular R-tree SplitNode from Guttman[1984].
-*/
-static int splitNodeGuttman(
-  Rtree *pRtree,
-  RtreeCell *aCell,
-  int nCell,
-  RtreeNode *pLeft,
-  RtreeNode *pRight,
-  RtreeCell *pBboxLeft,
-  RtreeCell *pBboxRight
-){
-  int iLeftSeed = 0;
-  int iRightSeed = 1;
-  int *aiUsed;
-  int i;
-
-  aiUsed = sqlite3_malloc(sizeof(int)*nCell);
-  if( !aiUsed ){
-    return SQLITE_NOMEM;
-  }
-  memset(aiUsed, 0, sizeof(int)*nCell);
-
-  PickSeeds(pRtree, aCell, nCell, &iLeftSeed, &iRightSeed);
-
-  memcpy(pBboxLeft, &aCell[iLeftSeed], sizeof(RtreeCell));
-  memcpy(pBboxRight, &aCell[iRightSeed], sizeof(RtreeCell));
-  nodeInsertCell(pRtree, pLeft, &aCell[iLeftSeed]);
-  nodeInsertCell(pRtree, pRight, &aCell[iRightSeed]);
-  aiUsed[iLeftSeed] = 1;
-  aiUsed[iRightSeed] = 1;
-
-  for(i=nCell-2; i>0; i--){
-    RtreeCell *pNext;
-    pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed);
-    RtreeDValue diff =  
-      cellGrowth(pRtree, pBboxLeft, pNext) - 
-      cellGrowth(pRtree, pBboxRight, pNext)
-    ;
-    if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i)
-     || (diff>0.0 && (RTREE_MINCELLS(pRtree)-NCELL(pLeft)!=i))
-    ){
-      nodeInsertCell(pRtree, pRight, pNext);
-      cellUnion(pRtree, pBboxRight, pNext);
-    }else{
-      nodeInsertCell(pRtree, pLeft, pNext);
-      cellUnion(pRtree, pBboxLeft, pNext);
-    }
-  }
-
-  sqlite3_free(aiUsed);
-  return SQLITE_OK;
-}
-#endif
 
 static int updateMapping(
   Rtree *pRtree, 
@@ -138571,7 +146912,8 @@ static int SplitNode(
   memset(pLeft->zData, 0, pRtree->iNodeSize);
   memset(pRight->zData, 0, pRtree->iNodeSize);
 
-  rc = AssignCells(pRtree, aCell, nCell, pLeft, pRight, &leftbbox, &rightbbox);
+  rc = splitNodeStartree(pRtree, aCell, nCell, pLeft, pRight,
+                         &leftbbox, &rightbbox);
   if( rc!=SQLITE_OK ){
     goto splitnode_out;
   }
@@ -138854,7 +147196,7 @@ static int Reinsert(
   }
 
   for(ii=0; ii<nCell; ii++){
-    aDistance[ii] = 0.0;
+    aDistance[ii] = RTREE_ZERO;
     for(iDim=0; iDim<pRtree->nDim; iDim++){
       RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - 
                                DCOORD(aCell[ii].aCoord[iDim*2]));
@@ -138920,16 +147262,12 @@ static int rtreeInsertCell(
     }
   }
   if( nodeInsertCell(pRtree, pNode, pCell) ){
-#if VARIANT_RSTARTREE_REINSERT
     if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){
       rc = SplitNode(pRtree, pNode, pCell, iHeight);
     }else{
       pRtree->iReinsertHeight = iHeight;
       rc = Reinsert(pRtree, pNode, pCell, iHeight);
     }
-#else
-    rc = SplitNode(pRtree, pNode, pCell, iHeight);
-#endif
   }else{
     rc = AdjustTree(pRtree, pNode, pCell);
     if( rc==SQLITE_OK ){
@@ -138999,7 +147337,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
   ** about to be deleted. 
   */
   if( rc==SQLITE_OK ){
-    rc = findLeafNode(pRtree, iDelete, &pLeaf);
+    rc = findLeafNode(pRtree, iDelete, &pLeaf, 0);
   }
 
   /* Delete the cell in question from the leaf node. */
@@ -139238,6 +147576,43 @@ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
   return rc;
 }
 
+/*
+** This function populates the pRtree->nRowEst variable with an estimate
+** of the number of rows in the virtual table. If possible, this is based
+** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST.
+*/
+static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
+  const char *zFmt = "SELECT stat FROM %Q.sqlite_stat1 WHERE tbl = '%q_rowid'";
+  char *zSql;
+  sqlite3_stmt *p;
+  int rc;
+  i64 nRow = 0;
+
+  zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
+  if( zSql==0 ){
+    rc = SQLITE_NOMEM;
+  }else{
+    rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0);
+    if( rc==SQLITE_OK ){
+      if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
+      rc = sqlite3_finalize(p);
+    }else if( rc!=SQLITE_NOMEM ){
+      rc = SQLITE_OK;
+    }
+
+    if( rc==SQLITE_OK ){
+      if( nRow==0 ){
+        pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
+      }else{
+        pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
+      }
+    }
+    sqlite3_free(zSql);
+  }
+
+  return rc;
+}
+
 static sqlite3_module rtreeModule = {
   0,                          /* iVersion */
   rtreeCreate,                /* xCreate - create a table */
@@ -139299,7 +147674,8 @@ static int rtreeSqlInit(
     char *zCreate = sqlite3_mprintf(
 "CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);"
 "CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);"
-"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY, parentnode INTEGER);"
+"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,"
+                                  " parentnode INTEGER);"
 "INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))",
       zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize
     );
@@ -139323,6 +147699,7 @@ static int rtreeSqlInit(
   appStmt[7] = &pRtree->pWriteParent;
   appStmt[8] = &pRtree->pDeleteParent;
 
+  rc = rtreeQueryStat1(db, pRtree);
   for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
     char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix);
     if( zSql ){
@@ -139500,6 +147877,8 @@ static int rtreeInit(
   if( rc==SQLITE_OK ){
     *ppVtab = (sqlite3_vtab *)pRtree;
   }else{
+    assert( *ppVtab==0 );
+    assert( pRtree->nBusy==1 );
     rtreeRelease(pRtree);
   }
   return rc;
@@ -139510,10 +147889,10 @@ static int rtreeInit(
 ** Implementation of a scalar function that decodes r-tree nodes to
 ** human readable strings. This can be used for debugging and analysis.
 **
-** The scalar function takes two arguments, a blob of data containing
-** an r-tree node, and the number of dimensions the r-tree indexes.
-** For a two-dimensional r-tree structure called "rt", to deserialize
-** all nodes, a statement like:
+** The scalar function takes two arguments: (1) the number of dimensions
+** to the rtree (between 1 and 5, inclusive) and (2) a blob of data containing
+** an r-tree node.  For a two-dimensional r-tree structure called "rt", to
+** deserialize all nodes, a statement like:
 **
 **   SELECT rtreenode(2, data) FROM rt_node;
 **
@@ -139546,7 +147925,7 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
     nCell = (int)strlen(zCell);
     for(jj=0; jj<tree.nDim*2; jj++){
 #ifndef SQLITE_RTREE_INT_ONLY
-      sqlite3_snprintf(512-nCell,&zCell[nCell], " %f",
+      sqlite3_snprintf(512-nCell,&zCell[nCell], " %g",
                        (double)cell.aCoord[jj].f);
 #else
       sqlite3_snprintf(512-nCell,&zCell[nCell], " %d",
@@ -139567,6 +147946,15 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
   sqlite3_result_text(ctx, zText, -1, sqlite3_free);
 }
 
+/* This routine implements an SQL function that returns the "depth" parameter
+** from the front of a blob that is an r-tree node.  For example:
+**
+**     SELECT rtreedepth(data) FROM rt_node WHERE nodeno=1;
+**
+** The depth value is 0 for all nodes other than the root node, and the root
+** node always has nodeno=1, so the example above is the primary use for this
+** routine.  This routine is intended for testing and analysis only.
+*/
 static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
   UNUSED_PARAMETER(nArg);
   if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB 
@@ -139609,22 +147997,31 @@ SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db){
 }
 
 /*
-** A version of sqlite3_free() that can be used as a callback. This is used
-** in two places - as the destructor for the blob value returned by the
-** invocation of a geometry function, and as the destructor for the geometry
-** functions themselves.
+** This routine deletes the RtreeGeomCallback object that was attached
+** one of the SQL functions create by sqlite3_rtree_geometry_callback()
+** or sqlite3_rtree_query_callback().  In other words, this routine is the
+** destructor for an RtreeGeomCallback objecct.  This routine is called when
+** the corresponding SQL function is deleted.
 */
-static void doSqlite3Free(void *p){
+static void rtreeFreeCallback(void *p){
+  RtreeGeomCallback *pInfo = (RtreeGeomCallback*)p;
+  if( pInfo->xDestructor ) pInfo->xDestructor(pInfo->pContext);
   sqlite3_free(p);
 }
 
 /*
-** Each call to sqlite3_rtree_geometry_callback() creates an ordinary SQLite
-** scalar user function. This C function is the callback used for all such
-** registered SQL functions.
+** Each call to sqlite3_rtree_geometry_callback() or
+** sqlite3_rtree_query_callback() creates an ordinary SQLite
+** scalar function that is implemented by this routine.
+**
+** All this function does is construct an RtreeMatchArg object that
+** contains the geometry-checking callback routines and a list of
+** parameters to this function, then return that RtreeMatchArg object
+** as a BLOB.
 **
-** The scalar user functions return a blob that is interpreted by r-tree
-** table MATCH operators.
+** The R-Tree MATCH operator will read the returned BLOB, deserialize
+** the RtreeMatchArg object, and use the RtreeMatchArg object to figure
+** out which elements of the R-Tree should be returned by the query.
 */
 static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
   RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
@@ -139638,8 +148035,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
   }else{
     int i;
     pBlob->magic = RTREE_GEOMETRY_MAGIC;
-    pBlob->xGeom = pGeomCtx->xGeom;
-    pBlob->pContext = pGeomCtx->pContext;
+    pBlob->cb = pGeomCtx[0];
     pBlob->nParam = nArg;
     for(i=0; i<nArg; i++){
 #ifdef SQLITE_RTREE_INT_ONLY
@@ -139648,7 +148044,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
       pBlob->aParam[i] = sqlite3_value_double(aArg[i]);
 #endif
     }
-    sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free);
+    sqlite3_result_blob(ctx, pBlob, nBlob, sqlite3_free);
   }
 }
 
@@ -139656,10 +148052,10 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
 ** Register a new geometry function for use with the r-tree MATCH operator.
 */
 SQLITE_API int sqlite3_rtree_geometry_callback(
-  sqlite3 *db,
-  const char *zGeom,
-  int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue *, int *),
-  void *pContext
+  sqlite3 *db,                  /* Register SQL function on this connection */
+  const char *zGeom,            /* Name of the new SQL function */
+  int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */
+  void *pContext                /* Extra data associated with the callback */
 ){
   RtreeGeomCallback *pGeomCtx;      /* Context object for new user-function */
 
@@ -139667,17 +148063,44 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
   pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
   if( !pGeomCtx ) return SQLITE_NOMEM;
   pGeomCtx->xGeom = xGeom;
+  pGeomCtx->xQueryFunc = 0;
+  pGeomCtx->xDestructor = 0;
   pGeomCtx->pContext = pContext;
-
-  /* Create the new user-function. Register a destructor function to delete
-  ** the context object when it is no longer required.  */
   return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, 
-      (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free
+      (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback
+  );
+}
+
+/*
+** Register a new 2nd-generation geometry function for use with the
+** r-tree MATCH operator.
+*/
+SQLITE_API int sqlite3_rtree_query_callback(
+  sqlite3 *db,                 /* Register SQL function on this connection */
+  const char *zQueryFunc,      /* Name of new SQL function */
+  int (*xQueryFunc)(sqlite3_rtree_query_info*), /* Callback */
+  void *pContext,              /* Extra data passed into the callback */
+  void (*xDestructor)(void*)   /* Destructor for the extra data */
+){
+  RtreeGeomCallback *pGeomCtx;      /* Context object for new user-function */
+
+  /* Allocate and populate the context object. */
+  pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
+  if( !pGeomCtx ) return SQLITE_NOMEM;
+  pGeomCtx->xGeom = 0;
+  pGeomCtx->xQueryFunc = xQueryFunc;
+  pGeomCtx->xDestructor = xDestructor;
+  pGeomCtx->pContext = pContext;
+  return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY, 
+      (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback
   );
 }
 
 #if !SQLITE_CORE
-SQLITE_API int sqlite3_extension_init(
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+SQLITE_API int sqlite3_rtree_init(
   sqlite3 *db,
   char **pzErrMsg,
   const sqlite3_api_routines *pApi
@@ -139715,7 +148138,7 @@ SQLITE_API int sqlite3_extension_init(
 **   * Implementations of the SQL scalar upper() and lower() functions
 **     for case mapping.
 **
-**   * Integration of ICU and SQLite collation seqences.
+**   * Integration of ICU and SQLite collation sequences.
 **
 **   * An implementation of the LIKE operator that uses ICU to 
 **     provide case-independent matching.
@@ -140179,7 +148602,10 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
 }
 
 #if !SQLITE_CORE
-SQLITE_API int sqlite3_extension_init(
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+SQLITE_API int sqlite3_icu_init(
   sqlite3 *db, 
   char **pzErrMsg,
   const sqlite3_api_routines *pApi
diff --git a/src/sqlite/sqlite3.h b/src/sqlite/sqlite3.h
index e398838..9879f80 100644
--- a/src/sqlite/sqlite3.h
+++ b/src/sqlite/sqlite3.h
@@ -107,9 +107,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.7.17"
-#define SQLITE_VERSION_NUMBER 3007017
-#define SQLITE_SOURCE_ID      "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668"
+#define SQLITE_VERSION        "3.8.6"
+#define SQLITE_VERSION_NUMBER 3008006
+#define SQLITE_SOURCE_ID      "2014-08-15 11:46:33 9491ba7d738528f168657adb43a198238abde19e"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -269,7 +269,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 **
 ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
 ** for the [sqlite3] object.
-** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
+** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
 ** the [sqlite3] object is successfully destroyed and all associated
 ** resources are deallocated.
 **
@@ -277,7 +277,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** statements or unfinished sqlite3_backup objects then sqlite3_close()
 ** will leave the database connection open and return [SQLITE_BUSY].
 ** ^If sqlite3_close_v2() is called with unfinalized prepared statements
-** and unfinished sqlite3_backups, then the database connection becomes
+** and/or unfinished sqlite3_backups, then the database connection becomes
 ** an unusable "zombie" which will automatically be deallocated when the
 ** last prepared statement is finalized or the last sqlite3_backup is
 ** finished.  The sqlite3_close_v2() interface is intended for use with
@@ -290,7 +290,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** with the [sqlite3] object prior to attempting to close the object.  ^If
 ** sqlite3_close_v2() is called on a [database connection] that still has
 ** outstanding [prepared statements], [BLOB handles], and/or
-** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
+** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
 ** of resources is deferred until all [prepared statements], [BLOB handles],
 ** and [sqlite3_backup] objects are also destroyed.
 **
@@ -370,7 +370,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 ** <ul>
 ** <li> The application must insure that the 1st parameter to sqlite3_exec()
 **      is a valid and open [database connection].
-** <li> The application must not close [database connection] specified by
+** <li> The application must not close the [database connection] specified by
 **      the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
 ** <li> The application must not modify the SQL statement text passed into
 **      the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
@@ -386,16 +386,14 @@ SQLITE_API int sqlite3_exec(
 
 /*
 ** CAPI3REF: Result Codes
-** KEYWORDS: SQLITE_OK {error code} {error codes}
-** KEYWORDS: {result code} {result codes}
+** KEYWORDS: {result code definitions}
 **
 ** Many SQLite functions return an integer result code from the set shown
 ** here in order to indicate success or failure.
 **
 ** New error codes may be added in future versions of SQLite.
 **
-** See also: [SQLITE_IOERR_READ | extended result codes],
-** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
+** See also: [extended result code definitions]
 */
 #define SQLITE_OK           0   /* Successful result */
 /* beginning-of-error-codes */
@@ -433,26 +431,19 @@ SQLITE_API int sqlite3_exec(
 
 /*
 ** CAPI3REF: Extended Result Codes
-** KEYWORDS: {extended error code} {extended error codes}
-** KEYWORDS: {extended result code} {extended result codes}
+** KEYWORDS: {extended result code definitions}
 **
-** In its default configuration, SQLite API routines return one of 26 integer
-** [SQLITE_OK | result codes].  However, experience has shown that many of
+** In its default configuration, SQLite API routines return one of 30 integer
+** [result codes].  However, experience has shown that many of
 ** these result codes are too coarse-grained.  They do not provide as
 ** much information about problems as programmers might like.  In an effort to
 ** address this, newer versions of SQLite (version 3.3.8 and later) include
 ** support for additional result codes that provide more detailed information
-** about errors. The extended result codes are enabled or disabled
+** about errors. These [extended result codes] are enabled or disabled
 ** on a per database connection basis using the
-** [sqlite3_extended_result_codes()] API.
-**
-** Some of the available extended result codes are listed here.
-** One may expect the number of extended result codes will be expand
-** over time.  Software that uses extended result codes should expect
-** to see new result codes in future releases of SQLite.
-**
-** The SQLITE_OK result code will never be extended.  It will always
-** be exactly zero.
+** [sqlite3_extended_result_codes()] API.  Or, the extended code for
+** the most recent error can be obtained using
+** [sqlite3_extended_errcode()].
 */
 #define SQLITE_IOERR_READ              (SQLITE_IOERR | (1<<8))
 #define SQLITE_IOERR_SHORT_READ        (SQLITE_IOERR | (2<<8))
@@ -478,15 +469,20 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
 #define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
 #define SQLITE_IOERR_MMAP              (SQLITE_IOERR | (24<<8))
+#define SQLITE_IOERR_GETTEMPPATH       (SQLITE_IOERR | (25<<8))
+#define SQLITE_IOERR_CONVPATH          (SQLITE_IOERR | (26<<8))
 #define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
 #define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
+#define SQLITE_BUSY_SNAPSHOT           (SQLITE_BUSY   |  (2<<8))
 #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
 #define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
 #define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
+#define SQLITE_CANTOPEN_CONVPATH       (SQLITE_CANTOPEN | (4<<8))
 #define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
 #define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
 #define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
 #define SQLITE_READONLY_ROLLBACK       (SQLITE_READONLY | (3<<8))
+#define SQLITE_READONLY_DBMOVED        (SQLITE_READONLY | (4<<8))
 #define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
 #define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
 #define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
@@ -497,8 +493,10 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
 #define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
 #define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
+#define SQLITE_CONSTRAINT_ROWID        (SQLITE_CONSTRAINT |(10<<8))
 #define SQLITE_NOTICE_RECOVER_WAL      (SQLITE_NOTICE | (1<<8))
 #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
+#define SQLITE_WARNING_AUTOINDEX       (SQLITE_WARNING | (1<<8))
 
 /*
 ** CAPI3REF: Flags For File Open Operations
@@ -552,7 +550,11 @@ SQLITE_API int sqlite3_exec(
 ** after reboot following a crash or power loss, the only bytes in a
 ** file that were written at the application level might have changed
 ** and that adjacent bytes, even bytes within the same sector are
-** guaranteed to be unchanged.
+** guaranteed to be unchanged.  The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
+** flag indicate that a file cannot be deleted when open.  The
+** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
+** read-only media and cannot be changed even by processes with
+** elevated privileges.
 */
 #define SQLITE_IOCAP_ATOMIC                 0x00000001
 #define SQLITE_IOCAP_ATOMIC512              0x00000002
@@ -567,6 +569,7 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_IOCAP_SEQUENTIAL             0x00000400
 #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN  0x00000800
 #define SQLITE_IOCAP_POWERSAFE_OVERWRITE    0x00001000
+#define SQLITE_IOCAP_IMMUTABLE              0x00002000
 
 /*
 ** CAPI3REF: File Locking Levels
@@ -673,7 +676,7 @@ struct sqlite3_file {
 ** locking strategy (for example to use dot-file locks), to inquire
 ** about the status of a lock, or to break stale locks.  The SQLite
 ** core reserves all opcodes less than 100 for its own use.
-** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
+** A [file control opcodes | list of opcodes] less than 100 is available.
 ** Applications that define a custom xFileControl method should use opcodes
 ** greater than 100 to avoid conflicts.  VFS implementations should
 ** return [SQLITE_NOTFOUND] for file control opcodes that they do not
@@ -746,6 +749,7 @@ struct sqlite3_io_methods {
 
 /*
 ** CAPI3REF: Standard File Control Opcodes
+** KEYWORDS: {file control opcodes} {file control opcode}
 **
 ** These integer constants are opcodes for the xFileControl method
 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
@@ -783,15 +787,29 @@ struct sqlite3_io_methods {
 ** additional information.
 **
 ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
-** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
-** SQLite and sent to all VFSes in place of a call to the xSync method
-** when the database connection has [PRAGMA synchronous] set to OFF.)^
-** Some specialized VFSes need this signal in order to operate correctly
-** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
-** VFSes do not need this signal and should silently ignore this opcode.
-** Applications should not call [sqlite3_file_control()] with this
-** opcode as doing so may disrupt the operation of the specialized VFSes
-** that do require it.  
+** No longer in use.
+**
+** <li>[[SQLITE_FCNTL_SYNC]]
+** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
+** sent to the VFS immediately before the xSync method is invoked on a
+** database file descriptor. Or, if the xSync method is not invoked 
+** because the user has configured SQLite with 
+** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place 
+** of the xSync method. In most cases, the pointer argument passed with
+** this file-control is NULL. However, if the database file is being synced
+** as part of a multi-database commit, the argument points to a nul-terminated
+** string containing the transactions master-journal file name. VFSes that 
+** do not need this signal should silently ignore this opcode. Applications 
+** should not call [sqlite3_file_control()] with this opcode as doing so may 
+** disrupt the operation of the specialized VFSes that do require it.  
+**
+** <li>[[SQLITE_FCNTL_COMMIT_PHASETWO]]
+** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite
+** and sent to the VFS after a transaction has been committed immediately
+** but before the database is unlocked. VFSes that do not need this signal
+** should silently ignore this opcode. Applications should not call
+** [sqlite3_file_control()] with this opcode as doing so may disrupt the 
+** operation of the specialized VFSes that do require it.  
 **
 ** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
 ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
@@ -907,6 +925,26 @@ struct sqlite3_io_methods {
 ** can be queried by passing in a pointer to a negative number.  This
 ** file-control is used internally to implement [PRAGMA mmap_size].
 **
+** <li>[[SQLITE_FCNTL_TRACE]]
+** The [SQLITE_FCNTL_TRACE] file control provides advisory information
+** to the VFS about what the higher layers of the SQLite stack are doing.
+** This file control is used by some VFS activity tracing [shims].
+** The argument is a zero-terminated string.  Higher layers in the
+** SQLite stack may generate instances of this file control if
+** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled.
+**
+** <li>[[SQLITE_FCNTL_HAS_MOVED]]
+** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
+** pointer to an integer and it writes a boolean into that integer depending
+** on whether or not the file has been renamed, moved, or deleted since it
+** was first opened.
+**
+** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
+** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging.  This
+** opcode causes the xFileControl method to swap the file handle with the one
+** pointed to by the pArg argument.  This capability is used during testing
+** and only needs to be supported when SQLITE_TEST is defined.
+**
 ** </ul>
 */
 #define SQLITE_FCNTL_LOCKSTATE               1
@@ -926,6 +964,11 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_BUSYHANDLER            15
 #define SQLITE_FCNTL_TEMPFILENAME           16
 #define SQLITE_FCNTL_MMAP_SIZE              18
+#define SQLITE_FCNTL_TRACE                  19
+#define SQLITE_FCNTL_HAS_MOVED              20
+#define SQLITE_FCNTL_SYNC                   21
+#define SQLITE_FCNTL_COMMIT_PHASETWO        22
+#define SQLITE_FCNTL_WIN32_SET_HANDLE       23
 
 /*
 ** CAPI3REF: Mutex Handle
@@ -1370,7 +1413,7 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
 ** or [sqlite3_realloc()] first calls xRoundup.  If xRoundup returns 0, 
 ** that causes the corresponding memory allocation to fail.
 **
-** The xInit method initializes the memory allocator.  (For example,
+** The xInit method initializes the memory allocator.  For example,
 ** it might allocate any require mutexes or initialize internal data
 ** structures.  The xShutdown method is invoked (indirectly) by
 ** [sqlite3_shutdown()] and should deallocate any resources acquired
@@ -1612,27 +1655,27 @@ struct sqlite3_mem_methods {
 ** function must be threadsafe. </dd>
 **
 ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
-** <dd> This option takes a single argument of type int. If non-zero, then
+** <dd>^(This option takes a single argument of type int. If non-zero, then
 ** URI handling is globally enabled. If the parameter is zero, then URI handling
-** is globally disabled. If URI handling is globally enabled, all filenames
+** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
 ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
 ** specified as part of [ATTACH] commands are interpreted as URIs, regardless
 ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
-** connection is opened. If it is globally disabled, filenames are
+** connection is opened. ^If it is globally disabled, filenames are
 ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
-** database connection is opened. By default, URI handling is globally
+** database connection is opened. ^(By default, URI handling is globally
 ** disabled. The default value may be changed by compiling with the
-** [SQLITE_USE_URI] symbol defined.
+** [SQLITE_USE_URI] symbol defined.)^
 **
 ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
-** <dd> This option takes a single integer argument which is interpreted as
+** <dd>^This option takes a single integer argument which is interpreted as
 ** a boolean in order to enable or disable the use of covering indices for
-** full table scans in the query optimizer.  The default setting is determined
+** full table scans in the query optimizer.  ^The default setting is determined
 ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
 ** if that compile-time option is omitted.
 ** The ability to disable the use of covering indices for full table scans
 ** is because some incorrectly coded legacy applications might malfunction
-** malfunction when the optimization is enabled.  Providing the ability to
+** when the optimization is enabled.  Providing the ability to
 ** disable the optimization allows the older, buggy application code to work
 ** without change even with newer versions of SQLite.
 **
@@ -1661,17 +1704,24 @@ struct sqlite3_mem_methods {
 **
 ** [[SQLITE_CONFIG_MMAP_SIZE]]
 ** <dt>SQLITE_CONFIG_MMAP_SIZE
-** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
+** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
 ** that are the default mmap size limit (the default setting for
 ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
-** The default setting can be overridden by each database connection using
+** ^The default setting can be overridden by each database connection using
 ** either the [PRAGMA mmap_size] command, or by using the
-** [SQLITE_FCNTL_MMAP_SIZE] file control.  The maximum allowed mmap size
+** [SQLITE_FCNTL_MMAP_SIZE] file control.  ^(The maximum allowed mmap size
 ** cannot be changed at run-time.  Nor may the maximum allowed mmap size
 ** exceed the compile-time maximum mmap size set by the
-** [SQLITE_MAX_MMAP_SIZE] compile-time option.  
-** If either argument to this option is negative, then that argument is
+** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
+** ^If either argument to this option is negative, then that argument is
 ** changed to its compile-time default.
+**
+** [[SQLITE_CONFIG_WIN32_HEAPSIZE]]
+** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
+** <dd>^This option is only available if SQLite is compiled for Windows
+** with the [SQLITE_WIN32_MALLOC] pre-processor macro defined.
+** SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
+** that specifies the maximum size of the created heap.
 ** </dl>
 */
 #define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
@@ -1696,6 +1746,7 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
 #define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
 #define SQLITE_CONFIG_MMAP_SIZE    22  /* sqlite3_int64, sqlite3_int64 */
+#define SQLITE_CONFIG_WIN32_HEAPSIZE      23  /* int nByte */
 
 /*
 ** CAPI3REF: Database Connection Configuration Options
@@ -1772,19 +1823,21 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
 /*
 ** CAPI3REF: Last Insert Rowid
 **
-** ^Each entry in an SQLite table has a unique 64-bit signed
+** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables)
+** has a unique 64-bit signed
 ** integer key called the [ROWID | "rowid"]. ^The rowid is always available
 ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
 ** names are not also used by explicitly declared columns. ^If
 ** the table has a column of type [INTEGER PRIMARY KEY] then that column
 ** is another alias for the rowid.
 **
-** ^This routine returns the [rowid] of the most recent
-** successful [INSERT] into the database from the [database connection]
-** in the first argument.  ^As of SQLite version 3.7.7, this routines
-** records the last insert rowid of both ordinary tables and [virtual tables].
-** ^If no successful [INSERT]s
-** have ever occurred on that database connection, zero is returned.
+** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the 
+** most recent successful [INSERT] into a rowid table or [virtual table]
+** on database connection D.
+** ^Inserts into [WITHOUT ROWID] tables are not recorded.
+** ^If no successful [INSERT]s into rowid tables
+** have ever occurred on the database connection D, 
+** then sqlite3_last_insert_rowid(D) returns zero.
 **
 ** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
 ** method, then this routine will return the [rowid] of the inserted
@@ -1976,27 +2029,33 @@ SQLITE_API int sqlite3_complete16(const void *sql);
 /*
 ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
 **
-** ^This routine sets a callback function that might be invoked whenever
-** an attempt is made to open a database table that another thread
-** or process has locked.
+** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
+** that might be invoked with argument P whenever
+** an attempt is made to access a database table associated with
+** [database connection] D when another thread
+** or process has the table locked.
+** The sqlite3_busy_handler() interface is used to implement
+** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
 **
-** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
+** ^If the busy callback is NULL, then [SQLITE_BUSY]
 ** is returned immediately upon encountering the lock.  ^If the busy callback
 ** is not NULL, then the callback might be invoked with two arguments.
 **
 ** ^The first argument to the busy handler is a copy of the void* pointer which
 ** is the third argument to sqlite3_busy_handler().  ^The second argument to
 ** the busy handler callback is the number of times that the busy handler has
-** been invoked for this locking event.  ^If the
+** been invoked for the same locking event.  ^If the
 ** busy callback returns 0, then no additional attempts are made to
-** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
+** access the database and [SQLITE_BUSY] is returned
+** to the application.
 ** ^If the callback returns non-zero, then another attempt
-** is made to open the database for reading and the cycle repeats.
+** is made to access the database and the cycle repeats.
 **
 ** The presence of a busy handler does not guarantee that it will be invoked
 ** when there is lock contention. ^If SQLite determines that invoking the busy
 ** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
-** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
+** to the application instead of invoking the 
+** busy handler.
 ** Consider a scenario where one process is holding a read lock that
 ** it is trying to promote to a reserved lock and
 ** a second process is holding a reserved lock that it is trying
@@ -2010,28 +2069,15 @@ SQLITE_API int sqlite3_complete16(const void *sql);
 **
 ** ^The default busy callback is NULL.
 **
-** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
-** when SQLite is in the middle of a large transaction where all the
-** changes will not fit into the in-memory cache.  SQLite will
-** already hold a RESERVED lock on the database file, but it needs
-** to promote this lock to EXCLUSIVE so that it can spill cache
-** pages into the database file without harm to concurrent
-** readers.  ^If it is unable to promote the lock, then the in-memory
-** cache will be left in an inconsistent state and so the error
-** code is promoted from the relatively benign [SQLITE_BUSY] to
-** the more severe [SQLITE_IOERR_BLOCKED].  ^This error code promotion
-** forces an automatic rollback of the changes.  See the
-** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
-** CorruptionFollowingBusyError</a> wiki page for a discussion of why
-** this is important.
-**
 ** ^(There can only be a single busy handler defined for each
 ** [database connection].  Setting a new busy handler clears any
 ** previously set handler.)^  ^Note that calling [sqlite3_busy_timeout()]
-** will also set or clear the busy handler.
+** or evaluating [PRAGMA busy_timeout=N] will change the
+** busy handler and thus clear any previously set busy handler.
 **
 ** The busy callback should not take any actions which modify the
-** database connection that invoked the busy handler.  Any such actions
+** database connection that invoked the busy handler.  In other words,
+** the busy handler is not reentrant.  Any such actions
 ** result in undefined behavior.
 ** 
 ** A busy handler must not close the database connection
@@ -2047,7 +2093,7 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
 ** will sleep multiple times until at least "ms" milliseconds of sleeping
 ** have accumulated.  ^After at least "ms" milliseconds of sleeping,
 ** the handler returns 0 which causes [sqlite3_step()] to return
-** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
+** [SQLITE_BUSY].
 **
 ** ^Calling this routine with an argument less than or equal to zero
 ** turns off all busy handlers.
@@ -2056,6 +2102,8 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
 ** [database connection] any any given moment.  If another busy handler
 ** was defined  (using [sqlite3_busy_handler()]) prior to calling
 ** this routine, that other busy handler is cleared.)^
+**
+** See also:  [PRAGMA busy_timeout]
 */
 SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
 
@@ -2350,11 +2398,13 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
 ** applications to access the same PRNG for other purposes.
 **
 ** ^A call to this routine stores N bytes of randomness into buffer P.
+** ^If N is less than one, then P can be a NULL pointer.
 **
-** ^The first time this routine is invoked (either internally or by
-** the application) the PRNG is seeded using randomness obtained
-** from the xRandomness method of the default [sqlite3_vfs] object.
-** ^On all subsequent invocations, the pseudo-randomness is generated
+** ^If this routine has not been previously called or if the previous
+** call had N less than one, then the PRNG is seeded using randomness
+** obtained from the xRandomness method of the default [sqlite3_vfs] object.
+** ^If the previous call to this routine had an N of 1 or more then
+** the pseudo-randomness is generated
 ** internally and without recourse to the [sqlite3_vfs] xRandomness
 ** method.
 */
@@ -2455,8 +2505,8 @@ SQLITE_API int sqlite3_set_authorizer(
 ** [sqlite3_set_authorizer | authorizer documentation] for additional
 ** information.
 **
-** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
-** from the [sqlite3_vtab_on_conflict()] interface.
+** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
+** returned from the [sqlite3_vtab_on_conflict()] interface.
 */
 #define SQLITE_DENY   1   /* Abort the SQL statement with an error */
 #define SQLITE_IGNORE 2   /* Don't allow access, but don't generate an error */
@@ -2514,6 +2564,7 @@ SQLITE_API int sqlite3_set_authorizer(
 #define SQLITE_FUNCTION             31   /* NULL            Function Name   */
 #define SQLITE_SAVEPOINT            32   /* Operation       Savepoint Name  */
 #define SQLITE_COPY                  0   /* No longer used */
+#define SQLITE_RECURSIVE            33   /* NULL            NULL            */
 
 /*
 ** CAPI3REF: Tracing And Profiling Functions
@@ -2557,9 +2608,10 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
 ** interface is to keep a GUI updated during a large query.
 **
 ** ^The parameter P is passed through as the only parameter to the 
-** callback function X.  ^The parameter N is the number of 
+** callback function X.  ^The parameter N is the approximate number of 
 ** [virtual machine instructions] that are evaluated between successive
-** invocations of the callback X.
+** invocations of the callback X.  ^If N is less than one then the progress
+** handler is disabled.
 **
 ** ^Only a single progress handler may be defined at one time per
 ** [database connection]; setting a new progress handler cancels the
@@ -2725,6 +2777,30 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
 **     a URI filename, its value overrides any behavior requested by setting
 **     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
+**
+**  <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
+**     "1") or "false" (or "off" or "no" or "0") to indicate that the
+**     [powersafe overwrite] property does or does not apply to the
+**     storage media on which the database file resides.  ^The psow query
+**     parameter only works for the built-in unix and Windows VFSes.
+**
+**  <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
+**     which if set disables file locking in rollback journal modes.  This
+**     is useful for accessing a database on a filesystem that does not
+**     support locking.  Caution:  Database corruption might result if two
+**     or more processes write to the same database and any one of those
+**     processes uses nolock=1.
+**
+**  <li> <b>immutable</b>: ^The immutable parameter is a boolean query
+**     parameter that indicates that the database file is stored on
+**     read-only media.  ^When immutable is set, SQLite assumes that the
+**     database file cannot be changed, even by a process with higher
+**     privilege, and so the database is opened read-only and all locking
+**     and change detection is disabled.  Caution: Setting the immutable
+**     property on a database file that does in fact change can result
+**     in incorrect query results and/or [SQLITE_CORRUPT] errors.
+**     See also: [SQLITE_IOCAP_IMMUTABLE].
+**       
 ** </ul>
 **
 ** ^Specifying an unknown parameter in the query component of a URI is not an
@@ -2754,8 +2830,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **          Open file "data.db" in the current directory for read-only access.
 **          Regardless of whether or not shared-cache mode is enabled by
 **          default, use a private cache.
-** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
-**          Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
+** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
+**          Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
+**          that uses dot-files in place of posix advisory locking.
 ** <tr><td> file:data.db?mode=readonly <td> 
 **          An error. "readonly" is not a valid option for the "mode" parameter.
 ** </table>
@@ -3093,7 +3170,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
 ** choice of query plan if the parameter is the left-hand side of a [LIKE]
 ** or [GLOB] operator or if the parameter is compared to an indexed column
 ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
-** the 
 ** </li>
 ** </ol>
 */
@@ -3755,19 +3831,19 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
 **
 ** <tr><td>  NULL    <td> INTEGER   <td> Result is 0
 ** <tr><td>  NULL    <td>  FLOAT    <td> Result is 0.0
-** <tr><td>  NULL    <td>   TEXT    <td> Result is NULL pointer
-** <tr><td>  NULL    <td>   BLOB    <td> Result is NULL pointer
+** <tr><td>  NULL    <td>   TEXT    <td> Result is a NULL pointer
+** <tr><td>  NULL    <td>   BLOB    <td> Result is a NULL pointer
 ** <tr><td> INTEGER  <td>  FLOAT    <td> Convert from integer to float
 ** <tr><td> INTEGER  <td>   TEXT    <td> ASCII rendering of the integer
 ** <tr><td> INTEGER  <td>   BLOB    <td> Same as INTEGER->TEXT
-** <tr><td>  FLOAT   <td> INTEGER   <td> Convert from float to integer
+** <tr><td>  FLOAT   <td> INTEGER   <td> [CAST] to INTEGER
 ** <tr><td>  FLOAT   <td>   TEXT    <td> ASCII rendering of the float
-** <tr><td>  FLOAT   <td>   BLOB    <td> Same as FLOAT->TEXT
-** <tr><td>  TEXT    <td> INTEGER   <td> Use atoi()
-** <tr><td>  TEXT    <td>  FLOAT    <td> Use atof()
+** <tr><td>  FLOAT   <td>   BLOB    <td> [CAST] to BLOB
+** <tr><td>  TEXT    <td> INTEGER   <td> [CAST] to INTEGER
+** <tr><td>  TEXT    <td>  FLOAT    <td> [CAST] to REAL
 ** <tr><td>  TEXT    <td>   BLOB    <td> No change
-** <tr><td>  BLOB    <td> INTEGER   <td> Convert to TEXT then use atoi()
-** <tr><td>  BLOB    <td>  FLOAT    <td> Convert to TEXT then use atof()
+** <tr><td>  BLOB    <td> INTEGER   <td> [CAST] to INTEGER
+** <tr><td>  BLOB    <td>  FLOAT    <td> [CAST] to REAL
 ** <tr><td>  BLOB    <td>   TEXT    <td> Add a zero terminator if needed
 ** </table>
 ** </blockquote>)^
@@ -3823,7 +3899,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
 ** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
 ** [sqlite3_finalize()] is called.  ^The memory space used to hold strings
 ** and BLOBs is freed automatically.  Do <b>not</b> pass the pointers returned
-** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
+** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
 ** [sqlite3_free()].
 **
 ** ^(If a memory allocation error occurs during the evaluation of any
@@ -3932,15 +4008,24 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
 **
 ** ^The fourth parameter, eTextRep, specifies what
 ** [SQLITE_UTF8 | text encoding] this SQL function prefers for
-** its parameters.  Every SQL function implementation must be able to work
-** with UTF-8, UTF-16le, or UTF-16be.  But some implementations may be
-** more efficient with one encoding than another.  ^An application may
-** invoke sqlite3_create_function() or sqlite3_create_function16() multiple
-** times with the same function but with different values of eTextRep.
+** its parameters.  The application should set this parameter to
+** [SQLITE_UTF16LE] if the function implementation invokes 
+** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the
+** implementation invokes [sqlite3_value_text16be()] on an input, or
+** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8]
+** otherwise.  ^The same SQL function may be registered multiple times using
+** different preferred text encodings, with different implementations for
+** each encoding.
 ** ^When multiple implementations of the same function are available, SQLite
 ** will pick the one that involves the least amount of data conversion.
-** If there is only a single implementation which does not care what text
-** encoding is used, then the fourth argument should be [SQLITE_ANY].
+**
+** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC]
+** to signal that the function will always return the same result given
+** the same inputs within a single SQL statement.  Most SQL functions are
+** deterministic.  The built-in [random()] SQL function is an example of a
+** function that is not deterministic.  The SQLite query planner is able to
+** perform additional optimizations on deterministic functions, so use
+** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
 **
 ** ^(The fifth parameter is an arbitrary pointer.  The implementation of the
 ** function can gain access to this pointer using [sqlite3_user_data()].)^
@@ -4026,10 +4111,20 @@ SQLITE_API int sqlite3_create_function_v2(
 #define SQLITE_UTF16LE        2
 #define SQLITE_UTF16BE        3
 #define SQLITE_UTF16          4    /* Use native byte order */
-#define SQLITE_ANY            5    /* sqlite3_create_function only */
+#define SQLITE_ANY            5    /* Deprecated */
 #define SQLITE_UTF16_ALIGNED  8    /* sqlite3_create_collation only */
 
 /*
+** CAPI3REF: Function Flags
+**
+** These constants may be ORed together with the 
+** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
+** to [sqlite3_create_function()], [sqlite3_create_function16()], or
+** [sqlite3_create_function_v2()].
+*/
+#define SQLITE_DETERMINISTIC    0x800
+
+/*
 ** CAPI3REF: Deprecated Functions
 ** DEPRECATED
 **
@@ -4179,41 +4274,49 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
 /*
 ** CAPI3REF: Function Auxiliary Data
 **
-** The following two functions may be used by scalar SQL functions to
+** These functions may be used by (non-aggregate) SQL functions to
 ** associate metadata with argument values. If the same value is passed to
 ** multiple invocations of the same SQL function during query execution, under
-** some circumstances the associated metadata may be preserved. This may
-** be used, for example, to add a regular-expression matching scalar
-** function. The compiled version of the regular expression is stored as
-** metadata associated with the SQL value passed as the regular expression
-** pattern.  The compiled regular expression can be reused on multiple
-** invocations of the same function so that the original pattern string
-** does not need to be recompiled on each invocation.
+** some circumstances the associated metadata may be preserved.  An example
+** of where this might be useful is in a regular-expression matching
+** function. The compiled version of the regular expression can be stored as
+** metadata associated with the pattern string.  
+** Then as long as the pattern string remains the same,
+** the compiled regular expression can be reused on multiple
+** invocations of the same function.
 **
 ** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
 ** associated by the sqlite3_set_auxdata() function with the Nth argument
-** value to the application-defined function. ^If no metadata has been ever
-** been set for the Nth argument of the function, or if the corresponding
-** function parameter has changed since the meta-data was set,
-** then sqlite3_get_auxdata() returns a NULL pointer.
-**
-** ^The sqlite3_set_auxdata() interface saves the metadata
-** pointed to by its 3rd parameter as the metadata for the N-th
-** argument of the application-defined function.  Subsequent
-** calls to sqlite3_get_auxdata() might return this data, if it has
-** not been destroyed.
-** ^If it is not NULL, SQLite will invoke the destructor
-** function given by the 4th parameter to sqlite3_set_auxdata() on
-** the metadata when the corresponding function parameter changes
-** or when the SQL statement completes, whichever comes first.
-**
-** SQLite is free to call the destructor and drop metadata on any
-** parameter of any function at any time.  ^The only guarantee is that
-** the destructor will be called before the metadata is dropped.
+** value to the application-defined function. ^If there is no metadata
+** associated with the function argument, this sqlite3_get_auxdata() interface
+** returns a NULL pointer.
+**
+** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
+** argument of the application-defined function.  ^Subsequent
+** calls to sqlite3_get_auxdata(C,N) return P from the most recent
+** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
+** NULL if the metadata has been discarded.
+** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
+** SQLite will invoke the destructor function X with parameter P exactly
+** once, when the metadata is discarded.
+** SQLite is free to discard the metadata at any time, including: <ul>
+** <li> when the corresponding function parameter changes, or
+** <li> when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
+**      SQL statement, or
+** <li> when sqlite3_set_auxdata() is invoked again on the same parameter, or
+** <li> during the original sqlite3_set_auxdata() call when a memory 
+**      allocation error occurs. </ul>)^
+**
+** Note the last bullet in particular.  The destructor X in 
+** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
+** sqlite3_set_auxdata() interface even returns.  Hence sqlite3_set_auxdata()
+** should be called near the end of the function implementation and the
+** function implementation should not make any use of P after
+** sqlite3_set_auxdata() has been called.
 **
 ** ^(In practice, metadata is preserved between function calls for
-** expressions that are constant at compile time. This includes literal
-** values and [parameters].)^
+** function parameters that are compile-time constants, including literal
+** values and [parameters] and expressions composed from the same.)^
 **
 ** These routines must be called from the same thread in which
 ** the SQL function is running.
@@ -4518,6 +4621,11 @@ SQLITE_API int sqlite3_key(
   sqlite3 *db,                   /* Database to be rekeyed */
   const void *pKey, int nKey     /* The key */
 );
+SQLITE_API int sqlite3_key_v2(
+  sqlite3 *db,                   /* Database to be rekeyed */
+  const char *zDbName,           /* Name of the database */
+  const void *pKey, int nKey     /* The key */
+);
 
 /*
 ** Change the key on an open database.  If the current database is not
@@ -4531,6 +4639,11 @@ SQLITE_API int sqlite3_rekey(
   sqlite3 *db,                   /* Database to be rekeyed */
   const void *pKey, int nKey     /* The new key */
 );
+SQLITE_API int sqlite3_rekey_v2(
+  sqlite3 *db,                   /* Database to be rekeyed */
+  const char *zDbName,           /* Name of the database */
+  const void *pKey, int nKey     /* The new key */
+);
 
 /*
 ** Specify the activation key for a SEE database.  Unless 
@@ -4580,6 +4693,13 @@ SQLITE_API int sqlite3_sleep(int);
 ** is a NULL pointer, then SQLite performs a search for an appropriate
 ** temporary file directory.
 **
+** Applications are strongly discouraged from using this global variable.
+** It is required to set a temporary folder on Windows Runtime (WinRT).
+** But for all other platforms, it is highly recommended that applications
+** neither read nor write this variable.  This global variable is a relic
+** that exists for backwards compatibility of legacy applications and should
+** be avoided in new projects.
+**
 ** It is not safe to read or modify this variable in more than one
 ** thread at a time.  It is not safe to read or modify this variable
 ** if a [database connection] is being used at the same time in a separate
@@ -4598,6 +4718,11 @@ SQLITE_API int sqlite3_sleep(int);
 ** Hence, if this variable is modified directly, either it should be
 ** made NULL or made to point to memory obtained from [sqlite3_malloc]
 ** or else the use of the [temp_store_directory pragma] should be avoided.
+** Except when requested by the [temp_store_directory pragma], SQLite
+** does not free the memory that sqlite3_temp_directory points to.  If
+** the application wants that memory to be freed, it must do
+** so itself, taking care to only do so after all [database connection]
+** objects have been destroyed.
 **
 ** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
 ** prior to calling [sqlite3_open] or [sqlite3_open_v2].  Otherwise, various
@@ -4782,12 +4907,13 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
 **
 ** ^The sqlite3_update_hook() interface registers a callback function
 ** with the [database connection] identified by the first argument
-** to be invoked whenever a row is updated, inserted or deleted.
+** to be invoked whenever a row is updated, inserted or deleted in
+** a rowid table.
 ** ^Any callback set by a previous call to this function
 ** for the same database connection is overridden.
 **
 ** ^The second argument is a pointer to the function to invoke when a
-** row is updated, inserted or deleted.
+** row is updated, inserted or deleted in a rowid table.
 ** ^The first argument to the callback is a copy of the third argument
 ** to sqlite3_update_hook().
 ** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
@@ -4800,6 +4926,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
 **
 ** ^(The update hook is not invoked when internal system tables are
 ** modified (i.e. sqlite_master and sqlite_sequence).)^
+** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
 **
 ** ^In the current implementation, the update hook
 ** is not invoked when duplication rows are deleted because of an
@@ -4881,8 +5008,8 @@ SQLITE_API int sqlite3_release_memory(int);
 **
 ** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
 ** memory as possible from database connection D. Unlike the
-** [sqlite3_release_memory()] interface, this interface is effect even
-** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
+** [sqlite3_release_memory()] interface, this interface is in effect even
+** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
 ** omitted.
 **
 ** See also: [sqlite3_release_memory()]
@@ -5116,11 +5243,24 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
 ** on the list of automatic extensions is a harmless no-op. ^No entry point
 ** will be called more than once for each database connection that is opened.
 **
-** See also: [sqlite3_reset_auto_extension()].
+** See also: [sqlite3_reset_auto_extension()]
+** and [sqlite3_cancel_auto_extension()]
 */
 SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
 
 /*
+** CAPI3REF: Cancel Automatic Extension Loading
+**
+** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
+** initialization routine X that was registered using a prior call to
+** [sqlite3_auto_extension(X)].  ^The [sqlite3_cancel_auto_extension(X)]
+** routine returns 1 if initialization routine X was successfully 
+** unregistered and it returns 0 if X was not on the list of initialization
+** routines.
+*/
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
+
+/*
 ** CAPI3REF: Reset Automatic Extension Loading
 **
 ** ^This interface disables all automatic extensions previously
@@ -5244,10 +5384,22 @@ struct sqlite3_module {
 ** the correct order to satisfy the ORDER BY clause so that no separate
 ** sorting step is required.
 **
-** ^The estimatedCost value is an estimate of the cost of doing the
-** particular lookup.  A full scan of a table with N entries should have
-** a cost of N.  A binary search of a table of N entries should have a
-** cost of approximately log(N).
+** ^The estimatedCost value is an estimate of the cost of a particular
+** strategy. A cost of N indicates that the cost of the strategy is similar
+** to a linear scan of an SQLite table with N rows. A cost of log(N) 
+** indicates that the expense of the operation is similar to that of a
+** binary search on a unique indexed field of an SQLite table with N rows.
+**
+** ^The estimatedRows value is an estimate of the number of rows that
+** will be returned by the strategy.
+**
+** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
+** structure for SQLite version 3.8.2. If a virtual table extension is
+** used with an SQLite version earlier than 3.8.2, the results of attempting 
+** to read or write the estimatedRows field are undefined (but are likely 
+** to included crashing the application). The estimatedRows field should
+** therefore only be used if [sqlite3_libversion_number()] returns a
+** value greater than or equal to 3008002.
 */
 struct sqlite3_index_info {
   /* Inputs */
@@ -5272,7 +5424,9 @@ struct sqlite3_index_info {
   char *idxStr;              /* String, possibly obtained from sqlite3_malloc */
   int needToFreeIdxStr;      /* Free idxStr using sqlite3_free() if true */
   int orderByConsumed;       /* True if output is already ordered */
-  double estimatedCost;      /* Estimated cost of using this index */
+  double estimatedCost;           /* Estimated cost of using this index */
+  /* Fields below are only available in SQLite 3.8.2 and later */
+  sqlite3_int64 estimatedRows;    /* Estimated number of rows returned */
 };
 
 /*
@@ -5476,6 +5630,9 @@ typedef struct sqlite3_blob sqlite3_blob;
 ** interface.  Use the [UPDATE] SQL command to change the size of a
 ** blob.
 **
+** ^The [sqlite3_blob_open()] interface will fail for a [WITHOUT ROWID]
+** table.  Incremental BLOB I/O is not possible on [WITHOUT ROWID] tables.
+**
 ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
 ** and the built-in [zeroblob] SQL function can be used, if desired,
 ** to create an empty, zero-filled blob in which to read or write using
@@ -5700,10 +5857,12 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
 ** <li>  SQLITE_MUTEX_RECURSIVE
 ** <li>  SQLITE_MUTEX_STATIC_MASTER
 ** <li>  SQLITE_MUTEX_STATIC_MEM
-** <li>  SQLITE_MUTEX_STATIC_MEM2
+** <li>  SQLITE_MUTEX_STATIC_OPEN
 ** <li>  SQLITE_MUTEX_STATIC_PRNG
 ** <li>  SQLITE_MUTEX_STATIC_LRU
-** <li>  SQLITE_MUTEX_STATIC_LRU2
+** <li>  SQLITE_MUTEX_STATIC_PMEM
+** <li>  SQLITE_MUTEX_STATIC_APP1
+** <li>  SQLITE_MUTEX_STATIC_APP2
 ** </ul>)^
 **
 ** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
@@ -5907,6 +6066,9 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
 #define SQLITE_MUTEX_STATIC_LRU       6  /* lru page list */
 #define SQLITE_MUTEX_STATIC_LRU2      7  /* NOT USED */
 #define SQLITE_MUTEX_STATIC_PMEM      7  /* sqlite3PageMalloc() */
+#define SQLITE_MUTEX_STATIC_APP1      8  /* For use by application */
+#define SQLITE_MUTEX_STATIC_APP2      9  /* For use by application */
+#define SQLITE_MUTEX_STATIC_APP3     10  /* For use by application */
 
 /*
 ** CAPI3REF: Retrieve the mutex for a database connection
@@ -5999,7 +6161,11 @@ SQLITE_API int sqlite3_test_control(int op, ...);
 #define SQLITE_TESTCTRL_SCRATCHMALLOC           17
 #define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
 #define SQLITE_TESTCTRL_EXPLAIN_STMT            19
-#define SQLITE_TESTCTRL_LAST                    19
+#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
+#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
+#define SQLITE_TESTCTRL_BYTEORDER               22
+#define SQLITE_TESTCTRL_ISINIT                  23
+#define SQLITE_TESTCTRL_LAST                    23
 
 /*
 ** CAPI3REF: SQLite Runtime Status
@@ -6232,6 +6398,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
 ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
 ** </dd>
+**
+** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
+** <dd>This parameter returns zero for the current value if and only if
+** all foreign key constraints (deferred or immediate) have been
+** resolved.)^  ^The highwater mark is always 0.
+** </dd>
 ** </dl>
 */
 #define SQLITE_DBSTATUS_LOOKASIDE_USED       0
@@ -6244,7 +6416,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
 #define SQLITE_DBSTATUS_CACHE_HIT            7
 #define SQLITE_DBSTATUS_CACHE_MISS           8
 #define SQLITE_DBSTATUS_CACHE_WRITE          9
-#define SQLITE_DBSTATUS_MAX                  9   /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_DEFERRED_FKS        10
+#define SQLITE_DBSTATUS_MAX                 10   /* Largest defined DBSTATUS */
 
 
 /*
@@ -6298,11 +6471,21 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
 ** A non-zero value in this counter may indicate an opportunity to
 ** improvement performance by adding permanent indices that do not
 ** need to be reinitialized each time the statement is run.</dd>
+**
+** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
+** <dd>^This is the number of virtual machine operations executed
+** by the prepared statement if that number is less than or equal
+** to 2147483647.  The number of virtual machine operations can be 
+** used as a proxy for the total work done by the prepared statement.
+** If the number of virtual machine operations exceeds 2147483647
+** then the value returned by this statement status code is undefined.
+** </dd>
 ** </dl>
 */
 #define SQLITE_STMTSTATUS_FULLSCAN_STEP     1
 #define SQLITE_STMTSTATUS_SORT              2
 #define SQLITE_STMTSTATUS_AUTOINDEX         3
+#define SQLITE_STMTSTATUS_VM_STEP           4
 
 /*
 ** CAPI3REF: Custom Page Cache Object
@@ -6966,6 +7149,9 @@ SQLITE_API void *sqlite3_wal_hook(
 ** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
 ** from SQL.
 **
+** ^Checkpoints initiated by this mechanism are
+** [sqlite3_wal_checkpoint_v2|PASSIVE].
+**
 ** ^Every new [database connection] defaults to having the auto-checkpoint
 ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
 ** pages.  The use of this interface
@@ -6982,6 +7168,10 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
 ** empty string, then a checkpoint is run on all databases of
 ** connection D.  ^If the database connection D is not in
 ** [WAL | write-ahead log mode] then this interface is a harmless no-op.
+** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
+** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
+** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
+** or RESET checkpoint.
 **
 ** ^The [wal_checkpoint pragma] can be used to invoke this interface
 ** from SQL.  ^The [sqlite3_wal_autocheckpoint()] interface and the
@@ -7004,10 +7194,12 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
 **   Checkpoint as many frames as possible without waiting for any database 
 **   readers or writers to finish. Sync the db file if all frames in the log
 **   are checkpointed. This mode is the same as calling 
-**   sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
+**   sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
+**   is never invoked.
 **
 ** <dt>SQLITE_CHECKPOINT_FULL<dd>
-**   This mode blocks (calls the busy-handler callback) until there is no
+**   This mode blocks (it invokes the
+**   [sqlite3_busy_handler|busy-handler callback]) until there is no
 **   database writer and all readers are reading from the most recent database
 **   snapshot. It then checkpoints all frames in the log file and syncs the
 **   database file. This call blocks database writers while it is running,
@@ -7015,7 +7207,8 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
 **
 ** <dt>SQLITE_CHECKPOINT_RESTART<dd>
 **   This mode works the same way as SQLITE_CHECKPOINT_FULL, except after 
-**   checkpointing the log file it blocks (calls the busy-handler callback)
+**   checkpointing the log file it blocks (calls the 
+**   [sqlite3_busy_handler|busy-handler callback])
 **   until all readers are reading from the database file only. This ensures 
 **   that the next client to write to the database file restarts the log file 
 **   from the beginning. This call blocks database writers while it is running,
@@ -7153,6 +7346,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
 
 /*
 ** CAPI3REF: Conflict resolution modes
+** KEYWORDS: {conflict resolution mode}
 **
 ** These constants are returned by [sqlite3_vtab_on_conflict()] to
 ** inform a [virtual table] implementation what the [ON CONFLICT] mode
@@ -7181,7 +7375,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
 #ifdef __cplusplus
 }  /* End of the 'extern "C"' block */
 #endif
-#endif
+#endif /* _SQLITE3_H_ */
 
 /*
 ** 2010 August 30
@@ -7205,6 +7399,16 @@ extern "C" {
 #endif
 
 typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
+typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
+
+/* The double-precision datatype used by RTree depends on the
+** SQLITE_RTREE_INT_ONLY compile-time option.
+*/
+#ifdef SQLITE_RTREE_INT_ONLY
+  typedef sqlite3_int64 sqlite3_rtree_dbl;
+#else
+  typedef double sqlite3_rtree_dbl;
+#endif
 
 /*
 ** Register a geometry callback named zGeom that can be used as part of an
@@ -7215,11 +7419,7 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
 SQLITE_API int sqlite3_rtree_geometry_callback(
   sqlite3 *db,
   const char *zGeom,
-#ifdef SQLITE_RTREE_INT_ONLY
-  int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
-#else
-  int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
-#endif
+  int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
   void *pContext
 );
 
@@ -7231,11 +7431,60 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
 struct sqlite3_rtree_geometry {
   void *pContext;                 /* Copy of pContext passed to s_r_g_c() */
   int nParam;                     /* Size of array aParam[] */
-  double *aParam;                 /* Parameters passed to SQL geom function */
+  sqlite3_rtree_dbl *aParam;      /* Parameters passed to SQL geom function */
   void *pUser;                    /* Callback implementation user data */
   void (*xDelUser)(void *);       /* Called by SQLite to clean up pUser */
 };
 
+/*
+** Register a 2nd-generation geometry callback named zScore that can be 
+** used as part of an R-Tree geometry query as follows:
+**
+**   SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
+*/
+SQLITE_API int sqlite3_rtree_query_callback(
+  sqlite3 *db,
+  const char *zQueryFunc,
+  int (*xQueryFunc)(sqlite3_rtree_query_info*),
+  void *pContext,
+  void (*xDestructor)(void*)
+);
+
+
+/*
+** A pointer to a structure of the following type is passed as the 
+** argument to scored geometry callback registered using
+** sqlite3_rtree_query_callback().
+**
+** Note that the first 5 fields of this structure are identical to
+** sqlite3_rtree_geometry.  This structure is a subclass of
+** sqlite3_rtree_geometry.
+*/
+struct sqlite3_rtree_query_info {
+  void *pContext;                   /* pContext from when function registered */
+  int nParam;                       /* Number of function parameters */
+  sqlite3_rtree_dbl *aParam;        /* value of function parameters */
+  void *pUser;                      /* callback can use this, if desired */
+  void (*xDelUser)(void*);          /* function to free pUser */
+  sqlite3_rtree_dbl *aCoord;        /* Coordinates of node or entry to check */
+  unsigned int *anQueue;            /* Number of pending entries in the queue */
+  int nCoord;                       /* Number of coordinates */
+  int iLevel;                       /* Level of current node or entry */
+  int mxLevel;                      /* The largest iLevel value in the tree */
+  sqlite3_int64 iRowid;             /* Rowid for current entry */
+  sqlite3_rtree_dbl rParentScore;   /* Score of parent node */
+  int eParentWithin;                /* Visibility of parent node */
+  int eWithin;                      /* OUT: Visiblity */
+  sqlite3_rtree_dbl rScore;         /* OUT: Write the score here */
+};
+
+/*
+** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
+*/
+#define NOT_WITHIN       0   /* Object completely outside of query region */
+#define PARTLY_WITHIN    1   /* Object partially overlaps query region */
+#define FULLY_WITHIN     2   /* Object fully contained within query region */
+
 
 #ifdef __cplusplus
 }  /* end of the 'extern "C"' block */
diff --git a/src/sqlite/sqlite3ext.h b/src/sqlite/sqlite3ext.h
index 928bb3b..ecf93f6 100644
--- a/src/sqlite/sqlite3ext.h
+++ b/src/sqlite/sqlite3ext.h
@@ -474,11 +474,14 @@ struct sqlite3_api_routines {
   ** extension */
 # define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
 # define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;
+# define SQLITE_EXTENSION_INIT3     \
+    extern const sqlite3_api_routines *sqlite3_api;
 #else
   /* This case when the file is being statically linked into the 
   ** application */
 # define SQLITE_EXTENSION_INIT1     /*no-op*/
 # define SQLITE_EXTENSION_INIT2(v)  (void)v; /* unused parameter */
+# define SQLITE_EXTENSION_INIT3     /*no-op*/
 #endif
 
 #endif /* _SQLITE3EXT_H_ */
diff --git a/src/test-dbDisconnect.R b/src/test-dbDisconnect.R
new file mode 100644
index 0000000..d37eb73
--- /dev/null
+++ b/src/test-dbDisconnect.R
@@ -0,0 +1,18 @@
+context("dbDiscconect")
+
+test_that("closes result set with warning", {
+  con <- dbConnect(SQLite())
+  dbSendQuery(con, "CREATE TABLE mytable (integer a)")
+  
+  expect_warning(dbDisconnect(con), "closing automatically")
+})
+
+test_that("connections are finalised", {
+  dbs <- lapply(1:50, function(x) {
+    dbConnect(SQLite(), dbname = ":memory:")
+  })
+  expect_equal(dbGetInfo(SQLite())$num_con, 50)
+
+  rm(dbs); gc()
+  expect_equal(dbGetInfo(SQLite())$num_con, 0)
+}) 
diff --git a/src/utils.c b/src/utils.c
new file mode 100644
index 0000000..c8437ac
--- /dev/null
+++ b/src/utils.c
@@ -0,0 +1,110 @@
+/* 
+ * Copyright (C) 1999-2002 The Omega Project for Statistical Computing
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "rsqlite.h"
+
+/* wrapper to strcpy */
+char*
+RS_DBI_copyString(const char* str) {
+  char* buffer;
+
+  buffer = malloc((size_t) strlen(str) + 1);
+  if (!buffer)
+    error("internal error in RS_DBI_copyString: could not alloc string space");
+  return strcpy(buffer, str);
+}
+
+int SQLite_decltype_to_type(const char* decltype) {
+  unsigned int h = 0;
+  if (!decltype)
+    return SQLITE_TEXT;
+  int len = strlen(decltype);
+  const unsigned char* zIn = (unsigned char*) decltype;
+  const unsigned char* zEnd = (unsigned char*) &(decltype[len]);
+  int col_type = SQLITE_FLOAT;
+
+  while (zIn != zEnd) {
+    h = (h << 8) + tolower(*zIn);
+    zIn++;
+    if (h == (('c' << 24) + ('h' << 16) + ('a' << 8) + 'r')) {             /* CHAR */
+      col_type = SQLITE_TEXT;
+    } else if (h == (('c' << 24) + ('l' << 16) + ('o' << 8) + 'b')) {       /* CLOB */
+      col_type = SQLITE_TEXT;
+    } else if (h == (('t' << 24) + ('e' << 16) + ('x' << 8) + 't')) {       /* TEXT */
+      col_type = SQLITE_TEXT;
+    } else if (h == (('b' << 24) + ('l' << 16) + ('o' << 8) + 'b')          /* BLOB */
+        && col_type == SQLITE_FLOAT) {
+      col_type = SQLITE_BLOB;
+#ifndef SQLITE_OMIT_FLOATING_POINT
+    } else if (h == (('r' << 24) + ('e' << 16) + ('a' << 8) + 'l')          /* REAL */
+        && col_type == SQLITE_FLOAT) {
+      col_type = SQLITE_FLOAT;
+    } else if (h == (('f' << 24) + ('l' << 16) + ('o' << 8) + 'a')          /* FLOA */
+        && col_type == SQLITE_FLOAT) {
+      col_type = SQLITE_FLOAT;
+    } else if (h == (('d' << 24) + ('o' << 16) + ('u' << 8) + 'b')          /* DOUB */
+        && col_type == SQLITE_FLOAT) {
+      col_type = SQLITE_FLOAT;
+#endif
+    } else if ((h & 0x00FFFFFF) == (('i' << 16) + ('n' << 8) + 't')) {    /* INT */
+      col_type = SQLITE_INTEGER;
+      break;
+    }
+  }
+  return col_type;
+}
+
+
+char* field_type(int type) {
+  switch (type) {
+    case SQLITE_TYPE_NULL:
+      return "NULL";
+    case SQLITE_TYPE_INTEGER:
+      return "INTEGER";
+    case SQLITE_TYPE_REAL:
+      return "REAL";
+    case SQLITE_TYPE_TEXT:
+      return "TEXT";
+    case SQLITE_TYPE_BLOB:
+      return "BLOB";
+    default:
+      return "unknown";
+  }
+}
+
+
+SEXP RS_SQLite_copy_database(SEXP fromConHandle, SEXP toConHandle) {
+  sqlite3_backup* backup = NULL;
+  SQLiteConnection* fromCon = rsqlite_connection_from_handle(fromConHandle);
+  SQLiteConnection* toCon = rsqlite_connection_from_handle(toConHandle);
+  sqlite3* dbFrom = (sqlite3*) fromCon->drvConnection;
+  sqlite3* dbTo = (sqlite3*) toCon->drvConnection;
+  int rc = 0;
+
+  backup = sqlite3_backup_init(dbTo, "main", dbFrom, "main");
+  if (backup) {
+    sqlite3_backup_step(backup, -1);
+    sqlite3_backup_finish(backup);
+  }
+  rc = sqlite3_errcode(dbTo);
+  if (rc != SQLITE_OK) {
+    rsqlite_exception_set(toCon, rc, sqlite3_errmsg(dbTo));
+    error(sqlite3_errmsg(dbTo));
+  }
+  return R_NilValue;
+}
diff --git a/tests/RSQLite_unit_tests.R b/tests/RSQLite_unit_tests.R
deleted file mode 100644
index bd5652e..0000000
--- a/tests/RSQLite_unit_tests.R
+++ /dev/null
@@ -1,3 +0,0 @@
-library("RSQLite")
-RSQLite:::.test()
-
diff --git a/tests/gc-tests.R b/tests/gc-tests.R
deleted file mode 100644
index 02761f9..0000000
--- a/tests/gc-tests.R
+++ /dev/null
@@ -1,32 +0,0 @@
-library("RSQLite")
-torture=FALSE
-drv <- SQLite()
-con <- dbConnect(drv, tempfile())
-table.name <- "testing"
-set.seed(123)
-df <- as.data.frame( matrix( rnorm( 225000 ), ncol = 225 ) )
-dbWriteTable( con, "testing", df, row.names = FALSE, 
-             overwrite = TRUE )
-
-get_data <- function( indices, con, table_name ) {
-   query <- paste(
-                  "select * from",
-                  table_name,
-                  "where _ROWID_ in (",
-                  paste( indices, collapse = "," ),
-                  ")"
-                  )
-   dbGetQuery( con, query )
-}
-
-gctorture(on=torture)
-ans <- get_data(1:3, con, table.name )[ ,1:5]
-ans
-gctorture(on=FALSE)
-
-df2 <- data.frame(name=letters[1:10],
-	          id=1:10,
-                  score=1:10 * 2.345)
-gctorture(on=torture)
-dbWriteTable(con, "t2", df2)
-gctorture(on=FALSE)
diff --git a/tests/testthat.R b/tests/testthat.R
new file mode 100644
index 0000000..e856725
--- /dev/null
+++ b/tests/testthat.R
@@ -0,0 +1,4 @@
+library(testthat)
+library(RSQLite)
+
+test_check("RSQLite")
diff --git a/inst/UnitTests/dat1.txt b/tests/testthat/dat-n.txt
similarity index 100%
rename from inst/UnitTests/dat1.txt
rename to tests/testthat/dat-n.txt
diff --git a/inst/UnitTests/dat3.txt b/tests/testthat/dat-rn.txt
similarity index 100%
rename from inst/UnitTests/dat3.txt
rename to tests/testthat/dat-rn.txt
diff --git a/tests/testthat/test-basic-types.R b/tests/testthat/test-basic-types.R
new file mode 100644
index 0000000..be6f08a
--- /dev/null
+++ b/tests/testthat/test-basic-types.R
@@ -0,0 +1,82 @@
+context("Basic types")
+
+memory_db <- function() {
+  dbConnect(SQLite(), ":memory:")
+}
+
+basicDf <- data.frame(
+  name = c("Alice", "Bob", "Carl", "NA", NA),
+  fldInt = as.integer(c(as.integer(1:4), NA)),
+  fldDbl = as.double(c(1.1, 2.2, 3.3, 4.4, NA)),
+  stringsAsFactors = FALSE
+)
+
+test_that("round-trip leaves data.frame unchanged", {
+  db <- memory_db()
+  dbWriteTable(db, "t1", basicDf, row.names = FALSE)
+
+  expect_equal(dbGetQuery(db, "select * from t1"), basicDf)
+  expect_equal(dbReadTable(db, "t1"), basicDf)
+})
+
+test_that("NAs work in first row", {
+  db <- memory_db()
+
+  na_first <- basicDf[c(5, 1:4), ]
+  rownames(na_first) <- NULL
+  dbWriteTable(db, "t1", na_first, row.names = FALSE)
+  
+  expect_equal(dbReadTable(db, "t1"), na_first)
+})
+
+test_that("row-by-row fetch is equivalent", {
+  db <- memory_db()
+  dbWriteTable(db, "t1", basicDf, row.names = FALSE)
+  
+  rs <- dbSendQuery(db, "SELECT * FROM t1")
+  on.exit(dbClearResult(rs))
+  for (i in 1:5) {
+    row <- dbFetch(rs, 1L)
+    expect_equal(row, basicDf[i, ], check.attributes = FALSE)
+  }
+  
+  row <- dbFetch(rs, 1L)
+  expect_equal(nrow(row), 0L)
+  
+  expect_true(dbHasCompleted(rs))
+})
+
+test_that("column types as expected in presence of NULLs", {
+  db <- memory_db()
+  dbWriteTable(db, "t1", datasets::USArrests)
+  
+  a1 <- dbGetQuery(db, "SELECT Murder/(Murder - 8.1) FROM t1 LIMIT 10")
+  expect_is(a1[[1]], "numeric")
+
+  ## This isn't ideal, but for now, if the first row of a result set
+  ## contains a NULL, then that column is forced to be character.
+  a2 <- dbGetQuery(db, "SELECT Murder/(Murder - 13.2) FROM t1 LIMIT 10")
+  expect_is(a2[[1]], "character")
+})
+
+test_that("correct number of columns, even if 0 rows", {
+  db <- memory_db()
+
+  ans <- dbGetQuery(db, "select 1 as a, 2 as b where 1")
+  expect_equal(dim(ans), c(1L, 2L))
+  
+  ans <- dbGetQuery(db, "select 1 as a, 2 as b where 0")
+  expect_equal(dim(ans), c(0L, 2L))  
+})
+
+test_that("BLOBs retrieve as raw vectors", {
+  con <- dbConnect(SQLite(), ":memory:")
+  local <- data.frame(
+    a = 1:10,
+    z = I(lapply(paste("hello", 1:10), charToRaw))
+  )
+  dbWriteTable(con, "t1", local)
+  
+  remote <- dbReadTable(con, "t1")
+  expect_equal(remote$z, unclass(local$z))
+})
diff --git a/tests/testthat/test-data-type.R b/tests/testthat/test-data-type.R
new file mode 100644
index 0000000..0c02a88
--- /dev/null
+++ b/tests/testthat/test-data-type.R
@@ -0,0 +1,49 @@
+context("Data type convertion")
+
+test_that("integers and boolean stored as INTEGER", {
+  expect_equal(sqliteDataType(1L), "INTEGER")
+  expect_equal(sqliteDataType(FALSE), "INTEGER")
+  expect_equal(sqliteDataType(TRUE), "INTEGER")
+  expect_equal(sqliteDataType(NA), "INTEGER")
+})
+
+test_that("doubles stored as REAL", {
+  expect_equal(sqliteDataType(1.0), "REAL")
+})
+
+test_that("character and factor stored as TEXT", {
+  expect_equal(sqliteDataType("a"), "TEXT")
+  expect_equal(sqliteDataType(factor(letters)), "TEXT")
+  expect_equal(sqliteDataType(ordered(letters)), "TEXT")
+})
+
+test_that("raw and list stored as BLOB", {
+  expect_equal(sqliteDataType(list(raw(1))), "BLOB")
+  expect_equal(sqliteDataType(list()), "BLOB")
+  expect_equal(sqliteDataType(list(a=NULL)), "BLOB")
+})
+
+test_that("AsIs class is ignored", {
+  df <- data.frame(
+    a = I(1:2),
+    b = I(c("x", "y")),
+    c = I(list(raw(3), raw(1))),
+    d = I(c(1.1, 2.2))
+  )
+  got <- sapply(df, sqliteDataType)
+  expect_equal(got, c(a="INTEGER", b="TEXT", c="BLOB", d="REAL"))
+})
+
+test_that("unknown cloasses default to storage.mode()", {
+  expect_equal(sqliteDataType(Sys.Date()), "REAL")
+  expect_equal(sqliteDataType(Sys.time()), "REAL")
+  
+  intClass <- structure(1L, class="unknown1")
+  expect_equal(sqliteDataType(intClass), "INTEGER")
+  
+  dblClass <- structure(3.14, class="unknown1")
+  expect_equal(sqliteDataType(dblClass), "REAL")
+  
+  strClass <- structure("abc", class="unknown1")
+  expect_equal(sqliteDataType(strClass), "TEXT")
+})
diff --git a/tests/testthat/test-dbClearResult.R b/tests/testthat/test-dbClearResult.R
new file mode 100644
index 0000000..c42f6e8
--- /dev/null
+++ b/tests/testthat/test-dbClearResult.R
@@ -0,0 +1,22 @@
+context("dbClearResult")
+
+test_that("warning on dbFetch if result set open", {
+  con <- dbConnect(SQLite(), ":memory:")
+  on.exit(dbDisconnect(con))
+  
+  res <- dbSendQuery(con, "SELECT 1;")
+  expect_false(dbHasCompleted(res))
+  
+  expect_warning(dbGetQuery(con, "SELECT 1;"), "pending rows")
+})
+
+test_that("accessing cleared result throws error", {
+  con <- dbConnect(SQLite(), ":memory:")
+  on.exit(dbDisconnect(con))
+  
+  res <- dbSendQuery(con, "SELECT 1;")
+  dbClearResult(res)
+  
+  expect_error(dbFetch(res), "Expired")
+  expect_error(dbGetInfo(res), "Expired")  
+})
diff --git a/tests/testthat/test-dbConnect.R b/tests/testthat/test-dbConnect.R
new file mode 100644
index 0000000..6083dd1
--- /dev/null
+++ b/tests/testthat/test-dbConnect.R
@@ -0,0 +1,78 @@
+context("dbConnect")
+
+os <- function() {
+  ostype <- .Platform[["OS.type"]]
+  if (ostype == "windows") return("windows")
+  if (grepl("darwin", R.Version()$os)) return("osx")
+  ostype
+}
+
+test_that("invalid dbnames throw errors", {
+  expect_error(dbConnect(SQLite(), dbname = 1:3))
+  expect_error(dbConnect(SQLite(), dbname = c("a", "b")))
+  expect_error(dbConnect(SQLite(), dbname = NA))
+  expect_error(dbConnect(SQLite(), dbname = as.character(NA)))
+})
+
+test_that("can get and set vfs values", {
+  allowed <- switch(os(),
+    osx = c("unix-posix", "unix-afp", "unix-flock", "unix-dotfile", "unix-none"),
+    unix = c("unix-dotfile", "unix-none"),
+    windows = character(0),
+    character(0)
+  )
+  
+  checkVfs <- function(v) {
+    db <- dbConnect(SQLite(), vfs = v)
+    on.exit(dbDisconnect(db))
+    expect_equal(v, db at vfs)
+  }  
+  for (v in allowed) checkVfs(v)
+}) 
+
+test_that("forbidden operations throw errors", {
+  tmpFile <- tempfile()
+  on.exit(unlink(tmpFile))
+  
+  ## error if file does not exist
+  expect_error(dbConnect(SQLite(), tmpFile, flags = SQLITE_RO))
+  expect_error(dbConnect(SQLite(), tmpFile, flags = SQLITE_RW))
+  
+  dbrw <- dbConnect(SQLite(), tmpFile, flags = SQLITE_RWC)
+  df <- data.frame(a=letters, b=runif(26L), stringsAsFactors=FALSE)
+  expect_true(dbWriteTable(dbrw, "t1", df))
+  dbDisconnect(dbrw)
+  
+  dbro <- dbConnect(SQLite(), dbname = tmpFile, flags = SQLITE_RO)
+  expect_error(dbWriteTable(dbro, "t2", df), "readonly database")
+  dbDisconnect(dbro)
+  
+  dbrw2 <- dbConnect(SQLite(), dbname = tmpFile, flags = SQLITE_RW)
+  expect_true(dbWriteTable(dbrw2, "t2", df))
+  dbDisconnect(dbrw2)
+})
+
+test_that("querying closed connection throws error", {
+  db <- dbConnect(SQLite(), dbname = ":memory:")
+  dbDisconnect(db)
+  expect_error(dbGetQuery(db, "select * from foo"), "expired")  
+})
+
+test_that("can connect to same db from multiple connections", {
+  dbfile <- tempfile()
+  con1 <- dbConnect(SQLite(), dbfile)  
+  con2 <- dbConnect(SQLite(), dbfile)
+  
+  dbWriteTable(con1, "mtcars", mtcars)
+  expect_equal(dbReadTable(con2, "mtcars"), mtcars)
+})
+
+test_that("temporary tables are connection local", {
+  dbfile <- tempfile()
+  con1 <- dbConnect(SQLite(), dbfile)  
+  con2 <- dbConnect(SQLite(), dbfile)
+
+  dbGetQuery(con1, "CREATE TEMPORARY TABLE temp (a TEXT)")
+  expect_true(dbExistsTable(con1, "temp"))
+  expect_false(dbExistsTable(con2, "temp"))  
+})
diff --git a/tests/testthat/test-dbSendQuery.R b/tests/testthat/test-dbSendQuery.R
new file mode 100644
index 0000000..c61623e
--- /dev/null
+++ b/tests/testthat/test-dbSendQuery.R
@@ -0,0 +1,95 @@
+context("dbSendQuery")
+
+test_that("attempting to change schema with pending rows generates warning", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+  
+  df <- data.frame(a = letters, b = LETTERS, c = 1:26, stringsAsFactors = FALSE)
+  dbWriteTable(con, "t1", df)
+  
+  rs <- dbSendQuery(con, "SELECT * FROM t1")
+  row1 <- fetch(rs, n = 1)
+  expect_equal(row1, df[1, ])
+  
+  expect_warning(dbSendQuery(con, "CREATE TABLE t2 (x text, y integer)"), 
+    "pending rows")
+})
+
+
+test_that("simple position binding works", {
+  con <- dbConnect(SQLite(), ":memory:")
+  dbWriteTable(con, "t1", data.frame(x = 1, y = 2))
+
+  dbGetPreparedQuery(con, "INSERT INTO t1 VALUES (?, ?)", 
+    bind.data = data.frame(x = 2, y = 1))
+  
+  expect_equal(dbReadTable(con, "t1")$x, c(1, 2)) 
+})
+
+test_that("simple named binding works", {
+  con <- dbConnect(SQLite(), ":memory:")
+  dbWriteTable(con, "t1", data.frame(x = 1, y = 2))
+  
+  dbGetPreparedQuery(con, "INSERT INTO t1 VALUES (:x, :y)", 
+    bind.data = data.frame(y = 1, x = 2))
+  
+  expect_equal(dbReadTable(con, "t1")$x, c(1, 2)) 
+})
+
+test_that("named binding errors if missing name", {
+  con <- dbConnect(SQLite(), ":memory:")
+  dbWriteTable(con, "t1", data.frame(x = 1, y = 2))
+  
+  expect_error(
+    dbGetPreparedQuery(con, "INSERT INTO t1 VALUES (:x, :y)", 
+      bind.data = data.frame(y = 1)), 
+    "incomplete data binding"
+  )
+})
+
+bind_select_setup <- function() {
+  con <- dbConnect(SQLite())
+  df <- data.frame(id = letters[1:5],
+    x = 1:5,
+    y = c(1L, 1L, 2L, 2L, 3L),
+    stringsAsFactors = FALSE)
+  
+  dbWriteTable(con, "t1", df, row.names = FALSE)
+  con
+}
+
+test_that("one row per bound select", {
+  con <- bind_select_setup()
+  
+  got <- dbGetPreparedQuery(con, "select * from t1 where id = ?", 
+    data.frame(id = c("e", "a", "c")))
+  
+  expect_equal(got$id, c("e", "a", "c"))
+})
+
+test_that("failed matches are silently dropped", {
+  con <- bind_select_setup()
+  sql <- "SELECT * FROM t1 WHERE id = ?"
+  
+  df1 <- dbGetPreparedQuery(con, sql, data.frame(id = "X"))
+  expect_equal(nrow(df1), 0)
+  expect_equal(names(df1), c("id", "x", "y"))
+  
+  df2 <- dbGetPreparedQuery(con, sql, data.frame(id = c("X", "Y")))
+  expect_equal(nrow(df2), 0)
+  expect_equal(names(df2), c("id", "x", "y"))
+  
+  df3 <- dbGetPreparedQuery(con, sql, data.frame(id = c("X", "a", "Y")))
+  expect_equal(nrow(df3), 1)
+  expect_equal(names(df3), c("id", "x", "y"))
+})
+
+test_that("NA matches NULL", {
+  con <- bind_select_setup()
+  dbGetQuery(con, "INSERT INTO t1 VALUES ('x', NULL, NULL)")
+  
+  got <- dbGetPreparedQuery(con, "SELECT id FROM t1 WHERE y IS :y",
+    data.frame(y = NA_integer_))
+
+  expect_equal(got$id, "x")
+})
diff --git a/tests/testthat/test-dbWriteTable.R b/tests/testthat/test-dbWriteTable.R
new file mode 100644
index 0000000..a4f5ff7
--- /dev/null
+++ b/tests/testthat/test-dbWriteTable.R
@@ -0,0 +1,145 @@
+context("dbWriteTable")
+
+# In memory --------------------------------------------------------------------
+
+test_that("can't override existing table with default options", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+  
+  x <- data.frame(col1 = 1:10, col2 = letters[1:10])  
+  dbWriteTable(con, "t1", x)
+  expect_error(dbWriteTable(con, "t1", x), "exists in database")
+})
+
+test_that("throws error if constrainted violated", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+  
+  x <- data.frame(col1 = 1:10, col2 = letters[1:10])
+  
+  dbWriteTable(con, "t1", x)
+  dbGetQuery(con, "CREATE UNIQUE INDEX t1_c1_c2_idx ON t1(col1, col2)")
+  expect_error(dbWriteTable(con, "t1", x, append = TRUE), 
+    "UNIQUE constraint failed")
+})
+
+test_that("can't add table when result set open", {
+  # This needs to fail because cloning a temporary file or in memory 
+  # database creates new database
+  con <- dbConnect(SQLite(), tempfile())
+  on.exit(dbDisconnect(con))
+  
+  x <- data.frame(col1 = 1:10, col2 = letters[1:10])
+  dbWriteTable(con, "t1", x)
+  
+  res <- dbSendQuery(con, "SELECT * FROM t1")
+  expect_warning(dbWriteTable(con, "t2", x), "pending rows")
+  expect_error(dbClearResult(res), "Expired")
+})
+
+test_that("rownames preserved", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+  
+  df <- data.frame(x = 1:10)
+  row.names(df) <- paste(letters[1:10], 1:10, sep="")
+  
+  dbWriteTable(con, "t1", df)
+  t1 <- dbReadTable(con, "t1")
+  expect_equal(rownames(t1), rownames(df))  
+})
+
+test_that("commas in fields are preserved", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+  
+  df <- data.frame(
+    x = c("ABC, Inc.","DEF Holdings"), 
+    stringsAsFactors = FALSE
+  )
+  dbWriteTable(con, "t1", df, row.names = FALSE)
+  expect_equal(dbReadTable(con, "t1"), df)
+})
+
+test_that("NAs preserved in factors", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+  
+  df <- data.frame(x = 1:10, y = factor(LETTERS[1:10]))
+  df$y[4] <- NA
+  
+  dbWriteTable(con, "bad_table", df)
+  bad_table <- dbReadTable(con, "bad_table")
+  expect_equal(bad_table$x, df$x)
+  expect_equal(bad_table$y, as.character(df$y))
+})
+
+test_that("logical converted to int", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+  
+  local <- data.frame(x = 1:3, y = c(NA, TRUE, FALSE))
+  dbWriteTable(con, "t1", local)
+  remote <- dbReadTable(con, "t1")
+  
+  expect_equal(remote$y, as.integer(local$y))
+})
+
+test_that("can roundtrip special field names", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+  
+  local <- data.frame(x = 1:3, select = 1:3, `  ` = 1:3, check.names = FALSE)
+  dbWriteTable(con, "torture", local)
+  remote <- dbReadTable(con, "torture", check.names = FALSE)
+  
+  expect_equal(local, remote)
+})
+
+# From file -------------------------------------------------------------------
+
+test_that("comments are preserved", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+  
+  tmp_file <- tempfile()
+  cat('A,B,C\n11,2#2,33\n', file = tmp_file)
+  on.exit(file.remove(tmp_file), add = TRUE)
+  
+  dbWriteTable(con, "t1", tmp_file, header = TRUE, sep = ",")
+  remote <- dbReadTable(con, "t1")
+  expect_equal(remote$B, "2#2")
+})
+
+test_that("colclasses overridden by argument", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+  
+  tmp_file <- tempfile()
+  cat('A,B,C\n1,2,3\n4,5,6\na,7,8\n', file = tmp_file)
+  on.exit(file.remove(tmp_file), add = TRUE)
+  
+  dbWriteTable(con, "t1", tmp_file, header = TRUE, sep = ",",
+    colClasses = c("character", "integer", "double"))
+  
+  remote <- dbReadTable(con, "t1")
+  expect_equal(sapply(remote, class), 
+    c(A="character", B="integer", C="numeric"))
+})
+
+test_that("options work", {
+  con <- dbConnect(SQLite())
+  on.exit(dbDisconnect(con))
+
+  expected <- data.frame(
+    a = c(1:3, NA), 
+    b = c("x", "y", "z", "E"),
+    stringsAsFactors = FALSE
+  )
+
+  dbWriteTable(con, "dat", "dat-n.txt", sep="|", eol="\n", overwrite = TRUE)
+  expect_equal(dbReadTable(con, "dat"), expected)
+  
+  dbWriteTable(con, "dat", "dat-rn.txt", sep="|", eol="\r\n", overwrite = TRUE)
+  expect_equal(dbReadTable(con, "dat"), expected)
+})
\ No newline at end of file
diff --git a/tests/testthat/test-sqliteCopyDatabase.R b/tests/testthat/test-sqliteCopyDatabase.R
new file mode 100644
index 0000000..c17a80d
--- /dev/null
+++ b/tests/testthat/test-sqliteCopyDatabase.R
@@ -0,0 +1,37 @@
+context("sqliteCopyDatabase")
+
+test_that("fails with bad arguments", {
+  dbfile <- tempfile()
+  con <- dbConnect(SQLite(), dbfile)
+
+  badnames <- list(
+    1:5,
+    character(0),
+    as.character(NA),
+    ""
+  )
+  for (badname in badnames) {
+    expect_error(sqliteCopyDatabase(con, badname), "must be")
+  }
+})
+
+test_that("can backup memory db to disk", {
+  con1 <- dbConnect(SQLite(), ":memory:")
+  dbWriteTable(con1, "mtcars", mtcars)
+  
+  dbfile <- tempfile()
+  sqliteCopyDatabase(con1, dbfile)
+  
+  con2 <- dbConnect(SQLite(), dbfile)
+  expect_true(dbExistsTable(con2, "mtcars"))
+})
+
+test_that("can backup to connection", {
+  con1 <- dbConnect(SQLite(), ":memory:")
+  dbWriteTable(con1, "mtcars", mtcars)
+  
+  con2 <- dbConnect(SQLite(), ":memory:")
+  sqliteCopyDatabase(con1, con2)
+  
+  expect_true(dbExistsTable(con2, "mtcars"))  
+})
diff --git a/tests/testthat/test-sqliteQuickColumn.R b/tests/testthat/test-sqliteQuickColumn.R
new file mode 100644
index 0000000..5bbdc60
--- /dev/null
+++ b/tests/testthat/test-sqliteQuickColumn.R
@@ -0,0 +1,23 @@
+context("sqliteQuickColumn")
+
+set.seed(0x977)
+
+test_that("sqliteQuickColumn round trips cleanly", {
+  mk_blob <- function(n) as.raw(sample(0:255, n, replace = TRUE))
+  
+  df <- data.frame(
+    a = letters[1:10], 
+    b = rnorm(10),
+    c = sample(1:10),
+    d = I(lapply(1:10, function(x) mk_blob(sample(10:256, 1)))),
+    stringsAsFactors = FALSE
+  )
+  
+  db <- dbConnect(SQLite(), dbname = ":memory:")
+  dbWriteTable(db, "t", df)
+  
+  expect_equal(sqliteQuickColumn(db, "t", "a"), df$a)
+  expect_equal(sqliteQuickColumn(db, "t", "b"), df$b)
+  expect_equal(sqliteQuickColumn(db, "t", "c"), df$c)
+  expect_equal(sqliteQuickColumn(db, "t", "d"), unclass(df$d))
+})

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-rsqlite.git



More information about the debian-med-commit mailing list